Replaced doc, doc.fields frappe/frappe#478

This commit is contained in:
Anand Doshi 2014-03-28 13:55:00 +05:30
parent 67d6a4e3aa
commit f78d1aee28
142 changed files with 2443 additions and 2444 deletions

View File

@ -15,13 +15,13 @@ class Account(Document):
nsm_parent_field = 'parent_account'
def autoname(self):
self.doc.name = self.doc.account_name.strip() + ' - ' + \
frappe.db.get_value("Company", self.doc.company, "abbr")
self.name = self.account_name.strip() + ' - ' + \
frappe.db.get_value("Company", self.company, "abbr")
def get_address(self):
return {
'address': frappe.db.get_value(self.doc.master_type,
self.doc.master_name, "address")
'address': frappe.db.get_value(self.master_type,
self.master_name, "address")
}
def validate(self):
@ -33,54 +33,54 @@ class Account(Document):
self.validate_warehouse_account()
self.validate_frozen_accounts_modifier()
if not self.doc.parent_account:
self.doc.parent_account = ''
if not self.parent_account:
self.parent_account = ''
def validate_master_name(self):
"""Remind to add master name"""
if self.doc.master_type in ('Customer', 'Supplier') or self.doc.account_type == "Warehouse":
if not self.doc.master_name:
if self.master_type in ('Customer', 'Supplier') or self.account_type == "Warehouse":
if not self.master_name:
msgprint(_("Please enter Master Name once the account is created."))
elif not frappe.db.exists(self.doc.master_type or self.doc.account_type,
self.doc.master_name):
elif not frappe.db.exists(self.master_type or self.account_type,
self.master_name):
throw(_("Invalid Master Name"))
def validate_parent(self):
"""Fetch Parent Details and validation for account not to be created under ledger"""
if self.doc.parent_account:
if self.parent_account:
par = frappe.db.sql("""select name, group_or_ledger, report_type
from tabAccount where name =%s""", self.doc.parent_account, as_dict=1)
from tabAccount where name =%s""", self.parent_account, as_dict=1)
if not par:
throw(_("Parent account does not exists"))
elif par[0]["name"] == self.doc.name:
elif par[0]["name"] == self.name:
throw(_("You can not assign itself as parent account"))
elif par[0]["group_or_ledger"] != 'Group':
throw(_("Parent account can not be a ledger"))
if par[0]["report_type"]:
self.doc.report_type = par[0]["report_type"]
self.report_type = par[0]["report_type"]
def validate_duplicate_account(self):
if self.doc.fields.get('__islocal') or not self.doc.name:
company_abbr = frappe.db.get_value("Company", self.doc.company, "abbr")
if self.get('__islocal') or not self.name:
company_abbr = frappe.db.get_value("Company", self.company, "abbr")
if frappe.db.sql("""select name from tabAccount where name=%s""",
(self.doc.account_name + " - " + company_abbr)):
(self.account_name + " - " + company_abbr)):
throw("{name}: {acc_name} {exist}, {rename}".format(**{
"name": _("Account Name"),
"acc_name": self.doc.account_name,
"acc_name": self.account_name,
"exist": _("already exists"),
"rename": _("please rename")
}))
def validate_root_details(self):
#does not exists parent
if frappe.db.exists("Account", self.doc.name):
if not frappe.db.get_value("Account", self.doc.name, "parent_account"):
if frappe.db.exists("Account", self.name):
if not frappe.db.get_value("Account", self.name, "parent_account"):
throw(_("Root cannot be edited."))
def validate_frozen_accounts_modifier(self):
old_value = frappe.db.get_value("Account", self.doc.name, "freeze_account")
if old_value and old_value != self.doc.freeze_account:
old_value = frappe.db.get_value("Account", self.name, "freeze_account")
if old_value and old_value != self.freeze_account:
frozen_accounts_modifier = frappe.db.get_value( 'Accounts Settings', None,
'frozen_accounts_modifier')
if not frozen_accounts_modifier or \
@ -91,50 +91,50 @@ class Account(Document):
if self.check_if_child_exists():
throw("{acc}: {account_name} {child}. {msg}".format(**{
"acc": _("Account"),
"account_name": self.doc.name,
"account_name": self.name,
"child": _("has existing child"),
"msg": _("You can not convert this account to ledger")
}))
elif self.check_gle_exists():
throw(_("Account with existing transaction can not be converted to ledger."))
else:
self.doc.group_or_ledger = 'Ledger'
self.doc.save()
self.group_or_ledger = 'Ledger'
self.save()
return 1
def convert_ledger_to_group(self):
if self.check_gle_exists():
throw(_("Account with existing transaction can not be converted to group."))
elif self.doc.master_type or self.doc.account_type:
elif self.master_type or self.account_type:
throw(_("Cannot covert to Group because Master Type or Account Type is selected."))
else:
self.doc.group_or_ledger = 'Group'
self.doc.save()
self.group_or_ledger = 'Group'
self.save()
return 1
# Check if any previous balance exists
def check_gle_exists(self):
return frappe.db.get_value("GL Entry", {"account": self.doc.name})
return frappe.db.get_value("GL Entry", {"account": self.name})
def check_if_child_exists(self):
return frappe.db.sql("""select name from `tabAccount` where parent_account = %s
and docstatus != 2""", self.doc.name)
and docstatus != 2""", self.name)
def validate_mandatory(self):
if not self.doc.report_type:
if not self.report_type:
throw(_("Report Type is mandatory"))
def validate_warehouse_account(self):
if not cint(frappe.defaults.get_global_default("auto_accounting_for_stock")):
return
if self.doc.account_type == "Warehouse":
old_warehouse = cstr(frappe.db.get_value("Account", self.doc.name, "master_name"))
if old_warehouse != cstr(self.doc.master_name):
if self.account_type == "Warehouse":
old_warehouse = cstr(frappe.db.get_value("Account", self.name, "master_name"))
if old_warehouse != cstr(self.master_name):
if old_warehouse:
self.validate_warehouse(old_warehouse)
if self.doc.master_name:
self.validate_warehouse(self.doc.master_name)
if self.master_name:
self.validate_warehouse(self.master_name)
else:
throw(_("Master Name is mandatory if account type is Warehouse"))
@ -163,10 +163,10 @@ class Account(Document):
credit_limit_from = 'Customer'
cr_limit = frappe.db.sql("""select t1.credit_limit from tabCustomer t1, `tabAccount` t2
where t2.name=%s and t1.name = t2.master_name""", self.doc.name)
where t2.name=%s and t1.name = t2.master_name""", self.name)
credit_limit = cr_limit and flt(cr_limit[0][0]) or 0
if not credit_limit:
credit_limit = frappe.db.get_value('Company', self.doc.company, 'credit_limit')
credit_limit = frappe.db.get_value('Company', self.company, 'credit_limit')
credit_limit_from = 'Company'
# If outstanding greater than credit limit and not authorized person raise exception
@ -175,11 +175,11 @@ class Account(Document):
throw("""Total Outstanding amount (%s) for <b>%s</b> can not be \
greater than credit limit (%s). To change your credit limit settings, \
please update in the <b>%s</b> master""" % (fmt_money(total_outstanding),
self.doc.name, fmt_money(credit_limit), credit_limit_from))
self.name, fmt_money(credit_limit), credit_limit_from))
def validate_trash(self):
"""checks gl entries and if child exists"""
if not self.doc.parent_account:
if not self.parent_account:
throw(_("Root account can not be deleted"))
if self.check_gle_exists():
@ -195,7 +195,7 @@ class Account(Document):
def before_rename(self, old, new, merge=False):
# Add company abbr if not provided
from erpnext.setup.doctype.company.company import get_name_with_abbr
new_account = get_name_with_abbr(new, self.doc.company)
new_account = get_name_with_abbr(new, self.company)
# Validate properties before merging
if merge:
@ -205,7 +205,7 @@ class Account(Document):
val = list(frappe.db.get_value("Account", new_account,
["group_or_ledger", "report_type", "company"]))
if val != [self.doc.group_or_ledger, self.doc.report_type, self.doc.company]:
if val != [self.group_or_ledger, self.report_type, self.company]:
throw(_("""Merging is only possible if following \
properties are same in both records.
Group or Ledger, Report Type, Company"""))

View File

@ -13,9 +13,9 @@ from frappe.model.document import Document
class AccountsSettings(Document):
def on_update(self):
frappe.db.set_default("auto_accounting_for_stock", self.doc.auto_accounting_for_stock)
frappe.db.set_default("auto_accounting_for_stock", self.auto_accounting_for_stock)
if cint(self.doc.auto_accounting_for_stock):
if cint(self.auto_accounting_for_stock):
# set default perpetual account in company
for company in frappe.db.sql("select name from tabCompany"):
frappe.bean("Company", company[0]).save()

View File

@ -12,17 +12,17 @@ from frappe.model.document import Document
class BankReconciliation(Document):
def get_details(self):
if not (self.doc.bank_account and self.doc.from_date and self.doc.to_date):
if not (self.bank_account and self.from_date and self.to_date):
msgprint("Bank Account, From Date and To Date are Mandatory")
return
dl = frappe.db.sql("select t1.name, t1.cheque_no, t1.cheque_date, t2.debit, t2.credit, t1.posting_date, t2.against_account from `tabJournal Voucher` t1, `tabJournal Voucher Detail` t2 where t2.parent = t1.name and t2.account = %s and (clearance_date is null or clearance_date = '0000-00-00' or clearance_date = '') and t1.posting_date >= %s and t1.posting_date <= %s and t1.docstatus=1", (self.doc.bank_account, self.doc.from_date, self.doc.to_date))
dl = frappe.db.sql("select t1.name, t1.cheque_no, t1.cheque_date, t2.debit, t2.credit, t1.posting_date, t2.against_account from `tabJournal Voucher` t1, `tabJournal Voucher Detail` t2 where t2.parent = t1.name and t2.account = %s and (clearance_date is null or clearance_date = '0000-00-00' or clearance_date = '') and t1.posting_date >= %s and t1.posting_date <= %s and t1.docstatus=1", (self.bank_account, self.from_date, self.to_date))
self.set('entries', [])
self.doc.total_amount = 0.0
self.total_amount = 0.0
for d in dl:
nl = self.doc.append('entries', {})
nl = self.append('entries', {})
nl.posting_date = cstr(d[5])
nl.voucher_id = cstr(d[0])
nl.cheque_number = cstr(d[1])
@ -30,7 +30,7 @@ class BankReconciliation(Document):
nl.debit = flt(d[3])
nl.credit = flt(d[4])
nl.against_account = cstr(d[6])
self.doc.total_amount += flt(flt(d[4]) - flt(d[3]))
self.total_amount += flt(flt(d[4]) - flt(d[3]))
def update_details(self):
vouchers = []

View File

@ -28,7 +28,7 @@ class CForm(Document):
frappe.msgprint("C-form is not applicable for Invoice: %s" %
d.invoice_no, raise_exception=1)
elif inv[0][1] and inv[0][1] != self.doc.name:
elif inv[0][1] and inv[0][1] != self.name:
frappe.msgprint("""Invoice %s is tagged in another C-form: %s.
If you want to change C-form no for this invoice,
please remove invoice no from the previous c-form and then try again""" %
@ -44,19 +44,19 @@ class CForm(Document):
def before_cancel(self):
# remove cform reference
frappe.db.sql("""update `tabSales Invoice` set c_form_no=null
where c_form_no=%s""", self.doc.name)
where c_form_no=%s""", self.name)
def set_cform_in_sales_invoices(self):
inv = [d.invoice_no for d in self.get('invoice_details')]
if inv:
frappe.db.sql("""update `tabSales Invoice` set c_form_no=%s, modified=%s
where name in (%s)""" % ('%s', '%s', ', '.join(['%s'] * len(inv))),
tuple([self.doc.name, self.doc.modified] + inv))
tuple([self.name, self.modified] + inv))
frappe.db.sql("""update `tabSales Invoice` set c_form_no = null, modified = %s
where name not in (%s) and ifnull(c_form_no, '') = %s""" %
('%s', ', '.join(['%s']*len(inv)), '%s'),
tuple([self.doc.modified] + inv + [self.doc.name]))
tuple([self.modified] + inv + [self.name]))
else:
frappe.msgprint("Please enter atleast 1 invoice in the table", raise_exception=1)

View File

@ -15,7 +15,7 @@ class ChartOfAccounts(Document):
def create_accounts(self, company):
chart = {}
with open(os.path.join(os.path.dirname(__file__), "charts",
self.doc.source_file), "r") as f:
self.source_file), "r") as f:
chart = json.loads(f.read())
from erpnext.accounts.doctype.chart_of_accounts.charts.account_properties \
@ -49,15 +49,15 @@ class ChartOfAccounts(Document):
accounts.append(account_name_in_db)
# set report_type for all parents where blank
if not account.doc.report_type or account.doc.report_type == 'None':
if not account.report_type or account.report_type == 'None':
self.no_report_type = True
elif self.no_report_type:
frappe.db.sql("""update tabAccount set report_type=%s
where lft<=%s and rgt>=%s and ifnull(report_type, '')=''""",
(account.doc.report_type, account.doc.lft, account.doc.rgt))
(account.report_type, account.lft, account.rgt))
if child.get("children"):
_import_accounts(child.get("children"), account.doc.name)
_import_accounts(child.get("children"), account.name)
_import_accounts(chart.get("root").get("children"), None)

View File

@ -19,7 +19,7 @@ def import_charts():
"source_file": fname,
"country": country
}).insert()
print bean.doc.name.encode("utf-8")
print bean.name.encode("utf-8")
else:
print "No chart for: " + chart.get("name").encode("utf-8")

View File

@ -14,47 +14,47 @@ class CostCenter(DocTypeNestedSet):
def autoname(self):
company_abbr = frappe.db.sql("select abbr from tabCompany where name=%s",
self.doc.company)[0][0]
self.doc.name = self.doc.cost_center_name.strip() + ' - ' + company_abbr
self.company)[0][0]
self.name = self.cost_center_name.strip() + ' - ' + company_abbr
def validate_mandatory(self):
if not self.doc.group_or_ledger:
if not self.group_or_ledger:
msgprint("Please select Group or Ledger value", raise_exception=1)
if self.doc.cost_center_name != self.doc.company and not self.doc.parent_cost_center:
if self.cost_center_name != self.company and not self.parent_cost_center:
msgprint("Please enter parent cost center", raise_exception=1)
elif self.doc.cost_center_name == self.doc.company and self.doc.parent_cost_center:
elif self.cost_center_name == self.company and self.parent_cost_center:
msgprint(_("Root cannot have a parent cost center"), raise_exception=1)
def convert_group_to_ledger(self):
if self.check_if_child_exists():
msgprint("Cost Center: %s has existing child. You can not convert this cost center to ledger" % (self.doc.name), raise_exception=1)
msgprint("Cost Center: %s has existing child. You can not convert this cost center to ledger" % (self.name), raise_exception=1)
elif self.check_gle_exists():
msgprint("Cost Center with existing transaction can not be converted to ledger.", raise_exception=1)
else:
self.doc.group_or_ledger = 'Ledger'
self.doc.save()
self.group_or_ledger = 'Ledger'
self.save()
return 1
def convert_ledger_to_group(self):
if self.check_gle_exists():
msgprint("Cost Center with existing transaction can not be converted to group.", raise_exception=1)
else:
self.doc.group_or_ledger = 'Group'
self.doc.save()
self.group_or_ledger = 'Group'
self.save()
return 1
def check_gle_exists(self):
return frappe.db.get_value("GL Entry", {"cost_center": self.doc.name})
return frappe.db.get_value("GL Entry", {"cost_center": self.name})
def check_if_child_exists(self):
return frappe.db.sql("select name from `tabCost Center` where \
parent_cost_center = %s and docstatus != 2", self.doc.name)
parent_cost_center = %s and docstatus != 2", self.name)
def validate_budget_details(self):
check_acc_list = []
for d in self.get('budget_details'):
if self.doc.group_or_ledger=="Group":
if self.group_or_ledger=="Group":
msgprint("Budget cannot be set for Group Cost Centers", raise_exception=1)
if [d.account, d.fiscal_year] in check_acc_list:
@ -66,7 +66,7 @@ class CostCenter(DocTypeNestedSet):
"""
Cost Center name must be unique
"""
if (self.doc.fields.get("__islocal") or not self.doc.name) and frappe.db.sql("select name from `tabCost Center` where cost_center_name = %s and company=%s", (self.doc.cost_center_name, self.doc.company)):
if (self.get("__islocal") or not self.name) and frappe.db.sql("select name from `tabCost Center` where cost_center_name = %s and company=%s", (self.cost_center_name, self.company)):
msgprint("Cost Center Name already exists, please rename", raise_exception=1)
self.validate_mandatory()
@ -75,7 +75,7 @@ class CostCenter(DocTypeNestedSet):
def before_rename(self, olddn, newdn, merge=False):
# Add company abbr if not provided
from erpnext.setup.doctype.company.company import get_name_with_abbr
new_cost_center = get_name_with_abbr(newdn, self.doc.company)
new_cost_center = get_name_with_abbr(newdn, self.company)
# Validate properties before merging
super(DocType, self).before_rename(olddn, new_cost_center, merge, "group_or_ledger")

View File

@ -11,35 +11,35 @@ from frappe.model.document import Document
class FiscalYear(Document):
def set_as_default(self):
frappe.db.set_value("Global Defaults", None, "current_fiscal_year", self.doc.name)
frappe.db.set_value("Global Defaults", None, "current_fiscal_year", self.name)
frappe.get_obj("Global Defaults").on_update()
# clear cache
frappe.clear_cache()
msgprint(self.doc.name + _(""" is now the default Fiscal Year. \
msgprint(self.name + _(""" is now the default Fiscal Year. \
Please refresh your browser for the change to take effect."""))
def validate(self):
year_start_end_dates = frappe.db.sql("""select year_start_date, year_end_date
from `tabFiscal Year` where name=%s""", (self.doc.name))
from `tabFiscal Year` where name=%s""", (self.name))
if year_start_end_dates:
if getdate(self.doc.year_start_date) != year_start_end_dates[0][0] or getdate(self.doc.year_end_date) != year_start_end_dates[0][1]:
if getdate(self.year_start_date) != year_start_end_dates[0][0] or getdate(self.year_end_date) != year_start_end_dates[0][1]:
frappe.throw(_("Cannot change Year Start Date and Year End Date once the Fiscal Year is saved."))
def on_update(self):
# validate year start date and year end date
if getdate(self.doc.year_start_date) > getdate(self.doc.year_end_date):
if getdate(self.year_start_date) > getdate(self.year_end_date):
frappe.throw(_("Year Start Date should not be greater than Year End Date"))
if (getdate(self.doc.year_end_date) - getdate(self.doc.year_start_date)).days > 366:
if (getdate(self.year_end_date) - getdate(self.year_start_date)).days > 366:
frappe.throw(_("Year Start Date and Year End Date are not within Fiscal Year."))
year_start_end_dates = frappe.db.sql("""select name, year_start_date, year_end_date
from `tabFiscal Year` where name!=%s""", (self.doc.name))
from `tabFiscal Year` where name!=%s""", (self.name))
for fiscal_year, ysd, yed in year_start_end_dates:
if (getdate(self.doc.year_start_date) == ysd and getdate(self.doc.year_end_date) == yed) \
if (getdate(self.year_start_date) == ysd and getdate(self.year_end_date) == yed) \
and (not frappe.flags.in_test):
frappe.throw(_("Year Start Date and Year End Date are already set in Fiscal Year: ") + fiscal_year)

View File

@ -20,42 +20,42 @@ class GlEntry(Document):
def on_update_with_args(self, adv_adj, update_outstanding = 'Yes'):
self.validate_account_details(adv_adj)
validate_frozen_account(self.doc.account, adv_adj)
check_freezing_date(self.doc.posting_date, adv_adj)
validate_balance_type(self.doc.account, adv_adj)
validate_frozen_account(self.account, adv_adj)
check_freezing_date(self.posting_date, adv_adj)
validate_balance_type(self.account, adv_adj)
# Update outstanding amt on against voucher
if self.doc.against_voucher and self.doc.against_voucher_type != "POS" \
if self.against_voucher and self.against_voucher_type != "POS" \
and update_outstanding == 'Yes':
update_outstanding_amt(self.doc.account, self.doc.against_voucher_type,
self.doc.against_voucher)
update_outstanding_amt(self.account, self.against_voucher_type,
self.against_voucher)
def check_mandatory(self):
mandatory = ['account','remarks','voucher_type','voucher_no','fiscal_year','company']
for k in mandatory:
if not self.doc.fields.get(k):
if not self.get(k):
frappe.throw(k + _(" is mandatory for GL Entry"))
# Zero value transaction is not allowed
if not (flt(self.doc.debit) or flt(self.doc.credit)):
if not (flt(self.debit) or flt(self.credit)):
frappe.throw(_("GL Entry: Debit or Credit amount is mandatory for ") +
self.doc.account)
self.account)
def pl_must_have_cost_center(self):
if frappe.db.get_value("Account", self.doc.account, "report_type") == "Profit and Loss":
if not self.doc.cost_center and self.doc.voucher_type != 'Period Closing Voucher':
if frappe.db.get_value("Account", self.account, "report_type") == "Profit and Loss":
if not self.cost_center and self.voucher_type != 'Period Closing Voucher':
frappe.throw(_("Cost Center must be specified for Profit and Loss type account: ")
+ self.doc.account)
elif self.doc.cost_center:
self.doc.cost_center = None
+ self.account)
elif self.cost_center:
self.cost_center = None
def validate_posting_date(self):
from erpnext.accounts.utils import validate_fiscal_year
validate_fiscal_year(self.doc.posting_date, self.doc.fiscal_year, "Posting Date")
validate_fiscal_year(self.posting_date, self.fiscal_year, "Posting Date")
def check_pl_account(self):
if self.doc.is_opening=='Yes' and \
frappe.db.get_value("Account", self.doc.account, "report_type")=="Profit and Loss":
if self.is_opening=='Yes' and \
frappe.db.get_value("Account", self.account, "report_type")=="Profit and Loss":
frappe.throw(_("For opening balance entry, account can not be \
a Profit and Loss type account"))
@ -63,32 +63,32 @@ class GlEntry(Document):
"""Account must be ledger, active and not freezed"""
ret = frappe.db.sql("""select group_or_ledger, docstatus, company
from tabAccount where name=%s""", self.doc.account, as_dict=1)[0]
from tabAccount where name=%s""", self.account, as_dict=1)[0]
if ret.group_or_ledger=='Group':
frappe.throw(_("Account") + ": " + self.doc.account + _(" is not a ledger"))
frappe.throw(_("Account") + ": " + self.account + _(" is not a ledger"))
if ret.docstatus==2:
frappe.throw(_("Account") + ": " + self.doc.account + _(" is not active"))
frappe.throw(_("Account") + ": " + self.account + _(" is not active"))
if ret.company != self.doc.company:
frappe.throw(_("Account") + ": " + self.doc.account +
_(" does not belong to the company") + ": " + self.doc.company)
if ret.company != self.company:
frappe.throw(_("Account") + ": " + self.account +
_(" does not belong to the company") + ": " + self.company)
def validate_cost_center(self):
if not hasattr(self, "cost_center_company"):
self.cost_center_company = {}
def _get_cost_center_company():
if not self.cost_center_company.get(self.doc.cost_center):
self.cost_center_company[self.doc.cost_center] = frappe.db.get_value(
"Cost Center", self.doc.cost_center, "company")
if not self.cost_center_company.get(self.cost_center):
self.cost_center_company[self.cost_center] = frappe.db.get_value(
"Cost Center", self.cost_center, "company")
return self.cost_center_company[self.doc.cost_center]
return self.cost_center_company[self.cost_center]
if self.doc.cost_center and _get_cost_center_company() != self.doc.company:
frappe.throw(_("Cost Center") + ": " + self.doc.cost_center +
_(" does not belong to the company") + ": " + self.doc.company)
if self.cost_center and _get_cost_center_company() != self.company:
frappe.throw(_("Cost Center") + ": " + self.cost_center +
_(" does not belong to the company") + ": " + self.company)
def validate_balance_type(account, adv_adj=False):
if not adv_adj and account:

View File

@ -18,10 +18,10 @@ class JournalVoucher(AccountsController):
self.is_approving_authority = -1
def validate(self):
if not self.doc.is_opening:
self.doc.is_opening='No'
if not self.is_opening:
self.is_opening='No'
self.doc.clearance_date = None
self.clearance_date = None
super(DocType, self).validate_date_with_fiscal_year()
@ -37,21 +37,21 @@ class JournalVoucher(AccountsController):
def on_submit(self):
if self.doc.voucher_type in ['Bank Voucher', 'Contra Voucher', 'Journal Entry']:
if self.voucher_type in ['Bank Voucher', 'Contra Voucher', 'Journal Entry']:
self.check_credit_days()
self.make_gl_entries()
self.check_credit_limit()
def on_cancel(self):
from erpnext.accounts.utils import remove_against_link_from_jv
remove_against_link_from_jv(self.doc.doctype, self.doc.name, "against_jv")
remove_against_link_from_jv(self.doctype, self.name, "against_jv")
self.make_gl_entries(1)
def on_trash(self):
pass
#if self.doc.amended_from:
# frappe.delete_doc("Journal Voucher", self.doc.amended_from)
#if self.amended_from:
# frappe.delete_doc("Journal Voucher", self.amended_from)
def validate_debit_credit(self):
for d in self.get('entries'):
@ -60,12 +60,12 @@ class JournalVoucher(AccountsController):
raise_exception=1)
def validate_cheque_info(self):
if self.doc.voucher_type in ['Bank Voucher']:
if not self.doc.cheque_no or not self.doc.cheque_date:
if self.voucher_type in ['Bank Voucher']:
if not self.cheque_no or not self.cheque_date:
msgprint("Reference No & Reference Date is required for %s" %
self.doc.voucher_type, raise_exception=1)
self.voucher_type, raise_exception=1)
if self.doc.cheque_date and not self.doc.cheque_no:
if self.cheque_date and not self.cheque_no:
msgprint("Reference No is mandatory if you entered Reference Date", raise_exception=1)
def validate_entries_for_advance(self):
@ -81,7 +81,7 @@ class JournalVoucher(AccountsController):
def validate_against_jv(self):
for d in self.get('entries'):
if d.against_jv:
if d.against_jv == self.doc.name:
if d.against_jv == self.name:
msgprint("You can not enter current voucher in 'Against JV' column",
raise_exception=1)
elif not frappe.db.sql("""select name from `tabJournal Voucher Detail`
@ -99,12 +99,12 @@ class JournalVoucher(AccountsController):
if flt(d.debit)>0 and (d.account not in debit_list): debit_list.append(d.account)
if flt(d.credit)>0 and (d.account not in credit_list): credit_list.append(d.account)
self.doc.total_debit = debit
self.doc.total_credit = credit
self.total_debit = debit
self.total_credit = credit
if abs(self.doc.total_debit-self.doc.total_credit) > 0.001:
if abs(self.total_debit-self.total_credit) > 0.001:
msgprint("Debit must be equal to Credit. The difference is %s" %
(self.doc.total_debit-self.doc.total_credit), raise_exception=1)
(self.total_debit-self.total_credit), raise_exception=1)
# update against account
for d in self.get('entries'):
@ -113,10 +113,10 @@ class JournalVoucher(AccountsController):
def create_remarks(self):
r = []
if self.doc.cheque_no :
if self.doc.cheque_date:
if self.cheque_no :
if self.cheque_date:
r.append('Via Reference #%s dated %s' %
(self.doc.cheque_no, formatdate(self.doc.cheque_date)))
(self.cheque_no, formatdate(self.cheque_date)))
else :
msgprint("Please enter Reference date", raise_exception=1)
@ -135,17 +135,17 @@ class JournalVoucher(AccountsController):
(cstr(bill_no[0][2]), fmt_money(flt(d.debit)), bill_no[0][0],
bill_no[0][1] and formatdate(bill_no[0][1].strftime('%Y-%m-%d')) or ''))
if self.doc.user_remark:
r.append("User Remark : %s"%self.doc.user_remark)
if self.user_remark:
r.append("User Remark : %s"%self.user_remark)
if r:
self.doc.remark = ("\n").join(r)
self.remark = ("\n").join(r)
else:
frappe.msgprint("User Remarks is mandatory", raise_exception=1)
def set_aging_date(self):
if self.doc.is_opening != 'Yes':
self.doc.aging_date = self.doc.posting_date
if self.is_opening != 'Yes':
self.aging_date = self.posting_date
else:
# check account type whether supplier or customer
exists = False
@ -156,10 +156,10 @@ class JournalVoucher(AccountsController):
break
# If customer/supplier account, aging date is mandatory
if exists and not self.doc.aging_date:
if exists and not self.aging_date:
msgprint("Aging Date is mandatory for opening entry", raise_exception=1)
else:
self.doc.aging_date = self.doc.posting_date
self.aging_date = self.posting_date
def set_print_format_fields(self):
for d in self.get('entries'):
@ -167,22 +167,22 @@ class JournalVoucher(AccountsController):
["account_type", "master_type"])
if master_type in ['Supplier', 'Customer']:
if not self.doc.pay_to_recd_from:
self.doc.pay_to_recd_from = frappe.db.get_value(master_type,
if not self.pay_to_recd_from:
self.pay_to_recd_from = frappe.db.get_value(master_type,
' - '.join(d.account.split(' - ')[:-1]),
master_type == 'Customer' and 'customer_name' or 'supplier_name')
if account_type in ['Bank', 'Cash']:
company_currency = get_company_currency(self.doc.company)
company_currency = get_company_currency(self.company)
amt = flt(d.debit) and d.debit or d.credit
self.doc.total_amount = company_currency + ' ' + cstr(amt)
self.total_amount = company_currency + ' ' + cstr(amt)
from frappe.utils import money_in_words
self.doc.total_amount_in_words = money_in_words(amt, company_currency)
self.total_amount_in_words = money_in_words(amt, company_currency)
def check_credit_days(self):
date_diff = 0
if self.doc.cheque_date:
date_diff = (getdate(self.doc.cheque_date)-getdate(self.doc.posting_date)).days
if self.cheque_date:
date_diff = (getdate(self.cheque_date)-getdate(self.posting_date)).days
if date_diff <= 0: return
@ -204,7 +204,7 @@ class JournalVoucher(AccountsController):
if not self.credit_days_for[ac]:
if self.credit_days_global==-1:
self.credit_days_global = cint(frappe.db.get_value("Company",
self.doc.company, "credit_days"))
self.company, "credit_days"))
return self.credit_days_global
else:
@ -255,7 +255,7 @@ class JournalVoucher(AccountsController):
or (d.against_invoice and "Sales Invoice")
or (d.against_jv and "Journal Voucher")),
"against_voucher": d.against_voucher or d.against_invoice or d.against_jv,
"remarks": self.doc.remark,
"remarks": self.remark,
"cost_center": d.cost_center
})
)
@ -273,8 +273,8 @@ class JournalVoucher(AccountsController):
if not self.get('entries'):
msgprint("Please enter atleast 1 entry in 'GL Entries' table")
else:
flag, self.doc.total_debit, self.doc.total_credit = 0, 0, 0
diff = flt(self.doc.difference, 2)
flag, self.total_debit, self.total_credit = 0, 0, 0
diff = flt(self.difference, 2)
# If any row without amount, set the diff on that row
for d in self.get('entries'):
@ -287,7 +287,7 @@ class JournalVoucher(AccountsController):
# Set the diff in a new row
if flag == 0 and diff != 0:
jd = self.doc.append('entries', {})
jd = self.append('entries', {})
if diff>0:
jd.credit = abs(diff)
elif diff<0:
@ -295,43 +295,43 @@ class JournalVoucher(AccountsController):
# Set the total debit, total credit and difference
for d in self.get('entries'):
self.doc.total_debit += flt(d.debit, 2)
self.doc.total_credit += flt(d.credit, 2)
self.total_debit += flt(d.debit, 2)
self.total_credit += flt(d.credit, 2)
self.doc.difference = flt(self.doc.total_debit, 2) - flt(self.doc.total_credit, 2)
self.difference = flt(self.total_debit, 2) - flt(self.total_credit, 2)
def get_outstanding_invoices(self):
self.set('entries', [])
total = 0
for d in self.get_values():
total += flt(d[2])
jd = self.doc.append('entries', {})
jd = self.append('entries', {})
jd.account = cstr(d[1])
if self.doc.write_off_based_on == 'Accounts Receivable':
if self.write_off_based_on == 'Accounts Receivable':
jd.credit = flt(d[2])
jd.against_invoice = cstr(d[0])
elif self.doc.write_off_based_on == 'Accounts Payable':
elif self.write_off_based_on == 'Accounts Payable':
jd.debit = flt(d[2])
jd.against_voucher = cstr(d[0])
jd.save(1)
jd = self.doc.append('entries', {})
if self.doc.write_off_based_on == 'Accounts Receivable':
jd = self.append('entries', {})
if self.write_off_based_on == 'Accounts Receivable':
jd.debit = total
elif self.doc.write_off_based_on == 'Accounts Payable':
elif self.write_off_based_on == 'Accounts Payable':
jd.credit = total
jd.save(1)
def get_values(self):
cond = (flt(self.doc.write_off_amount) > 0) and \
' and outstanding_amount <= '+ self.doc.write_off_amount or ''
if self.doc.write_off_based_on == 'Accounts Receivable':
cond = (flt(self.write_off_amount) > 0) and \
' and outstanding_amount <= '+ self.write_off_amount or ''
if self.write_off_based_on == 'Accounts Receivable':
return frappe.db.sql("""select name, debit_to, outstanding_amount
from `tabSales Invoice` where docstatus = 1 and company = %s
and outstanding_amount > 0 %s""" % ('%s', cond), self.doc.company)
elif self.doc.write_off_based_on == 'Accounts Payable':
and outstanding_amount > 0 %s""" % ('%s', cond), self.company)
elif self.write_off_based_on == 'Accounts Payable':
return frappe.db.sql("""select name, credit_to, outstanding_amount
from `tabPurchase Invoice` where docstatus = 1 and company = %s
and outstanding_amount > 0 %s""" % ('%s', cond), self.doc.company)
and outstanding_amount > 0 %s""" % ('%s', cond), self.company)
@frappe.whitelist()
def get_default_bank_cash_account(company, voucher_type):
@ -349,16 +349,16 @@ def get_payment_entry_from_sales_invoice(sales_invoice):
from erpnext.accounts.utils import get_balance_on
si = frappe.bean("Sales Invoice", sales_invoice)
jv = get_payment_entry(si.doc)
jv.doc.remark = 'Payment received against Sales Invoice %(name)s. %(remarks)s' % si.doc.fields
jv.remark = 'Payment received against Sales Invoice %(name)s. %(remarks)s' % si.fields
# credit customer
jv.doclist[1].account = si.doc.debit_to
jv.doclist[1].balance = get_balance_on(si.doc.debit_to)
jv.doclist[1].credit = si.doc.outstanding_amount
jv.doclist[1].against_invoice = si.doc.name
jv.doclist[1].account = si.debit_to
jv.doclist[1].balance = get_balance_on(si.debit_to)
jv.doclist[1].credit = si.outstanding_amount
jv.doclist[1].against_invoice = si.name
# debit bank
jv.doclist[2].debit = si.doc.outstanding_amount
jv.doclist[2].debit = si.outstanding_amount
return [d.fields for d in jv.doclist]
@ -367,16 +367,16 @@ def get_payment_entry_from_purchase_invoice(purchase_invoice):
from erpnext.accounts.utils import get_balance_on
pi = frappe.bean("Purchase Invoice", purchase_invoice)
jv = get_payment_entry(pi.doc)
jv.doc.remark = 'Payment against Purchase Invoice %(name)s. %(remarks)s' % pi.doc.fields
jv.remark = 'Payment against Purchase Invoice %(name)s. %(remarks)s' % pi.fields
# credit supplier
jv.doclist[1].account = pi.doc.credit_to
jv.doclist[1].balance = get_balance_on(pi.doc.credit_to)
jv.doclist[1].debit = pi.doc.outstanding_amount
jv.doclist[1].against_voucher = pi.doc.name
jv.doclist[1].account = pi.credit_to
jv.doclist[1].balance = get_balance_on(pi.credit_to)
jv.doclist[1].debit = pi.outstanding_amount
jv.doclist[1].against_voucher = pi.name
# credit bank
jv.doclist[2].credit = pi.doc.outstanding_amount
jv.doclist[2].credit = pi.outstanding_amount
return [d.fields for d in jv.doclist]
@ -384,10 +384,10 @@ def get_payment_entry(doc):
bank_account = get_default_bank_cash_account(doc.company, "Bank Voucher")
jv = frappe.new_bean('Journal Voucher')
jv.doc.voucher_type = 'Bank Voucher'
jv.voucher_type = 'Bank Voucher'
jv.doc.company = doc.company
jv.doc.fiscal_year = doc.fiscal_year
jv.company = doc.company
jv.fiscal_year = doc.fiscal_year
d1 = jv.append("entries")
d2 = jv.append("entries")

View File

@ -14,24 +14,24 @@ class TestJournalVoucher(unittest.TestCase):
jv_invoice.submit()
self.assertTrue(not frappe.db.sql("""select name from `tabJournal Voucher Detail`
where against_jv=%s""", jv_invoice.doc.name))
where against_jv=%s""", jv_invoice.name))
jv_payment = frappe.bean(copy=test_records[0])
jv_payment.doclist[1].against_jv = jv_invoice.doc.name
jv_payment.doclist[1].against_jv = jv_invoice.name
jv_payment.insert()
jv_payment.submit()
self.assertTrue(frappe.db.sql("""select name from `tabJournal Voucher Detail`
where against_jv=%s""", jv_invoice.doc.name))
where against_jv=%s""", jv_invoice.name))
self.assertTrue(frappe.db.sql("""select name from `tabJournal Voucher Detail`
where against_jv=%s and credit=400""", jv_invoice.doc.name))
where against_jv=%s and credit=400""", jv_invoice.name))
# cancel jv_invoice
jv_invoice.cancel()
self.assertTrue(not frappe.db.sql("""select name from `tabJournal Voucher Detail`
where against_jv=%s""", jv_invoice.doc.name))
where against_jv=%s""", jv_invoice.name))
def test_jv_against_stock_account(self):
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
@ -58,7 +58,7 @@ class TestJournalVoucher(unittest.TestCase):
jv.insert()
jv.submit()
self.assertTrue(frappe.db.get_value("GL Entry",
{"voucher_type": "Journal Voucher", "voucher_no": jv.doc.name}))
{"voucher_type": "Journal Voucher", "voucher_no": jv.name}))
def test_monthly_budget_crossed_stop(self):
from erpnext.accounts.utils import BudgetError
@ -84,7 +84,7 @@ class TestJournalVoucher(unittest.TestCase):
frappe.db.set_value("Company", "_Test Company", "yearly_bgt_flag", "Stop")
jv = frappe.bean(copy=test_records[0])
jv.doc.posting_date = "2013-08-12"
jv.posting_date = "2013-08-12"
jv.doclist[2].account = "_Test Account Cost for Goods Sold - _TC"
jv.doclist[2].cost_center = "_Test Cost Center - _TC"
jv.doclist[2].debit = 150000.0
@ -108,7 +108,7 @@ class TestJournalVoucher(unittest.TestCase):
jv.submit()
self.assertTrue(frappe.db.get_value("GL Entry",
{"voucher_type": "Journal Voucher", "voucher_no": jv.doc.name}))
{"voucher_type": "Journal Voucher", "voucher_no": jv.name}))
jv1 = frappe.bean(copy=test_records[0])
jv1.doclist[2].account = "_Test Account Cost for Goods Sold - _TC"
@ -118,7 +118,7 @@ class TestJournalVoucher(unittest.TestCase):
jv1.submit()
self.assertTrue(frappe.db.get_value("GL Entry",
{"voucher_type": "Journal Voucher", "voucher_no": jv1.doc.name}))
{"voucher_type": "Journal Voucher", "voucher_no": jv1.name}))
self.assertRaises(BudgetError, jv.cancel)

View File

@ -15,13 +15,13 @@ class PaymentToInvoiceMatchingTool(Document):
total_amount = frappe.db.sql("""select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
from `tabGL Entry`
where voucher_type = %s and voucher_no = %s
and account = %s""", (self.doc.voucher_type, self.doc.voucher_no, self.doc.account))
and account = %s""", (self.voucher_type, self.voucher_no, self.account))
total_amount = total_amount and flt(total_amount[0][0]) or 0
reconciled_payment = frappe.db.sql("""
select abs(sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))) from `tabGL Entry` where
against_voucher = %s and voucher_no != %s
and account = %s""", (self.doc.voucher_no, self.doc.voucher_no, self.doc.account))
and account = %s""", (self.voucher_no, self.voucher_no, self.account))
reconciled_payment = reconciled_payment and flt(reconciled_payment[0][0]) or 0
ret = {
@ -44,15 +44,15 @@ class PaymentToInvoiceMatchingTool(Document):
def get_gl_entries(self):
self.validate_mandatory()
cond = self.doc.from_date and " and t1.posting_date >= '" + self.doc.from_date + "'" or ""
cond += self.doc.to_date and " and t1.posting_date <= '" + self.doc.to_date + "'"or ""
cond = self.from_date and " and t1.posting_date >= '" + self.from_date + "'" or ""
cond += self.to_date and " and t1.posting_date <= '" + self.to_date + "'"or ""
if self.doc.amt_greater_than:
if self.amt_greater_than:
cond += ' and abs(ifnull(t2.debit, 0) - ifnull(t2.credit, 0)) >= ' + \
self.doc.amt_greater_than
if self.doc.amt_less_than:
self.amt_greater_than
if self.amt_less_than:
cond += ' and abs(ifnull(t2.debit, 0) - ifnull(t2.credit, 0)) >= ' + \
self.doc.amt_less_than
self.amt_less_than
gle = frappe.db.sql("""
select t1.name as voucher_no, t1.posting_date, t1.total_debit as total_amt,
@ -62,13 +62,13 @@ class PaymentToInvoiceMatchingTool(Document):
where t1.name = t2.parent and t1.docstatus = 1 and t2.account = %s
and ifnull(t2.against_voucher, '')='' and ifnull(t2.against_invoice, '')=''
and ifnull(t2.against_jv, '')='' and t1.name != %s %s group by t1.name, t2.name """ %
('%s', '%s', cond), (self.doc.account, self.doc.voucher_no), as_dict=1)
('%s', '%s', cond), (self.account, self.voucher_no), as_dict=1)
return gle
def create_payment_table(self, gle):
for d in gle:
ch = self.doc.append('ir_payment_details', {})
ch = self.append('ir_payment_details', {})
ch.voucher_no = d.get('voucher_no')
ch.posting_date = d.get('posting_date')
ch.amt_due = flt(d.get('amt_due'))
@ -78,7 +78,7 @@ class PaymentToInvoiceMatchingTool(Document):
ch.voucher_detail_no = d.get('voucher_detail_no')
def validate_mandatory(self):
if not self.doc.account:
if not self.account:
msgprint("Please select Account first", raise_exception=1)
def reconcile(self):
@ -88,8 +88,8 @@ class PaymentToInvoiceMatchingTool(Document):
2. split into multiple rows if partially adjusted, assign against voucher
3. submit payment voucher
"""
if not self.doc.voucher_no or not frappe.db.sql("""select name from `tab%s`
where name = %s""" % (self.doc.voucher_type, '%s'), self.doc.voucher_no):
if not self.voucher_no or not frappe.db.sql("""select name from `tab%s`
where name = %s""" % (self.voucher_type, '%s'), self.voucher_no):
frappe.throw(_("Please select valid Voucher No to proceed"))
lst = []
@ -98,11 +98,11 @@ class PaymentToInvoiceMatchingTool(Document):
args = {
'voucher_no' : d.voucher_no,
'voucher_detail_no' : d.voucher_detail_no,
'against_voucher_type' : self.doc.voucher_type,
'against_voucher' : self.doc.voucher_no,
'account' : self.doc.account,
'against_voucher_type' : self.voucher_type,
'against_voucher' : self.voucher_no,
'account' : self.account,
'is_advance' : 'No',
# 'dr_or_cr' : self.doc.account_type=='debit' and 'credit' or 'debit',
# 'dr_or_cr' : self.account_type=='debit' and 'credit' or 'debit',
'unadjusted_amt' : flt(d.amt_due),
'allocated_amt' : flt(d.amt_to_be_reconciled)
}

View File

@ -19,24 +19,24 @@ class PeriodClosingVoucher(AccountsController):
def on_cancel(self):
frappe.db.sql("""delete from `tabGL Entry`
where voucher_type = 'Period Closing Voucher' and voucher_no=%s""", self.doc.name)
where voucher_type = 'Period Closing Voucher' and voucher_no=%s""", self.name)
def validate_account_head(self):
if frappe.db.get_value("Account", self.doc.closing_account_head, "report_type") \
if frappe.db.get_value("Account", self.closing_account_head, "report_type") \
!= "Balance Sheet":
frappe.throw(_("Account") + ": " + self.doc.closing_account_head +
frappe.throw(_("Account") + ": " + self.closing_account_head +
_("must be a Liability account"))
def validate_posting_date(self):
from erpnext.accounts.utils import get_fiscal_year
self.year_start_date = get_fiscal_year(self.doc.posting_date, self.doc.fiscal_year)[1]
self.year_start_date = get_fiscal_year(self.posting_date, self.fiscal_year)[1]
pce = frappe.db.sql("""select name from `tabPeriod Closing Voucher`
where posting_date > %s and fiscal_year = %s and docstatus = 1""",
(self.doc.posting_date, self.doc.fiscal_year))
(self.posting_date, self.fiscal_year))
if pce and pce[0][0]:
frappe.throw(_("Another Period Closing Entry") + ": " + cstr(pce[0][0]) +
_("has been made after posting date") + ": " + self.doc.posting_date)
_("has been made after posting date") + ": " + self.posting_date)
def get_pl_balances(self):
"""Get balance for pl accounts"""
@ -47,7 +47,7 @@ class PeriodClosingVoucher(AccountsController):
and t2.docstatus < 2 and t2.company = %s
and t1.posting_date between %s and %s
group by t1.account
""", (self.doc.company, self.year_start_date, self.doc.posting_date), as_dict=1)
""", (self.company, self.year_start_date, self.posting_date), as_dict=1)
def make_gl_entries(self):
gl_entries = []
@ -65,7 +65,7 @@ class PeriodClosingVoucher(AccountsController):
if net_pl_balance:
gl_entries.append(self.get_gl_dict({
"account": self.doc.closing_account_head,
"account": self.closing_account_head,
"debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0
}))

View File

@ -29,7 +29,7 @@ class TestPeriodClosingVoucher(unittest.TestCase):
gl_entries = frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Period Closing Voucher' and voucher_no=%s
order by account asc, debit asc""", pcv.doc.name, as_dict=1)
order by account asc, debit asc""", pcv.name, as_dict=1)
self.assertTrue(gl_entries)

View File

@ -24,30 +24,30 @@ class PosSetting(Document):
def check_for_duplicate(self):
res = frappe.db.sql("""select name, user from `tabPOS Setting`
where ifnull(user, '') = %s and name != %s and company = %s""",
(self.doc.user, self.doc.name, self.doc.company))
(self.user, self.name, self.company))
if res:
if res[0][1]:
msgprint("POS Setting '%s' already created for user: '%s' and company: '%s'" %
(res[0][0], res[0][1], self.doc.company), raise_exception=1)
(res[0][0], res[0][1], self.company), raise_exception=1)
else:
msgprint("Global POS Setting already created - %s for this company: '%s'" %
(res[0][0], self.doc.company), raise_exception=1)
(res[0][0], self.company), raise_exception=1)
def validate_expense_account(self):
if cint(frappe.defaults.get_global_default("auto_accounting_for_stock")) \
and not self.doc.expense_account:
and not self.expense_account:
msgprint(_("Expense Account is mandatory"), raise_exception=1)
def validate_all_link_fields(self):
accounts = {"Account": [self.doc.cash_bank_account, self.doc.income_account,
self.doc.expense_account], "Cost Center": [self.doc.cost_center],
"Warehouse": [self.doc.warehouse]}
accounts = {"Account": [self.cash_bank_account, self.income_account,
self.expense_account], "Cost Center": [self.cost_center],
"Warehouse": [self.warehouse]}
for link_dt, dn_list in accounts.items():
for link_dn in dn_list:
if link_dn and not frappe.db.exists({"doctype": link_dt,
"company": self.doc.company, "name": link_dn}):
frappe.throw(link_dn +_(" does not belong to ") + self.doc.company)
"company": self.company, "name": link_dn}):
frappe.throw(link_dn +_(" does not belong to ") + self.company)
def on_update(self):
self.set_defaults()
@ -59,7 +59,7 @@ class PosSetting(Document):
frappe.defaults.clear_default("is_pos")
if not include_current_pos:
condition = " where name != '%s'" % self.doc.name.replace("'", "\'")
condition = " where name != '%s'" % self.name.replace("'", "\'")
else:
condition = ""

View File

@ -16,14 +16,14 @@ class PricingRule(DocListController):
def validate_mandatory(self):
for field in ["apply_on", "applicable_for", "price_or_discount"]:
val = self.doc.fields.get("applicable_for")
if val and not self.doc.fields.get(frappe.scrub(val)):
val = self.get("applicable_for")
if val and not self.get(frappe.scrub(val)):
throw("{fname} {msg}".format(fname = _(val), msg = _(" is mandatory")),
frappe.MandatoryError)
def cleanup_fields_value(self):
for logic_field in ["apply_on", "applicable_for", "price_or_discount"]:
fieldname = frappe.scrub(self.doc.fields.get(logic_field) or "")
fieldname = frappe.scrub(self.get(logic_field) or "")
# reset all values except for the logic field
options = (self.meta.get_options(logic_field) or "").split("\n")
@ -32,5 +32,5 @@ class PricingRule(DocListController):
f = frappe.scrub(f)
if f!=fieldname:
self.doc.fields[f] = None
self.set(f, None)

View File

@ -39,18 +39,18 @@ class TestPricingRule(unittest.TestCase):
self.assertEquals(details.get("discount_percentage"), 10)
prule = frappe.bean(copy=test_record)
prule.doc.applicable_for = "Customer"
prule.applicable_for = "Customer"
self.assertRaises(MandatoryError, prule.insert)
prule.doc.customer = "_Test Customer"
prule.doc.discount_percentage = 20
prule.customer = "_Test Customer"
prule.discount_percentage = 20
prule.insert()
details = get_item_details(args)
self.assertEquals(details.get("discount_percentage"), 20)
prule = frappe.bean(copy=test_record)
prule.doc.apply_on = "Item Group"
prule.doc.item_group = "All Item Groups"
prule.doc.discount_percentage = 15
prule.apply_on = "Item Group"
prule.item_group = "All Item Groups"
prule.discount_percentage = 15
prule.insert()
args.customer = None
@ -58,10 +58,10 @@ class TestPricingRule(unittest.TestCase):
self.assertEquals(details.get("discount_percentage"), 10)
prule = frappe.bean(copy=test_record)
prule.doc.applicable_for = "Campaign"
prule.doc.campaign = "_Test Campaign"
prule.doc.discount_percentage = 5
prule.doc.priority = 8
prule.applicable_for = "Campaign"
prule.campaign = "_Test Campaign"
prule.discount_percentage = 5
prule.priority = 8
prule.insert()
args.campaign = "_Test Campaign"

View File

@ -31,8 +31,8 @@ class PurchaseInvoice(BuyingController):
}]
def validate(self):
if not self.doc.is_opening:
self.doc.is_opening = 'No'
if not self.is_opening:
self.is_opening = 'No'
super(DocType, self).validate()
@ -56,16 +56,16 @@ class PurchaseInvoice(BuyingController):
"purchase_receipt_details")
def set_missing_values(self, for_validate=False):
if not self.doc.credit_to:
self.doc.credit_to = get_party_account(self.doc.company, self.doc.supplier, "Supplier")
if not self.doc.due_date:
self.doc.due_date = get_due_date(self.doc.posting_date, self.doc.supplier, "Supplier",
self.doc.credit_to, self.doc.company)
if not self.credit_to:
self.credit_to = get_party_account(self.company, self.supplier, "Supplier")
if not self.due_date:
self.due_date = get_due_date(self.posting_date, self.supplier, "Supplier",
self.credit_to, self.company)
super(DocType, self).set_missing_values(for_validate)
def get_advances(self):
super(DocType, self).get_advances(self.doc.credit_to,
super(DocType, self).get_advances(self.credit_to,
"Purchase Invoice Advance", "advance_allocation_details", "debit")
def check_active_purchase_items(self):
@ -80,44 +80,44 @@ class PurchaseInvoice(BuyingController):
raise Exception
def check_conversion_rate(self):
default_currency = get_company_currency(self.doc.company)
default_currency = get_company_currency(self.company)
if not default_currency:
msgprint('Message: Please enter default currency in Company Master')
raise Exception
if (self.doc.currency == default_currency and flt(self.doc.conversion_rate) != 1.00) or not self.doc.conversion_rate or (self.doc.currency != default_currency and flt(self.doc.conversion_rate) == 1.00):
if (self.currency == default_currency and flt(self.conversion_rate) != 1.00) or not self.conversion_rate or (self.currency != default_currency and flt(self.conversion_rate) == 1.00):
msgprint("Message: Please Enter Appropriate Conversion Rate.")
raise Exception
def validate_bill_no(self):
if self.doc.bill_no and self.doc.bill_no.lower().strip() \
if self.bill_no and self.bill_no.lower().strip() \
not in ['na', 'not applicable', 'none']:
b_no = frappe.db.sql("""select bill_no, name, ifnull(is_opening,'') from `tabPurchase Invoice`
where bill_no = %s and credit_to = %s and docstatus = 1 and name != %s""",
(self.doc.bill_no, self.doc.credit_to, self.doc.name))
if b_no and cstr(b_no[0][2]) == cstr(self.doc.is_opening):
(self.bill_no, self.credit_to, self.name))
if b_no and cstr(b_no[0][2]) == cstr(self.is_opening):
msgprint("Please check you have already booked expense against Bill No. %s \
in Purchase Invoice %s" % (cstr(b_no[0][0]), cstr(b_no[0][1])),
raise_exception=1)
if not self.doc.remarks and self.doc.bill_date:
self.doc.remarks = (self.doc.remarks or '') + "\n" + ("Against Bill %s dated %s"
% (self.doc.bill_no, formatdate(self.doc.bill_date)))
if not self.remarks and self.bill_date:
self.remarks = (self.remarks or '') + "\n" + ("Against Bill %s dated %s"
% (self.bill_no, formatdate(self.bill_date)))
if not self.doc.remarks:
self.doc.remarks = "No Remarks"
if not self.remarks:
self.remarks = "No Remarks"
def validate_credit_acc(self):
if frappe.db.get_value("Account", self.doc.credit_to, "report_type") != "Balance Sheet":
if frappe.db.get_value("Account", self.credit_to, "report_type") != "Balance Sheet":
frappe.throw(_("Account must be a balance sheet account"))
# Validate Acc Head of Supplier and Credit To Account entered
# ------------------------------------------------------------
def check_for_acc_head_of_supplier(self):
if self.doc.supplier and self.doc.credit_to:
acc_head = frappe.db.sql("select master_name from `tabAccount` where name = %s", self.doc.credit_to)
if self.supplier and self.credit_to:
acc_head = frappe.db.sql("select master_name from `tabAccount` where name = %s", self.credit_to)
if (acc_head and cstr(acc_head[0][0]) != cstr(self.doc.supplier)) or (not acc_head and (self.doc.credit_to != cstr(self.doc.supplier) + " - " + self.company_abbr)):
msgprint("Credit To: %s do not match with Supplier: %s for Company: %s.\n If both correctly entered, please select Master Type and Master Name in account master." %(self.doc.credit_to,self.doc.supplier,self.doc.company), raise_exception=1)
if (acc_head and cstr(acc_head[0][0]) != cstr(self.supplier)) or (not acc_head and (self.credit_to != cstr(self.supplier) + " - " + self.company_abbr)):
msgprint("Credit To: %s do not match with Supplier: %s for Company: %s.\n If both correctly entered, please select Master Type and Master Name in account master." %(self.credit_to,self.supplier,self.company), raise_exception=1)
# Check for Stopped PO
# ---------------------
@ -171,9 +171,9 @@ class PurchaseInvoice(BuyingController):
def set_aging_date(self):
if self.doc.is_opening != 'Yes':
self.doc.aging_date = self.doc.posting_date
elif not self.doc.aging_date:
if self.is_opening != 'Yes':
self.aging_date = self.posting_date
elif not self.aging_date:
msgprint("Aging Date is mandatory for opening entry")
raise Exception
@ -187,7 +187,7 @@ class PurchaseInvoice(BuyingController):
stock_items = self.get_stock_items()
for item in self.get("entries"):
if auto_accounting_for_stock and item.item_code in stock_items \
and self.doc.is_opening == 'No':
and self.is_opening == 'No':
# in case of auto inventory accounting, against expense account is always
# Stock Received But Not Billed for a stock item
item.expense_account = stock_not_billed_account
@ -204,7 +204,7 @@ class PurchaseInvoice(BuyingController):
# if no auto_accounting_for_stock or not a stock item
against_accounts.append(item.expense_account)
self.doc.against_expense_account = ",".join(against_accounts)
self.against_expense_account = ",".join(against_accounts)
def po_required(self):
if frappe.db.get_value("Buying Settings", None, "po_required") == 'Yes':
@ -221,7 +221,7 @@ class PurchaseInvoice(BuyingController):
raise Exception
def validate_write_off_account(self):
if self.doc.write_off_amount and not self.doc.write_off_account:
if self.write_off_amount and not self.write_off_account:
msgprint("Please enter Write Off Account", raise_exception=1)
def check_prev_docstatus(self):
@ -251,8 +251,8 @@ class PurchaseInvoice(BuyingController):
'voucher_no' : d.journal_voucher,
'voucher_detail_no' : d.jv_detail_no,
'against_voucher_type' : 'Purchase Invoice',
'against_voucher' : self.doc.name,
'account' : self.doc.credit_to,
'against_voucher' : self.name,
'account' : self.credit_to,
'is_advance' : 'Yes',
'dr_or_cr' : 'debit',
'unadjusted_amt' : flt(d.advance_amount),
@ -267,8 +267,8 @@ class PurchaseInvoice(BuyingController):
def on_submit(self):
self.check_prev_docstatus()
get_obj('Authorization Control').validate_approving_authority(self.doc.doctype,
self.doc.company, self.doc.grand_total)
get_obj('Authorization Control').validate_approving_authority(self.doctype,
self.company, self.grand_total)
# this sequence because outstanding may get -negative
self.make_gl_entries()
@ -283,15 +283,15 @@ class PurchaseInvoice(BuyingController):
gl_entries = []
# parent's gl entry
if self.doc.grand_total:
if self.grand_total:
gl_entries.append(
self.get_gl_dict({
"account": self.doc.credit_to,
"against": self.doc.against_expense_account,
"credit": self.doc.total_amount_to_pay,
"remarks": self.doc.remarks,
"against_voucher": self.doc.name,
"against_voucher_type": self.doc.doctype,
"account": self.credit_to,
"against": self.against_expense_account,
"credit": self.total_amount_to_pay,
"remarks": self.remarks,
"against_voucher": self.name,
"against_voucher_type": self.doctype,
})
)
@ -302,10 +302,10 @@ class PurchaseInvoice(BuyingController):
gl_entries.append(
self.get_gl_dict({
"account": tax.account_head,
"against": self.doc.credit_to,
"against": self.credit_to,
"debit": tax.add_deduct_tax == "Add" and tax.tax_amount or 0,
"credit": tax.add_deduct_tax == "Deduct" and tax.tax_amount or 0,
"remarks": self.doc.remarks,
"remarks": self.remarks,
"cost_center": tax.cost_center
})
)
@ -337,9 +337,9 @@ class PurchaseInvoice(BuyingController):
gl_entries.append(
self.get_gl_dict({
"account": item.expense_account,
"against": self.doc.credit_to,
"against": self.credit_to,
"debit": valuation_amt,
"remarks": self.doc.remarks or "Accounting Entry for Stock"
"remarks": self.remarks or "Accounting Entry for Stock"
})
)
@ -348,9 +348,9 @@ class PurchaseInvoice(BuyingController):
gl_entries.append(
self.get_gl_dict({
"account": item.expense_account,
"against": self.doc.credit_to,
"against": self.credit_to,
"debit": item.base_amount,
"remarks": self.doc.remarks,
"remarks": self.remarks,
"cost_center": item.cost_center
})
)
@ -366,32 +366,32 @@ class PurchaseInvoice(BuyingController):
self.get_gl_dict({
"account": expenses_included_in_valuation,
"cost_center": cost_center,
"against": self.doc.credit_to,
"against": self.credit_to,
"credit": amount,
"remarks": self.doc.remarks or "Accounting Entry for Stock"
"remarks": self.remarks or "Accounting Entry for Stock"
})
)
# writeoff account includes petty difference in the invoice amount
# and the amount that is paid
if self.doc.write_off_account and flt(self.doc.write_off_amount):
if self.write_off_account and flt(self.write_off_amount):
gl_entries.append(
self.get_gl_dict({
"account": self.doc.write_off_account,
"against": self.doc.credit_to,
"credit": flt(self.doc.write_off_amount),
"remarks": self.doc.remarks,
"cost_center": self.doc.write_off_cost_center
"account": self.write_off_account,
"against": self.credit_to,
"credit": flt(self.write_off_amount),
"remarks": self.remarks,
"cost_center": self.write_off_cost_center
})
)
if gl_entries:
from erpnext.accounts.general_ledger import make_gl_entries
make_gl_entries(gl_entries, cancel=(self.doc.docstatus == 2))
make_gl_entries(gl_entries, cancel=(self.docstatus == 2))
def on_cancel(self):
from erpnext.accounts.utils import remove_against_link_from_jv
remove_against_link_from_jv(self.doc.doctype, self.doc.name, "against_voucher")
remove_against_link_from_jv(self.doctype, self.name, "against_voucher")
self.update_prevdoc_status()
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")

View File

@ -51,7 +51,7 @@ class TestPurchaseInvoice(unittest.TestCase):
gl_entries = frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
order by account asc""", pi.doc.name, as_dict=1)
order by account asc""", pi.name, as_dict=1)
self.assertTrue(gl_entries)
expected_values = sorted([
@ -83,7 +83,7 @@ class TestPurchaseInvoice(unittest.TestCase):
gl_entries = frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
order by account asc""", pi.doc.name, as_dict=1)
order by account asc""", pi.name, as_dict=1)
self.assertTrue(gl_entries)
expected_values = sorted([
@ -175,28 +175,28 @@ class TestPurchaseInvoice(unittest.TestCase):
pi = frappe.bean(copy=test_records[0])
pi.append("advance_allocation_details", {
"journal_voucher": jv.doc.name,
"journal_voucher": jv.name,
"jv_detail_no": jv.doclist[1].name,
"advance_amount": 400,
"allocated_amount": 300,
"remarks": jv.doc.remark
"remarks": jv.remark
})
pi.insert()
pi.submit()
pi.load_from_db()
self.assertTrue(frappe.db.sql("""select name from `tabJournal Voucher Detail`
where against_voucher=%s""", pi.doc.name))
where against_voucher=%s""", pi.name))
self.assertTrue(frappe.db.sql("""select name from `tabJournal Voucher Detail`
where against_voucher=%s and debit=300""", pi.doc.name))
where against_voucher=%s and debit=300""", pi.name))
self.assertEqual(pi.doc.outstanding_amount, 1212.30)
self.assertEqual(pi.outstanding_amount, 1212.30)
pi.cancel()
self.assertTrue(not frappe.db.sql("""select name from `tabJournal Voucher Detail`
where against_voucher=%s""", pi.doc.name))
where against_voucher=%s""", pi.name))
test_records = [
[

View File

@ -52,17 +52,17 @@ class SalesInvoice(SellingController):
self.clear_unallocated_advances("Sales Invoice Advance", "advance_adjustment_details")
self.add_remarks()
if cint(self.doc.is_pos):
if cint(self.is_pos):
self.validate_pos()
self.validate_write_off_account()
if cint(self.doc.update_stock):
if cint(self.update_stock):
self.validate_item_code()
self.update_current_stock()
self.validate_delivery_note()
if not self.doc.is_opening:
self.doc.is_opening = 'No'
if not self.is_opening:
self.is_opening = 'No'
self.set_aging_date()
self.set_against_income_account()
@ -73,13 +73,13 @@ class SalesInvoice(SellingController):
"delivery_note_details")
def on_submit(self):
if cint(self.doc.update_stock) == 1:
if cint(self.update_stock) == 1:
self.update_stock_ledger()
else:
# Check for Approving Authority
if not self.doc.recurring_id:
get_obj('Authorization Control').validate_approving_authority(self.doc.doctype,
self.doc.company, self.doc.grand_total, self)
if not self.recurring_id:
get_obj('Authorization Control').validate_approving_authority(self.doctype,
self.company, self.grand_total, self)
self.check_prev_docstatus()
@ -89,26 +89,26 @@ class SalesInvoice(SellingController):
# this sequence because outstanding may get -ve
self.make_gl_entries()
self.check_credit_limit(self.doc.debit_to)
self.check_credit_limit(self.debit_to)
if not cint(self.doc.is_pos) == 1:
if not cint(self.is_pos) == 1:
self.update_against_document_in_jv()
self.update_c_form()
self.update_time_log_batch(self.doc.name)
self.update_time_log_batch(self.name)
self.convert_to_recurring()
def before_cancel(self):
self.update_time_log_batch(None)
def on_cancel(self):
if cint(self.doc.update_stock) == 1:
if cint(self.update_stock) == 1:
self.update_stock_ledger()
self.check_stop_sales_order("sales_order")
from erpnext.accounts.utils import remove_against_link_from_jv
remove_against_link_from_jv(self.doc.doctype, self.doc.name, "against_invoice")
remove_against_link_from_jv(self.doctype, self.name, "against_invoice")
self.update_status_updater_args()
self.update_prevdoc_status()
@ -117,7 +117,7 @@ class SalesInvoice(SellingController):
self.make_cancel_gl_entries()
def update_status_updater_args(self):
if cint(self.doc.update_stock):
if cint(self.update_stock):
self.status_updater.append({
'source_dt':'Sales Invoice Item',
'target_dt':'Sales Order Item',
@ -140,16 +140,16 @@ class SalesInvoice(SellingController):
self.convert_to_recurring()
def get_portal_page(self):
return "invoice" if self.doc.docstatus==1 else None
return "invoice" if self.docstatus==1 else None
def set_missing_values(self, for_validate=False):
self.set_pos_fields(for_validate)
if not self.doc.debit_to:
self.doc.debit_to = get_party_account(self.doc.company, self.doc.customer, "Customer")
if not self.doc.due_date:
self.doc.due_date = get_due_date(self.doc.posting_date, self.doc.customer, "Customer",
self.doc.debit_to, self.doc.company)
if not self.debit_to:
self.debit_to = get_party_account(self.company, self.customer, "Customer")
if not self.due_date:
self.due_date = get_due_date(self.posting_date, self.customer, "Customer",
self.debit_to, self.company)
super(DocType, self).set_missing_values(for_validate)
@ -157,7 +157,7 @@ class SalesInvoice(SellingController):
for d in self.doclist.get({"doctype":"Sales Invoice Item"}):
if d.time_log_batch:
tlb = frappe.bean("Time Log Batch", d.time_log_batch)
tlb.doc.sales_invoice = sales_invoice
tlb.sales_invoice = sales_invoice
tlb.update_after_submit()
def validate_time_logs_are_submitted(self):
@ -170,48 +170,48 @@ class SalesInvoice(SellingController):
def set_pos_fields(self, for_validate=False):
"""Set retail related fields from pos settings"""
if cint(self.doc.is_pos) != 1:
if cint(self.is_pos) != 1:
return
from erpnext.stock.get_item_details import get_pos_settings_item_details, get_pos_settings
pos = get_pos_settings(self.doc.company)
pos = get_pos_settings(self.company)
if pos:
if not for_validate and not self.doc.customer:
self.doc.customer = pos.customer
if not for_validate and not self.customer:
self.customer = pos.customer
# self.set_customer_defaults()
for fieldname in ('territory', 'naming_series', 'currency', 'taxes_and_charges', 'letter_head', 'tc_name',
'selling_price_list', 'company', 'select_print_heading', 'cash_bank_account'):
if (not for_validate) or (for_validate and not self.doc.fields.get(fieldname)):
self.doc.fields[fieldname] = pos.get(fieldname)
if (not for_validate) or (for_validate and not self.get(fieldname)):
self.set(fieldname, pos.get(fieldname))
if not for_validate:
self.doc.update_stock = cint(pos.get("update_stock"))
self.update_stock = cint(pos.get("update_stock"))
# set pos values in items
for item in self.get("entries"):
if item.fields.get('item_code'):
if item.get('item_code'):
for fname, val in get_pos_settings_item_details(pos,
frappe._dict(item.fields), pos).items():
if (not for_validate) or (for_validate and not item.fields.get(fname)):
item.fields[fname] = val
if (not for_validate) or (for_validate and not item.get(fname)):
item.set(fname, val)
# fetch terms
if self.doc.tc_name and not self.doc.terms:
self.doc.terms = frappe.db.get_value("Terms and Conditions", self.doc.tc_name, "terms")
if self.tc_name and not self.terms:
self.terms = frappe.db.get_value("Terms and Conditions", self.tc_name, "terms")
# fetch charges
if self.doc.charge and not len(self.get("other_charges")):
if self.charge and not len(self.get("other_charges")):
self.set_taxes("other_charges", "taxes_and_charges")
def get_advances(self):
super(DocType, self).get_advances(self.doc.debit_to,
super(DocType, self).get_advances(self.debit_to,
"Sales Invoice Advance", "advance_adjustment_details", "credit")
def get_company_abbr(self):
return frappe.db.sql("select abbr from tabCompany where name=%s", self.doc.company)[0][0]
return frappe.db.sql("select abbr from tabCompany where name=%s", self.company)[0][0]
def update_against_document_in_jv(self):
"""
@ -228,8 +228,8 @@ class SalesInvoice(SellingController):
'voucher_no' : d.journal_voucher,
'voucher_detail_no' : d.jv_detail_no,
'against_voucher_type' : 'Sales Invoice',
'against_voucher' : self.doc.name,
'account' : self.doc.debit_to,
'against_voucher' : self.name,
'account' : self.debit_to,
'is_advance' : 'Yes',
'dr_or_cr' : 'credit',
'unadjusted_amt' : flt(d.advance_amount),
@ -243,17 +243,17 @@ class SalesInvoice(SellingController):
def validate_customer_account(self):
"""Validates Debit To Account and Customer Matches"""
if self.doc.customer and self.doc.debit_to and not cint(self.doc.is_pos):
acc_head = frappe.db.sql("select master_name from `tabAccount` where name = %s and docstatus != 2", self.doc.debit_to)
if self.customer and self.debit_to and not cint(self.is_pos):
acc_head = frappe.db.sql("select master_name from `tabAccount` where name = %s and docstatus != 2", self.debit_to)
if (acc_head and cstr(acc_head[0][0]) != cstr(self.doc.customer)) or \
(not acc_head and (self.doc.debit_to != cstr(self.doc.customer) + " - " + self.get_company_abbr())):
if (acc_head and cstr(acc_head[0][0]) != cstr(self.customer)) or \
(not acc_head and (self.debit_to != cstr(self.customer) + " - " + self.get_company_abbr())):
msgprint("Debit To: %s do not match with Customer: %s for Company: %s.\n If both correctly entered, please select Master Type \
and Master Name in account master." %(self.doc.debit_to, self.doc.customer,self.doc.company), raise_exception=1)
and Master Name in account master." %(self.debit_to, self.customer,self.company), raise_exception=1)
def validate_debit_acc(self):
if frappe.db.get_value("Account", self.doc.debit_to, "report_type") != "Balance Sheet":
if frappe.db.get_value("Account", self.debit_to, "report_type") != "Balance Sheet":
frappe.throw(_("Account must be a balance sheet account"))
def validate_fixed_asset_account(self):
@ -300,9 +300,9 @@ class SalesInvoice(SellingController):
def set_aging_date(self):
if self.doc.is_opening != 'Yes':
self.doc.aging_date = self.doc.posting_date
elif not self.doc.aging_date:
if self.is_opening != 'Yes':
self.aging_date = self.posting_date
elif not self.aging_date:
msgprint("Aging Date is mandatory for opening entry")
raise Exception
@ -313,11 +313,11 @@ class SalesInvoice(SellingController):
for d in self.get('entries'):
if d.income_account not in against_acc:
against_acc.append(d.income_account)
self.doc.against_income_account = ','.join(against_acc)
self.against_income_account = ','.join(against_acc)
def add_remarks(self):
if not self.doc.remarks: self.doc.remarks = 'No Remarks'
if not self.remarks: self.remarks = 'No Remarks'
def so_dn_required(self):
@ -333,20 +333,20 @@ class SalesInvoice(SellingController):
def validate_proj_cust(self):
"""check for does customer belong to same project as entered.."""
if self.doc.project_name and self.doc.customer:
if self.project_name and self.customer:
res = frappe.db.sql("""select name from `tabProject`
where name = %s and (customer = %s or
ifnull(customer,'')='')""", (self.doc.project_name, self.doc.customer))
ifnull(customer,'')='')""", (self.project_name, self.customer))
if not res:
msgprint("Customer - %s does not belong to project - %s. \n\nIf you want to use project for multiple customers then please make customer details blank in that project."%(self.doc.customer,self.doc.project_name))
msgprint("Customer - %s does not belong to project - %s. \n\nIf you want to use project for multiple customers then please make customer details blank in that project."%(self.customer,self.project_name))
raise Exception
def validate_pos(self):
if not self.doc.cash_bank_account and flt(self.doc.paid_amount):
if not self.cash_bank_account and flt(self.paid_amount):
msgprint("Cash/Bank Account is mandatory for POS, for making payment entry")
raise Exception
if flt(self.doc.paid_amount) + flt(self.doc.write_off_amount) \
- flt(self.doc.grand_total) > 1/(10**(self.precision("grand_total") + 1)):
if flt(self.paid_amount) + flt(self.write_off_amount) \
- flt(self.grand_total) > 1/(10**(self.precision("grand_total") + 1)):
frappe.throw(_("""(Paid amount + Write Off Amount) can not be \
greater than Grand Total"""))
@ -364,15 +364,15 @@ class SalesInvoice(SellingController):
def validate_write_off_account(self):
if flt(self.doc.write_off_amount) and not self.doc.write_off_account:
if flt(self.write_off_amount) and not self.write_off_account:
msgprint("Please enter Write Off Account", raise_exception=1)
def validate_c_form(self):
""" Blank C-form no if C-form applicable marked as 'No'"""
if self.doc.amended_from and self.doc.c_form_applicable == 'No' and self.doc.c_form_no:
if self.amended_from and self.c_form_applicable == 'No' and self.c_form_no:
frappe.db.sql("""delete from `tabC-Form Invoice Detail` where invoice_no = %s
and parent = %s""", (self.doc.amended_from, self.doc.c_form_no))
and parent = %s""", (self.amended_from, self.c_form_no))
frappe.db.set(self.doc, 'c_form_no', '')
@ -391,11 +391,11 @@ class SalesInvoice(SellingController):
def get_warehouse(self):
w = frappe.db.sql("""select warehouse from `tabPOS Setting`
where ifnull(user,'') = %s and company = %s""",
(frappe.session['user'], self.doc.company))
(frappe.session['user'], self.company))
w = w and w[0][0] or ''
if not w:
ps = frappe.db.sql("""select name, warehouse from `tabPOS Setting`
where ifnull(user,'') = '' and company = %s""", self.doc.company)
where ifnull(user,'') = '' and company = %s""", self.company)
if not ps:
msgprint("To make POS entry, please create POS Setting from Accounts --> POS Setting page and refresh the system.", raise_exception=True)
elif not ps[0][1]:
@ -405,9 +405,9 @@ class SalesInvoice(SellingController):
return w
def on_update(self):
if cint(self.doc.update_stock) == 1:
if cint(self.update_stock) == 1:
# Set default warehouse from pos setting
if cint(self.doc.is_pos) == 1:
if cint(self.is_pos) == 1:
w = self.get_warehouse()
if w:
for d in self.get('entries'):
@ -419,11 +419,11 @@ class SalesInvoice(SellingController):
else:
self.set('packing_details', [])
if cint(self.doc.is_pos) == 1:
if flt(self.doc.paid_amount) == 0:
if self.doc.cash_bank_account:
if cint(self.is_pos) == 1:
if flt(self.paid_amount) == 0:
if self.cash_bank_account:
frappe.db.set(self.doc, 'paid_amount',
(flt(self.doc.grand_total) - flt(self.doc.write_off_amount)))
(flt(self.grand_total) - flt(self.write_off_amount)))
else:
# show message that the amount is not paid
frappe.db.set(self.doc,'paid_amount',0)
@ -465,16 +465,16 @@ class SalesInvoice(SellingController):
if gl_entries:
from erpnext.accounts.general_ledger import make_gl_entries
update_outstanding = cint(self.doc.is_pos) and self.doc.write_off_account \
update_outstanding = cint(self.is_pos) and self.write_off_account \
and 'No' or 'Yes'
make_gl_entries(gl_entries, cancel=(self.doc.docstatus == 2),
make_gl_entries(gl_entries, cancel=(self.docstatus == 2),
update_outstanding=update_outstanding, merge_entries=False)
if repost_future_gle and cint(self.doc.update_stock) \
if repost_future_gle and cint(self.update_stock) \
and cint(frappe.defaults.get_global_default("auto_accounting_for_stock")):
items, warehouse_account = self.get_items_and_warehouse_accounts()
from controllers.stock_controller import update_gl_entries_after
update_gl_entries_after(self.doc.posting_date, self.doc.posting_time,
update_gl_entries_after(self.posting_date, self.posting_time,
warehouse_account, items)
def get_gl_entries(self, warehouse_account=None):
@ -496,15 +496,15 @@ class SalesInvoice(SellingController):
return gl_entries
def make_customer_gl_entry(self, gl_entries):
if self.doc.grand_total:
if self.grand_total:
gl_entries.append(
self.get_gl_dict({
"account": self.doc.debit_to,
"against": self.doc.against_income_account,
"debit": self.doc.grand_total,
"remarks": self.doc.remarks,
"against_voucher": self.doc.name,
"against_voucher_type": self.doc.doctype,
"account": self.debit_to,
"against": self.against_income_account,
"debit": self.grand_total,
"remarks": self.remarks,
"against_voucher": self.name,
"against_voucher_type": self.doctype,
})
)
@ -514,9 +514,9 @@ class SalesInvoice(SellingController):
gl_entries.append(
self.get_gl_dict({
"account": tax.account_head,
"against": self.doc.debit_to,
"against": self.debit_to,
"credit": flt(tax.tax_amount_after_discount_amount),
"remarks": self.doc.remarks,
"remarks": self.remarks,
"cost_center": tax.cost_center
})
)
@ -528,101 +528,101 @@ class SalesInvoice(SellingController):
gl_entries.append(
self.get_gl_dict({
"account": item.income_account,
"against": self.doc.debit_to,
"against": self.debit_to,
"credit": item.base_amount,
"remarks": self.doc.remarks,
"remarks": self.remarks,
"cost_center": item.cost_center
})
)
# expense account gl entries
if cint(frappe.defaults.get_global_default("auto_accounting_for_stock")) \
and cint(self.doc.update_stock):
and cint(self.update_stock):
gl_entries += super(DocType, self).get_gl_entries()
def make_pos_gl_entries(self, gl_entries):
if cint(self.doc.is_pos) and self.doc.cash_bank_account and self.doc.paid_amount:
if cint(self.is_pos) and self.cash_bank_account and self.paid_amount:
# POS, make payment entries
gl_entries.append(
self.get_gl_dict({
"account": self.doc.debit_to,
"against": self.doc.cash_bank_account,
"credit": self.doc.paid_amount,
"remarks": self.doc.remarks,
"against_voucher": self.doc.name,
"against_voucher_type": self.doc.doctype,
"account": self.debit_to,
"against": self.cash_bank_account,
"credit": self.paid_amount,
"remarks": self.remarks,
"against_voucher": self.name,
"against_voucher_type": self.doctype,
})
)
gl_entries.append(
self.get_gl_dict({
"account": self.doc.cash_bank_account,
"against": self.doc.debit_to,
"debit": self.doc.paid_amount,
"remarks": self.doc.remarks,
"account": self.cash_bank_account,
"against": self.debit_to,
"debit": self.paid_amount,
"remarks": self.remarks,
})
)
# write off entries, applicable if only pos
if self.doc.write_off_account and self.doc.write_off_amount:
if self.write_off_account and self.write_off_amount:
gl_entries.append(
self.get_gl_dict({
"account": self.doc.debit_to,
"against": self.doc.write_off_account,
"credit": self.doc.write_off_amount,
"remarks": self.doc.remarks,
"against_voucher": self.doc.name,
"against_voucher_type": self.doc.doctype,
"account": self.debit_to,
"against": self.write_off_account,
"credit": self.write_off_amount,
"remarks": self.remarks,
"against_voucher": self.name,
"against_voucher_type": self.doctype,
})
)
gl_entries.append(
self.get_gl_dict({
"account": self.doc.write_off_account,
"against": self.doc.debit_to,
"debit": self.doc.write_off_amount,
"remarks": self.doc.remarks,
"cost_center": self.doc.write_off_cost_center
"account": self.write_off_account,
"against": self.debit_to,
"debit": self.write_off_amount,
"remarks": self.remarks,
"cost_center": self.write_off_cost_center
})
)
def update_c_form(self):
"""Update amended id in C-form"""
if self.doc.c_form_no and self.doc.amended_from:
if self.c_form_no and self.amended_from:
frappe.db.sql("""update `tabC-Form Invoice Detail` set invoice_no = %s,
invoice_date = %s, territory = %s, net_total = %s,
grand_total = %s where invoice_no = %s and parent = %s""",
(self.doc.name, self.doc.amended_from, self.doc.c_form_no))
(self.name, self.amended_from, self.c_form_no))
def validate_recurring_invoice(self):
if self.doc.convert_into_recurring_invoice:
if self.convert_into_recurring_invoice:
self.validate_notification_email_id()
if not self.doc.recurring_type:
if not self.recurring_type:
msgprint(_("Please select: ") + self.meta.get_label("recurring_type"),
raise_exception=1)
elif not (self.doc.invoice_period_from_date and \
self.doc.invoice_period_to_date):
elif not (self.invoice_period_from_date and \
self.invoice_period_to_date):
msgprint(comma_and([self.meta.get_label("invoice_period_from_date"),
self.meta.get_label("invoice_period_to_date")])
+ _(": Mandatory for a Recurring Invoice."),
raise_exception=True)
def convert_to_recurring(self):
if self.doc.convert_into_recurring_invoice:
if not self.doc.recurring_id:
if self.convert_into_recurring_invoice:
if not self.recurring_id:
frappe.db.set(self.doc, "recurring_id",
make_autoname("RECINV/.#####"))
self.set_next_date()
elif self.doc.recurring_id:
elif self.recurring_id:
frappe.db.sql("""update `tabSales Invoice`
set convert_into_recurring_invoice = 0
where recurring_id = %s""", (self.doc.recurring_id,))
where recurring_id = %s""", (self.recurring_id,))
def validate_notification_email_id(self):
if self.doc.notification_email_address:
if self.notification_email_address:
email_list = filter(None, [cstr(email).strip() for email in
self.doc.notification_email_address.replace("\n", "").split(",")])
self.notification_email_address.replace("\n", "").split(",")])
from frappe.utils import validate_email_add
for email in email_list:
@ -637,13 +637,13 @@ class SalesInvoice(SellingController):
def set_next_date(self):
""" Set next date on which auto invoice will be created"""
if not self.doc.repeat_on_day_of_month:
if not self.repeat_on_day_of_month:
msgprint("""Please enter 'Repeat on Day of Month' field value.
The day of the month on which auto invoice
will be generated e.g. 05, 28 etc.""", raise_exception=1)
next_date = get_next_date(self.doc.posting_date,
month_map[self.doc.recurring_type], cint(self.doc.repeat_on_day_of_month))
next_date = get_next_date(self.posting_date,
month_map[self.recurring_type], cint(self.repeat_on_day_of_month))
frappe.db.set(self.doc, 'next_date', next_date)
@ -684,7 +684,7 @@ def manage_recurring_invoices(next_date=None, commit=True):
frappe.db.begin()
frappe.db.sql("update `tabSales Invoice` set \
convert_into_recurring_invoice = 0 where name = %s", ref_invoice)
notify_errors(ref_invoice, ref_wrapper.doc.customer, ref_wrapper.doc.owner)
notify_errors(ref_invoice, ref_wrapper.customer, ref_wrapper.owner)
frappe.db.commit()
exception_list.append(frappe.get_traceback())
@ -701,30 +701,30 @@ def make_new_invoice(ref_wrapper, posting_date):
from erpnext.accounts.utils import get_fiscal_year
new_invoice = clone(ref_wrapper)
mcount = month_map[ref_wrapper.doc.recurring_type]
mcount = month_map[ref_wrapper.recurring_type]
invoice_period_from_date = get_next_date(ref_wrapper.doc.invoice_period_from_date, mcount)
invoice_period_from_date = get_next_date(ref_wrapper.invoice_period_from_date, mcount)
# get last day of the month to maintain period if the from date is first day of its own month
# and to date is the last day of its own month
if (cstr(get_first_day(ref_wrapper.doc.invoice_period_from_date)) == \
cstr(ref_wrapper.doc.invoice_period_from_date)) and \
(cstr(get_last_day(ref_wrapper.doc.invoice_period_to_date)) == \
cstr(ref_wrapper.doc.invoice_period_to_date)):
invoice_period_to_date = get_last_day(get_next_date(ref_wrapper.doc.invoice_period_to_date,
if (cstr(get_first_day(ref_wrapper.invoice_period_from_date)) == \
cstr(ref_wrapper.invoice_period_from_date)) and \
(cstr(get_last_day(ref_wrapper.invoice_period_to_date)) == \
cstr(ref_wrapper.invoice_period_to_date)):
invoice_period_to_date = get_last_day(get_next_date(ref_wrapper.invoice_period_to_date,
mcount))
else:
invoice_period_to_date = get_next_date(ref_wrapper.doc.invoice_period_to_date, mcount)
invoice_period_to_date = get_next_date(ref_wrapper.invoice_period_to_date, mcount)
new_invoice.doc.fields.update({
new_invoice.update({
"posting_date": posting_date,
"aging_date": posting_date,
"due_date": add_days(posting_date, cint(date_diff(ref_wrapper.doc.due_date,
ref_wrapper.doc.posting_date))),
"due_date": add_days(posting_date, cint(date_diff(ref_wrapper.due_date,
ref_wrapper.posting_date))),
"invoice_period_from_date": invoice_period_from_date,
"invoice_period_to_date": invoice_period_to_date,
"fiscal_year": get_fiscal_year(posting_date)[0],
"owner": ref_wrapper.doc.owner,
"owner": ref_wrapper.owner,
})
new_invoice.submit()
@ -735,8 +735,8 @@ def send_notification(new_rv):
"""Notify concerned persons about recurring invoice generation"""
from frappe.core.doctype.print_format.print_format import get_html
frappe.sendmail(new_rv.doc.notification_email_address,
subject="New Invoice : " + new_rv.doc.name,
frappe.sendmail(new_rv.notification_email_address,
subject="New Invoice : " + new_rv.name,
message = get_html(new_rv.doc, new_rv.doclist, "SalesInvoice"))
def notify_errors(inv, customer, owner):

View File

@ -11,14 +11,14 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_per
class TestSalesInvoice(unittest.TestCase):
def make(self):
w = frappe.bean(copy=test_records[0])
w.doc.is_pos = 0
w.is_pos = 0
w.insert()
w.submit()
return w
def test_double_submission(self):
w = frappe.bean(copy=test_records[0])
w.doc.docstatus = '0'
w.docstatus = '0'
w.insert()
w2 = [d for d in w.doclist]
@ -29,7 +29,7 @@ class TestSalesInvoice(unittest.TestCase):
def test_timestamp_change(self):
w = frappe.bean(copy=test_records[0])
w.doc.docstatus = '0'
w.docstatus = '0'
w.insert()
w2 = frappe.bean([d.fields.copy() for d in w.doclist])
@ -60,11 +60,11 @@ class TestSalesInvoice(unittest.TestCase):
# check if item values are calculated
for d in si.get("entries"):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(d.fields.get(k), expected_values[d.item_code][i])
self.assertEquals(d.get(k), expected_values[d.item_code][i])
# check net total
self.assertEquals(si.doc.net_total, 1250)
self.assertEquals(si.doc.net_total_export, 1250)
self.assertEquals(si.net_total, 1250)
self.assertEquals(si.net_total_export, 1250)
# check tax calculation
expected_values = {
@ -81,15 +81,15 @@ class TestSalesInvoice(unittest.TestCase):
for d in si.get("other_charges"):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(d.fields.get(k), expected_values[d.account_head][i])
self.assertEquals(d.get(k), expected_values[d.account_head][i])
self.assertEquals(si.doc.grand_total, 1627.05)
self.assertEquals(si.doc.grand_total_export, 1627.05)
self.assertEquals(si.grand_total, 1627.05)
self.assertEquals(si.grand_total_export, 1627.05)
def test_sales_invoice_calculation_export_currency(self):
si = frappe.bean(copy=test_records[2])
si.doc.currency = "USD"
si.doc.conversion_rate = 50
si.currency = "USD"
si.conversion_rate = 50
si.doclist[1].rate = 1
si.doclist[1].price_list_rate = 1
si.doclist[2].rate = 3
@ -110,11 +110,11 @@ class TestSalesInvoice(unittest.TestCase):
# check if item values are calculated
for d in si.get("entries"):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(d.fields.get(k), expected_values[d.item_code][i])
self.assertEquals(d.get(k), expected_values[d.item_code][i])
# check net total
self.assertEquals(si.doc.net_total, 1250)
self.assertEquals(si.doc.net_total_export, 25)
self.assertEquals(si.net_total, 1250)
self.assertEquals(si.net_total_export, 25)
# check tax calculation
expected_values = {
@ -131,14 +131,14 @@ class TestSalesInvoice(unittest.TestCase):
for d in si.get("other_charges"):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(d.fields.get(k), expected_values[d.account_head][i])
self.assertEquals(d.get(k), expected_values[d.account_head][i])
self.assertEquals(si.doc.grand_total, 1627.05)
self.assertEquals(si.doc.grand_total_export, 32.54)
self.assertEquals(si.grand_total, 1627.05)
self.assertEquals(si.grand_total_export, 32.54)
def test_sales_invoice_discount_amount(self):
si = frappe.bean(copy=test_records[3])
si.doc.discount_amount = 104.95
si.discount_amount = 104.95
si.append("other_charges", {
"doctype": "Sales Taxes and Charges",
"charge_type": "On Previous Row Amount",
@ -164,11 +164,11 @@ class TestSalesInvoice(unittest.TestCase):
# check if item values are calculated
for d in si.get("entries"):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(d.fields.get(k), expected_values[d.item_code][i])
self.assertEquals(d.get(k), expected_values[d.item_code][i])
# check net total
self.assertEquals(si.doc.net_total, 1163.45)
self.assertEquals(si.doc.net_total_export, 1578.3)
self.assertEquals(si.net_total, 1163.45)
self.assertEquals(si.net_total_export, 1578.3)
# check tax calculation
expected_values = {
@ -186,14 +186,14 @@ class TestSalesInvoice(unittest.TestCase):
for d in si.get("other_charges"):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(d.fields.get(k), expected_values[d.account_head][i])
self.assertEquals(d.get(k), expected_values[d.account_head][i])
self.assertEquals(si.doc.grand_total, 1500)
self.assertEquals(si.doc.grand_total_export, 1500)
self.assertEquals(si.grand_total, 1500)
self.assertEquals(si.grand_total_export, 1500)
def test_discount_amount_gl_entry(self):
si = frappe.bean(copy=test_records[3])
si.doc.discount_amount = 104.95
si.discount_amount = 104.95
si.append("other_charges", {
"doctype": "Sales Taxes and Charges",
"charge_type": "On Previous Row Amount",
@ -208,12 +208,12 @@ class TestSalesInvoice(unittest.TestCase):
gl_entries = frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
order by account asc""", si.doc.name, as_dict=1)
order by account asc""", si.name, as_dict=1)
self.assertTrue(gl_entries)
expected_values = sorted([
[si.doc.debit_to, 1500, 0.0],
[si.debit_to, 1500, 0.0],
[test_records[3][1]["income_account"], 0.0, 1163.45],
[test_records[3][3]["account_head"], 0.0, 130.31],
[test_records[3][4]["account_head"], 0.0, 2.61],
@ -235,7 +235,7 @@ class TestSalesInvoice(unittest.TestCase):
si.cancel()
gle = frappe.db.sql("""select * from `tabGL Entry`
where voucher_type='Sales Invoice' and voucher_no=%s""", si.doc.name)
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
self.assertFalse(gle)
@ -275,11 +275,11 @@ class TestSalesInvoice(unittest.TestCase):
# check if item values are calculated
for d in si.get("entries"):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(d.fields.get(k), expected_values[d.item_code][i])
self.assertEquals(d.get(k), expected_values[d.item_code][i])
# check net total
self.assertEquals(si.doc.net_total, 1249.98)
self.assertEquals(si.doc.net_total_export, 1578.3)
self.assertEquals(si.net_total, 1249.98)
self.assertEquals(si.net_total_export, 1578.3)
# check tax calculation
expected_values = {
@ -296,16 +296,16 @@ class TestSalesInvoice(unittest.TestCase):
for d in si.get("other_charges"):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(d.fields.get(k), expected_values[d.account_head][i])
self.assertEquals(d.get(k), expected_values[d.account_head][i])
self.assertEquals(si.doc.grand_total, 1622.98)
self.assertEquals(si.doc.grand_total_export, 1622.98)
self.assertEquals(si.grand_total, 1622.98)
self.assertEquals(si.grand_total_export, 1622.98)
def test_sales_invoice_calculation_export_currency_with_tax_inclusive_price(self):
# prepare
si = frappe.bean(copy=test_records[3])
si.doc.currency = "USD"
si.doc.conversion_rate = 50
si.currency = "USD"
si.conversion_rate = 50
si.doclist[1].price_list_rate = 55.56
si.doclist[1].discount_percentage = 10
si.doclist[2].price_list_rate = 187.5
@ -328,11 +328,11 @@ class TestSalesInvoice(unittest.TestCase):
# check if item values are calculated
for d in si.get("entries"):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(d.fields.get(k), expected_values[d.item_code][i])
self.assertEquals(d.get(k), expected_values[d.item_code][i])
# check net total
self.assertEquals(si.doc.net_total, 49501.7)
self.assertEquals(si.doc.net_total_export, 1250)
self.assertEquals(si.net_total, 49501.7)
self.assertEquals(si.net_total_export, 1250)
# check tax calculation
expected_values = {
@ -349,14 +349,14 @@ class TestSalesInvoice(unittest.TestCase):
for d in si.get("other_charges"):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(d.fields.get(k), expected_values[d.account_head][i])
self.assertEquals(d.get(k), expected_values[d.account_head][i])
self.assertEquals(si.doc.grand_total, 65205.16)
self.assertEquals(si.doc.grand_total_export, 1304.1)
self.assertEquals(si.grand_total, 65205.16)
self.assertEquals(si.grand_total_export, 1304.1)
def test_outstanding(self):
w = self.make()
self.assertEquals(w.doc.outstanding_amount, w.doc.grand_total)
self.assertEquals(w.outstanding_amount, w.grand_total)
def test_payment(self):
frappe.db.sql("""delete from `tabGL Entry`""")
@ -366,15 +366,15 @@ class TestSalesInvoice(unittest.TestCase):
import test_records as jv_test_records
jv = frappe.bean(frappe.copy_doc(jv_test_records[0]))
jv.doclist[1].against_invoice = w.doc.name
jv.doclist[1].against_invoice = w.name
jv.insert()
jv.submit()
self.assertEquals(frappe.db.get_value("Sales Invoice", w.doc.name, "outstanding_amount"),
self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"),
161.8)
jv.cancel()
self.assertEquals(frappe.db.get_value("Sales Invoice", w.doc.name, "outstanding_amount"),
self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"),
561.8)
def test_time_log_batch(self):
@ -409,12 +409,12 @@ class TestSalesInvoice(unittest.TestCase):
gl_entries = frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
order by account asc""", si.doc.name, as_dict=1)
order by account asc""", si.name, as_dict=1)
self.assertTrue(gl_entries)
expected_values = sorted([
[si.doc.debit_to, 630.0, 0.0],
[si.debit_to, 630.0, 0.0],
[test_records[1][1]["income_account"], 0.0, 500.0],
[test_records[1][2]["account_head"], 0.0, 80.0],
[test_records[1][3]["account_head"], 0.0, 50.0],
@ -429,7 +429,7 @@ class TestSalesInvoice(unittest.TestCase):
si.cancel()
gle = frappe.db.sql("""select * from `tabGL Entry`
where voucher_type='Sales Invoice' and voucher_no=%s""", si.doc.name)
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
self.assertFalse(gle)
@ -454,7 +454,7 @@ class TestSalesInvoice(unittest.TestCase):
# check stock ledger entries
sle = frappe.db.sql("""select * from `tabStock Ledger Entry`
where voucher_type = 'Sales Invoice' and voucher_no = %s""",
si.doc.name, as_dict=1)[0]
si.name, as_dict=1)[0]
self.assertTrue(sle)
self.assertEquals([sle.item_code, sle.warehouse, sle.actual_qty],
["_Test Item", "_Test Warehouse - _TC", -1.0])
@ -462,19 +462,19 @@ class TestSalesInvoice(unittest.TestCase):
# check gl entries
gl_entries = frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
order by account asc, debit asc""", si.doc.name, as_dict=1)
order by account asc, debit asc""", si.name, as_dict=1)
self.assertTrue(gl_entries)
stock_in_hand = frappe.db.get_value("Account", {"master_name": "_Test Warehouse - _TC"})
expected_gl_entries = sorted([
[si.doc.debit_to, 630.0, 0.0],
[si.debit_to, 630.0, 0.0],
[pos[1]["income_account"], 0.0, 500.0],
[pos[2]["account_head"], 0.0, 80.0],
[pos[3]["account_head"], 0.0, 50.0],
[stock_in_hand, 0.0, 75.0],
[pos[1]["expense_account"], 75.0, 0.0],
[si.doc.debit_to, 0.0, 600.0],
[si.debit_to, 0.0, 600.0],
["_Test Account Bank Account - _TC", 600.0, 0.0]
])
for i, gle in enumerate(gl_entries):
@ -484,7 +484,7 @@ class TestSalesInvoice(unittest.TestCase):
si.cancel()
gle = frappe.db.sql("""select * from `tabGL Entry`
where voucher_type='Sales Invoice' and voucher_no=%s""", si.doc.name)
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
self.assertFalse(gle)
@ -501,7 +501,7 @@ class TestSalesInvoice(unittest.TestCase):
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import test_records \
as pr_test_records
pr = frappe.bean(copy=pr_test_records[0])
pr.doc.naming_series = "_T-Purchase Receipt-"
pr.naming_series = "_T-Purchase Receipt-"
pr.doclist[1].warehouse = "_Test Warehouse No Account - _TC"
pr.insert()
pr.submit()
@ -518,7 +518,7 @@ class TestSalesInvoice(unittest.TestCase):
# check stock ledger entries
sle = frappe.db.sql("""select * from `tabStock Ledger Entry`
where voucher_type = 'Sales Invoice' and voucher_no = %s""",
si.doc.name, as_dict=1)[0]
si.name, as_dict=1)[0]
self.assertTrue(sle)
self.assertEquals([sle.item_code, sle.warehouse, sle.actual_qty],
["_Test Item", "_Test Warehouse No Account - _TC", -1.0])
@ -526,11 +526,11 @@ class TestSalesInvoice(unittest.TestCase):
# check gl entries
gl_entries = frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
order by account asc, debit asc""", si.doc.name, as_dict=1)
order by account asc, debit asc""", si.name, as_dict=1)
self.assertTrue(gl_entries)
expected_gl_entries = sorted([
[si.doc.debit_to, 630.0, 0.0],
[si.debit_to, 630.0, 0.0],
[si_doclist[1]["income_account"], 0.0, 500.0],
[si_doclist[2]["account_head"], 0.0, 80.0],
[si_doclist[3]["account_head"], 0.0, 50.0],
@ -542,7 +542,7 @@ class TestSalesInvoice(unittest.TestCase):
si.cancel()
gle = frappe.db.sql("""select * from `tabGL Entry`
where voucher_type='Sales Invoice' and voucher_no=%s""", si.doc.name)
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
self.assertFalse(gle)
set_perpetual_inventory(0)
@ -559,11 +559,11 @@ class TestSalesInvoice(unittest.TestCase):
gl_entries = frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
order by account asc""", si.doc.name, as_dict=1)
order by account asc""", si.name, as_dict=1)
self.assertTrue(gl_entries)
expected_values = sorted([
[si.doc.debit_to, 630.0, 0.0],
[si.debit_to, 630.0, 0.0],
[test_records[1][1]["income_account"], 0.0, 500.0],
[test_records[1][2]["account_head"], 0.0, 80.0],
[test_records[1][3]["account_head"], 0.0, 50.0],
@ -586,11 +586,11 @@ class TestSalesInvoice(unittest.TestCase):
gl_entries = frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
order by account asc""", si.doc.name, as_dict=1)
order by account asc""", si.name, as_dict=1)
self.assertTrue(gl_entries)
expected_values = sorted([
[si.doc.debit_to, 630.0, 0.0],
[si.debit_to, 630.0, 0.0],
[test_records[1][1]["income_account"], 0.0, 500.0],
[test_records[1][2]["account_head"], 0.0, 80.0],
[test_records[1][3]["account_head"], 0.0, 50.0],
@ -606,7 +606,7 @@ class TestSalesInvoice(unittest.TestCase):
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import test_records \
as pr_test_records
pr = frappe.bean(copy=pr_test_records[0])
pr.doc.naming_series = "_T-Purchase Receipt-"
pr.naming_series = "_T-Purchase Receipt-"
pr.insert()
pr.submit()
@ -614,7 +614,7 @@ class TestSalesInvoice(unittest.TestCase):
from erpnext.stock.doctype.delivery_note.test_delivery_note import test_records \
as dn_test_records
dn = frappe.bean(copy=dn_test_records[0])
dn.doc.naming_series = "_T-Delivery Note-"
dn.naming_series = "_T-Delivery Note-"
dn.insert()
dn.submit()
return dn
@ -638,35 +638,35 @@ class TestSalesInvoice(unittest.TestCase):
si = frappe.bean(copy=test_records[0])
si.append("advance_adjustment_details", {
"doctype": "Sales Invoice Advance",
"journal_voucher": jv.doc.name,
"journal_voucher": jv.name,
"jv_detail_no": jv.doclist[1].name,
"advance_amount": 400,
"allocated_amount": 300,
"remarks": jv.doc.remark
"remarks": jv.remark
})
si.insert()
si.submit()
si.load_from_db()
self.assertTrue(frappe.db.sql("""select name from `tabJournal Voucher Detail`
where against_invoice=%s""", si.doc.name))
where against_invoice=%s""", si.name))
self.assertTrue(frappe.db.sql("""select name from `tabJournal Voucher Detail`
where against_invoice=%s and credit=300""", si.doc.name))
where against_invoice=%s and credit=300""", si.name))
self.assertEqual(si.doc.outstanding_amount, 261.8)
self.assertEqual(si.outstanding_amount, 261.8)
si.cancel()
self.assertTrue(not frappe.db.sql("""select name from `tabJournal Voucher Detail`
where against_invoice=%s""", si.doc.name))
where against_invoice=%s""", si.name))
def test_recurring_invoice(self):
from frappe.utils import get_first_day, get_last_day, add_to_date, nowdate, getdate
from erpnext.accounts.utils import get_fiscal_year
today = nowdate()
base_si = frappe.bean(copy=test_records[0])
base_si.doc.fields.update({
base_si.update({
"convert_into_recurring_invoice": 1,
"recurring_type": "Monthly",
"notification_email_address": "test@example.com, test1@example.com, test2@example.com",
@ -685,7 +685,7 @@ class TestSalesInvoice(unittest.TestCase):
# monthly without a first and last day period
si2 = frappe.bean(copy=base_si.doclist)
si2.doc.fields.update({
si2.update({
"invoice_period_from_date": today,
"invoice_period_to_date": add_to_date(today, days=30)
})
@ -695,7 +695,7 @@ class TestSalesInvoice(unittest.TestCase):
# quarterly
si3 = frappe.bean(copy=base_si.doclist)
si3.doc.fields.update({
si3.update({
"recurring_type": "Quarterly",
"invoice_period_from_date": get_first_day(today),
"invoice_period_to_date": get_last_day(add_to_date(today, months=3))
@ -706,7 +706,7 @@ class TestSalesInvoice(unittest.TestCase):
# quarterly without a first and last day period
si4 = frappe.bean(copy=base_si.doclist)
si4.doc.fields.update({
si4.update({
"recurring_type": "Quarterly",
"invoice_period_from_date": today,
"invoice_period_to_date": add_to_date(today, months=3)
@ -717,7 +717,7 @@ class TestSalesInvoice(unittest.TestCase):
# yearly
si5 = frappe.bean(copy=base_si.doclist)
si5.doc.fields.update({
si5.update({
"recurring_type": "Yearly",
"invoice_period_from_date": get_first_day(today),
"invoice_period_to_date": get_last_day(add_to_date(today, years=1))
@ -728,7 +728,7 @@ class TestSalesInvoice(unittest.TestCase):
# yearly without a first and last day period
si6 = frappe.bean(copy=base_si.doclist)
si6.doc.fields.update({
si6.update({
"recurring_type": "Yearly",
"invoice_period_from_date": today,
"invoice_period_to_date": add_to_date(today, years=1)
@ -739,14 +739,14 @@ class TestSalesInvoice(unittest.TestCase):
# change posting date but keep recuring day to be today
si7 = frappe.bean(copy=base_si.doclist)
si7.doc.fields.update({
si7.update({
"posting_date": add_to_date(today, days=-1)
})
si7.insert()
si7.submit()
# setting so that _test function works
si7.doc.posting_date = today
si7.posting_date = today
self._test_recurring_invoice(si7, True)
def _test_recurring_invoice(self, base_si, first_and_last_day):
@ -754,20 +754,20 @@ class TestSalesInvoice(unittest.TestCase):
from erpnext.accounts.doctype.sales_invoice.sales_invoice \
import manage_recurring_invoices, get_next_date
no_of_months = ({"Monthly": 1, "Quarterly": 3, "Yearly": 12})[base_si.doc.recurring_type]
no_of_months = ({"Monthly": 1, "Quarterly": 3, "Yearly": 12})[base_si.recurring_type]
def _test(i):
self.assertEquals(i+1, frappe.db.sql("""select count(*) from `tabSales Invoice`
where recurring_id=%s and docstatus=1""", base_si.doc.recurring_id)[0][0])
where recurring_id=%s and docstatus=1""", base_si.recurring_id)[0][0])
next_date = get_next_date(base_si.doc.posting_date, no_of_months,
base_si.doc.repeat_on_day_of_month)
next_date = get_next_date(base_si.posting_date, no_of_months,
base_si.repeat_on_day_of_month)
manage_recurring_invoices(next_date=next_date, commit=False)
recurred_invoices = frappe.db.sql("""select name from `tabSales Invoice`
where recurring_id=%s and docstatus=1 order by name desc""",
base_si.doc.recurring_id)
base_si.recurring_id)
self.assertEquals(i+2, len(recurred_invoices))
@ -775,21 +775,21 @@ class TestSalesInvoice(unittest.TestCase):
for fieldname in ["convert_into_recurring_invoice", "recurring_type",
"repeat_on_day_of_month", "notification_email_address"]:
self.assertEquals(base_si.doc.fields.get(fieldname),
new_si.doc.fields.get(fieldname))
self.assertEquals(base_si.get(fieldname),
new_si.get(fieldname))
self.assertEquals(new_si.doc.posting_date, unicode(next_date))
self.assertEquals(new_si.posting_date, unicode(next_date))
self.assertEquals(new_si.doc.invoice_period_from_date,
unicode(add_months(base_si.doc.invoice_period_from_date, no_of_months)))
self.assertEquals(new_si.invoice_period_from_date,
unicode(add_months(base_si.invoice_period_from_date, no_of_months)))
if first_and_last_day:
self.assertEquals(new_si.doc.invoice_period_to_date,
unicode(get_last_day(add_months(base_si.doc.invoice_period_to_date,
self.assertEquals(new_si.invoice_period_to_date,
unicode(get_last_day(add_months(base_si.invoice_period_to_date,
no_of_months))))
else:
self.assertEquals(new_si.doc.invoice_period_to_date,
unicode(add_months(base_si.doc.invoice_period_to_date, no_of_months)))
self.assertEquals(new_si.invoice_period_to_date,
unicode(add_months(base_si.invoice_period_to_date, no_of_months)))
return new_si
@ -812,7 +812,7 @@ class TestSalesInvoice(unittest.TestCase):
serial_nos = get_serial_nos(se.doclist[1].serial_no)
si = frappe.bean(copy=test_records[0])
si.doc.update_stock = 1
si.update_stock = 1
si.doclist[1].item_code = "_Test Serialized Item With Series"
si.doclist[1].qty = 1
si.doclist[1].serial_no = serial_nos[0]
@ -822,7 +822,7 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "status"), "Delivered")
self.assertFalse(frappe.db.get_value("Serial No", serial_nos[0], "warehouse"))
self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0],
"delivery_document_no"), si.doc.name)
"delivery_document_no"), si.name)
return si
@ -846,11 +846,11 @@ class TestSalesInvoice(unittest.TestCase):
serial_nos = get_serial_nos(se.doclist[1].serial_no)
sr = frappe.bean("Serial No", serial_nos[0])
sr.doc.status = "Not Available"
sr.status = "Not Available"
sr.save()
si = frappe.bean(copy=test_records[0])
si.doc.update_stock = 1
si.update_stock = 1
si.doclist[1].item_code = "_Test Serialized Item With Series"
si.doclist[1].qty = 1
si.doclist[1].serial_no = serial_nos[0]

View File

@ -8,10 +8,10 @@ from frappe.model.controller import DocListController
class SalesTaxesAndChargesMaster(DocListController):
def validate(self):
if self.doc.is_default == 1:
if self.is_default == 1:
frappe.db.sql("""update `tabSales Taxes and Charges Master` set is_default = 0
where ifnull(is_default,0) = 1 and name != %s and company = %s""",
(self.doc.name, self.doc.company))
(self.name, self.company))
# at least one territory
self.validate_table_has_rows("valid_for_territories")

View File

@ -74,7 +74,7 @@ class ShippingRule(DocListController):
overlaps.append([d1, d2])
if overlaps:
company_currency = get_company_currency(self.doc.company)
company_currency = get_company_currency(self.company)
msgprint(_("Error") + ": " + _("Overlapping Conditions found between") + ":")
messages = []
for d1, d2 in overlaps:

View File

@ -178,4 +178,4 @@ def create_party_account(party, party_type, company):
"report_type": "Balance Sheet"
}).insert(ignore_permissions=True)
frappe.msgprint(_("Account Created") + ": " + account.doc.name)
frappe.msgprint(_("Account Created") + ": " + account.name)

View File

@ -104,11 +104,11 @@ def add_ac(args=None):
args.pop("cmd")
ac = frappe.bean(args)
ac.doc.doctype = "Account"
ac.doc.old_parent = ""
ac.doc.freeze_account = "No"
ac.doctype = "Account"
ac.old_parent = ""
ac.freeze_account = "No"
ac.insert()
return ac.doc.name
return ac.name
@frappe.whitelist()
def add_cc(args=None):
@ -117,10 +117,10 @@ def add_cc(args=None):
args.pop("cmd")
cc = frappe.bean(args)
cc.doc.doctype = "Cost Center"
cc.doc.old_parent = ""
cc.doctype = "Cost Center"
cc.old_parent = ""
cc.insert()
return cc.doc.name
return cc.name
def reconcile_against_document(args):
"""
@ -185,8 +185,8 @@ def update_against_doc(d, jv_obj):
ch.account = d['account']
ch.cost_center = cstr(jvd[0][0])
ch.balance = cstr(jvd[0][1])
ch.fields[d['dr_or_cr']] = flt(d['unadjusted_amt']) - flt(d['allocated_amt'])
ch.fields[d['dr_or_cr']== 'debit' and 'credit' or 'debit'] = 0
ch.set(d['dr_or_cr'], flt(d['unadjusted_amt']) - flt(d['allocated_amt']))
ch.set(d['dr_or_cr']== 'debit' and 'credit' or 'debit', 0)
ch.against_account = cstr(jvd[0][2])
ch.is_advance = cstr(jvd[0][3])
ch.docstatus = 1

View File

@ -12,8 +12,8 @@ class BuyingSettings(Document):
def validate(self):
for key in ["supplier_type", "supp_master_name", "maintain_same_rate", "buying_price_list"]:
frappe.db.set_default(key, self.doc.fields.get(key, ""))
frappe.db.set_default(key, self.get(key, ""))
from erpnext.setup.doctype.naming_series.naming_series import set_by_naming_series
set_by_naming_series("Supplier", "supplier_name",
self.doc.get("supp_master_name")=="Naming Series", hide_name_field=False)
self.get("supp_master_name")=="Naming Series", hide_name_field=False)

View File

@ -17,11 +17,11 @@ class PurchaseCommon(BuyingController):
"""updates last_purchase_rate in item table for each item"""
import frappe.utils
this_purchase_date = frappe.utils.getdate(obj.doc.fields.get('posting_date') or obj.doc.fields.get('transaction_date'))
this_purchase_date = frappe.utils.getdate(obj.get('posting_date') or obj.get('transaction_date'))
for d in getlist(obj.doclist,obj.fname):
# get last purchase details
last_purchase_details = get_last_purchase_details(d.item_code, obj.doc.name)
last_purchase_details = get_last_purchase_details(d.item_code, obj.name)
# compare last purchase date and this transaction's date
last_purchase_rate = None
@ -44,8 +44,8 @@ class PurchaseCommon(BuyingController):
def get_last_purchase_rate(self, obj):
"""get last purchase rates for all items"""
doc_name = obj.doc.name
conversion_rate = flt(obj.doc.fields.get('conversion_rate')) or 1.0
doc_name = obj.name
conversion_rate = flt(obj.get('conversion_rate')) or 1.0
for d in getlist(obj.doclist, obj.fname):
if d.item_code:
@ -83,7 +83,7 @@ class PurchaseCommon(BuyingController):
f_lst.pop('received_qty')
for x in f_lst :
if d.fields.has_key(x):
d.fields[x] = f_lst[x]
d.set(x, f_lst[x])
item = frappe.db.sql("""select is_stock_item, is_purchase_item,
is_sub_contracted_item, end_of_life from `tabItem` where name=%s""", d.item_code)

View File

@ -29,11 +29,11 @@ class PurchaseOrder(BuyingController):
def validate(self):
super(DocType, self).validate()
if not self.doc.status:
self.doc.status = "Draft"
if not self.status:
self.status = "Draft"
from erpnext.utilities import validate_status
validate_status(self.doc.status, ["Draft", "Submitted", "Stopped",
validate_status(self.status, ["Draft", "Submitted", "Stopped",
"Cancelled"])
pc_obj = get_obj(dt='Purchase Common')
@ -99,7 +99,7 @@ class PurchaseOrder(BuyingController):
# get qty and pending_qty of prevdoc
curr_ref_qty = pc_obj.get_qty(d.doctype, 'prevdoc_detail_docname',
d.prevdoc_detail_docname, 'Material Request Item',
'Material Request - Purchase Order', self.doc.name)
'Material Request - Purchase Order', self.name)
max_qty, qty, curr_qty = flt(curr_ref_qty.split('~~~')[1]), \
flt(curr_ref_qty.split('~~~')[0]), 0
@ -119,17 +119,17 @@ class PurchaseOrder(BuyingController):
"warehouse": d.warehouse,
"ordered_qty": (is_submit and 1 or -1) * flt(po_qty),
"indented_qty": (is_submit and 1 or -1) * flt(ind_qty),
"posting_date": self.doc.transaction_date
"posting_date": self.transaction_date
}
update_bin(args)
def check_modified_date(self):
mod_db = frappe.db.sql("select modified from `tabPurchase Order` where name = %s",
self.doc.name)
date_diff = frappe.db.sql("select TIMEDIFF('%s', '%s')" % ( mod_db[0][0],cstr(self.doc.modified)))
self.name)
date_diff = frappe.db.sql("select TIMEDIFF('%s', '%s')" % ( mod_db[0][0],cstr(self.modified)))
if date_diff and date_diff[0][0]:
msgprint(cstr(self.doc.doctype) +" => "+ cstr(self.doc.name) +" has been modified. Please Refresh. ")
msgprint(cstr(self.doctype) +" => "+ cstr(self.name) +" has been modified. Please Refresh. ")
raise Exception
def update_status(self, status):
@ -141,7 +141,7 @@ class PurchaseOrder(BuyingController):
self.update_bin(is_submit = (status == 'Submitted') and 1 or 0, is_stopped = 1)
# step 3:=> Acknowledge user
msgprint(self.doc.doctype + ": " + self.doc.name + " has been %s." % ((status == 'Submitted') and 'Unstopped' or cstr(status)))
msgprint(self.doctype + ": " + self.name + " has been %s." % ((status == 'Submitted') and 'Unstopped' or cstr(status)))
def on_submit(self):
purchase_controller = frappe.get_obj("Purchase Common")
@ -149,8 +149,8 @@ class PurchaseOrder(BuyingController):
self.update_prevdoc_status()
self.update_bin(is_submit = 1, is_stopped = 0)
get_obj('Authorization Control').validate_approving_authority(self.doc.doctype,
self.doc.company, self.doc.grand_total)
get_obj('Authorization Control').validate_approving_authority(self.doctype,
self.company, self.grand_total)
purchase_controller.update_last_purchase_rate(self, is_submit = 1)
@ -161,13 +161,13 @@ class PurchaseOrder(BuyingController):
self.check_for_stopped_status(pc_obj)
# Check if Purchase Receipt has been submitted against current Purchase Order
pc_obj.check_docstatus(check = 'Next', doctype = 'Purchase Receipt', docname = self.doc.name, detail_doctype = 'Purchase Receipt Item')
pc_obj.check_docstatus(check = 'Next', doctype = 'Purchase Receipt', docname = self.name, detail_doctype = 'Purchase Receipt Item')
# Check if Purchase Invoice has been submitted against current Purchase Order
submitted = frappe.db.sql("""select t1.name
from `tabPurchase Invoice` t1,`tabPurchase Invoice Item` t2
where t1.name = t2.parent and t2.purchase_order = %s and t1.docstatus = 1""",
self.doc.name)
self.name)
if submitted:
msgprint("Purchase Invoice : " + cstr(submitted[0][0]) + " has already been submitted !")
raise Exception

View File

@ -14,12 +14,12 @@ class TestPurchaseOrder(unittest.TestCase):
po = frappe.bean(copy=test_records[0]).insert()
self.assertRaises(frappe.ValidationError, make_purchase_receipt,
po.doc.name)
po.name)
po = frappe.bean("Purchase Order", po.doc.name)
po = frappe.bean("Purchase Order", po.name)
po.submit()
pr = make_purchase_receipt(po.doc.name)
pr = make_purchase_receipt(po.name)
pr[0]["supplier_warehouse"] = "_Test Warehouse 1 - _TC"
pr[0]["posting_date"] = "2013-05-12"
self.assertEquals(pr[0]["doctype"], "Purchase Receipt")
@ -37,17 +37,17 @@ class TestPurchaseOrder(unittest.TestCase):
po = frappe.bean(copy=test_records[0]).insert()
self.assertRaises(frappe.ValidationError, make_purchase_receipt,
po.doc.name)
po.name)
po = frappe.bean("Purchase Order", po.doc.name)
po.doc.is_subcontracted = "No"
po = frappe.bean("Purchase Order", po.name)
po.is_subcontracted = "No"
po.doclist[1].item_code = "_Test Item"
po.submit()
self.assertEquals(frappe.db.get_value("Bin", {"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC"}, "ordered_qty"), 10)
pr = make_purchase_receipt(po.doc.name)
pr = make_purchase_receipt(po.name)
self.assertEquals(pr[0]["doctype"], "Purchase Receipt")
self.assertEquals(len(pr), len(test_records[0]))
@ -63,7 +63,7 @@ class TestPurchaseOrder(unittest.TestCase):
frappe.db.set_value('Item', '_Test Item', 'tolerance', 50)
pr1 = make_purchase_receipt(po.doc.name)
pr1 = make_purchase_receipt(po.name)
pr1[0]["naming_series"] = "_T-Purchase Receipt-"
pr1[0]["posting_date"] = "2013-05-12"
pr1[1]["qty"] = 8
@ -80,11 +80,11 @@ class TestPurchaseOrder(unittest.TestCase):
po = frappe.bean(copy=test_records[0]).insert()
self.assertRaises(frappe.ValidationError, make_purchase_invoice,
po.doc.name)
po.name)
po = frappe.bean("Purchase Order", po.doc.name)
po = frappe.bean("Purchase Order", po.name)
po.submit()
pi = make_purchase_invoice(po.doc.name)
pi = make_purchase_invoice(po.name)
self.assertEquals(pi[0]["doctype"], "Purchase Invoice")
self.assertEquals(len(pi), len(test_records[0]))
@ -100,8 +100,8 @@ class TestPurchaseOrder(unittest.TestCase):
def test_warehouse_company_validation(self):
from erpnext.stock.utils import InvalidWarehouseCompany
po = frappe.bean(copy=test_records[0])
po.doc.company = "_Test Company 1"
po.doc.conversion_rate = 0.0167
po.company = "_Test Company 1"
po.conversion_rate = 0.0167
self.assertRaises(InvalidWarehouseCompany, po.insert)
def test_uom_integer_validation(self):

View File

@ -12,28 +12,28 @@ class QualityInspection(Document):
def get_item_specification_details(self):
self.set('qa_specification_details', [])
specification = frappe.db.sql("select specification, value from `tabItem Quality Inspection Parameter` \
where parent = '%s' order by idx" % (self.doc.item_code))
where parent = '%s' order by idx" % (self.item_code))
for d in specification:
child = self.doc.append('qa_specification_details', {})
child = self.append('qa_specification_details', {})
child.specification = d[0]
child.value = d[1]
child.status = 'Accepted'
def on_submit(self):
if self.doc.purchase_receipt_no:
if self.purchase_receipt_no:
frappe.db.sql("""update `tabPurchase Receipt Item` t1, `tabPurchase Receipt` t2
set t1.qa_no = %s, t2.modified = %s
where t1.parent = %s and t1.item_code = %s and t1.parent = t2.name""",
(self.doc.name, self.doc.modified, self.doc.purchase_receipt_no,
self.doc.item_code))
(self.name, self.modified, self.purchase_receipt_no,
self.item_code))
def on_cancel(self):
if self.doc.purchase_receipt_no:
if self.purchase_receipt_no:
frappe.db.sql("""update `tabPurchase Receipt Item` t1, `tabPurchase Receipt` t2
set t1.qa_no = '', t2.modified = %s
where t1.parent = %s and t1.item_code = %s and t1.parent = t2.name""",
(self.doc.modified, self.doc.purchase_receipt_no, self.doc.item_code))
(self.modified, self.purchase_receipt_no, self.item_code))
def item_query(doctype, txt, searchfield, start, page_len, filters):

View File

@ -18,44 +18,44 @@ class Supplier(TransactionBase):
supp_master_name = frappe.defaults.get_global_default('supp_master_name')
if supp_master_name == 'Supplier Name':
if frappe.db.exists("Customer", self.doc.supplier_name):
if frappe.db.exists("Customer", self.supplier_name):
frappe.msgprint(_("A Customer exists with same name"), raise_exception=1)
self.doc.name = self.doc.supplier_name
self.name = self.supplier_name
else:
self.doc.name = make_autoname(self.doc.naming_series + '.#####')
self.name = make_autoname(self.naming_series + '.#####')
def update_address(self):
frappe.db.sql("""update `tabAddress` set supplier_name=%s, modified=NOW()
where supplier=%s""", (self.doc.supplier_name, self.doc.name))
where supplier=%s""", (self.supplier_name, self.name))
def update_contact(self):
frappe.db.sql("""update `tabContact` set supplier_name=%s, modified=NOW()
where supplier=%s""", (self.doc.supplier_name, self.doc.name))
where supplier=%s""", (self.supplier_name, self.name))
def update_credit_days_limit(self):
frappe.db.sql("""update tabAccount set credit_days = %s where name = %s""",
(cint(self.doc.credit_days), self.doc.name + " - " + self.get_company_abbr()))
(cint(self.credit_days), self.name + " - " + self.get_company_abbr()))
def on_update(self):
if not self.doc.naming_series:
self.doc.naming_series = ''
if not self.naming_series:
self.naming_series = ''
self.update_address()
self.update_contact()
# create account head
create_party_account(self.doc.name, "Supplier", self.doc.company)
create_party_account(self.name, "Supplier", self.company)
# update credit days and limit in account
self.update_credit_days_limit()
def get_company_abbr(self):
return frappe.db.sql("select abbr from tabCompany where name=%s", self.doc.company)[0][0]
return frappe.db.sql("select abbr from tabCompany where name=%s", self.company)[0][0]
def validate(self):
#validation for Naming Series mandatory field...
if frappe.defaults.get_global_default('supp_master_name') == 'Naming Series':
if not self.doc.naming_series:
if not self.naming_series:
msgprint("Series is Mandatory.", raise_exception=1)
def get_contacts(self,nm):
@ -67,18 +67,18 @@ class Supplier(TransactionBase):
return ''
def delete_supplier_address(self):
for rec in frappe.db.sql("select * from `tabAddress` where supplier=%s", (self.doc.name,), as_dict=1):
for rec in frappe.db.sql("select * from `tabAddress` where supplier=%s", (self.name,), as_dict=1):
frappe.db.sql("delete from `tabAddress` where name=%s",(rec['name']))
def delete_supplier_contact(self):
for contact in frappe.db.sql_list("""select name from `tabContact`
where supplier=%s""", self.doc.name):
where supplier=%s""", self.name):
frappe.delete_doc("Contact", contact)
def delete_supplier_account(self):
"""delete supplier's ledger if exist and check balance before deletion"""
acc = frappe.db.sql("select name from `tabAccount` where master_type = 'Supplier' \
and master_name = %s and docstatus < 2", self.doc.name)
and master_name = %s and docstatus < 2", self.name)
if acc:
frappe.delete_doc('Account', acc[0][0])
@ -89,7 +89,7 @@ class Supplier(TransactionBase):
def before_rename(self, olddn, newdn, merge=False):
from erpnext.accounts.utils import rename_account_for
rename_account_for("Supplier", olddn, newdn, merge, self.doc.company)
rename_account_for("Supplier", olddn, newdn, merge, self.company)
def after_rename(self, olddn, newdn, merge=False):
set_field = ''

View File

@ -14,11 +14,11 @@ class SupplierQuotation(BuyingController):
def validate(self):
super(DocType, self).validate()
if not self.doc.status:
self.doc.status = "Draft"
if not self.status:
self.status = "Draft"
from erpnext.utilities import validate_status
validate_status(self.doc.status, ["Draft", "Submitted", "Stopped",
validate_status(self.status, ["Draft", "Submitted", "Stopped",
"Cancelled"])
self.validate_common()

View File

@ -14,11 +14,11 @@ class TestPurchaseOrder(unittest.TestCase):
sq = frappe.bean(copy=test_records[0]).insert()
self.assertRaises(frappe.ValidationError, make_purchase_order,
sq.doc.name)
sq.name)
sq = frappe.bean("Supplier Quotation", sq.doc.name)
sq = frappe.bean("Supplier Quotation", sq.name)
sq.submit()
po = make_purchase_order(sq.doc.name)
po = make_purchase_order(sq.name)
self.assertEquals(po[0]["doctype"], "Purchase Order")
self.assertEquals(len(po), len(sq.doclist))

View File

@ -24,10 +24,10 @@ class AccountsController(TransactionBase):
def set_missing_values(self, for_validate=False):
for fieldname in ["posting_date", "transaction_date"]:
if not self.doc.fields.get(fieldname) and self.meta.get_field(fieldname):
self.doc.fields[fieldname] = today()
if not self.doc.fiscal_year:
self.doc.fiscal_year = get_fiscal_year(self.doc.fields[fieldname])[0]
if not self.get(fieldname) and self.meta.get_field(fieldname):
self.set(fieldname, today())
if not self.fiscal_year:
self.fiscal_year = get_fiscal_year(self.fields[fieldname])[0]
def validate_date_with_fiscal_year(self):
if self.meta.get_field("fiscal_year") :
@ -37,16 +37,16 @@ class AccountsController(TransactionBase):
elif self.meta.get_field("transaction_date"):
date_field = "transaction_date"
if date_field and self.doc.fields[date_field]:
validate_fiscal_year(self.doc.fields[date_field], self.doc.fiscal_year,
if date_field and self.fields[date_field]:
validate_fiscal_year(self.fields[date_field], self.fiscal_year,
label=self.meta.get_label(date_field))
def validate_for_freezed_account(self):
for fieldname in ["customer", "supplier"]:
if self.meta.get_field(fieldname) and self.doc.fields.get(fieldname):
if self.meta.get_field(fieldname) and self.get(fieldname):
accounts = frappe.db.get_values("Account",
{"master_type": fieldname.title(), "master_name": self.doc.fields[fieldname],
"company": self.doc.company}, "name")
{"master_type": fieldname.title(), "master_name": self.fields[fieldname],
"company": self.company}, "name")
if accounts:
from erpnext.accounts.doctype.gl_entry.gl_entry import validate_frozen_account
for account in accounts:
@ -54,30 +54,30 @@ class AccountsController(TransactionBase):
def set_price_list_currency(self, buying_or_selling):
if self.meta.get_field("currency"):
company_currency = get_company_currency(self.doc.company)
company_currency = get_company_currency(self.company)
# price list part
fieldname = "selling_price_list" if buying_or_selling.lower() == "selling" \
else "buying_price_list"
if self.meta.get_field(fieldname) and self.doc.fields.get(fieldname):
self.doc.price_list_currency = frappe.db.get_value("Price List",
self.doc.fields.get(fieldname), "currency")
if self.meta.get_field(fieldname) and self.get(fieldname):
self.price_list_currency = frappe.db.get_value("Price List",
self.get(fieldname), "currency")
if self.doc.price_list_currency == company_currency:
self.doc.plc_conversion_rate = 1.0
if self.price_list_currency == company_currency:
self.plc_conversion_rate = 1.0
elif not self.doc.plc_conversion_rate:
self.doc.plc_conversion_rate = self.get_exchange_rate(
self.doc.price_list_currency, company_currency)
elif not self.plc_conversion_rate:
self.plc_conversion_rate = self.get_exchange_rate(
self.price_list_currency, company_currency)
# currency
if not self.doc.currency:
self.doc.currency = self.doc.price_list_currency
self.doc.conversion_rate = self.doc.plc_conversion_rate
elif self.doc.currency == company_currency:
self.doc.conversion_rate = 1.0
elif not self.doc.conversion_rate:
self.doc.conversion_rate = self.get_exchange_rate(self.doc.currency,
if not self.currency:
self.currency = self.price_list_currency
self.conversion_rate = self.plc_conversion_rate
elif self.currency == company_currency:
self.conversion_rate = 1.0
elif not self.conversion_rate:
self.conversion_rate = self.get_exchange_rate(self.currency,
company_currency)
def get_exchange_rate(self, from_currency, to_currency):
@ -88,14 +88,14 @@ class AccountsController(TransactionBase):
"""set missing item values"""
from erpnext.stock.get_item_details import get_item_details
for item in self.get(self.fname):
if item.fields.get("item_code"):
if item.get("item_code"):
args = item.fields.copy()
args.update(self.doc.fields)
args.update(self.fields)
ret = get_item_details(args)
for fieldname, value in ret.items():
if self.meta.get_field(fieldname, parentfield=self.fname) and \
item.fields.get(fieldname) is None and value is not None:
item.fields[fieldname] = value
item.get(fieldname) is None and value is not None:
item.set(fieldname, value)
def set_taxes(self, tax_parentfield, tax_master_field):
if not self.meta.get_field(tax_parentfield):
@ -104,22 +104,21 @@ class AccountsController(TransactionBase):
tax_master_doctype = self.meta.get_field(tax_master_field).options
if not self.get(tax_parentfield):
if not self.doc.fields.get(tax_master_field):
if not self.get(tax_master_field):
# get the default tax master
self.doc.fields[tax_master_field] = \
frappe.db.get_value(tax_master_doctype, {"is_default": 1})
self.set(tax_master_field, frappe.db.get_value(tax_master_doctype, {"is_default": 1}))
self.append_taxes_from_master(tax_parentfield, tax_master_field, tax_master_doctype)
def append_taxes_from_master(self, tax_parentfield, tax_master_field, tax_master_doctype=None):
if self.doc.fields.get(tax_master_field):
if self.get(tax_master_field):
if not tax_master_doctype:
tax_master_doctype = self.meta.get_field(tax_master_field).options
tax_doctype = self.meta.get_field(tax_parentfield).options
from frappe.model import default_fields
tax_master = frappe.bean(tax_master_doctype, self.doc.fields.get(tax_master_field))
tax_master = frappe.bean(tax_master_doctype, self.get(tax_master_field))
for i, tax in enumerate(tax_master.get(tax_parentfield)):
for fieldname in default_fields:
@ -140,16 +139,16 @@ class AccountsController(TransactionBase):
def _calculate_taxes_and_totals(self):
# validate conversion rate
company_currency = get_company_currency(self.doc.company)
if not self.doc.currency or self.doc.currency == company_currency:
self.doc.currency = company_currency
self.doc.conversion_rate = 1.0
company_currency = get_company_currency(self.company)
if not self.currency or self.currency == company_currency:
self.currency = company_currency
self.conversion_rate = 1.0
else:
from erpnext.setup.doctype.currency.currency import validate_conversion_rate
validate_conversion_rate(self.doc.currency, self.doc.conversion_rate,
self.meta.get_label("conversion_rate"), self.doc.company)
validate_conversion_rate(self.currency, self.conversion_rate,
self.meta.get_label("conversion_rate"), self.company)
self.doc.conversion_rate = flt(self.doc.conversion_rate)
self.conversion_rate = flt(self.conversion_rate)
self.item_doclist = self.get(self.fname)
self.tax_doclist = self.get(self.other_fname)
@ -175,7 +174,7 @@ class AccountsController(TransactionBase):
tax_fields.append("tax_amount")
for fieldname in tax_fields:
tax.fields[fieldname] = 0.0
tax.set(fieldname, 0.0)
self.validate_on_previous_row(tax)
self.validate_inclusive_tax(tax)
@ -297,7 +296,7 @@ class AccountsController(TransactionBase):
self.precision("tax_amount", tax))
def adjust_discount_amount_loss(self, tax):
discount_amount_loss = self.doc.grand_total - flt(self.doc.discount_amount) - tax.total
discount_amount_loss = self.grand_total - flt(self.discount_amount) - tax.total
tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount +
discount_amount_loss, self.precision("tax_amount", tax))
tax.total = flt(tax.total + discount_amount_loss, self.precision("total", tax))
@ -309,8 +308,8 @@ class AccountsController(TransactionBase):
if tax.charge_type == "Actual":
# distribute the tax amount proportionally to each item row
actual = flt(tax.rate, self.precision("tax_amount", tax))
current_tax_amount = (self.doc.net_total
and ((item.base_amount / self.doc.net_total) * actual)
current_tax_amount = (self.net_total
and ((item.base_amount / self.net_total) * actual)
or 0)
elif tax.charge_type == "On Net Total":
current_tax_amount = (tax_rate / 100.0) * item.base_amount
@ -355,32 +354,32 @@ class AccountsController(TransactionBase):
def _set_in_company_currency(self, item, print_field, base_field):
"""set values in base currency"""
item.fields[base_field] = flt((flt(item.fields[print_field],
self.precision(print_field, item)) * self.doc.conversion_rate),
item.set(base_field, flt((flt(item.fields[print_field],)
self.precision(print_field, item)) * self.conversion_rate),
self.precision(base_field, item))
def calculate_total_advance(self, parenttype, advance_parentfield):
if self.doc.doctype == parenttype and self.doc.docstatus < 2:
if self.doctype == parenttype and self.docstatus < 2:
sum_of_allocated_amount = sum([flt(adv.allocated_amount, self.precision("allocated_amount", adv))
for adv in self.get(advance_parentfield)])
self.doc.total_advance = flt(sum_of_allocated_amount, self.precision("total_advance"))
self.total_advance = flt(sum_of_allocated_amount, self.precision("total_advance"))
self.calculate_outstanding_amount()
def get_gl_dict(self, args):
"""this method populates the common properties of a gl entry record"""
gl_dict = frappe._dict({
'company': self.doc.company,
'posting_date': self.doc.posting_date,
'voucher_type': self.doc.doctype,
'voucher_no': self.doc.name,
'aging_date': self.doc.fields.get("aging_date") or self.doc.posting_date,
'remarks': self.doc.remarks,
'fiscal_year': self.doc.fiscal_year,
'company': self.company,
'posting_date': self.posting_date,
'voucher_type': self.doctype,
'voucher_no': self.name,
'aging_date': self.get("aging_date") or self.posting_date,
'remarks': self.remarks,
'fiscal_year': self.fiscal_year,
'debit': 0,
'credit': 0,
'is_opening': self.doc.fields.get("is_opening") or "No",
'is_opening': self.get("is_opening") or "No",
})
gl_dict.update(args)
return gl_dict
@ -389,7 +388,7 @@ class AccountsController(TransactionBase):
self.doclist.remove_items({"parentfield": parentfield, "allocated_amount": ["in", [0, None, ""]]})
frappe.db.sql("""delete from `tab%s` where parentfield=%s and parent = %s
and ifnull(allocated_amount, 0) = 0""" % (childtype, '%s', '%s'), (parentfield, self.doc.name))
and ifnull(allocated_amount, 0) = 0""" % (childtype, '%s', '%s'), (parentfield, self.name))
def get_advances(self, account_head, child_doctype, parentfield, dr_or_cr):
res = frappe.db.sql("""select t1.name as jv_no, t1.remark,
@ -419,7 +418,7 @@ class AccountsController(TransactionBase):
global_tolerance = None
for item in self.get("entries"):
if item.fields.get(item_ref_dn):
if item.get(item_ref_dn):
ref_amt = flt(frappe.db.get_value(ref_dt + " Item",
item.fields[item_ref_dn], based_on), self.precision(based_on, item))
if not ref_amt:
@ -429,7 +428,7 @@ class AccountsController(TransactionBase):
already_billed = frappe.db.sql("""select sum(%s) from `tab%s`
where %s=%s and docstatus=1 and parent != %s""" %
(based_on, self.tname, item_ref_dn, '%s', '%s'),
(item.fields[item_ref_dn], self.doc.name))[0][0]
(item.fields[item_ref_dn], self.name))[0][0]
total_billed_amt = flt(flt(already_billed) + flt(item.fields[based_on]),
self.precision(based_on, item))
@ -455,7 +454,7 @@ class AccountsController(TransactionBase):
def get_company_default(self, fieldname):
from erpnext.accounts.utils import get_company_default
return get_company_default(self.doc.company, fieldname)
return get_company_default(self.company, fieldname)
def get_stock_items(self):
stock_items = []
@ -471,7 +470,7 @@ class AccountsController(TransactionBase):
@property
def company_abbr(self):
if not hasattr(self, "_abbr"):
self._abbr = frappe.db.get_value("Company", self.doc.company, "abbr")
self._abbr = frappe.db.get_value("Company", self.company, "abbr")
return self._abbr

View File

@ -17,9 +17,9 @@ class BuyingController(StockController):
def validate(self):
super(BuyingController, self).validate()
if self.doc.supplier and not self.doc.supplier_name:
self.doc.supplier_name = frappe.db.get_value("Supplier",
self.doc.supplier, "supplier_name")
if self.supplier and not self.supplier_name:
self.supplier_name = frappe.db.get_value("Supplier",
self.supplier, "supplier_name")
self.is_item_table_empty()
self.validate_stock_or_nonstock_items()
self.validate_warehouse()
@ -31,19 +31,19 @@ class BuyingController(StockController):
self.set_price_list_currency("Buying")
# set contact and address details for supplier, if they are not mentioned
if self.doc.supplier:
self.doc.update_if_missing(get_party_details(self.doc.supplier, party_type="Supplier"))
if self.supplier:
self.update_if_missing(get_party_details(self.supplier, party_type="Supplier"))
self.set_missing_item_details()
if self.doc.fields.get("__islocal"):
if self.get("__islocal"):
self.set_taxes("other_charges", "taxes_and_charges")
def set_supplier_from_item_default(self):
if self.meta.get_field("supplier") and not self.doc.supplier:
if self.meta.get_field("supplier") and not self.supplier:
for d in self.doclist.get({"doctype": self.tname}):
supplier = frappe.db.get_value("Item", d.item_code, "default_supplier")
if supplier:
self.doc.supplier = supplier
self.supplier = supplier
break
def validate_warehouse(self):
@ -53,7 +53,7 @@ class BuyingController(StockController):
self.doclist.get({"doctype": self.tname}) if d.warehouse]))
for w in warehouses:
validate_warehouse_company(w, self.doc.company)
validate_warehouse_company(w, self.company)
def validate_stock_or_nonstock_items(self):
if not self.get_stock_items():
@ -65,12 +65,12 @@ class BuyingController(StockController):
def set_total_in_words(self):
from frappe.utils import money_in_words
company_currency = get_company_currency(self.doc.company)
company_currency = get_company_currency(self.company)
if self.meta.get_field("in_words"):
self.doc.in_words = money_in_words(self.doc.grand_total, company_currency)
self.in_words = money_in_words(self.grand_total, company_currency)
if self.meta.get_field("in_words_import"):
self.doc.in_words_import = money_in_words(self.doc.grand_total_import,
self.doc.currency)
self.in_words_import = money_in_words(self.grand_total_import,
self.currency)
def calculate_taxes_and_totals(self):
self.other_fname = "other_charges"
@ -97,54 +97,54 @@ class BuyingController(StockController):
def calculate_net_total(self):
self.doc.net_total = self.doc.net_total_import = 0.0
self.net_total = self.net_total_import = 0.0
for item in self.item_doclist:
self.doc.net_total += item.base_amount
self.doc.net_total_import += item.amount
self.net_total += item.base_amount
self.net_total_import += item.amount
self.round_floats_in(self.doc, ["net_total", "net_total_import"])
def calculate_totals(self):
self.doc.grand_total = flt(self.tax_doclist[-1].total if self.tax_doclist
else self.doc.net_total, self.precision("grand_total"))
self.doc.grand_total_import = flt(self.doc.grand_total / self.doc.conversion_rate,
self.grand_total = flt(self.tax_doclist[-1].total if self.tax_doclist
else self.net_total, self.precision("grand_total"))
self.grand_total_import = flt(self.grand_total / self.conversion_rate,
self.precision("grand_total_import"))
self.doc.total_tax = flt(self.doc.grand_total - self.doc.net_total,
self.total_tax = flt(self.grand_total - self.net_total,
self.precision("total_tax"))
if self.meta.get_field("rounded_total"):
self.doc.rounded_total = _round(self.doc.grand_total)
self.rounded_total = _round(self.grand_total)
if self.meta.get_field("rounded_total_import"):
self.doc.rounded_total_import = _round(self.doc.grand_total_import)
self.rounded_total_import = _round(self.grand_total_import)
if self.meta.get_field("other_charges_added"):
self.doc.other_charges_added = flt(sum([flt(d.tax_amount) for d in self.tax_doclist
self.other_charges_added = flt(sum([flt(d.tax_amount) for d in self.tax_doclist
if d.add_deduct_tax=="Add" and d.category in ["Valuation and Total", "Total"]]),
self.precision("other_charges_added"))
if self.meta.get_field("other_charges_deducted"):
self.doc.other_charges_deducted = flt(sum([flt(d.tax_amount) for d in self.tax_doclist
self.other_charges_deducted = flt(sum([flt(d.tax_amount) for d in self.tax_doclist
if d.add_deduct_tax=="Deduct" and d.category in ["Valuation and Total", "Total"]]),
self.precision("other_charges_deducted"))
if self.meta.get_field("other_charges_added_import"):
self.doc.other_charges_added_import = flt(self.doc.other_charges_added /
self.doc.conversion_rate, self.precision("other_charges_added_import"))
self.other_charges_added_import = flt(self.other_charges_added /
self.conversion_rate, self.precision("other_charges_added_import"))
if self.meta.get_field("other_charges_deducted_import"):
self.doc.other_charges_deducted_import = flt(self.doc.other_charges_deducted /
self.doc.conversion_rate, self.precision("other_charges_deducted_import"))
self.other_charges_deducted_import = flt(self.other_charges_deducted /
self.conversion_rate, self.precision("other_charges_deducted_import"))
def calculate_outstanding_amount(self):
if self.doc.doctype == "Purchase Invoice" and self.doc.docstatus == 0:
self.doc.total_advance = flt(self.doc.total_advance,
if self.doctype == "Purchase Invoice" and self.docstatus == 0:
self.total_advance = flt(self.total_advance,
self.precision("total_advance"))
self.doc.total_amount_to_pay = flt(self.doc.grand_total - flt(self.doc.write_off_amount,
self.total_amount_to_pay = flt(self.grand_total - flt(self.write_off_amount,
self.precision("write_off_amount")), self.precision("total_amount_to_pay"))
self.doc.outstanding_amount = flt(self.doc.total_amount_to_pay - self.doc.total_advance,
self.outstanding_amount = flt(self.total_amount_to_pay - self.total_advance,
self.precision("outstanding_amount"))
def _cleanup(self):
@ -208,18 +208,18 @@ class BuyingController(StockController):
item.valuation_rate = 0.0
def validate_for_subcontracting(self):
if not self.doc.is_subcontracted and self.sub_contracted_items:
if not self.is_subcontracted and self.sub_contracted_items:
frappe.msgprint(_("""Please enter whether %s is made for subcontracting or purchasing,
in 'Is Subcontracted' field""" % self.doc.doctype), raise_exception=1)
in 'Is Subcontracted' field""" % self.doctype), raise_exception=1)
if self.doc.doctype == "Purchase Receipt" and self.doc.is_subcontracted=="Yes" \
and not self.doc.supplier_warehouse:
if self.doctype == "Purchase Receipt" and self.is_subcontracted=="Yes" \
and not self.supplier_warehouse:
frappe.msgprint(_("Supplier Warehouse mandatory subcontracted purchase receipt"),
raise_exception=1)
def update_raw_materials_supplied(self, raw_material_table):
self.set(raw_material_table, [])
if self.doc.is_subcontracted=="Yes":
if self.is_subcontracted=="Yes":
for item in self.get(self.fname):
if item.item_code in self.sub_contracted_items:
self.add_bom_items(item, raw_material_table)
@ -230,7 +230,7 @@ class BuyingController(StockController):
for item in bom_items:
required_qty = flt(item.qty_consumed_per_unit) * flt(d.qty) * flt(d.conversion_factor)
rm_doclist = {
"doctype": self.doc.doctype + " Item Supplied",
"doctype": self.doctype + " Item Supplied",
"reference_name": d.name,
"bom_detail_no": item.name,
"main_item_code": d.item_code,
@ -241,7 +241,7 @@ class BuyingController(StockController):
"rate": item.rate,
"amount": required_qty * flt(item.rate)
}
if self.doc.doctype == "Purchase Receipt":
if self.doctype == "Purchase Receipt":
rm_doclist.update({
"consumed_qty": required_qty,
"description": item.description,
@ -251,7 +251,7 @@ class BuyingController(StockController):
raw_materials_cost += required_qty * flt(item.rate)
if self.doc.doctype == "Purchase Receipt":
if self.doctype == "Purchase Receipt":
d.rm_supp_cost = raw_materials_cost
def get_items_from_default_bom(self, item_code):

View File

@ -28,27 +28,27 @@ class SellingController(StockController):
# set contact and address details for customer, if they are not mentioned
self.set_missing_lead_customer_details()
self.set_price_list_and_item_details()
if self.doc.fields.get("__islocal"):
if self.get("__islocal"):
self.set_taxes("other_charges", "taxes_and_charges")
def set_missing_lead_customer_details(self):
if self.doc.customer:
if self.customer:
from erpnext.accounts.party import _get_party_details
self.doc.update_if_missing(_get_party_details(self.doc.customer,
self.update_if_missing(_get_party_details(self.customer,
ignore_permissions=self.bean.ignore_permissions))
elif self.doc.lead:
elif self.lead:
from erpnext.selling.doctype.lead.lead import get_lead_details
self.doc.update_if_missing(get_lead_details(self.doc.lead))
self.update_if_missing(get_lead_details(self.lead))
def set_price_list_and_item_details(self):
self.set_price_list_currency("Selling")
self.set_missing_item_details()
def apply_shipping_rule(self):
if self.doc.shipping_rule:
shipping_rule = frappe.bean("Shipping Rule", self.doc.shipping_rule)
value = self.doc.net_total
if self.shipping_rule:
shipping_rule = frappe.bean("Shipping Rule", self.shipping_rule)
value = self.net_total
# TODO
# shipping rule calculation based on item's net weight
@ -62,25 +62,25 @@ class SellingController(StockController):
self.append("other_charges", {
"doctype": "Sales Taxes and Charges",
"charge_type": "Actual",
"account_head": shipping_rule.doc.account,
"cost_center": shipping_rule.doc.cost_center,
"description": shipping_rule.doc.label,
"account_head": shipping_rule.account,
"cost_center": shipping_rule.cost_center,
"description": shipping_rule.label,
"rate": shipping_amount
})
def set_total_in_words(self):
from frappe.utils import money_in_words
company_currency = get_company_currency(self.doc.company)
company_currency = get_company_currency(self.company)
disable_rounded_total = cint(frappe.db.get_value("Global Defaults", None,
"disable_rounded_total"))
if self.meta.get_field("in_words"):
self.doc.in_words = money_in_words(disable_rounded_total and
self.doc.grand_total or self.doc.rounded_total, company_currency)
self.in_words = money_in_words(disable_rounded_total and
self.grand_total or self.rounded_total, company_currency)
if self.meta.get_field("in_words_export"):
self.doc.in_words_export = money_in_words(disable_rounded_total and
self.doc.grand_total_export or self.doc.rounded_total_export, self.doc.currency)
self.in_words_export = money_in_words(disable_rounded_total and
self.grand_total_export or self.rounded_total_export, self.currency)
def calculate_taxes_and_totals(self):
self.other_fname = "other_charges"
@ -112,7 +112,7 @@ class SellingController(StockController):
cumulated_tax_fraction += tax.tax_fraction_for_current_item
if cumulated_tax_fraction and not self.discount_amount_applied:
item.base_amount = flt((item.amount * self.doc.conversion_rate) /
item.base_amount = flt((item.amount * self.conversion_rate) /
(1 + cumulated_tax_fraction), self.precision("base_amount", item))
item.base_rate = flt(item.base_amount / item.qty, self.precision("base_rate", item))
@ -166,38 +166,38 @@ class SellingController(StockController):
self._set_in_company_currency(item, "amount", "base_amount")
def calculate_net_total(self):
self.doc.net_total = self.doc.net_total_export = 0.0
self.net_total = self.net_total_export = 0.0
for item in self.item_doclist:
self.doc.net_total += item.base_amount
self.doc.net_total_export += item.amount
self.net_total += item.base_amount
self.net_total_export += item.amount
self.round_floats_in(self.doc, ["net_total", "net_total_export"])
def calculate_totals(self):
self.doc.grand_total = flt(self.tax_doclist and \
self.tax_doclist[-1].total or self.doc.net_total, self.precision("grand_total"))
self.doc.grand_total_export = flt(self.doc.grand_total / self.doc.conversion_rate,
self.grand_total = flt(self.tax_doclist and \
self.tax_doclist[-1].total or self.net_total, self.precision("grand_total"))
self.grand_total_export = flt(self.grand_total / self.conversion_rate,
self.precision("grand_total_export"))
self.doc.other_charges_total = flt(self.doc.grand_total - self.doc.net_total,
self.other_charges_total = flt(self.grand_total - self.net_total,
self.precision("other_charges_total"))
self.doc.other_charges_total_export = flt(self.doc.grand_total_export -
self.doc.net_total_export + flt(self.doc.discount_amount),
self.other_charges_total_export = flt(self.grand_total_export -
self.net_total_export + flt(self.discount_amount),
self.precision("other_charges_total_export"))
self.doc.rounded_total = _round(self.doc.grand_total)
self.doc.rounded_total_export = _round(self.doc.grand_total_export)
self.rounded_total = _round(self.grand_total)
self.rounded_total_export = _round(self.grand_total_export)
def apply_discount_amount(self):
if self.doc.discount_amount:
if self.discount_amount:
grand_total_for_discount_amount = self.get_grand_total_for_discount_amount()
if grand_total_for_discount_amount:
# calculate item amount after Discount Amount
for item in self.item_doclist:
distributed_amount = flt(self.doc.discount_amount) * item.base_amount / grand_total_for_discount_amount
distributed_amount = flt(self.discount_amount) * item.base_amount / grand_total_for_discount_amount
item.base_amount = flt(item.base_amount - distributed_amount, self.precision("base_amount", item))
self.discount_amount_applied = True
@ -214,7 +214,7 @@ class SellingController(StockController):
flt(tax.rate) / 100
actual_taxes_dict.setdefault(tax.idx, actual_tax_amount)
grand_total_for_discount_amount = flt(self.doc.grand_total - sum(actual_taxes_dict.values()),
grand_total_for_discount_amount = flt(self.grand_total - sum(actual_taxes_dict.values()),
self.precision("grand_total"))
return grand_total_for_discount_amount
@ -222,21 +222,21 @@ class SellingController(StockController):
# NOTE:
# write_off_amount is only for POS Invoice
# total_advance is only for non POS Invoice
if self.doc.doctype == "Sales Invoice" and self.doc.docstatus == 0:
if self.doctype == "Sales Invoice" and self.docstatus == 0:
self.round_floats_in(self.doc, ["grand_total", "total_advance", "write_off_amount",
"paid_amount"])
total_amount_to_pay = self.doc.grand_total - self.doc.write_off_amount
self.doc.outstanding_amount = flt(total_amount_to_pay - self.doc.total_advance \
- self.doc.paid_amount, self.precision("outstanding_amount"))
total_amount_to_pay = self.grand_total - self.write_off_amount
self.outstanding_amount = flt(total_amount_to_pay - self.total_advance \
- self.paid_amount, self.precision("outstanding_amount"))
def calculate_commission(self):
if self.meta.get_field("commission_rate"):
self.round_floats_in(self.doc, ["net_total", "commission_rate"])
if self.doc.commission_rate > 100.0:
if self.commission_rate > 100.0:
msgprint(_(self.meta.get_label("commission_rate")) + " " +
_("cannot be greater than 100"), raise_exception=True)
self.doc.total_commission = flt(self.doc.net_total * self.doc.commission_rate / 100.0,
self.total_commission = flt(self.net_total * self.commission_rate / 100.0,
self.precision("total_commission"))
def calculate_contribution(self):
@ -246,7 +246,7 @@ class SellingController(StockController):
self.round_floats_in(sales_person)
sales_person.allocated_amount = flt(
self.doc.net_total * sales_person.allocated_percentage / 100.0,
self.net_total * sales_person.allocated_percentage / 100.0,
self.precision("allocated_amount", sales_person))
total += sales_person.allocated_percentage
@ -258,15 +258,15 @@ class SellingController(StockController):
def validate_order_type(self):
valid_types = ["Sales", "Maintenance", "Shopping Cart"]
if not self.doc.order_type:
self.doc.order_type = "Sales"
elif self.doc.order_type not in valid_types:
if not self.order_type:
self.order_type = "Sales"
elif self.order_type not in valid_types:
msgprint(_(self.meta.get_label("order_type")) + " " +
_("must be one of") + ": " + comma_or(valid_types), raise_exception=True)
def check_credit(self, grand_total):
customer_account = frappe.db.get_value("Account", {"company": self.doc.company,
"master_name": self.doc.customer}, "name")
customer_account = frappe.db.get_value("Account", {"company": self.company,
"master_name": self.customer}, "name")
if customer_account:
total_outstanding = frappe.db.sql("""select
sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
@ -291,7 +291,7 @@ class SellingController(StockController):
reserved_warehouse = ""
reserved_qty_for_main_item = 0
if self.doc.doctype == "Sales Order":
if self.doctype == "Sales Order":
if (frappe.db.get_value("Item", d.item_code, "is_stock_item") == 'Yes' or
self.has_sales_bom(d.item_code)) and not d.warehouse:
frappe.throw(_("Please enter Reserved Warehouse for item ") +
@ -300,11 +300,11 @@ class SellingController(StockController):
if flt(d.qty) > flt(d.delivered_qty):
reserved_qty_for_main_item = flt(d.qty) - flt(d.delivered_qty)
if self.doc.doctype == "Delivery Note" and d.against_sales_order:
if self.doctype == "Delivery Note" and d.against_sales_order:
# if SO qty is 10 and there is tolerance of 20%, then it will allow DN of 12.
# But in this case reserved qty should only be reduced by 10 and not 12
already_delivered_qty = self.get_already_delivered_qty(self.doc.name,
already_delivered_qty = self.get_already_delivered_qty(self.name,
d.against_sales_order, d.prevdoc_detail_docname)
so_qty, reserved_warehouse = self.get_so_qty_and_warehouse(d.prevdoc_detail_docname)
@ -362,10 +362,10 @@ class SellingController(StockController):
def check_stop_sales_order(self, ref_fieldname):
for d in self.get(self.fname):
if d.fields.get(ref_fieldname):
if d.get(ref_fieldname):
status = frappe.db.get_value("Sales Order", d.fields[ref_fieldname], "status")
if status == "Stopped":
frappe.throw(self.doc.doctype +
frappe.throw(self.doctype +
_(" can not be created/modified against stopped Sales Order ") +
d.fields[ref_fieldname])

View File

@ -25,27 +25,27 @@ status_map = {
],
"Opportunity": [
["Draft", None],
["Submitted", "eval:self.doc.docstatus==1"],
["Lost", "eval:self.doc.status=='Lost'"],
["Submitted", "eval:self.docstatus==1"],
["Lost", "eval:self.status=='Lost'"],
["Quotation", "has_quotation"],
["Replied", "communication_sent"],
["Cancelled", "eval:self.doc.docstatus==2"],
["Cancelled", "eval:self.docstatus==2"],
["Open", "communication_received"],
],
"Quotation": [
["Draft", None],
["Submitted", "eval:self.doc.docstatus==1"],
["Lost", "eval:self.doc.status=='Lost'"],
["Submitted", "eval:self.docstatus==1"],
["Lost", "eval:self.status=='Lost'"],
["Ordered", "has_sales_order"],
["Replied", "communication_sent"],
["Cancelled", "eval:self.doc.docstatus==2"],
["Cancelled", "eval:self.docstatus==2"],
["Open", "communication_received"],
],
"Sales Order": [
["Draft", None],
["Submitted", "eval:self.doc.docstatus==1"],
["Stopped", "eval:self.doc.status=='Stopped'"],
["Cancelled", "eval:self.doc.docstatus==2"],
["Submitted", "eval:self.docstatus==1"],
["Stopped", "eval:self.status=='Stopped'"],
["Cancelled", "eval:self.docstatus==2"],
],
"Support Ticket": [
["Replied", "communication_sent"],
@ -66,26 +66,26 @@ class StatusUpdater(DocListController):
self.validate_qty()
def set_status(self, update=False):
if self.doc.get("__islocal"):
if self.get("__islocal"):
return
if self.doc.doctype in status_map:
sl = status_map[self.doc.doctype][:]
if self.doctype in status_map:
sl = status_map[self.doctype][:]
sl.reverse()
for s in sl:
if not s[1]:
self.doc.status = s[0]
self.status = s[0]
break
elif s[1].startswith("eval:"):
if eval(s[1][5:]):
self.doc.status = s[0]
self.status = s[0]
break
elif getattr(self, s[1])():
self.doc.status = s[0]
self.status = s[0]
break
if update:
frappe.db.set_value(self.doc.doctype, self.doc.name, "status", self.doc.status)
frappe.db.set_value(self.doctype, self.name, "status", self.status)
def on_communication(self):
self.communication_set = True
@ -114,7 +114,7 @@ class StatusUpdater(DocListController):
for args in self.status_updater:
# get unique transactions to update
for d in self.doclist:
if d.doctype == args['source_dt'] and d.fields.get(args["join_field"]):
if d.doctype == args['source_dt'] and d.get(args["join_field"]):
args['name'] = d.fields[args['join_field']]
# get all qty where qty > target_field
@ -181,10 +181,10 @@ class StatusUpdater(DocListController):
"""
for args in self.status_updater:
# condition to include current record (if submit or no if cancel)
if self.doc.docstatus == 1:
args['cond'] = ' or parent="%s"' % self.doc.name.replace('"', '\"')
if self.docstatus == 1:
args['cond'] = ' or parent="%s"' % self.name.replace('"', '\"')
else:
args['cond'] = ' and parent!="%s"' % self.doc.name.replace('"', '\"')
args['cond'] = ' and parent!="%s"' % self.name.replace('"', '\"')
args['modified_cond'] = ''
if change_modified:
@ -194,7 +194,7 @@ class StatusUpdater(DocListController):
for d in self.doclist:
if d.doctype == args['source_dt']:
# updates qty in the child table
args['detail_id'] = d.fields.get(args['join_field'])
args['detail_id'] = d.get(args['join_field'])
args['second_source_condition'] = ""
if args.get('second_source_dt') and args.get('second_source_field') \
@ -212,7 +212,7 @@ class StatusUpdater(DocListController):
where name='%(detail_id)s'""" % args)
# get unique transactions to update
for name in set([d.fields.get(args['percent_join_field']) for d in self.doclist
for name in set([d.get(args['percent_join_field']) for d in self.doclist
if d.doctype == args['source_dt']]):
if name:
args['name'] = name
@ -241,9 +241,9 @@ class StatusUpdater(DocListController):
where docstatus=1 and net_total = 0""" % ref_dt)
for item in self.get("entries"):
if item.fields.get(ref_fieldname) \
and item.fields.get(ref_fieldname) in all_zero_amount_refdoc \
and item.fields.get(ref_fieldname) not in zero_amount_refdoc:
if item.get(ref_fieldname) \
and item.get(ref_fieldname) in all_zero_amount_refdoc \
and item.get(ref_fieldname) not in zero_amount_refdoc:
zero_amount_refdoc.append(item.fields[ref_fieldname])
if zero_amount_refdoc:
@ -256,7 +256,7 @@ class StatusUpdater(DocListController):
billed_qty = flt(frappe.db.sql("""select sum(ifnull(qty, 0))
from `tab%s Item` where %s=%s and docstatus=1""" %
(self.doc.doctype, ref_fieldname, '%s'), (ref_dn))[0][0])
(self.doctype, ref_fieldname, '%s'), (ref_dn))[0][0])
per_billed = ((ref_doc_qty if billed_qty > ref_doc_qty else billed_qty)\
/ ref_doc_qty)*100

View File

@ -12,19 +12,19 @@ from erpnext.accounts.general_ledger import make_gl_entries, delete_gl_entries
class StockController(AccountsController):
def make_gl_entries(self, repost_future_gle=True):
if self.doc.docstatus == 2:
delete_gl_entries(voucher_type=self.doc.doctype, voucher_no=self.doc.name)
if self.docstatus == 2:
delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
if cint(frappe.defaults.get_global_default("auto_accounting_for_stock")):
warehouse_account = self.get_warehouse_account()
if self.doc.docstatus==1:
if self.docstatus==1:
gl_entries = self.get_gl_entries(warehouse_account)
make_gl_entries(gl_entries)
if repost_future_gle:
items, warehouse_account = self.get_items_and_warehouse_accounts(warehouse_account)
update_gl_entries_after(self.doc.posting_date, self.doc.posting_time,
update_gl_entries_after(self.posting_date, self.posting_time,
warehouse_account, items)
def get_gl_entries(self, warehouse_account=None, default_expense_account=None,
@ -49,7 +49,7 @@ class StockController(AccountsController):
"account": warehouse_account[sle.warehouse],
"against": detail.expense_account,
"cost_center": detail.cost_center,
"remarks": self.doc.remarks or "Accounting Entry for Stock",
"remarks": self.remarks or "Accounting Entry for Stock",
"debit": flt(sle.stock_value_difference, 2)
}))
@ -58,7 +58,7 @@ class StockController(AccountsController):
"account": detail.expense_account,
"against": warehouse_account[sle.warehouse],
"cost_center": detail.cost_center,
"remarks": self.doc.remarks or "Accounting Entry for Stock",
"remarks": self.remarks or "Accounting Entry for Stock",
"credit": flt(sle.stock_value_difference, 2)
}))
elif sle.warehouse not in warehouse_with_no_account:
@ -91,10 +91,10 @@ class StockController(AccountsController):
if hasattr(self, "fname"):
item_doclist = self.doclist.get({"parentfield": self.fname})
elif self.doc.doctype == "Stock Reconciliation":
elif self.doctype == "Stock Reconciliation":
import json
item_doclist = []
data = json.loads(self.doc.reconciliation_json)
data = json.loads(self.reconciliation_json)
for row in data[data.index(self.head_row)+1:]:
d = frappe._dict(zip(["item_code", "warehouse", "qty", "valuation_rate"], row))
item_doclist.append(d)
@ -115,7 +115,7 @@ class StockController(AccountsController):
stock_ledger = {}
for sle in frappe.db.sql("""select warehouse, stock_value_difference, voucher_detail_no
from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s""",
(self.doc.doctype, self.doc.name), as_dict=True):
(self.doctype, self.name), as_dict=True):
stock_ledger.setdefault(sle.voucher_detail_no, []).append(sle)
return stock_ledger
@ -167,7 +167,7 @@ class StockController(AccountsController):
from `tabStock Ledger Entry` sle
where timestamp(sle.posting_date, sle.posting_time) >= timestamp(%s, %s) %s
order by timestamp(sle.posting_date, sle.posting_time) asc, name asc""" %
('%s', '%s', condition), (self.doc.posting_date, self.doc.posting_time),
('%s', '%s', condition), (self.posting_date, self.posting_time),
as_dict=True):
future_stock_vouchers.append([d.voucher_type, d.voucher_no])
@ -179,7 +179,7 @@ class StockController(AccountsController):
for d in frappe.db.sql("""select * from `tabGL Entry`
where posting_date >= %s and voucher_no in (%s)""" %
('%s', ', '.join(['%s']*len(future_stock_vouchers))),
tuple([self.doc.posting_date] + [d[1] for d in future_stock_vouchers]), as_dict=1):
tuple([self.posting_date] + [d[1] for d in future_stock_vouchers]), as_dict=1):
gl_entries.setdefault((d.voucher_type, d.voucher_no), []).append(d)
return gl_entries
@ -235,20 +235,20 @@ class StockController(AccountsController):
sl_dict = {
"item_code": d.item_code,
"warehouse": d.warehouse,
"posting_date": self.doc.posting_date,
"posting_time": self.doc.posting_time,
"voucher_type": self.doc.doctype,
"voucher_no": self.doc.name,
"posting_date": self.posting_date,
"posting_time": self.posting_time,
"voucher_type": self.doctype,
"voucher_no": self.name,
"voucher_detail_no": d.name,
"actual_qty": (self.doc.docstatus==1 and 1 or -1)*flt(d.stock_qty),
"actual_qty": (self.docstatus==1 and 1 or -1)*flt(d.stock_qty),
"stock_uom": d.stock_uom,
"incoming_rate": 0,
"company": self.doc.company,
"fiscal_year": self.doc.fiscal_year,
"company": self.company,
"fiscal_year": self.fiscal_year,
"batch_no": cstr(d.batch_no).strip(),
"serial_no": d.serial_no,
"project": d.project_name,
"is_cancelled": self.doc.docstatus==2 and "Yes" or "No"
"is_cancelled": self.docstatus==2 and "Yes" or "No"
}
sl_dict.update(args)
@ -260,7 +260,7 @@ class StockController(AccountsController):
def make_cancel_gl_entries(self):
if frappe.db.sql("""select name from `tabGL Entry` where voucher_type=%s
and voucher_no=%s""", (self.doc.doctype, self.doc.name)):
and voucher_no=%s""", (self.doctype, self.name)):
self.make_gl_entries()
def update_gl_entries_after(posting_date, posting_time, warehouse_account=None, for_items=None):

View File

@ -13,21 +13,21 @@ from frappe.model.document import Document
class Appraisal(Document):
def validate(self):
if not self.doc.status:
self.doc.status = "Draft"
if not self.status:
self.status = "Draft"
self.validate_dates()
self.validate_existing_appraisal()
self.calculate_total()
def get_employee_name(self):
emp_nm = frappe.db.sql("select employee_name from `tabEmployee` where name=%s", self.doc.employee)
emp_nm = frappe.db.sql("select employee_name from `tabEmployee` where name=%s", self.employee)
emp_nm= emp_nm and emp_nm[0][0] or ''
self.doc.employee_name = emp_nm
self.employee_name = emp_nm
return emp_nm
def validate_dates(self):
if getdate(self.doc.start_date) > getdate(self.doc.end_date):
if getdate(self.start_date) > getdate(self.end_date):
msgprint("End Date can not be less than Start Date")
raise Exception
@ -35,11 +35,11 @@ class Appraisal(Document):
chk = frappe.db.sql("""select name from `tabAppraisal` where employee=%s
and (status='Submitted' or status='Completed')
and ((start_date>=%s and start_date<=%s)
or (end_date>=%s and end_date<=%s))""",(self.doc.employee,self.doc.start_date,self.doc.end_date,self.doc.start_date,self.doc.end_date))
or (end_date>=%s and end_date<=%s))""",(self.employee,self.start_date,self.end_date,self.start_date,self.end_date))
if chk:
msgprint("You have already created Appraisal "\
+cstr(chk[0][0])+" in the current date range for employee "\
+cstr(self.doc.employee_name))
+cstr(self.employee_name))
raise Exception
def calculate_total(self):
@ -54,11 +54,11 @@ class Appraisal(Document):
msgprint("Total weightage assigned should be 100%. It is :" + str(total_w) + "%",
raise_exception=1)
if frappe.db.get_value("Employee", self.doc.employee, "user_id") != \
if frappe.db.get_value("Employee", self.employee, "user_id") != \
frappe.session.user and total == 0:
msgprint("Total can't be zero. You must atleast give some points!", raise_exception=1)
self.doc.total_score = total
self.total_score = total
def on_submit(self):
frappe.db.set(self.doc, 'status', 'Submitted')

View File

@ -10,11 +10,11 @@ from frappe.model.document import Document
class AppraisalTemplate(Document):
def validate(self):
self.doc.total_points = 0
self.total_points = 0
for d in self.doclist.get({"doctype":"Appraisal Template Goal"}):
self.doc.total_points += int(d.per_weightage or 0)
self.total_points += int(d.per_weightage or 0)
if int(self.doc.total_points) != 100:
if int(self.total_points) != 100:
frappe.msgprint(_("Total (sum of) points distribution for all goals should be 100.") \
+ " " + _("Not") + " " + str(self.doc.total_points),
+ " " + _("Not") + " " + str(self.total_points),
raise_exception=True)

View File

@ -15,40 +15,40 @@ class Attendance(Document):
def validate_duplicate_record(self):
res = frappe.db.sql("""select name from `tabAttendance` where employee = %s and att_date = %s
and name != %s and docstatus = 1""",
(self.doc.employee, self.doc.att_date, self.doc.name))
(self.employee, self.att_date, self.name))
if res:
msgprint(_("Attendance for the employee: ") + self.doc.employee +
msgprint(_("Attendance for the employee: ") + self.employee +
_(" already marked"), raise_exception=1)
def check_leave_record(self):
if self.doc.status == 'Present':
if self.status == 'Present':
leave = frappe.db.sql("""select name from `tabLeave Application`
where employee = %s and %s between from_date and to_date and status = 'Approved'
and docstatus = 1""", (self.doc.employee, self.doc.att_date))
and docstatus = 1""", (self.employee, self.att_date))
if leave:
frappe.msgprint(_("Employee: ") + self.doc.employee + _(" was on leave on ")
+ self.doc.att_date + _(". You can not mark his attendance as 'Present'"),
frappe.msgprint(_("Employee: ") + self.employee + _(" was on leave on ")
+ self.att_date + _(". You can not mark his attendance as 'Present'"),
raise_exception=1)
def validate_fiscal_year(self):
from erpnext.accounts.utils import validate_fiscal_year
validate_fiscal_year(self.doc.att_date, self.doc.fiscal_year)
validate_fiscal_year(self.att_date, self.fiscal_year)
def validate_att_date(self):
if getdate(self.doc.att_date) > getdate(nowdate()):
if getdate(self.att_date) > getdate(nowdate()):
msgprint(_("Attendance can not be marked for future dates"), raise_exception=1)
def validate_employee(self):
emp = frappe.db.sql("select name from `tabEmployee` where name = %s and status = 'Active'",
self.doc.employee)
self.employee)
if not emp:
msgprint(_("Employee: ") + self.doc.employee +
msgprint(_("Employee: ") + self.employee +
_(" not active or does not exists in the system"), raise_exception=1)
def validate(self):
from erpnext.utilities import validate_status
validate_status(self.doc.status, ["Present", "Absent", "Half Day"])
validate_status(self.status, ["Present", "Absent", "Half Day"])
self.validate_fiscal_year()
self.validate_att_date()
self.validate_duplicate_record()
@ -57,5 +57,5 @@ class Attendance(Document):
def on_update(self):
# this is done because sometimes user entered wrong employee name
# while uploading employee attendance
employee_name = frappe.db.get_value("Employee", self.doc.employee, "employee_name")
employee_name = frappe.db.get_value("Employee", self.employee, "employee_name")
frappe.db.set(self.doc, 'employee_name', employee_name)

View File

@ -18,28 +18,28 @@ class Employee(DocListController):
throw(_("Please setup Employee Naming System in Human Resource > HR Settings"))
else:
if naming_method=='Naming Series':
self.doc.name = make_autoname(self.doc.naming_series + '.####')
self.name = make_autoname(self.naming_series + '.####')
elif naming_method=='Employee Number':
self.doc.name = self.doc.employee_number
self.name = self.employee_number
self.doc.employee = self.doc.name
self.employee = self.name
def validate(self):
from erpnext.utilities import validate_status
validate_status(self.doc.status, ["Active", "Left"])
validate_status(self.status, ["Active", "Left"])
self.doc.employee = self.doc.name
self.employee = self.name
self.validate_date()
self.validate_email()
self.validate_status()
self.validate_employee_leave_approver()
if self.doc.user_id:
if self.user_id:
self.validate_for_enabled_user_id()
self.validate_duplicate_user_id()
def on_update(self):
if self.doc.user_id and frappe.db.get_value("User", self.doc.user_id, 'docstatus') == 0:
if self.user_id and frappe.db.get_value("User", self.user_id, 'docstatus') == 0:
self.restrict_user()
self.update_user_default()
self.update_user()
@ -49,17 +49,17 @@ class Employee(DocListController):
def restrict_user(self):
"""restrict to this employee for user"""
self.add_restriction_if_required("Employee", self.doc.user_id)
self.add_restriction_if_required("Employee", self.user_id)
def update_user_default(self):
frappe.db.set_default("employee_name", self.doc.employee_name, self.doc.user_id)
frappe.db.set_default("company", self.doc.company, self.doc.user_id)
frappe.db.set_default("employee_name", self.employee_name, self.user_id)
frappe.db.set_default("company", self.company, self.user_id)
def restrict_leave_approver(self):
"""restrict to this employee for leave approver"""
employee_leave_approvers = [d.leave_approver for d in self.get("employee_leave_approvers")]
if self.doc.reports_to and self.doc.reports_to not in employee_leave_approvers:
employee_leave_approvers.append(frappe.db.get_value("Employee", self.doc.reports_to, "user_id"))
if self.reports_to and self.reports_to not in employee_leave_approvers:
employee_leave_approvers.append(frappe.db.get_value("Employee", self.reports_to, "user_id"))
for user in employee_leave_approvers:
self.add_restriction_if_required("Employee", user)
@ -67,45 +67,45 @@ class Employee(DocListController):
def add_restriction_if_required(self, doctype, user):
if frappe.permissions.has_only_non_restrict_role(doctype, user) \
and self.doc.name not in get_restrictions(user).get("Employee", []):
and self.name not in get_restrictions(user).get("Employee", []):
frappe.defaults.add_default("Employee", self.doc.name, user, "Restriction")
frappe.defaults.add_default("Employee", self.name, user, "Restriction")
def update_user(self):
# add employee role if missing
if not "Employee" in frappe.db.sql_list("""select role from tabUserRole
where parent=%s""", self.doc.user_id):
where parent=%s""", self.user_id):
from frappe.utils.user import add_role
add_role(self.doc.user_id, "Employee")
add_role(self.user_id, "Employee")
user_wrapper = frappe.bean("User", self.doc.user_id)
user_wrapper = frappe.bean("User", self.user_id)
# copy details like Fullname, DOB and Image to User
if self.doc.employee_name:
employee_name = self.doc.employee_name.split(" ")
if self.employee_name:
employee_name = self.employee_name.split(" ")
if len(employee_name) >= 3:
user_wrapper.doc.last_name = " ".join(employee_name[2:])
user_wrapper.doc.middle_name = employee_name[1]
user_wrapper.last_name = " ".join(employee_name[2:])
user_wrapper.middle_name = employee_name[1]
elif len(employee_name) == 2:
user_wrapper.doc.last_name = employee_name[1]
user_wrapper.last_name = employee_name[1]
user_wrapper.doc.first_name = employee_name[0]
user_wrapper.first_name = employee_name[0]
if self.doc.date_of_birth:
user_wrapper.doc.birth_date = self.doc.date_of_birth
if self.date_of_birth:
user_wrapper.birth_date = self.date_of_birth
if self.doc.gender:
user_wrapper.doc.gender = self.doc.gender
if self.gender:
user_wrapper.gender = self.gender
if self.doc.image:
if not user_wrapper.doc.user_image == self.doc.image:
user_wrapper.doc.user_image = self.doc.image
if self.image:
if not user_wrapper.user_image == self.image:
user_wrapper.user_image = self.image
try:
frappe.doc({
"doctype": "File Data",
"file_name": self.doc.image,
"file_name": self.image,
"attached_to_doctype": "User",
"attached_to_name": self.doc.user_id
"attached_to_name": self.user_id
}).insert()
except frappe.DuplicateEntryError, e:
# already exists
@ -114,51 +114,51 @@ class Employee(DocListController):
user_wrapper.save()
def validate_date(self):
if self.doc.date_of_birth and self.doc.date_of_joining and getdate(self.doc.date_of_birth) >= getdate(self.doc.date_of_joining):
if self.date_of_birth and self.date_of_joining and getdate(self.date_of_birth) >= getdate(self.date_of_joining):
throw(_("Date of Joining must be greater than Date of Birth"))
elif self.doc.scheduled_confirmation_date and self.doc.date_of_joining and (getdate(self.doc.scheduled_confirmation_date) < getdate(self.doc.date_of_joining)):
elif self.scheduled_confirmation_date and self.date_of_joining and (getdate(self.scheduled_confirmation_date) < getdate(self.date_of_joining)):
throw(_("Scheduled Confirmation Date must be greater than Date of Joining"))
elif self.doc.final_confirmation_date and self.doc.date_of_joining and (getdate(self.doc.final_confirmation_date) < getdate(self.doc.date_of_joining)):
elif self.final_confirmation_date and self.date_of_joining and (getdate(self.final_confirmation_date) < getdate(self.date_of_joining)):
throw(_("Final Confirmation Date must be greater than Date of Joining"))
elif self.doc.date_of_retirement and self.doc.date_of_joining and (getdate(self.doc.date_of_retirement) <= getdate(self.doc.date_of_joining)):
elif self.date_of_retirement and self.date_of_joining and (getdate(self.date_of_retirement) <= getdate(self.date_of_joining)):
throw(_("Date Of Retirement must be greater than Date of Joining"))
elif self.doc.relieving_date and self.doc.date_of_joining and (getdate(self.doc.relieving_date) <= getdate(self.doc.date_of_joining)):
elif self.relieving_date and self.date_of_joining and (getdate(self.relieving_date) <= getdate(self.date_of_joining)):
throw(_("Relieving Date must be greater than Date of Joining"))
elif self.doc.contract_end_date and self.doc.date_of_joining and (getdate(self.doc.contract_end_date)<=getdate(self.doc.date_of_joining)):
elif self.contract_end_date and self.date_of_joining and (getdate(self.contract_end_date)<=getdate(self.date_of_joining)):
throw(_("Contract End Date must be greater than Date of Joining"))
def validate_email(self):
if self.doc.company_email and not validate_email_add(self.doc.company_email):
if self.company_email and not validate_email_add(self.company_email):
throw(_("Please enter valid Company Email"))
if self.doc.personal_email and not validate_email_add(self.doc.personal_email):
if self.personal_email and not validate_email_add(self.personal_email):
throw(_("Please enter valid Personal Email"))
def validate_status(self):
if self.doc.status == 'Left' and not self.doc.relieving_date:
if self.status == 'Left' and not self.relieving_date:
throw(_("Please enter relieving date."))
def validate_for_enabled_user_id(self):
enabled = frappe.db.sql("""select name from `tabUser` where
name=%s and enabled=1""", self.doc.user_id)
name=%s and enabled=1""", self.user_id)
if not enabled:
throw("{id}: {user_id} {msg}".format(**{
"id": _("User ID"),
"user_id": self.doc.user_id,
"user_id": self.user_id,
"msg": _("is disabled.")
}))
def validate_duplicate_user_id(self):
employee = frappe.db.sql_list("""select name from `tabEmployee` where
user_id=%s and status='Active' and name!=%s""", (self.doc.user_id, self.doc.name))
user_id=%s and status='Active' and name!=%s""", (self.user_id, self.name))
if employee:
throw("{id}: {user_id} {msg}: {employee}".format(**{
"id": _("User ID"),
"user_id": self.doc.user_id,
"user_id": self.user_id,
"msg": _("is already assigned to Employee"),
"employee": employee[0]
}))
@ -173,24 +173,24 @@ class Employee(DocListController):
exc=InvalidLeaveApproverError)
def update_dob_event(self):
if self.doc.status == "Active" and self.doc.date_of_birth \
if self.status == "Active" and self.date_of_birth \
and not cint(frappe.db.get_value("HR Settings", None, "stop_birthday_reminders")):
birthday_event = frappe.db.sql("""select name from `tabEvent` where repeat_on='Every Year'
and ref_type='Employee' and ref_name=%s""", self.doc.name)
and ref_type='Employee' and ref_name=%s""", self.name)
starts_on = self.doc.date_of_birth + " 00:00:00"
ends_on = self.doc.date_of_birth + " 00:15:00"
starts_on = self.date_of_birth + " 00:00:00"
ends_on = self.date_of_birth + " 00:15:00"
if birthday_event:
event = frappe.bean("Event", birthday_event[0][0])
event.doc.starts_on = starts_on
event.doc.ends_on = ends_on
event.starts_on = starts_on
event.ends_on = ends_on
event.save()
else:
frappe.bean({
"doctype": "Event",
"subject": _("Birthday") + ": " + self.doc.employee_name,
"description": _("Happy Birthday!") + " " + self.doc.employee_name,
"subject": _("Birthday") + ": " + self.employee_name,
"description": _("Happy Birthday!") + " " + self.employee_name,
"starts_on": starts_on,
"ends_on": ends_on,
"event_type": "Public",
@ -199,11 +199,11 @@ class Employee(DocListController):
"repeat_this_event": 1,
"repeat_on": "Every Year",
"ref_type": "Employee",
"ref_name": self.doc.name
"ref_name": self.name
}).insert()
else:
frappe.db.sql("""delete from `tabEvent` where repeat_on='Every Year' and
ref_type='Employee' and ref_name=%s""", self.doc.name)
ref_type='Employee' and ref_name=%s""", self.name)
@frappe.whitelist()
def get_retirement_date(date_of_birth=None):

View File

@ -16,13 +16,13 @@ class ExpenseClaim(Document):
self.validate_exp_details()
def on_submit(self):
if self.doc.approval_status=="Draft":
if self.approval_status=="Draft":
frappe.msgprint("""Please set Approval Status to 'Approved' or \
'Rejected' before submitting""", raise_exception=1)
def validate_fiscal_year(self):
from erpnext.accounts.utils import validate_fiscal_year
validate_fiscal_year(self.doc.posting_date, self.doc.fiscal_year, "Posting Date")
validate_fiscal_year(self.posting_date, self.fiscal_year, "Posting Date")
def validate_exp_details(self):
if not self.get('expense_voucher_details'):

View File

@ -13,7 +13,7 @@ from frappe.model.document import Document
class HolidayList(Document):
def autoname(self):
self.doc.name = make_autoname(self.doc.fiscal_year + "/" + self.doc.holiday_list_name + "/.###")
self.name = make_autoname(self.fiscal_year + "/" + self.holiday_list_name + "/.###")
def validate(self):
self.update_default_holiday_list()
@ -25,20 +25,20 @@ class HolidayList(Document):
last_idx = max([cint(d.idx) for d in self.doclist.get(
{"parentfield": "holiday_list_details"})] or [0,])
for i, d in enumerate(date_list):
ch = self.doc.append('holiday_list_details', {})
ch.description = self.doc.weekly_off
ch = self.append('holiday_list_details', {})
ch.description = self.weekly_off
ch.holiday_date = d
ch.idx = last_idx + i + 1
def validate_values(self):
if not self.doc.fiscal_year:
if not self.fiscal_year:
throw(_("Please select Fiscal Year"))
if not self.doc.weekly_off:
if not self.weekly_off:
throw(_("Please select weekly off day"))
def get_fy_start_end_dates(self):
return frappe.db.sql("""select year_start_date, year_end_date
from `tabFiscal Year` where name=%s""", (self.doc.fiscal_year,))[0]
from `tabFiscal Year` where name=%s""", (self.fiscal_year,))[0]
def get_weekly_off_date_list(self, year_start_date, year_end_date):
from frappe.utils import getdate
@ -49,7 +49,7 @@ class HolidayList(Document):
import calendar
date_list = []
weekday = getattr(calendar, (self.doc.weekly_off).upper())
weekday = getattr(calendar, (self.weekly_off).upper())
reference_date = year_start_date + relativedelta.relativedelta(weekday=weekday)
while reference_date <= year_end_date:
@ -63,4 +63,4 @@ class HolidayList(Document):
def update_default_holiday_list(self):
frappe.db.sql("""update `tabHoliday List` set is_default = 0
where ifnull(is_default, 0) = 1 and fiscal_year = %s""", (self.doc.fiscal_year,))
where ifnull(is_default, 0) = 1 and fiscal_year = %s""", (self.fiscal_year,))

View File

@ -17,17 +17,17 @@ class HrSettings(Document):
from erpnext.setup.doctype.naming_series.naming_series import set_by_naming_series
set_by_naming_series("Employee", "employee_number",
self.doc.get("emp_created_by")=="Naming Series", hide_name_field=True)
self.get("emp_created_by")=="Naming Series", hide_name_field=True)
def update_birthday_reminders(self):
original_stop_birthday_reminders = cint(frappe.db.get_value("HR Settings",
None, "stop_birthday_reminders"))
# reset birthday reminders
if cint(self.doc.stop_birthday_reminders) != original_stop_birthday_reminders:
if cint(self.stop_birthday_reminders) != original_stop_birthday_reminders:
frappe.db.sql("""delete from `tabEvent` where repeat_on='Every Year' and ref_type='Employee'""")
if not self.doc.stop_birthday_reminders:
if not self.stop_birthday_reminders:
for employee in frappe.db.sql_list("""select name from `tabEmployee` where status='Active' and
ifnull(date_of_birth, '')!=''"""):
frappe.get_obj("Employee", employee).update_dob_event()

View File

@ -19,10 +19,10 @@ class JobsMailbox(POP3Mailbox):
"name")
if name:
applicant = frappe.bean("Job Applicant", name)
if applicant.doc.status!="Rejected":
applicant.doc.status = "Open"
if applicant.status!="Rejected":
applicant.status = "Open"
applicant.ignore_permissions = True
applicant.doc.save()
applicant.save()
else:
name = (mail.from_real_name and (mail.from_real_name + " - ") or "") \
+ mail.from_email
@ -40,7 +40,7 @@ class JobsMailbox(POP3Mailbox):
mail.save_attachments_in_doc(applicant.doc)
_make(content=mail.content, sender=mail.from_email, subject=mail.subject or "No Subject",
doctype="Job Applicant", name=applicant.doc.name, sent_or_received="Received")
doctype="Job Applicant", name=applicant.name, sent_or_received="Received")
def get_job_applications():
if cint(frappe.db.get_value('Jobs Email Settings', None, 'extract_emails')):

View File

@ -29,8 +29,8 @@ class LeaveAllocation(Document):
def validate_new_leaves_allocated_value(self):
"""validate that leave allocation is in multiples of 0.5"""
if flt(self.doc.new_leaves_allocated) % 0.5:
guess = round(flt(self.doc.new_leaves_allocated) * 2.0) / 2.0
if flt(self.new_leaves_allocated) % 0.5:
guess = round(flt(self.new_leaves_allocated) * 2.0) / 2.0
msgprint("""New Leaves Allocated should be a multiple of 0.5.
Perhaps you should enter %s or %s""" % (guess, guess + 0.5),
@ -40,25 +40,25 @@ class LeaveAllocation(Document):
"""check whether leave for same type is already allocated or not"""
leave_allocation = frappe.db.sql("""select name from `tabLeave Allocation`
where employee=%s and leave_type=%s and fiscal_year=%s and docstatus=1""",
(self.doc.employee, self.doc.leave_type, self.doc.fiscal_year))
(self.employee, self.leave_type, self.fiscal_year))
if leave_allocation:
msgprint("""%s is already allocated to Employee: %s for Fiscal Year: %s.
Please refere Leave Allocation: \
<a href="#Form/Leave Allocation/%s">%s</a>""" % \
(self.doc.leave_type, self.doc.employee, self.doc.fiscal_year,
(self.leave_type, self.employee, self.fiscal_year,
leave_allocation[0][0], leave_allocation[0][0]), raise_exception=1)
def validate_new_leaves_allocated(self):
"""check if Total Leaves Allocated >= Leave Applications"""
self.doc.total_leaves_allocated = flt(self.doc.carry_forwarded_leaves) + \
flt(self.doc.new_leaves_allocated)
leaves_applied = self.get_leaves_applied(self.doc.fiscal_year)
if leaves_applied > self.doc.total_leaves_allocated:
expected_new_leaves = flt(self.doc.new_leaves_allocated) + \
(leaves_applied - self.doc.total_leaves_allocated)
self.total_leaves_allocated = flt(self.carry_forwarded_leaves) + \
flt(self.new_leaves_allocated)
leaves_applied = self.get_leaves_applied(self.fiscal_year)
if leaves_applied > self.total_leaves_allocated:
expected_new_leaves = flt(self.new_leaves_allocated) + \
(leaves_applied - self.total_leaves_allocated)
msgprint("""Employee: %s has already applied for %s leaves.
Hence, New Leaves Allocated should be atleast %s""" % \
(self.doc.employee, leaves_applied, expected_new_leaves),
(self.employee, leaves_applied, expected_new_leaves),
raise_exception=1)
def get_leave_bal(self, prev_fyear):
@ -68,40 +68,40 @@ class LeaveAllocation(Document):
leaves_applied = frappe.db.sql("""select SUM(ifnull(total_leave_days, 0))
from `tabLeave Application` where employee=%s and leave_type=%s
and fiscal_year=%s and docstatus=1""",
(self.doc.employee, self.doc.leave_type, fiscal_year))
(self.employee, self.leave_type, fiscal_year))
return leaves_applied and flt(leaves_applied[0][0]) or 0
def get_leaves_allocated(self, fiscal_year):
leaves_allocated = frappe.db.sql("""select SUM(ifnull(total_leaves_allocated, 0))
from `tabLeave Allocation` where employee=%s and leave_type=%s
and fiscal_year=%s and docstatus=1 and name!=%s""",
(self.doc.employee, self.doc.leave_type, fiscal_year, self.doc.name))
(self.employee, self.leave_type, fiscal_year, self.name))
return leaves_allocated and flt(leaves_allocated[0][0]) or 0
def allow_carry_forward(self):
"""check whether carry forward is allowed or not for this leave type"""
cf = frappe.db.sql("""select is_carry_forward from `tabLeave Type` where name = %s""",
self.doc.leave_type)
self.leave_type)
cf = cf and cint(cf[0][0]) or 0
if not cf:
frappe.db.set(self.doc,'carry_forward',0)
msgprint("Sorry! You cannot carry forward %s" % (self.doc.leave_type),
msgprint("Sorry! You cannot carry forward %s" % (self.leave_type),
raise_exception=1)
def get_carry_forwarded_leaves(self):
if self.doc.carry_forward:
if self.carry_forward:
self.allow_carry_forward()
prev_fiscal_year = frappe.db.sql("""select name from `tabFiscal Year`
where year_start_date = (select date_add(year_start_date, interval -1 year)
from `tabFiscal Year` where name=%s)
order by name desc limit 1""", self.doc.fiscal_year)
order by name desc limit 1""", self.fiscal_year)
prev_fiscal_year = prev_fiscal_year and prev_fiscal_year[0][0] or ''
prev_bal = 0
if prev_fiscal_year and cint(self.doc.carry_forward) == 1:
if prev_fiscal_year and cint(self.carry_forward) == 1:
prev_bal = self.get_leave_bal(prev_fiscal_year)
ret = {
'carry_forwarded_leaves': prev_bal,
'total_leaves_allocated': flt(prev_bal) + flt(self.doc.new_leaves_allocated)
'total_leaves_allocated': flt(prev_bal) + flt(self.new_leaves_allocated)
}
return ret
@ -113,12 +113,12 @@ class LeaveAllocation(Document):
def check_for_leave_application(self):
exists = frappe.db.sql("""select name from `tabLeave Application`
where employee=%s and leave_type=%s and fiscal_year=%s and docstatus=1""",
(self.doc.employee, self.doc.leave_type, self.doc.fiscal_year))
(self.employee, self.leave_type, self.fiscal_year))
if exists:
msgprint("""Cannot cancel this Leave Allocation as \
Employee : %s has already applied for %s.
Please check Leave Application: \
<a href="#Form/Leave Application/%s">%s</a>""" % \
(self.doc.employee, self.doc.leave_type, exists[0][0], exists[0][0]))
(self.employee, self.leave_type, exists[0][0], exists[0][0]))
raise Exception

View File

@ -17,8 +17,8 @@ class LeaveApproverIdentityError(frappe.ValidationError): pass
from frappe.model.controller import DocListController
class LeaveApplication(DocListController):
def setup(self):
if frappe.db.exists(self.doc.doctype, self.doc.name):
self.previous_doc = frappe.doc(self.doc.doctype, self.doc.name)
if frappe.db.exists(self.doctype, self.name):
self.previous_doc = frappe.doc(self.doctype, self.name)
else:
self.previous_doc = None
@ -32,22 +32,22 @@ class LeaveApplication(DocListController):
self.validate_leave_approver()
def on_update(self):
if (not self.previous_doc and self.doc.leave_approver) or (self.previous_doc and \
self.doc.status == "Open" and self.previous_doc.leave_approver != self.doc.leave_approver):
if (not self.previous_doc and self.leave_approver) or (self.previous_doc and \
self.status == "Open" and self.previous_doc.leave_approver != self.leave_approver):
# notify leave approver about creation
self.notify_leave_approver()
elif self.previous_doc and \
self.previous_doc.status == "Open" and self.doc.status == "Rejected":
self.previous_doc.status == "Open" and self.status == "Rejected":
# notify employee about rejection
self.notify_employee(self.doc.status)
self.notify_employee(self.status)
def on_submit(self):
if self.doc.status != "Approved":
if self.status != "Approved":
frappe.msgprint("""Only Leave Applications with status 'Approved' can be Submitted.""",
raise_exception=True)
# notify leave applier about approval
self.notify_employee(self.doc.status)
self.notify_employee(self.status)
def on_cancel(self):
# notify leave applier about cancellation
@ -56,8 +56,8 @@ class LeaveApplication(DocListController):
def show_block_day_warning(self):
from erpnext.hr.doctype.leave_block_list.leave_block_list import get_applicable_block_dates
block_dates = get_applicable_block_dates(self.doc.from_date, self.doc.to_date,
self.doc.employee, self.doc.company, all_lists=True)
block_dates = get_applicable_block_dates(self.from_date, self.to_date,
self.employee, self.company, all_lists=True)
if block_dates:
frappe.msgprint(_("Warning: Leave application contains following block dates") + ":")
@ -67,30 +67,30 @@ class LeaveApplication(DocListController):
def validate_block_days(self):
from erpnext.hr.doctype.leave_block_list.leave_block_list import get_applicable_block_dates
block_dates = get_applicable_block_dates(self.doc.from_date, self.doc.to_date,
self.doc.employee, self.doc.company)
block_dates = get_applicable_block_dates(self.from_date, self.to_date,
self.employee, self.company)
if block_dates:
if self.doc.status == "Approved":
if self.status == "Approved":
frappe.msgprint(_("Cannot approve leave as you are not authorized to approve leaves on Block Dates."))
raise LeaveDayBlockedError
def get_holidays(self):
tot_hol = frappe.db.sql("""select count(*) from `tabHoliday` h1, `tabHoliday List` h2, `tabEmployee` e1
where e1.name = %s and h1.parent = h2.name and e1.holiday_list = h2.name
and h1.holiday_date between %s and %s""", (self.doc.employee, self.doc.from_date, self.doc.to_date))
and h1.holiday_date between %s and %s""", (self.employee, self.from_date, self.to_date))
if not tot_hol:
tot_hol = frappe.db.sql("""select count(*) from `tabHoliday` h1, `tabHoliday List` h2
where h1.parent = h2.name and h1.holiday_date between %s and %s
and ifnull(h2.is_default,0) = 1 and h2.fiscal_year = %s""",
(self.doc.from_date, self.doc.to_date, self.doc.fiscal_year))
(self.from_date, self.to_date, self.fiscal_year))
return tot_hol and flt(tot_hol[0][0]) or 0
def get_total_leave_days(self):
"""Calculates total leave days based on input and holidays"""
ret = {'total_leave_days' : 0.5}
if not self.doc.half_day:
tot_days = date_diff(self.doc.to_date, self.doc.from_date) + 1
if not self.half_day:
tot_days = date_diff(self.to_date, self.from_date) + 1
holidays = self.get_holidays()
ret = {
'total_leave_days' : flt(tot_days)-flt(holidays)
@ -98,33 +98,33 @@ class LeaveApplication(DocListController):
return ret
def validate_to_date(self):
if self.doc.from_date and self.doc.to_date and \
(getdate(self.doc.to_date) < getdate(self.doc.from_date)):
if self.from_date and self.to_date and \
(getdate(self.to_date) < getdate(self.from_date)):
msgprint("To date cannot be before from date")
raise Exception
def validate_balance_leaves(self):
if self.doc.from_date and self.doc.to_date:
self.doc.total_leave_days = self.get_total_leave_days()["total_leave_days"]
if self.from_date and self.to_date:
self.total_leave_days = self.get_total_leave_days()["total_leave_days"]
if self.doc.total_leave_days == 0:
if self.total_leave_days == 0:
msgprint(_("The day(s) on which you are applying for leave coincide with holiday(s). You need not apply for leave."),
raise_exception=1)
if not is_lwp(self.doc.leave_type):
self.doc.leave_balance = get_leave_balance(self.doc.employee,
self.doc.leave_type, self.doc.fiscal_year)["leave_balance"]
if not is_lwp(self.leave_type):
self.leave_balance = get_leave_balance(self.employee,
self.leave_type, self.fiscal_year)["leave_balance"]
if self.doc.status != "Rejected" \
and self.doc.leave_balance - self.doc.total_leave_days < 0:
if self.status != "Rejected" \
and self.leave_balance - self.total_leave_days < 0:
#check if this leave type allow the remaining balance to be in negative. If yes then warn the user and continue to save else warn the user and don't save.
msgprint("There is not enough leave balance for Leave Type: %s" % \
(self.doc.leave_type,),
raise_exception=not(frappe.db.get_value("Leave Type", self.doc.leave_type,"allow_negative") or None))
(self.leave_type,),
raise_exception=not(frappe.db.get_value("Leave Type", self.leave_type,"allow_negative") or None))
def validate_leave_overlap(self):
if not self.doc.name:
self.doc.name = "New Leave Application"
if not self.name:
self.name = "New Leave Application"
for d in frappe.db.sql("""select name, leave_type, posting_date,
from_date, to_date
@ -136,45 +136,45 @@ class LeaveApplication(DocListController):
and (from_date between %(from_date)s and %(to_date)s
or to_date between %(from_date)s and %(to_date)s
or %(from_date)s between from_date and to_date)
and name != %(name)s""", self.doc.fields, as_dict = 1):
and name != %(name)s""", self.fields, as_dict = 1):
msgprint("Employee : %s has already applied for %s between %s and %s on %s. Please refer Leave Application : <a href=\"#Form/Leave Application/%s\">%s</a>" % (self.doc.employee, cstr(d['leave_type']), formatdate(d['from_date']), formatdate(d['to_date']), formatdate(d['posting_date']), d['name'], d['name']), raise_exception = OverlapError)
msgprint("Employee : %s has already applied for %s between %s and %s on %s. Please refer Leave Application : <a href=\"#Form/Leave Application/%s\">%s</a>" % (self.employee, cstr(d['leave_type']), formatdate(d['from_date']), formatdate(d['to_date']), formatdate(d['posting_date']), d['name'], d['name']), raise_exception = OverlapError)
def validate_max_days(self):
max_days = frappe.db.get_value("Leave Type", self.doc.leave_type, "max_days_allowed")
if max_days and self.doc.total_leave_days > max_days:
max_days = frappe.db.get_value("Leave Type", self.leave_type, "max_days_allowed")
if max_days and self.total_leave_days > max_days:
frappe.throw("Sorry ! You cannot apply for %s for more than %s days" %
(self.doc.leave_type, max_days))
(self.leave_type, max_days))
def validate_leave_approver(self):
employee = frappe.bean("Employee", self.doc.employee)
employee = frappe.bean("Employee", self.employee)
leave_approvers = [l.leave_approver for l in
employee.get("employee_leave_approvers")]
if len(leave_approvers) and self.doc.leave_approver not in leave_approvers:
msgprint(("[" + _("For Employee") + ' "' + self.doc.employee + '"] '
if len(leave_approvers) and self.leave_approver not in leave_approvers:
msgprint(("[" + _("For Employee") + ' "' + self.employee + '"] '
+ _("Leave Approver can be one of") + ": "
+ comma_or(leave_approvers)), raise_exception=InvalidLeaveApproverError)
elif self.doc.leave_approver and not frappe.db.sql("""select name from `tabUserRole`
where parent=%s and role='Leave Approver'""", self.doc.leave_approver):
msgprint(get_fullname(self.doc.leave_approver) + ": " \
elif self.leave_approver and not frappe.db.sql("""select name from `tabUserRole`
where parent=%s and role='Leave Approver'""", self.leave_approver):
msgprint(get_fullname(self.leave_approver) + ": " \
+ _("does not have role 'Leave Approver'"), raise_exception=InvalidLeaveApproverError)
elif self.doc.docstatus==1 and len(leave_approvers) and self.doc.leave_approver != frappe.session.user:
elif self.docstatus==1 and len(leave_approvers) and self.leave_approver != frappe.session.user:
msgprint(_("Only the selected Leave Approver can submit this Leave Application"),
raise_exception=LeaveApproverIdentityError)
def notify_employee(self, status):
employee = frappe.doc("Employee", self.doc.employee)
employee = frappe.doc("Employee", self.employee)
if not employee.user_id:
return
def _get_message(url=False):
if url:
name = get_url_to_form(self.doc.doctype, self.doc.name)
name = get_url_to_form(self.doctype, self.name)
else:
name = self.doc.name
name = self.name
return (_("Leave Application") + ": %s - %s") % (name, _(status))
@ -186,21 +186,21 @@ class LeaveApplication(DocListController):
})
def notify_leave_approver(self):
employee = frappe.doc("Employee", self.doc.employee)
employee = frappe.doc("Employee", self.employee)
def _get_message(url=False):
name = self.doc.name
name = self.name
employee_name = cstr(employee.employee_name)
if url:
name = get_url_to_form(self.doc.doctype, self.doc.name)
employee_name = get_url_to_form("Employee", self.doc.employee, label=employee_name)
name = get_url_to_form(self.doctype, self.name)
employee_name = get_url_to_form("Employee", self.employee, label=employee_name)
return (_("New Leave Application") + ": %s - " + _("Employee") + ": %s") % (name, employee_name)
self.notify({
# for post in messages
"message": _get_message(url=True),
"message_to": self.doc.leave_approver,
"message_to": self.leave_approver,
# for email
"subject": _get_message()
@ -210,7 +210,7 @@ class LeaveApplication(DocListController):
args = frappe._dict(args)
from frappe.core.page.messages.messages import post
post({"txt": args.message, "contact": args.message_to, "subject": args.subject,
"notify": cint(self.doc.follow_via_email)})
"notify": cint(self.follow_via_email)})
@frappe.whitelist()
def get_leave_balance(employee, leave_type, fiscal_year):

View File

@ -33,8 +33,8 @@ class TestLeaveApplication(unittest.TestCase):
def get_application(self, doclist):
application = frappe.bean(copy=doclist)
application.doc.from_date = "2013-01-01"
application.doc.to_date = "2013-01-05"
application.from_date = "2013-01-01"
application.to_date = "2013-01-05"
return application
def test_block_list(self):
@ -48,7 +48,7 @@ class TestLeaveApplication(unittest.TestCase):
application = self.get_application(test_records[1])
application.insert()
application.doc.status = "Approved"
application.status = "Approved"
self.assertRaises(LeaveDayBlockedError, application.submit)
frappe.set_user("test1@example.com")
@ -69,11 +69,11 @@ class TestLeaveApplication(unittest.TestCase):
frappe.set_user("test@example.com")
application = self.get_application(test_records[1])
application.doc.leave_approver = "test2@example.com"
application.leave_approver = "test2@example.com"
application.insert()
application = self.get_application(test_records[1])
application.doc.leave_approver = "test2@example.com"
application.leave_approver = "test2@example.com"
self.assertRaises(OverlapError, application.insert)
def test_global_block_list(self):
@ -84,7 +84,7 @@ class TestLeaveApplication(unittest.TestCase):
add_role("test@example.com", "Leave Approver")
application = self.get_application(test_records[3])
application.doc.leave_approver = "test@example.com"
application.leave_approver = "test@example.com"
frappe.db.set_value("Leave Block List", "_Test Leave Block List",
"applies_to_all_departments", 1)
@ -95,7 +95,7 @@ class TestLeaveApplication(unittest.TestCase):
application.insert()
frappe.set_user("test@example.com")
application.doc.status = "Approved"
application.status = "Approved"
self.assertRaises(LeaveDayBlockedError, application.submit)
frappe.db.set_value("Leave Block List", "_Test Leave Block List",
@ -120,14 +120,14 @@ class TestLeaveApplication(unittest.TestCase):
# create leave application as Employee
frappe.set_user("test@example.com")
application = self.get_application(test_records[1])
application.doc.leave_approver = "test1@example.com"
application.leave_approver = "test1@example.com"
application.insert()
# submit leave application by Leave Approver
frappe.set_user("test1@example.com")
application.doc.status = "Approved"
application.status = "Approved"
application.submit()
self.assertEqual(frappe.db.get_value("Leave Application", application.doc.name,
self.assertEqual(frappe.db.get_value("Leave Application", application.name,
"docstatus"), 1)
def _test_leave_approval_invalid_leave_approver_insert(self):
@ -143,7 +143,7 @@ class TestLeaveApplication(unittest.TestCase):
application = self.get_application(test_records[1])
frappe.set_user("test@example.com")
application.doc.leave_approver = "test1@example.com"
application.leave_approver = "test1@example.com"
self.assertRaises(InvalidLeaveApproverError, application.insert)
frappe.db.sql("""delete from `tabEmployee Leave Approver` where parent=%s""",
@ -157,10 +157,10 @@ class TestLeaveApplication(unittest.TestCase):
# but submit as invalid leave approver - should raise exception
frappe.set_user("test@example.com")
application = self.get_application(test_records[1])
application.doc.leave_approver = "test2@example.com"
application.leave_approver = "test2@example.com"
application.insert()
frappe.set_user("test1@example.com")
application.doc.status = "Approved"
application.status = "Approved"
from erpnext.hr.doctype.leave_application.leave_application import LeaveApproverIdentityError
self.assertRaises(LeaveApproverIdentityError, application.submit)
@ -177,14 +177,14 @@ class TestLeaveApplication(unittest.TestCase):
frappe.set_user("test@example.com")
application = self.get_application(test_records[1])
application.doc.leave_approver = "test2@example.com"
application.leave_approver = "test2@example.com"
application.insert()
# change to valid leave approver and try to submit leave application
frappe.set_user("test2@example.com")
application.doc.status = "Approved"
application.status = "Approved"
application.submit()
self.assertEqual(frappe.db.get_value("Leave Application", application.doc.name,
self.assertEqual(frappe.db.get_value("Leave Application", application.name,
"docstatus"), 1)
frappe.db.sql("""delete from `tabEmployee Leave Approver` where parent=%s""",

View File

@ -16,7 +16,7 @@ class LeaveBlockList(Document):
dates = []
for d in self.doclist.get({"doctype":"Leave Block List Date"}):
# validate fiscal year
validate_fiscal_year(d.block_date, self.doc.year, _("Block Date"))
validate_fiscal_year(d.block_date, self.year, _("Block Date"))
# date is not repeated
if d.block_date in dates:

View File

@ -20,7 +20,7 @@ class LeaveControlPanel(Document):
def get_employees(self):
lst1 = [[self.doc.employee_type,"employment_type"],[self.doc.branch,"branch"],[self.doc.designation,"designation"],[self.doc.department, "department"],[self.doc.grade,"grade"]]
lst1 = [[self.employee_type,"employment_type"],[self.branch,"branch"],[self.designation,"designation"],[self.department, "department"],[self.grade,"grade"]]
condition = "where "
flag = 0
for l in lst1:
@ -54,11 +54,11 @@ class LeaveControlPanel(Document):
la.set("__islocal", 1)
la.employee = cstr(d[0])
la.employee_name = frappe.db.get_value('Employee',cstr(d[0]),'employee_name')
la.leave_type = self.doc.leave_type
la.fiscal_year = self.doc.fiscal_year
la.leave_type = self.leave_type
la.fiscal_year = self.fiscal_year
la.posting_date = nowdate()
la.carry_forward = cint(self.doc.carry_forward)
la.new_leaves_allocated = flt(self.doc.no_of_days)
la.carry_forward = cint(self.carry_forward)
la.new_leaves_allocated = flt(self.no_of_days)
la.docstatus = 1
la.save()
leave_allocated_for.append(d[0])

View File

@ -35,14 +35,14 @@ class SalaryManager(Document):
cond = ''
for f in ['company', 'branch', 'department', 'designation', 'grade']:
if self.doc.fields.get(f):
cond += " and t1." + f + " = '" + self.doc.fields.get(f).replace("'", "\'") + "'"
if self.get(f):
cond += " and t1." + f + " = '" + self.get(f).replace("'", "\'") + "'"
return cond
def get_joining_releiving_condition(self):
m = self.get_month_details(self.doc.fiscal_year, self.doc.month)
m = self.get_month_details(self.fiscal_year, self.month)
cond = """
and ifnull(t1.date_of_joining, '0000-00-00') <= '%(month_end_date)s'
and ifnull(t1.relieving_date, '2199-12-31') >= '%(month_start_date)s'
@ -52,7 +52,7 @@ class SalaryManager(Document):
def check_mandatory(self):
for f in ['company', 'month', 'fiscal_year']:
if not self.doc.fields[f]:
if not self.fields[f]:
msgprint("Please select %s to proceed" % f, raise_exception=1)
@ -85,17 +85,17 @@ class SalaryManager(Document):
for emp in emp_list:
if not frappe.db.sql("""select name from `tabSalary Slip`
where docstatus!= 2 and employee = %s and month = %s and fiscal_year = %s and company = %s
""", (emp[0], self.doc.month, self.doc.fiscal_year, self.doc.company)):
""", (emp[0], self.month, self.fiscal_year, self.company)):
ss = frappe.bean({
"doctype": "Salary Slip",
"fiscal_year": self.doc.fiscal_year,
"fiscal_year": self.fiscal_year,
"employee": emp[0],
"month": self.doc.month,
"email_check": self.doc.send_email,
"company": self.doc.company,
"month": self.month,
"email_check": self.send_email,
"company": self.company,
})
ss.insert()
ss_list.append(ss.doc.name)
ss_list.append(ss.name)
return self.create_log(ss_list)
@ -117,7 +117,7 @@ class SalaryManager(Document):
ss_list = frappe.db.sql("""
select t1.name from `tabSalary Slip` t1
where t1.docstatus = 0 and month = %s and fiscal_year = %s %s
""" % ('%s', '%s', cond), (self.doc.month, self.doc.fiscal_year))
""" % ('%s', '%s', cond), (self.month, self.fiscal_year))
return ss_list
@ -130,8 +130,8 @@ class SalaryManager(Document):
for ss in ss_list:
ss_obj = get_obj("Salary Slip",ss[0],with_children=1)
try:
frappe.db.set(ss_obj.doc, 'email_check', cint(self.doc.send_mail))
if cint(self.doc.send_email) == 1:
frappe.db.set(ss_obj.doc, 'email_check', cint(self.send_mail))
if cint(self.send_email) == 1:
ss_obj.send_mail_funct()
frappe.db.set(ss_obj.doc, 'docstatus', 1)
@ -152,7 +152,7 @@ class SalaryManager(Document):
submitted_ss = list(set(all_ss) - set(not_submitted_ss))
if submitted_ss:
mail_sent_msg = self.doc.send_email and " (Mail has been sent to the employee)" or ""
mail_sent_msg = self.send_email and " (Mail has been sent to the employee)" or ""
log = """
<b>Submitted Salary Slips%s:</b>\
<br><br> %s <br><br>
@ -179,7 +179,7 @@ class SalaryManager(Document):
tot = frappe.db.sql("""
select sum(rounded_total) from `tabSalary Slip` t1
where t1.docstatus = 1 and month = %s and fiscal_year = %s %s
""" % ('%s', '%s', cond), (self.doc.month, self.doc.fiscal_year))
""" % ('%s', '%s', cond), (self.month, self.fiscal_year))
return flt(tot[0][0])
@ -189,7 +189,7 @@ class SalaryManager(Document):
get default bank account,default salary acount from company
"""
amt = self.get_total_salary()
default_bank_account = frappe.db.get_value("Company", self.doc.company,
default_bank_account = frappe.db.get_value("Company", self.company,
"default_bank_account")
if not default_bank_account:
msgprint("You can set Default Bank Account in Company master.")

View File

@ -16,10 +16,10 @@ from erpnext.utilities.transaction_base import TransactionBase
class SalarySlip(TransactionBase):
def autoname(self):
self.doc.name = make_autoname('Sal Slip/' +self.doc.employee + '/.#####')
self.name = make_autoname('Sal Slip/' +self.employee + '/.#####')
def get_emp_and_leave_details(self):
if self.doc.employee:
if self.employee:
self.get_leave_details()
struct = self.check_sal_struct()
if struct:
@ -27,10 +27,10 @@ class SalarySlip(TransactionBase):
def check_sal_struct(self):
struct = frappe.db.sql("""select name from `tabSalary Structure`
where employee=%s and is_active = 'Yes'""", self.doc.employee)
where employee=%s and is_active = 'Yes'""", self.employee)
if not struct:
msgprint("Please create Salary Structure for employee '%s'" % self.doc.employee)
self.doc.employee = None
msgprint("Please create Salary Structure for employee '%s'" % self.employee)
self.employee = None
return struct and struct[0][0] or ''
def pull_sal_struct(self, struct):
@ -38,21 +38,21 @@ class SalarySlip(TransactionBase):
self.doclist = get_mapped_doclist(struct, self.doclist)
def pull_emp_details(self):
emp = frappe.db.get_value("Employee", self.doc.employee,
emp = frappe.db.get_value("Employee", self.employee,
["bank_name", "bank_ac_no", "esic_card_no", "pf_number"], as_dict=1)
if emp:
self.doc.bank_name = emp.bank_name
self.doc.bank_account_no = emp.bank_ac_no
self.doc.esic_no = emp.esic_card_no
self.doc.pf_no = emp.pf_number
self.bank_name = emp.bank_name
self.bank_account_no = emp.bank_ac_no
self.esic_no = emp.esic_card_no
self.pf_no = emp.pf_number
def get_leave_details(self, lwp=None):
if not self.doc.fiscal_year:
self.doc.fiscal_year = frappe.get_default("fiscal_year")
if not self.doc.month:
self.doc.month = "%02d" % getdate(nowdate()).month
if not self.fiscal_year:
self.fiscal_year = frappe.get_default("fiscal_year")
if not self.month:
self.month = "%02d" % getdate(nowdate()).month
m = get_obj('Salary Manager').get_month_details(self.doc.fiscal_year, self.doc.month)
m = get_obj('Salary Manager').get_month_details(self.fiscal_year, self.month)
holidays = self.get_holidays_for_employee(m)
if not cint(frappe.db.get_value("HR Settings", "HR Settings",
@ -64,16 +64,16 @@ class SalarySlip(TransactionBase):
if not lwp:
lwp = self.calculate_lwp(holidays, m)
self.doc.total_days_in_month = m['month_days']
self.doc.leave_without_pay = lwp
self.total_days_in_month = m['month_days']
self.leave_without_pay = lwp
payment_days = flt(self.get_payment_days(m)) - flt(lwp)
self.doc.payment_days = payment_days > 0 and payment_days or 0
self.payment_days = payment_days > 0 and payment_days or 0
def get_payment_days(self, m):
payment_days = m['month_days']
emp = frappe.db.sql("select date_of_joining, relieving_date from `tabEmployee` \
where name = %s", self.doc.employee, as_dict=1)[0]
where name = %s", self.employee, as_dict=1)[0]
if emp['relieving_date']:
if getdate(emp['relieving_date']) > m['month_start_date'] and \
@ -98,13 +98,13 @@ class SalarySlip(TransactionBase):
from `tabHoliday` t1, tabEmployee t2
where t1.parent = t2.holiday_list and t2.name = %s
and t1.holiday_date between %s and %s""",
(self.doc.employee, m['month_start_date'], m['month_end_date']))
(self.employee, m['month_start_date'], m['month_end_date']))
if not holidays:
holidays = frappe.db.sql("""select t1.holiday_date
from `tabHoliday` t1, `tabHoliday List` t2
where t1.parent = t2.name and ifnull(t2.is_default, 0) = 1
and t2.fiscal_year = %s
and t1.holiday_date between %s and %s""", (self.doc.fiscal_year,
and t1.holiday_date between %s and %s""", (self.fiscal_year,
m['month_start_date'], m['month_end_date']))
holidays = [cstr(i[0]) for i in holidays]
return holidays
@ -122,7 +122,7 @@ class SalarySlip(TransactionBase):
and t1.docstatus = 1
and t1.employee = %s
and %s between from_date and to_date
""", (self.doc.employee, dt))
""", (self.employee, dt))
if leave:
lwp = cint(leave[0][1]) and (lwp + 0.5) or (lwp + 1)
return lwp
@ -131,11 +131,11 @@ class SalarySlip(TransactionBase):
ret_exist = frappe.db.sql("""select name from `tabSalary Slip`
where month = %s and fiscal_year = %s and docstatus != 2
and employee = %s and name != %s""",
(self.doc.month, self.doc.fiscal_year, self.doc.employee, self.doc.name))
(self.month, self.fiscal_year, self.employee, self.name))
if ret_exist:
self.doc.employee = ''
self.employee = ''
msgprint("Salary Slip of employee '%s' already created for this month"
% self.doc.employee, raise_exception=1)
% self.employee, raise_exception=1)
def validate(self):
@ -146,59 +146,59 @@ class SalarySlip(TransactionBase):
len(self.get("deduction_details"))):
self.get_emp_and_leave_details()
else:
self.get_leave_details(self.doc.leave_without_pay)
self.get_leave_details(self.leave_without_pay)
if not self.doc.net_pay:
if not self.net_pay:
self.calculate_net_pay()
company_currency = get_company_currency(self.doc.company)
self.doc.total_in_words = money_in_words(self.doc.rounded_total, company_currency)
company_currency = get_company_currency(self.company)
self.total_in_words = money_in_words(self.rounded_total, company_currency)
def calculate_earning_total(self):
self.doc.gross_pay = flt(self.doc.arrear_amount) + flt(self.doc.leave_encashment_amount)
self.gross_pay = flt(self.arrear_amount) + flt(self.leave_encashment_amount)
for d in self.get("earning_details"):
if cint(d.e_depends_on_lwp) == 1:
d.e_modified_amount = _round(flt(d.e_amount) * flt(self.doc.payment_days)
/ cint(self.doc.total_days_in_month), 2)
elif not self.doc.payment_days:
d.e_modified_amount = _round(flt(d.e_amount) * flt(self.payment_days)
/ cint(self.total_days_in_month), 2)
elif not self.payment_days:
d.e_modified_amount = 0
else:
d.e_modified_amount = d.e_amount
self.doc.gross_pay += flt(d.e_modified_amount)
self.gross_pay += flt(d.e_modified_amount)
def calculate_ded_total(self):
self.doc.total_deduction = 0
self.total_deduction = 0
for d in self.get('deduction_details'):
if cint(d.d_depends_on_lwp) == 1:
d.d_modified_amount = _round(flt(d.d_amount) * flt(self.doc.payment_days)
/ cint(self.doc.total_days_in_month), 2)
elif not self.doc.payment_days:
d.d_modified_amount = _round(flt(d.d_amount) * flt(self.payment_days)
/ cint(self.total_days_in_month), 2)
elif not self.payment_days:
d.d_modified_amount = 0
else:
d.d_modified_amount = d.d_amount
self.doc.total_deduction += flt(d.d_modified_amount)
self.total_deduction += flt(d.d_modified_amount)
def calculate_net_pay(self):
self.calculate_earning_total()
self.calculate_ded_total()
self.doc.net_pay = flt(self.doc.gross_pay) - flt(self.doc.total_deduction)
self.doc.rounded_total = _round(self.doc.net_pay)
self.net_pay = flt(self.gross_pay) - flt(self.total_deduction)
self.rounded_total = _round(self.net_pay)
def on_submit(self):
if(self.doc.email_check == 1):
if(self.email_check == 1):
self.send_mail_funct()
def send_mail_funct(self):
from frappe.utils.email_lib import sendmail
receiver = frappe.db.get_value("Employee", self.doc.employee, "company_email")
receiver = frappe.db.get_value("Employee", self.employee, "company_email")
if receiver:
subj = 'Salary Slip - ' + cstr(self.doc.month) +'/'+cstr(self.doc.fiscal_year)
subj = 'Salary Slip - ' + cstr(self.month) +'/'+cstr(self.fiscal_year)
earn_ret=frappe.db.sql("""select e_type, e_modified_amount from `tabSalary Slip Earning`
where parent = %s""", self.doc.name)
where parent = %s""", self.name)
ded_ret=frappe.db.sql("""select d_type, d_modified_amount from `tabSalary Slip Deduction`
where parent = %s""", self.doc.name)
where parent = %s""", self.name)
earn_table = ''
ded_table = ''
@ -288,13 +288,13 @@ class SalarySlip(TransactionBase):
<td width='25%%'><b>Net Pay(in words) : </td>
<td colspan = '3' width = '50%%'>%s</b></td>
</tr>
</table></div>''' % (cstr(letter_head), cstr(self.doc.employee),
cstr(self.doc.employee_name), cstr(self.doc.month), cstr(self.doc.fiscal_year),
cstr(self.doc.department), cstr(self.doc.branch), cstr(self.doc.designation),
cstr(self.doc.grade), cstr(self.doc.bank_account_no), cstr(self.doc.bank_name),
cstr(self.doc.arrear_amount), cstr(self.doc.payment_days), earn_table, ded_table,
cstr(flt(self.doc.gross_pay)), cstr(flt(self.doc.total_deduction)),
cstr(flt(self.doc.net_pay)), cstr(self.doc.total_in_words))
</table></div>''' % (cstr(letter_head), cstr(self.employee),
cstr(self.employee_name), cstr(self.month), cstr(self.fiscal_year),
cstr(self.department), cstr(self.branch), cstr(self.designation),
cstr(self.grade), cstr(self.bank_account_no), cstr(self.bank_name),
cstr(self.arrear_amount), cstr(self.payment_days), earn_table, ded_table,
cstr(flt(self.gross_pay)), cstr(flt(self.total_deduction)),
cstr(flt(self.net_pay)), cstr(self.total_in_words))
sendmail([receiver], subject=subj, msg = msg)
else:

View File

@ -11,7 +11,7 @@ class TestSalarySlip(unittest.TestCase):
from erpnext.hr.doctype.leave_application.test_leave_application import test_records as leave_applications
la = frappe.bean(copy=leave_applications[4])
la.insert()
la.doc.status = "Approved"
la.status = "Approved"
la.submit()
def tearDown(self):
@ -21,26 +21,26 @@ class TestSalarySlip(unittest.TestCase):
frappe.db.set_value("HR Settings", "HR Settings", "include_holidays_in_total_working_days", 1)
ss = frappe.bean(copy=test_records[0])
ss.insert()
self.assertEquals(ss.doc.total_days_in_month, 31)
self.assertEquals(ss.doc.payment_days, 30)
self.assertEquals(ss.total_days_in_month, 31)
self.assertEquals(ss.payment_days, 30)
self.assertEquals(ss.doclist[1].e_modified_amount, 14516.13)
self.assertEquals(ss.doclist[2].e_modified_amount, 500)
self.assertEquals(ss.doclist[3].d_modified_amount, 100)
self.assertEquals(ss.doclist[4].d_modified_amount, 48.39)
self.assertEquals(ss.doc.gross_pay, 15016.13)
self.assertEquals(ss.doc.net_pay, 14867.74)
self.assertEquals(ss.gross_pay, 15016.13)
self.assertEquals(ss.net_pay, 14867.74)
def test_salary_slip_with_holidays_excluded(self):
ss = frappe.bean(copy=test_records[0])
ss.insert()
self.assertEquals(ss.doc.total_days_in_month, 30)
self.assertEquals(ss.doc.payment_days, 29)
self.assertEquals(ss.total_days_in_month, 30)
self.assertEquals(ss.payment_days, 29)
self.assertEquals(ss.doclist[1].e_modified_amount, 14500)
self.assertEquals(ss.doclist[2].e_modified_amount, 500)
self.assertEquals(ss.doclist[3].d_modified_amount, 100)
self.assertEquals(ss.doclist[4].d_modified_amount, 48.33)
self.assertEquals(ss.doc.gross_pay, 15000)
self.assertEquals(ss.doc.net_pay, 14851.67)
self.assertEquals(ss.gross_pay, 15000)
self.assertEquals(ss.net_pay, 14851.67)
test_dependencies = ["Leave Application"]

View File

@ -13,12 +13,12 @@ from frappe.model.document import Document
class SalaryStructure(Document):
def autoname(self):
self.doc.name = make_autoname(self.doc.employee + '/.SST' + '/.#####')
self.name = make_autoname(self.employee + '/.SST' + '/.#####')
def get_employee_details(self):
ret = {}
det = frappe.db.sql("""select employee_name, branch, designation, department, grade
from `tabEmployee` where name = %s""", self.doc.employee)
from `tabEmployee` where name = %s""", self.employee)
if det:
ret = {
'employee_name': cstr(det[0][0]),
@ -26,7 +26,7 @@ class SalaryStructure(Document):
'designation': cstr(det[0][2]),
'department': cstr(det[0][3]),
'grade': cstr(det[0][4]),
'backup_employee': cstr(self.doc.employee)
'backup_employee': cstr(self.employee)
}
return ret
@ -42,7 +42,7 @@ class SalaryStructure(Document):
def make_table(self, doct_name, tab_fname, tab_name):
list1 = frappe.db.sql("select name from `tab%s` where docstatus != 2" % doct_name)
for li in list1:
child = self.doc.append(tab_fname, {})
child = self.append(tab_fname, {})
if(tab_fname == 'earning_details'):
child.e_type = cstr(li[0])
child.modified_value = 0
@ -56,13 +56,13 @@ class SalaryStructure(Document):
def check_existing(self):
ret = frappe.db.sql("""select name from `tabSalary Structure` where is_active = 'Yes'
and employee = %s and name!=%s""", (self.doc.employee,self.doc.name))
if ret and self.doc.is_active=='Yes':
and employee = %s and name!=%s""", (self.employee,self.name))
if ret and self.is_active=='Yes':
msgprint(_("""Another Salary Structure '%s' is active for employee '%s'. Please make its status 'Inactive' to proceed.""") %
(cstr(ret), self.doc.employee), raise_exception=1)
(cstr(ret), self.employee), raise_exception=1)
def validate_amount(self):
if flt(self.doc.net_pay) < 0:
if flt(self.net_pay) < 0:
msgprint(_("Net pay can not be negative"), raise_exception=1)
def validate(self):

View File

@ -16,13 +16,13 @@ class Bom(Document):
def autoname(self):
last_name = frappe.db.sql("""select max(name) from `tabBOM`
where name like "BOM/%s/%%" """ % cstr(self.doc.item).replace('"', '\\"'))
where name like "BOM/%s/%%" """ % cstr(self.item).replace('"', '\\"'))
if last_name:
idx = cint(cstr(last_name[0][0]).split('/')[-1].split('-')[0]) + 1
else:
idx = 1
self.doc.name = 'BOM/' + self.doc.item + ('/%.3i' % idx)
self.name = 'BOM/' + self.item + ('/%.3i' % idx)
def validate(self):
self.clear_operations()
@ -39,7 +39,7 @@ class Bom(Document):
def on_update(self):
self.check_recursion()
self.update_exploded_items()
self.doc.save()
self.save()
def on_submit(self):
self.manage_default_bom()
@ -65,7 +65,7 @@ class Bom(Document):
return item
def validate_rm_item(self, item):
if item[0]['name'] == self.doc.item:
if item[0]['name'] == self.item:
msgprint("Item_code: %s in materials tab cannot be same as FG Item",
item[0]['name'], raise_exception=1)
@ -78,8 +78,8 @@ class Bom(Document):
"qty": item.qty})
for r in ret:
if not item.fields.get(r):
item.fields[r] = ret[r]
if not item.get(r):
item.set(r, ret[r])
def get_bom_material_detail(self, args=None):
""" Get raw material details like uom, desc and rate"""
@ -111,16 +111,16 @@ class Bom(Document):
if arg['bom_no']:
rate = self.get_bom_unitcost(arg['bom_no'])
elif arg and (arg['is_purchase_item'] == 'Yes' or arg['is_sub_contracted_item'] == 'Yes'):
if self.doc.rm_cost_as_per == 'Valuation Rate':
if self.rm_cost_as_per == 'Valuation Rate':
rate = self.get_valuation_rate(arg)
elif self.doc.rm_cost_as_per == 'Last Purchase Rate':
elif self.rm_cost_as_per == 'Last Purchase Rate':
rate = arg['last_purchase_rate']
elif self.doc.rm_cost_as_per == "Price List":
if not self.doc.buying_price_list:
elif self.rm_cost_as_per == "Price List":
if not self.buying_price_list:
frappe.throw(_("Please select Price List"))
rate = frappe.db.get_value("Item Price", {"price_list": self.doc.buying_price_list,
rate = frappe.db.get_value("Item Price", {"price_list": self.buying_price_list,
"item_code": arg["item_code"]}, "price_list_rate") or 0
elif self.doc.rm_cost_as_per == 'Standard Rate':
elif self.rm_cost_as_per == 'Standard Rate':
rate = arg['standard_rate']
return rate
@ -133,9 +133,9 @@ class Bom(Document):
'qty': d.qty
})["rate"]
if self.doc.docstatus == 0:
if self.docstatus == 0:
frappe.bean(self.doclist).save()
elif self.doc.docstatus == 1:
elif self.docstatus == 1:
self.calculate_cost()
self.update_exploded_items()
frappe.bean(self.doclist).update_after_submit()
@ -151,8 +151,8 @@ class Bom(Document):
as on costing date
"""
from erpnext.stock.utils import get_incoming_rate
dt = self.doc.costing_date or nowdate()
time = self.doc.costing_date == nowdate() and now().split()[1] or '23:59'
dt = self.costing_date or nowdate()
time = self.costing_date == nowdate() and now().split()[1] or '23:59'
warehouse = frappe.db.sql("select warehouse from `tabBin` where item_code = %s", args['item_code'])
rate = []
for wh in warehouse:
@ -172,38 +172,38 @@ class Bom(Document):
""" Uncheck others if current one is selected as default,
update default bom in item master
"""
if self.doc.is_default and self.doc.is_active:
if self.is_default and self.is_active:
from frappe.model.utils import set_default
set_default(self.doc, "item")
frappe.db.set_value("Item", self.doc.item, "default_bom", self.doc.name)
frappe.db.set_value("Item", self.item, "default_bom", self.name)
else:
if not self.doc.is_active:
if not self.is_active:
frappe.db.set(self.doc, "is_default", 0)
frappe.db.sql("update `tabItem` set default_bom = null where name = %s and default_bom = %s",
(self.doc.item, self.doc.name))
(self.item, self.name))
def clear_operations(self):
if not self.doc.with_operations:
if not self.with_operations:
self.set('bom_operations', [])
for d in self.get("bom_materials"):
d.operation_no = None
def validate_main_item(self):
""" Validate main FG item"""
item = self.get_item_det(self.doc.item)
item = self.get_item_det(self.item)
if not item:
msgprint("Item %s does not exists in the system or expired." %
self.doc.item, raise_exception = 1)
self.item, raise_exception = 1)
elif item[0]['is_manufactured_item'] != 'Yes' \
and item[0]['is_sub_contracted_item'] != 'Yes':
msgprint("""As Item: %s is not a manufactured / sub-contracted item, \
you can not make BOM for it""" % self.doc.item, raise_exception = 1)
you can not make BOM for it""" % self.item, raise_exception = 1)
else:
ret = frappe.db.get_value("Item", self.doc.item, ["description", "stock_uom"])
self.doc.description = ret[0]
self.doc.uom = ret[1]
ret = frappe.db.get_value("Item", self.item, ["description", "stock_uom"])
self.description = ret[0]
self.uom = ret[1]
def validate_operations(self):
""" Check duplicate operation no"""
@ -221,7 +221,7 @@ class Bom(Document):
check_list = []
for m in self.get('bom_materials'):
# check if operation no not in op table
if self.doc.with_operations and cstr(m.operation_no) not in self.op:
if self.with_operations and cstr(m.operation_no) not in self.op:
msgprint("""Operation no: %s against item: %s at row no: %s \
is not present at Operations table""" %
(m.operation_no, m.item_code, m.idx), raise_exception = 1)
@ -267,15 +267,15 @@ class Bom(Document):
check_list = [['parent', 'bom_no', 'parent'], ['bom_no', 'parent', 'child']]
for d in check_list:
bom_list, count = [self.doc.name], 0
bom_list, count = [self.name], 0
while (len(bom_list) > count ):
boms = frappe.db.sql(" select %s from `tabBOM Item` where %s = %s " %
(d[0], d[1], '%s'), cstr(bom_list[count]))
count = count + 1
for b in boms:
if b[0] == self.doc.name:
if b[0] == self.name:
msgprint("""Recursion Occured => '%s' cannot be '%s' of '%s'.
""" % (cstr(b[0]), cstr(d[2]), self.doc.name), raise_exception = 1)
""" % (cstr(b[0]), cstr(d[2]), self.name), raise_exception = 1)
if b[0]:
bom_list.append(b[0])
@ -293,8 +293,8 @@ class Bom(Document):
where parent = %s and ifnull(bom_no, '') != ''""", bom_no)]
count = 0
if self.doc.name not in bom_list:
bom_list.append(self.doc.name)
if self.name not in bom_list:
bom_list.append(self.name)
while(count < len(bom_list)):
for child_bom in _get_children(bom_list[count]):
@ -308,7 +308,7 @@ class Bom(Document):
"""Calculate bom totals"""
self.calculate_op_cost()
self.calculate_rm_cost()
self.doc.total_cost = self.doc.raw_material_cost + self.doc.operating_cost
self.total_cost = self.raw_material_cost + self.operating_cost
def calculate_op_cost(self):
"""Update workstation rate and calculates totals"""
@ -319,7 +319,7 @@ class Bom(Document):
if d.hour_rate and d.time_in_mins:
d.operating_cost = flt(d.hour_rate) * flt(d.time_in_mins) / 60.0
total_op_cost += flt(d.operating_cost)
self.doc.operating_cost = total_op_cost
self.operating_cost = total_op_cost
def calculate_rm_cost(self):
"""Fetch RM rate as per today's valuation rate and calculate totals"""
@ -328,10 +328,10 @@ class Bom(Document):
if d.bom_no:
d.rate = self.get_bom_unitcost(d.bom_no)
d.amount = flt(d.rate) * flt(d.qty)
d.qty_consumed_per_unit = flt(d.qty) / flt(self.doc.quantity)
d.qty_consumed_per_unit = flt(d.qty) / flt(self.quantity)
total_rm_cost += d.amount
self.doc.raw_material_cost = total_rm_cost
self.raw_material_cost = total_rm_cost
def update_exploded_items(self):
""" Update Flat BOM, following will be correct data"""
@ -379,23 +379,23 @@ class Bom(Document):
"Add items to Flat BOM table"
self.set('flat_bom_details', [])
for d in self.cur_exploded_items:
ch = self.doc.append('flat_bom_details', {})
ch = self.append('flat_bom_details', {})
for i in self.cur_exploded_items[d].keys():
ch.fields[i] = self.cur_exploded_items[d][i]
ch.set(i, self.cur_exploded_items[d][i])
ch.amount = flt(ch.qty) * flt(ch.rate)
ch.qty_consumed_per_unit = flt(ch.qty) / flt(self.doc.quantity)
ch.docstatus = self.doc.docstatus
ch.qty_consumed_per_unit = flt(ch.qty) / flt(self.quantity)
ch.docstatus = self.docstatus
ch.save(1)
def validate_bom_links(self):
if not self.doc.is_active:
if not self.is_active:
act_pbom = frappe.db.sql("""select distinct bom_item.parent from `tabBOM Item` bom_item
where bom_item.bom_no = %s and bom_item.docstatus = 1
and exists (select * from `tabBOM` where name = bom_item.parent
and docstatus = 1 and is_active = 1)""", self.doc.name)
and docstatus = 1 and is_active = 1)""", self.name)
if act_pbom and act_pbom[0][0]:
action = self.doc.docstatus < 2 and _("deactivate") or _("cancel")
action = self.docstatus < 2 and _("deactivate") or _("cancel")
msgprint(_("Cannot ") + action + _(": It is linked to other active BOM(s)"),
raise_exception=1)

View File

@ -26,18 +26,18 @@ class BomReplaceTool(Document):
frappe.msgprint(_("BOM replaced"))
def validate_bom(self):
if cstr(self.doc.current_bom) == cstr(self.doc.new_bom):
if cstr(self.current_bom) == cstr(self.new_bom):
msgprint("Current BOM and New BOM can not be same", raise_exception=1)
def update_new_bom(self):
current_bom_unitcost = frappe.db.sql("""select total_cost/quantity
from `tabBOM` where name = %s""", self.doc.current_bom)
from `tabBOM` where name = %s""", self.current_bom)
current_bom_unitcost = current_bom_unitcost and flt(current_bom_unitcost[0][0]) or 0
frappe.db.sql("""update `tabBOM Item` set bom_no=%s,
rate=%s, amount=qty*%s where bom_no = %s and docstatus < 2""",
(self.doc.new_bom, current_bom_unitcost, current_bom_unitcost, self.doc.current_bom))
(self.new_bom, current_bom_unitcost, current_bom_unitcost, self.current_bom))
def get_parent_boms(self):
return [d[0] for d in frappe.db.sql("""select distinct parent
from `tabBOM Item` where ifnull(bom_no, '') = %s and docstatus < 2""",
self.doc.new_bom)]
self.new_bom)]

View File

@ -15,11 +15,11 @@ from frappe.model.document import Document
class ProductionOrder(Document):
def validate(self):
if self.doc.docstatus == 0:
self.doc.status = "Draft"
if self.docstatus == 0:
self.status = "Draft"
from erpnext.utilities import validate_status
validate_status(self.doc.status, ["Draft", "Submitted", "Stopped",
validate_status(self.status, ["Draft", "Submitted", "Stopped",
"In Process", "Completed", "Cancelled"])
self.validate_bom_no()
@ -30,64 +30,64 @@ class ProductionOrder(Document):
validate_uom_is_integer(self.doclist, "stock_uom", ["qty", "produced_qty"])
def validate_bom_no(self):
if self.doc.bom_no:
if self.bom_no:
bom = frappe.db.sql("""select name from `tabBOM` where name=%s and docstatus=1
and is_active=1 and item=%s"""
, (self.doc.bom_no, self.doc.production_item), as_dict =1)
, (self.bom_no, self.production_item), as_dict =1)
if not bom:
frappe.throw("""Incorrect BOM: %s entered.
May be BOM not exists or inactive or not submitted
or for some other item.""" % cstr(self.doc.bom_no))
or for some other item.""" % cstr(self.bom_no))
def validate_sales_order(self):
if self.doc.sales_order:
if self.sales_order:
so = frappe.db.sql("""select name, delivery_date from `tabSales Order`
where name=%s and docstatus = 1""", self.doc.sales_order, as_dict=1)[0]
where name=%s and docstatus = 1""", self.sales_order, as_dict=1)[0]
if not so.name:
frappe.throw("Sales Order: %s is not valid" % self.doc.sales_order)
frappe.throw("Sales Order: %s is not valid" % self.sales_order)
if not self.doc.expected_delivery_date:
self.doc.expected_delivery_date = so.delivery_date
if not self.expected_delivery_date:
self.expected_delivery_date = so.delivery_date
self.validate_production_order_against_so()
def validate_warehouse(self):
from erpnext.stock.utils import validate_warehouse_company
for w in [self.doc.fg_warehouse, self.doc.wip_warehouse]:
validate_warehouse_company(w, self.doc.company)
for w in [self.fg_warehouse, self.wip_warehouse]:
validate_warehouse_company(w, self.company)
def validate_production_order_against_so(self):
# already ordered qty
ordered_qty_against_so = frappe.db.sql("""select sum(qty) from `tabProduction Order`
where production_item = %s and sales_order = %s and docstatus < 2 and name != %s""",
(self.doc.production_item, self.doc.sales_order, self.doc.name))[0][0]
(self.production_item, self.sales_order, self.name))[0][0]
total_qty = flt(ordered_qty_against_so) + flt(self.doc.qty)
total_qty = flt(ordered_qty_against_so) + flt(self.qty)
# get qty from Sales Order Item table
so_item_qty = frappe.db.sql("""select sum(qty) from `tabSales Order Item`
where parent = %s and item_code = %s""",
(self.doc.sales_order, self.doc.production_item))[0][0]
(self.sales_order, self.production_item))[0][0]
# get qty from Packing Item table
dnpi_qty = frappe.db.sql("""select sum(qty) from `tabPacked Item`
where parent = %s and parenttype = 'Sales Order' and item_code = %s""",
(self.doc.sales_order, self.doc.production_item))[0][0]
(self.sales_order, self.production_item))[0][0]
# total qty in SO
so_qty = flt(so_item_qty) + flt(dnpi_qty)
if total_qty > so_qty:
frappe.throw(_("Total production order qty for item") + ": " +
cstr(self.doc.production_item) + _(" against sales order") + ": " +
cstr(self.doc.sales_order) + _(" will be ") + cstr(total_qty) + ", " +
cstr(self.production_item) + _(" against sales order") + ": " +
cstr(self.sales_order) + _(" will be ") + cstr(total_qty) + ", " +
_("which is greater than sales order qty ") + "(" + cstr(so_qty) + ")" +
_("Please reduce qty."), exc=OverProductionError)
def stop_unstop(self, status):
""" Called from client side on Stop/Unstop event"""
self.update_status(status)
qty = (flt(self.doc.qty)-flt(self.doc.produced_qty)) * ((status == 'Stopped') and -1 or 1)
qty = (flt(self.qty)-flt(self.produced_qty)) * ((status == 'Stopped') and -1 or 1)
self.update_planned_qty(qty)
msgprint("Production Order has been %s" % status)
@ -96,37 +96,37 @@ class ProductionOrder(Document):
if status == 'Stopped':
frappe.db.set(self.doc, 'status', cstr(status))
else:
if flt(self.doc.qty) == flt(self.doc.produced_qty):
if flt(self.qty) == flt(self.produced_qty):
frappe.db.set(self.doc, 'status', 'Completed')
if flt(self.doc.qty) > flt(self.doc.produced_qty):
if flt(self.qty) > flt(self.produced_qty):
frappe.db.set(self.doc, 'status', 'In Process')
if flt(self.doc.produced_qty) == 0:
if flt(self.produced_qty) == 0:
frappe.db.set(self.doc, 'status', 'Submitted')
def on_submit(self):
if not self.doc.wip_warehouse:
if not self.wip_warehouse:
frappe.throw(_("WIP Warehouse required before Submit"))
frappe.db.set(self.doc,'status', 'Submitted')
self.update_planned_qty(self.doc.qty)
self.update_planned_qty(self.qty)
def on_cancel(self):
# Check whether any stock entry exists against this Production Order
stock_entry = frappe.db.sql("""select name from `tabStock Entry`
where production_order = %s and docstatus = 1""", self.doc.name)
where production_order = %s and docstatus = 1""", self.name)
if stock_entry:
frappe.throw("""Submitted Stock Entry %s exists against this production order.
Hence can not be cancelled.""" % stock_entry[0][0])
frappe.db.set(self.doc,'status', 'Cancelled')
self.update_planned_qty(-self.doc.qty)
self.update_planned_qty(-self.qty)
def update_planned_qty(self, qty):
"""update planned qty in bin"""
args = {
"item_code": self.doc.production_item,
"warehouse": self.doc.fg_warehouse,
"item_code": self.production_item,
"warehouse": self.fg_warehouse,
"posting_date": nowdate(),
"planned_qty": flt(qty)
}
@ -155,18 +155,18 @@ def make_stock_entry(production_order_id, purpose):
production_order = frappe.bean("Production Order", production_order_id)
stock_entry = frappe.new_bean("Stock Entry")
stock_entry.doc.purpose = purpose
stock_entry.doc.production_order = production_order_id
stock_entry.doc.company = production_order.doc.company
stock_entry.doc.bom_no = production_order.doc.bom_no
stock_entry.doc.use_multi_level_bom = production_order.doc.use_multi_level_bom
stock_entry.doc.fg_completed_qty = flt(production_order.doc.qty) - flt(production_order.doc.produced_qty)
stock_entry.purpose = purpose
stock_entry.production_order = production_order_id
stock_entry.company = production_order.company
stock_entry.bom_no = production_order.bom_no
stock_entry.use_multi_level_bom = production_order.use_multi_level_bom
stock_entry.fg_completed_qty = flt(production_order.qty) - flt(production_order.produced_qty)
if purpose=="Material Transfer":
stock_entry.doc.to_warehouse = production_order.doc.wip_warehouse
stock_entry.to_warehouse = production_order.wip_warehouse
else:
stock_entry.doc.from_warehouse = production_order.doc.wip_warehouse
stock_entry.doc.to_warehouse = production_order.doc.fg_warehouse
stock_entry.from_warehouse = production_order.wip_warehouse
stock_entry.to_warehouse = production_order.fg_warehouse
stock_entry.run_method("get_items")
return [d.fields for d in stock_entry.doclist]

View File

@ -31,21 +31,21 @@ class TestProductionOrder(unittest.TestCase):
mr2.insert()
mr2.submit()
stock_entry = make_stock_entry(pro_bean.doc.name, "Manufacture/Repack")
stock_entry = make_stock_entry(pro_bean.name, "Manufacture/Repack")
stock_entry = frappe.bean(stock_entry)
stock_entry.doc.fiscal_year = "_Test Fiscal Year 2013"
stock_entry.doc.fg_completed_qty = 4
stock_entry.doc.posting_date = "2013-05-12"
stock_entry.doc.fiscal_year = "_Test Fiscal Year 2013"
stock_entry.fiscal_year = "_Test Fiscal Year 2013"
stock_entry.fg_completed_qty = 4
stock_entry.posting_date = "2013-05-12"
stock_entry.fiscal_year = "_Test Fiscal Year 2013"
stock_entry.run_method("get_items")
stock_entry.submit()
self.assertEqual(frappe.db.get_value("Production Order", pro_bean.doc.name,
self.assertEqual(frappe.db.get_value("Production Order", pro_bean.name,
"produced_qty"), 4)
self.assertEqual(frappe.db.get_value("Bin", {"item_code": "_Test FG Item",
"warehouse": "_Test Warehouse 1 - _TC"}, "planned_qty"), 6)
return pro_bean.doc.name
return pro_bean.name
def test_over_production(self):
from erpnext.stock.doctype.stock_entry.stock_entry import StockOverProductionError
@ -53,9 +53,9 @@ class TestProductionOrder(unittest.TestCase):
stock_entry = make_stock_entry(pro_order, "Manufacture/Repack")
stock_entry = frappe.bean(stock_entry)
stock_entry.doc.posting_date = "2013-05-12"
stock_entry.doc.fiscal_year = "_Test Fiscal Year 2013"
stock_entry.doc.fg_completed_qty = 15
stock_entry.posting_date = "2013-05-12"
stock_entry.fiscal_year = "_Test Fiscal Year 2013"
stock_entry.fg_completed_qty = 15
stock_entry.run_method("get_items")
stock_entry.insert()

View File

@ -43,21 +43,21 @@ class ProductionPlanningTool(Document):
self.set('pp_details', [])
def validate_company(self):
if not self.doc.company:
if not self.company:
frappe.throw(_("Please enter Company"))
def get_open_sales_orders(self):
""" Pull sales orders which are pending to deliver based on criteria selected"""
so_filter = item_filter = ""
if self.doc.from_date:
so_filter += ' and so.transaction_date >= "' + self.doc.from_date + '"'
if self.doc.to_date:
so_filter += ' and so.transaction_date <= "' + self.doc.to_date + '"'
if self.doc.customer:
so_filter += ' and so.customer = "' + self.doc.customer + '"'
if self.from_date:
so_filter += ' and so.transaction_date >= "' + self.from_date + '"'
if self.to_date:
so_filter += ' and so.transaction_date <= "' + self.to_date + '"'
if self.customer:
so_filter += ' and so.customer = "' + self.customer + '"'
if self.doc.fg_item:
item_filter += ' and item.name = "' + self.doc.fg_item + '"'
if self.fg_item:
item_filter += ' and item.name = "' + self.fg_item + '"'
open_so = frappe.db.sql("""
select distinct so.name, so.transaction_date, so.customer, so.grand_total
@ -74,7 +74,7 @@ class ProductionPlanningTool(Document):
and exists (select name from `tabItem` item where item.name=pi.item_code
and (ifnull(item.is_pro_applicable, 'No') = 'Yes'
or ifnull(item.is_sub_contracted_item, 'No') = 'Yes') %s)))
""" % ('%s', so_filter, item_filter, item_filter), self.doc.company, as_dict=1)
""" % ('%s', so_filter, item_filter, item_filter), self.company, as_dict=1)
self.add_so_in_table(open_so)
@ -85,7 +85,7 @@ class ProductionPlanningTool(Document):
so_list = [d.sales_order for d in self.get('pp_so_details')]
for r in open_so:
if cstr(r['name']) not in so_list:
pp_so = self.doc.append('pp_so_details', {})
pp_so = self.append('pp_so_details', {})
pp_so.sales_order = r['name']
pp_so.sales_order_date = cstr(r['transaction_date'])
pp_so.customer = cstr(r['customer'])
@ -135,7 +135,7 @@ class ProductionPlanningTool(Document):
for p in items:
item_details = frappe.db.sql("""select description, stock_uom, default_bom
from tabItem where name=%s""", p['item_code'])
pi = self.doc.append('pp_details', {})
pi = self.append('pp_details', {})
pi.sales_order = p['parent']
pi.warehouse = p['warehouse']
pi.item_code = p['item_code']
@ -200,7 +200,7 @@ class ProductionPlanningTool(Document):
"bom_no" : d.bom_no,
"description" : d.description,
"stock_uom" : d.stock_uom,
"company" : self.doc.company,
"company" : self.company,
"wip_warehouse" : "",
"fg_warehouse" : d.warehouse,
"status" : "Draft",
@ -214,12 +214,12 @@ class ProductionPlanningTool(Document):
pro_list = []
for key in items:
pro = frappe.new_bean("Production Order")
pro.doc.fields.update(items[key])
pro.update(items[key])
frappe.flags.mute_messages = True
try:
pro.insert()
pro_list.append(pro.doc.name)
pro_list.append(pro.name)
except OverProductionError, e:
pass
@ -244,7 +244,7 @@ class ProductionPlanningTool(Document):
for bom, so_wise_qty in bom_dict.items():
bom_wise_item_details = {}
if self.doc.use_multi_level_bom:
if self.use_multi_level_bom:
# get all raw materials with sub assembly childs
for d in frappe.db.sql("""select fb.item_code,
ifnull(sum(fb.qty_consumed_per_unit), 0) as qty,
@ -303,7 +303,7 @@ class ProductionPlanningTool(Document):
Requested qty should be shortage qty considering minimum order qty
"""
self.validate_data()
if not self.doc.purchase_request_for_warehouse:
if not self.purchase_request_for_warehouse:
frappe.throw(_("Please enter Warehouse for which Material Request will be raised"))
bom_dict = self.get_distinct_items_and_boms()[0]
@ -372,7 +372,7 @@ class ProductionPlanningTool(Document):
"naming_series": "IDT",
"transaction_date": nowdate(),
"status": "Draft",
"company": self.doc.company,
"company": self.company,
"fiscal_year": fiscal_year,
"requested_by": frappe.session.user,
"material_request_type": "Purchase"
@ -382,14 +382,14 @@ class ProductionPlanningTool(Document):
"doctype": "Material Request Item",
"__islocal": 1,
"item_code": item,
"item_name": item_wrapper.doc.item_name,
"description": item_wrapper.doc.description,
"uom": item_wrapper.doc.stock_uom,
"item_group": item_wrapper.doc.item_group,
"brand": item_wrapper.doc.brand,
"item_name": item_wrapper.item_name,
"description": item_wrapper.description,
"uom": item_wrapper.stock_uom,
"item_group": item_wrapper.item_group,
"brand": item_wrapper.brand,
"qty": requested_qty,
"schedule_date": add_days(nowdate(), cint(item_wrapper.doc.lead_time_days)),
"warehouse": self.doc.purchase_request_for_warehouse,
"schedule_date": add_days(nowdate(), cint(item_wrapper.lead_time_days)),
"warehouse": self.purchase_request_for_warehouse,
"sales_order_no": sales_order if sales_order!="No Sales Order" else None
})

View File

@ -14,14 +14,14 @@ class Workstation(Document):
def update_bom_operation(self):
bom_list = frappe.db.sql("""select DISTINCT parent from `tabBOM Operation`
where workstation = %s""", self.doc.name)
where workstation = %s""", self.name)
for bom_no in bom_list:
frappe.db.sql("""update `tabBOM Operation` set hour_rate = %s
where parent = %s and workstation = %s""",
(self.doc.hour_rate, bom_no[0], self.doc.name))
(self.hour_rate, bom_no[0], self.name))
def on_update(self):
frappe.db.set(self.doc, 'overhead', flt(self.doc.hour_rate_electricity) +
flt(self.doc.hour_rate_consumable) + flt(self.doc.hour_rate_rent))
frappe.db.set(self.doc, 'hour_rate', flt(self.doc.hour_rate_labour) + flt(self.doc.overhead))
frappe.db.set(self.doc, 'overhead', flt(self.hour_rate_electricity) +
flt(self.hour_rate_consumable) + flt(self.hour_rate_rent))
frappe.db.set(self.doc, 'hour_rate', flt(self.hour_rate_labour) + flt(self.overhead))
self.update_bom_operation()

View File

@ -7,6 +7,6 @@ def execute():
address = frappe.doc("Address", address)
contact = frappe.bean("Contact Us Settings", "Contact Us Settings")
for f in ("address_title", "address_line1", "address_line2", "city", "state", "country", "pincode"):
contact.doc.fields[f] = address.get(f)
contact.set(f, address.get(f))
contact.save()

View File

@ -25,7 +25,7 @@ def map_outgoing_email_settings(email_settings):
else:
from_fieldname = to_fieldname = fieldname
outgoing_email_settings.doc.fields[to_fieldname] = email_settings.doc.fields.get(from_fieldname)
outgoing_email_settings.set(to_fieldname, email_settings.get(from_fieldname))
outgoing_email_settings.save()
@ -44,7 +44,7 @@ def map_support_email_settings(email_settings):
else:
from_fieldname = to_fieldname = fieldname
support_email_settings.doc.fields[to_fieldname] = email_settings.doc.fields.get(from_fieldname)
support_email_settings.set(to_fieldname, email_settings.get(from_fieldname))
support_email_settings.save()

View File

@ -14,16 +14,16 @@ class Project(Document):
def get_gross_profit(self):
pft, per_pft =0, 0
pft = flt(self.doc.project_value) - flt(self.doc.est_material_cost)
pft = flt(self.project_value) - flt(self.est_material_cost)
#if pft > 0:
per_pft = (flt(pft) / flt(self.doc.project_value)) * 100
per_pft = (flt(pft) / flt(self.project_value)) * 100
ret = {'gross_margin_value': pft, 'per_gross_margin': per_pft}
return ret
def validate(self):
"""validate start date before end date"""
if self.doc.project_start_date and self.doc.completion_date:
if getdate(self.doc.completion_date) < getdate(self.doc.project_start_date):
if self.project_start_date and self.completion_date:
if getdate(self.completion_date) < getdate(self.project_start_date):
msgprint("Expected Completion Date can not be less than Project Start Date")
raise Exception
@ -32,31 +32,31 @@ class Project(Document):
def update_percent_complete(self):
total = frappe.db.sql("""select count(*) from tabTask where project=%s""",
self.doc.name)[0][0]
self.name)[0][0]
if total:
completed = frappe.db.sql("""select count(*) from tabTask where
project=%s and status in ('Closed', 'Cancelled')""", self.doc.name)[0][0]
frappe.db.set_value("Project", self.doc.name, "percent_complete",
project=%s and status in ('Closed', 'Cancelled')""", self.name)[0][0]
frappe.db.set_value("Project", self.name, "percent_complete",
int(float(completed) / total * 100))
def add_calendar_event(self):
# delete any earlier event for this project
delete_events(self.doc.doctype, self.doc.name)
delete_events(self.doctype, self.name)
# add events
for milestone in self.get("project_milestones"):
if milestone.milestone_date:
description = (milestone.milestone or "Milestone") + " for " + self.doc.name
description = (milestone.milestone or "Milestone") + " for " + self.name
frappe.bean({
"doctype": "Event",
"owner": self.doc.owner,
"owner": self.owner,
"subject": description,
"description": description,
"starts_on": milestone.milestone_date + " 10:00:00",
"event_type": "Private",
"ref_type": self.doc.doctype,
"ref_name": self.doc.name
"ref_type": self.doctype,
"ref_name": self.name
}).insert()
def on_trash(self):
delete_events(self.doc.doctype, self.doc.name)
delete_events(self.doctype, self.name)

View File

@ -13,38 +13,38 @@ from frappe.model.document import Document
class Task(Document):
def get_project_details(self):
return {
"project": self.doc.project
"project": self.project
}
def get_customer_details(self):
cust = frappe.db.sql("select customer_name from `tabCustomer` where name=%s", self.doc.customer)
cust = frappe.db.sql("select customer_name from `tabCustomer` where name=%s", self.customer)
if cust:
ret = {'customer_name': cust and cust[0][0] or ''}
return ret
def validate(self):
if self.doc.exp_start_date and self.doc.exp_end_date and getdate(self.doc.exp_start_date) > getdate(self.doc.exp_end_date):
if self.exp_start_date and self.exp_end_date and getdate(self.exp_start_date) > getdate(self.exp_end_date):
msgprint("'Expected Start Date' can not be greater than 'Expected End Date'")
raise Exception
if self.doc.act_start_date and self.doc.act_end_date and getdate(self.doc.act_start_date) > getdate(self.doc.act_end_date):
if self.act_start_date and self.act_end_date and getdate(self.act_start_date) > getdate(self.act_end_date):
msgprint("'Actual Start Date' can not be greater than 'Actual End Date'")
raise Exception
self.update_status()
def update_status(self):
status = frappe.db.get_value("Task", self.doc.name, "status")
if self.doc.status=="Working" and status !="Working" and not self.doc.act_start_date:
self.doc.act_start_date = today()
status = frappe.db.get_value("Task", self.name, "status")
if self.status=="Working" and status !="Working" and not self.act_start_date:
self.act_start_date = today()
if self.doc.status=="Closed" and status != "Closed" and not self.doc.act_end_date:
self.doc.act_end_date = today()
if self.status=="Closed" and status != "Closed" and not self.act_end_date:
self.act_end_date = today()
def on_update(self):
"""update percent complete in project"""
if self.doc.project:
project = frappe.bean("Project", self.doc.project)
if self.project:
project = frappe.bean("Project", self.project)
project.run_method("update_percent_complete")
@frappe.whitelist()

View File

@ -22,20 +22,20 @@ class TimeLog(Document):
def calculate_total_hours(self):
from frappe.utils import time_diff_in_hours
self.doc.hours = time_diff_in_hours(self.doc.to_time, self.doc.from_time)
self.hours = time_diff_in_hours(self.to_time, self.from_time)
def set_status(self):
self.doc.status = {
self.status = {
0: "Draft",
1: "Submitted",
2: "Cancelled"
}[self.doc.docstatus or 0]
}[self.docstatus or 0]
if self.doc.time_log_batch:
self.doc.status="Batched for Billing"
if self.time_log_batch:
self.status="Batched for Billing"
if self.doc.sales_invoice:
self.doc.status="Billed"
if self.sales_invoice:
self.status="Billed"
def validate_overlap(self):
existing = frappe.db.sql_list("""select name from `tabTime Log` where owner=%s and
@ -46,9 +46,9 @@ class TimeLog(Document):
and name!=%s
and ifnull(task, "")=%s
and docstatus < 2""",
(self.doc.owner, self.doc.from_time, self.doc.to_time, self.doc.from_time,
self.doc.to_time, self.doc.from_time, self.doc.name or "No Name",
cstr(self.doc.task)))
(self.owner, self.from_time, self.to_time, self.from_time,
self.to_time, self.from_time, self.name or "No Name",
cstr(self.task)))
if existing:
frappe.msgprint(_("This Time Log conflicts with") + ":" + ', '.join(existing),

View File

@ -7,7 +7,7 @@ class TimeLogBatchTest(unittest.TestCase):
def test_time_log_status(self):
from erpnext.projects.doctype.time_log.test_time_log import test_records as time_log_records
time_log = frappe.bean(copy=time_log_records[0])
time_log.doc.fields.update({
time_log.update({
"from_time": "2013-01-02 10:00:00.000000",
"to_time": "2013-01-02 11:00:00.000000",
"docstatus": 0
@ -15,15 +15,15 @@ class TimeLogBatchTest(unittest.TestCase):
time_log.insert()
time_log.submit()
self.assertEquals(frappe.db.get_value("Time Log", time_log.doc.name, "status"), "Submitted")
self.assertEquals(frappe.db.get_value("Time Log", time_log.name, "status"), "Submitted")
tlb = frappe.bean(copy=test_records[0])
tlb.doclist[1].time_log = time_log.doc.name
tlb.doclist[1].time_log = time_log.name
tlb.insert()
tlb.submit()
self.assertEquals(frappe.db.get_value("Time Log", time_log.doc.name, "status"), "Batched for Billing")
self.assertEquals(frappe.db.get_value("Time Log", time_log.name, "status"), "Batched for Billing")
tlb.cancel()
self.assertEquals(frappe.db.get_value("Time Log", time_log.doc.name, "status"), "Submitted")
self.assertEquals(frappe.db.get_value("Time Log", time_log.name, "status"), "Submitted")
test_records = [[
{

View File

@ -13,12 +13,12 @@ class TimeLogBatch(Document):
def validate(self):
self.set_status()
self.doc.total_hours = 0.0
self.total_hours = 0.0
for d in self.doclist.get({"doctype":"Time Log Batch Detail"}):
tl = frappe.doc("Time Log", d.time_log)
self.update_time_log_values(d, tl)
self.validate_time_log_is_submitted(tl)
self.doc.total_hours += float(tl.hours or 0.0)
self.total_hours += float(tl.hours or 0.0)
def update_time_log_values(self, d, tl):
d.fields.update({
@ -28,33 +28,33 @@ class TimeLogBatch(Document):
})
def validate_time_log_is_submitted(self, tl):
if tl.status != "Submitted" and self.doc.docstatus == 0:
if tl.status != "Submitted" and self.docstatus == 0:
frappe.msgprint(_("Time Log must have status 'Submitted'") + \
" :" + tl.name + " (" + _(tl.status) + ")", raise_exception=True)
def set_status(self):
self.doc.status = {
self.status = {
"0": "Draft",
"1": "Submitted",
"2": "Cancelled"
}[str(self.doc.docstatus or 0)]
}[str(self.docstatus or 0)]
if self.doc.sales_invoice:
self.doc.status = "Billed"
if self.sales_invoice:
self.status = "Billed"
def on_submit(self):
self.update_status(self.doc.name)
self.update_status(self.name)
def before_cancel(self):
self.update_status(None)
def before_update_after_submit(self):
self.update_status(self.doc.name)
self.update_status(self.name)
def update_status(self, time_log_batch):
self.set_status()
for d in self.doclist.get({"doctype":"Time Log Batch Detail"}):
tl = frappe.bean("Time Log", d.time_log)
tl.doc.time_log_batch = time_log_batch
tl.doc.sales_invoice = self.doc.sales_invoice
tl.time_log_batch = time_log_batch
tl.sales_invoice = self.sales_invoice
tl.update_after_submit()

View File

@ -16,54 +16,54 @@ class Customer(TransactionBase):
def autoname(self):
cust_master_name = frappe.defaults.get_global_default('cust_master_name')
if cust_master_name == 'Customer Name':
if frappe.db.exists("Supplier", self.doc.customer_name):
if frappe.db.exists("Supplier", self.customer_name):
msgprint(_("A Supplier exists with same name"), raise_exception=1)
self.doc.name = self.doc.customer_name
self.name = self.customer_name
else:
self.doc.name = make_autoname(self.doc.naming_series+'.#####')
self.name = make_autoname(self.naming_series+'.#####')
def get_company_abbr(self):
return frappe.db.get_value('Company', self.doc.company, 'abbr')
return frappe.db.get_value('Company', self.company, 'abbr')
def validate_values(self):
if frappe.defaults.get_global_default('cust_master_name') == 'Naming Series' and not self.doc.naming_series:
if frappe.defaults.get_global_default('cust_master_name') == 'Naming Series' and not self.naming_series:
frappe.throw("Series is Mandatory.", frappe.MandatoryError)
def validate(self):
self.validate_values()
def update_lead_status(self):
if self.doc.lead_name:
frappe.db.sql("update `tabLead` set status='Converted' where name = %s", self.doc.lead_name)
if self.lead_name:
frappe.db.sql("update `tabLead` set status='Converted' where name = %s", self.lead_name)
def update_address(self):
frappe.db.sql("""update `tabAddress` set customer_name=%s, modified=NOW()
where customer=%s""", (self.doc.customer_name, self.doc.name))
where customer=%s""", (self.customer_name, self.name))
def update_contact(self):
frappe.db.sql("""update `tabContact` set customer_name=%s, modified=NOW()
where customer=%s""", (self.doc.customer_name, self.doc.name))
where customer=%s""", (self.customer_name, self.name))
def update_credit_days_limit(self):
frappe.db.sql("""update tabAccount set credit_days = %s, credit_limit = %s
where master_type='Customer' and master_name = %s""",
(self.doc.credit_days or 0, self.doc.credit_limit or 0, self.doc.name))
(self.credit_days or 0, self.credit_limit or 0, self.name))
def create_lead_address_contact(self):
if self.doc.lead_name:
if not frappe.db.get_value("Address", {"lead": self.doc.lead_name, "customer": self.doc.customer}):
if self.lead_name:
if not frappe.db.get_value("Address", {"lead": self.lead_name, "customer": self.customer}):
frappe.db.sql("""update `tabAddress` set customer=%s, customer_name=%s where lead=%s""",
(self.doc.name, self.doc.customer_name, self.doc.lead_name))
(self.name, self.customer_name, self.lead_name))
lead = frappe.db.get_value("Lead", self.doc.lead_name, ["lead_name", "email_id", "phone", "mobile_no"], as_dict=True)
lead = frappe.db.get_value("Lead", self.lead_name, ["lead_name", "email_id", "phone", "mobile_no"], as_dict=True)
c = frappe.get_doc('Contact')
c.set("__islocal", 1)
c.first_name = lead.lead_name
c.email_id = lead.email_id
c.phone = lead.phone
c.mobile_no = lead.mobile_no
c.customer = self.doc.name
c.customer_name = self.doc.customer_name
c.customer = self.name
c.customer_name = self.customer_name
c.is_primary_contact = 1
try:
c.save()
@ -78,7 +78,7 @@ class Customer(TransactionBase):
self.update_contact()
# create account head
create_party_account(self.doc.name, "Customer", self.doc.company)
create_party_account(self.name, "Customer", self.company)
# update credit days and limit in account
self.update_credit_days_limit()
@ -86,14 +86,14 @@ class Customer(TransactionBase):
self.create_lead_address_contact()
def validate_name_with_customer_group(self):
if frappe.db.exists("Customer Group", self.doc.name):
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.doc.name, raise_exception=1)
self.name, raise_exception=1)
def delete_customer_address(self):
addresses = frappe.db.sql("""select name, lead from `tabAddress`
where customer=%s""", (self.doc.name,))
where customer=%s""", (self.name,))
for name, lead in addresses:
if lead:
@ -104,13 +104,13 @@ class Customer(TransactionBase):
def delete_customer_contact(self):
for contact in frappe.db.sql_list("""select name from `tabContact`
where customer=%s""", self.doc.name):
where customer=%s""", self.name):
frappe.delete_doc("Contact", contact)
def delete_customer_account(self):
"""delete customer's ledger if exist and check balance before deletion"""
acc = frappe.db.sql("select name from `tabAccount` where master_type = 'Customer' \
and master_name = %s and docstatus < 2", self.doc.name)
and master_name = %s and docstatus < 2", self.name)
if acc:
frappe.delete_doc('Account', acc[0][0])
@ -118,12 +118,12 @@ class Customer(TransactionBase):
self.delete_customer_address()
self.delete_customer_contact()
self.delete_customer_account()
if self.doc.lead_name:
frappe.db.sql("update `tabLead` set status='Interested' where name=%s",self.doc.lead_name)
if self.lead_name:
frappe.db.sql("update `tabLead` set status='Interested' where name=%s",self.lead_name)
def before_rename(self, olddn, newdn, merge=False):
from erpnext.accounts.utils import rename_account_for
rename_account_for("Customer", olddn, newdn, merge, self.doc.company)
rename_account_for("Customer", olddn, newdn, merge, self.company)
def after_rename(self, olddn, newdn, merge=False):
set_field = ''

View File

@ -38,7 +38,7 @@ class InstallationNote(TransactionBase):
def validate_fiscal_year(self):
from erpnext.accounts.utils import validate_fiscal_year
validate_fiscal_year(self.doc.inst_date, self.doc.fiscal_year, "Installation Date")
validate_fiscal_year(self.inst_date, self.fiscal_year, "Installation Date")
def is_serial_no_added(self, item_code, serial_no):
ar_required = frappe.db.get_value("Item", item_code, "has_serial_no")
@ -91,7 +91,7 @@ class InstallationNote(TransactionBase):
for d in self.get('installed_item_details'):
if d.prevdoc_docname:
d_date = frappe.db.get_value("Delivery Note", d.prevdoc_docname, "posting_date")
if d_date > getdate(self.doc.inst_date):
if d_date > getdate(self.inst_date):
msgprint("Installation Date can not be before Delivery Date " + cstr(d_date) +
" for item "+d.item_code, raise_exception=1)

View File

@ -24,7 +24,7 @@ def add_sales_communication(subject, content, sender, real_name, mail=None,
lead.ignore_permissions = True
lead.ignore_mandatory = True
lead.insert()
lead_name = lead.doc.name
lead_name = lead.name
parent_doctype = "Contact" if contact_name else "Lead"
parent_name = contact_name or lead_name

View File

@ -13,25 +13,25 @@ from erpnext.controllers.selling_controller import SellingController
class Lead(SellingController):
self._prev = frappe._dict({
"contact_date": frappe.db.get_value("Lead", self.doc.name, "contact_date") if \
(not cint(self.doc.fields.get("__islocal"))) else None,
"contact_by": frappe.db.get_value("Lead", self.doc.name, "contact_by") if \
(not cint(self.doc.fields.get("__islocal"))) else None,
"contact_date": frappe.db.get_value("Lead", self.name, "contact_date") if \
(not cint(self.get("__islocal"))) else None,
"contact_by": frappe.db.get_value("Lead", self.name, "contact_by") if \
(not cint(self.get("__islocal"))) else None,
})
def onload(self):
customer = frappe.db.get_value("Customer", {"lead_name": self.doc.name})
customer = frappe.db.get_value("Customer", {"lead_name": self.name})
if customer:
self.doc.fields["__is_customer"] = customer
self.set("__is_customer", customer)
def validate(self):
self.set_status()
if self.doc.source == 'Campaign' and not self.doc.campaign_name and session['user'] != 'Guest':
if self.source == 'Campaign' and not self.campaign_name and session['user'] != 'Guest':
frappe.throw("Please specify campaign name")
if self.doc.email_id:
if not validate_email_add(self.doc.email_id):
if self.email_id:
if not validate_email_add(self.email_id):
frappe.throw('Please enter valid email id.')
def on_update(self):
@ -40,34 +40,34 @@ class Lead(SellingController):
def add_calendar_event(self, opts=None, force=False):
super(DocType, self).add_calendar_event({
"owner": self.doc.lead_owner,
"subject": ('Contact ' + cstr(self.doc.lead_name)),
"description": ('Contact ' + cstr(self.doc.lead_name)) + \
(self.doc.contact_by and ('. By : ' + cstr(self.doc.contact_by)) or '') + \
(self.doc.remark and ('.To Discuss : ' + cstr(self.doc.remark)) or '')
"owner": self.lead_owner,
"subject": ('Contact ' + cstr(self.lead_name)),
"description": ('Contact ' + cstr(self.lead_name)) + \
(self.contact_by and ('. By : ' + cstr(self.contact_by)) or '') + \
(self.remark and ('.To Discuss : ' + cstr(self.remark)) or '')
}, force)
def check_email_id_is_unique(self):
if self.doc.email_id:
if self.email_id:
# validate email is unique
email_list = frappe.db.sql("""select name from tabLead where email_id=%s""",
self.doc.email_id)
self.email_id)
if len(email_list) > 1:
items = [e[0] for e in email_list if e[0]!=self.doc.name]
items = [e[0] for e in email_list if e[0]!=self.name]
frappe.msgprint(_("""Email Id must be unique, already exists for: """) + \
", ".join(items), raise_exception=True)
def on_trash(self):
frappe.db.sql("""update `tabSupport Ticket` set lead='' where lead=%s""",
self.doc.name)
self.name)
self.delete_events()
def has_customer(self):
return frappe.db.get_value("Customer", {"lead_name": self.doc.name})
return frappe.db.get_value("Customer", {"lead_name": self.name})
def has_opportunity(self):
return frappe.db.get_value("Opportunity", {"lead": self.doc.name, "docstatus": 1,
return frappe.db.get_value("Opportunity", {"lead": self.name, "docstatus": 1,
"status": ["!=", "Lost"]})
@frappe.whitelist()
@ -78,12 +78,12 @@ def _make_customer(source_name, target_doclist=None, ignore_permissions=False):
from frappe.model.mapper import get_mapped_doclist
def set_missing_values(source, target):
if source.doc.company_name:
if source.company_name:
target[0].customer_type = "Company"
target[0].customer_name = source.doc.company_name
target[0].customer_name = source.company_name
else:
target[0].customer_type = "Individual"
target[0].customer_name = source.doc.lead_name
target[0].customer_name = source.lead_name
target[0].customer_group = frappe.db.get_default("customer_group")

View File

@ -61,22 +61,22 @@ class Opportunity(TransactionBase):
opts.description = ""
if self.doc.customer:
if self.doc.contact_person:
opts.description = 'Contact '+cstr(self.doc.contact_person)
if self.customer:
if self.contact_person:
opts.description = 'Contact '+cstr(self.contact_person)
else:
opts.description = 'Contact customer '+cstr(self.doc.customer)
elif self.doc.lead:
if self.doc.contact_display:
opts.description = 'Contact '+cstr(self.doc.contact_display)
opts.description = 'Contact customer '+cstr(self.customer)
elif self.lead:
if self.contact_display:
opts.description = 'Contact '+cstr(self.contact_display)
else:
opts.description = 'Contact lead '+cstr(self.doc.lead)
opts.description = 'Contact lead '+cstr(self.lead)
opts.subject = opts.description
opts.description += '. By : ' + cstr(self.doc.contact_by)
opts.description += '. By : ' + cstr(self.contact_by)
if self.doc.to_discuss:
opts.description += ' To Discuss : ' + cstr(self.doc.to_discuss)
if self.to_discuss:
opts.description += ' To Discuss : ' + cstr(self.to_discuss)
super(DocType, self).add_calendar_event(opts, force)
@ -86,17 +86,17 @@ class Opportunity(TransactionBase):
raise Exception
def validate_lead_cust(self):
if self.doc.enquiry_from == 'Lead' and not self.doc.lead:
if self.enquiry_from == 'Lead' and not self.lead:
msgprint("Lead Id is mandatory if 'Opportunity From' is selected as Lead", raise_exception=1)
elif self.doc.enquiry_from == 'Customer' and not self.doc.customer:
elif self.enquiry_from == 'Customer' and not self.customer:
msgprint("Customer is mandatory if 'Opportunity From' is selected as Customer", raise_exception=1)
def validate(self):
self._prev = frappe._dict({
"contact_date": frappe.db.get_value("Opportunity", self.doc.name, "contact_date") if \
(not cint(self.doc.fields.get("__islocal"))) else None,
"contact_by": frappe.db.get_value("Opportunity", self.doc.name, "contact_by") if \
(not cint(self.doc.fields.get("__islocal"))) else None,
"contact_date": frappe.db.get_value("Opportunity", self.name, "contact_date") if \
(not cint(self.get("__islocal"))) else None,
"contact_by": frappe.db.get_value("Opportunity", self.name, "contact_by") if \
(not cint(self.get("__islocal"))) else None,
})
self.set_status()
@ -105,11 +105,11 @@ class Opportunity(TransactionBase):
self.validate_lead_cust()
from erpnext.accounts.utils import validate_fiscal_year
validate_fiscal_year(self.doc.transaction_date, self.doc.fiscal_year, "Opportunity Date")
validate_fiscal_year(self.transaction_date, self.fiscal_year, "Opportunity Date")
def on_submit(self):
if self.doc.lead:
frappe.bean("Lead", self.doc.lead).get_controller().set_status(update=True)
if self.lead:
frappe.bean("Lead", self.lead).get_controller().set_status(update=True)
def on_cancel(self):
if self.has_quotation():
@ -127,7 +127,7 @@ class Opportunity(TransactionBase):
self.delete_events()
def has_quotation(self):
return frappe.db.get_value("Quotation Item", {"prevdoc_docname": self.doc.name, "docstatus": 1})
return frappe.db.get_value("Quotation Item", {"prevdoc_docname": self.name, "docstatus": 1})
@frappe.whitelist()
def make_quotation(source_name, target_doclist=None):

View File

@ -15,7 +15,7 @@ class Quotation(SellingController):
self.fname = 'quotation_details'
def has_sales_order(self):
return frappe.db.get_value("Sales Order Item", {"prevdoc_docname": self.doc.name, "docstatus": 1})
return frappe.db.get_value("Sales Order Item", {"prevdoc_docname": self.name, "docstatus": 1})
def validate_for_items(self):
chk_dupl_itm = []
@ -29,7 +29,7 @@ class Quotation(SellingController):
def validate_order_type(self):
super(DocType, self).validate_order_type()
if self.doc.order_type in ['Maintenance', 'Service']:
if self.order_type in ['Maintenance', 'Service']:
for d in self.get('quotation_details'):
is_service_item = frappe.db.sql("select is_service_item from `tabItem` where name=%s", d.item_code)
is_service_item = is_service_item and is_service_item[0][0] or 'No'
@ -74,7 +74,7 @@ class Quotation(SellingController):
self.check_item_table()
# Check for Approving Authority
get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.company, self.doc.grand_total, self)
get_obj('Authorization Control').validate_approving_authority(self.doctype, self.company, self.grand_total, self)
#update enquiry status
self.update_opportunity()
@ -105,8 +105,8 @@ def _make_sales_order(source_name, target_doclist=None, ignore_permissions=False
def set_missing_values(source, target):
if customer:
target[0].customer = customer.doc.name
target[0].customer_name = customer.doc.customer_name
target[0].customer = customer.name
target[0].customer_name = customer.customer_name
si = frappe.bean(target)
si.ignore_permissions = ignore_permissions
@ -150,7 +150,7 @@ def _make_customer(source_name, ignore_permissions=False):
customer = frappe.bean(customer_doclist)
customer.ignore_permissions = ignore_permissions
if quotation[1] == "Shopping Cart":
customer.doc.customer_group = frappe.db.get_value("Shopping Cart Settings", None,
customer.customer_group = frappe.db.get_value("Shopping Cart Settings", None,
"default_customer_group")
try:
@ -159,7 +159,7 @@ def _make_customer(source_name, ignore_permissions=False):
except NameError:
if frappe.defaults.get_global_default('cust_master_name') == "Customer Name":
customer.run_method("autoname")
customer.doc.name += "-" + lead_name
customer.name += "-" + lead_name
customer.insert()
return customer
else:

View File

@ -14,16 +14,16 @@ class TestQuotation(unittest.TestCase):
quotation = frappe.bean(copy=test_records[0])
quotation.insert()
self.assertRaises(frappe.ValidationError, make_sales_order, quotation.doc.name)
self.assertRaises(frappe.ValidationError, make_sales_order, quotation.name)
quotation.submit()
sales_order = make_sales_order(quotation.doc.name)
sales_order = make_sales_order(quotation.name)
self.assertEquals(sales_order[0]["doctype"], "Sales Order")
self.assertEquals(len(sales_order), 2)
self.assertEquals(sales_order[1]["doctype"], "Sales Order Item")
self.assertEquals(sales_order[1]["prevdoc_docname"], quotation.doc.name)
self.assertEquals(sales_order[1]["prevdoc_docname"], quotation.name)
self.assertEquals(sales_order[0]["customer"], "_Test Customer")
sales_order[0]["delivery_date"] = "2014-01-01"

View File

@ -10,7 +10,7 @@ class SalesBom(Document):
def autoname(self):
self.doc.name = self.doc.new_item_code
self.name = self.new_item_code
def validate(self):
self.validate_main_item()
@ -21,7 +21,7 @@ class SalesBom(Document):
def validate_main_item(self):
"""main item must have Is Stock Item as No and Is Sales Item as Yes"""
if not frappe.db.sql("""select name from tabItem where name=%s and
ifnull(is_stock_item,'')='No' and ifnull(is_sales_item,'')='Yes'""", self.doc.new_item_code):
ifnull(is_stock_item,'')='No' and ifnull(is_sales_item,'')='Yes'""", self.new_item_code):
frappe.msgprint("""Parent Item %s is either a Stock Item or a not a Sales Item""",
raise_exception=1)

View File

@ -26,21 +26,21 @@ class SalesOrder(SellingController):
def validate_mandatory(self):
# validate transaction date v/s delivery date
if self.doc.delivery_date:
if getdate(self.doc.transaction_date) > getdate(self.doc.delivery_date):
if self.delivery_date:
if getdate(self.transaction_date) > getdate(self.delivery_date):
msgprint("Expected Delivery Date cannot be before Sales Order Date")
raise Exception
def validate_po(self):
# validate p.o date v/s delivery date
if self.doc.po_date and self.doc.delivery_date and getdate(self.doc.po_date) > getdate(self.doc.delivery_date):
if self.po_date and self.delivery_date and getdate(self.po_date) > getdate(self.delivery_date):
msgprint("Expected Delivery Date cannot be before Purchase Order Date")
raise Exception
if self.doc.po_no and self.doc.customer:
if self.po_no and self.customer:
so = frappe.db.sql("select name from `tabSales Order` \
where ifnull(po_no, '') = %s and name != %s and docstatus < 2\
and customer = %s", (self.doc.po_no, self.doc.name, self.doc.customer))
and customer = %s", (self.po_no, self.name, self.customer))
if so and so[0][0]:
msgprint("""Another Sales Order (%s) exists against same PO No and Customer.
Please be sure, you are not making duplicate entry.""" % so[0][0])
@ -68,7 +68,7 @@ class SalesOrder(SellingController):
chk_dupl_itm.append(f)
# used for production plan
d.transaction_date = self.doc.transaction_date
d.transaction_date = self.transaction_date
tot_avail_qty = frappe.db.sql("select projected_qty from `tabBin` \
where item_code = %s and warehouse = %s", (d.item_code,d.warehouse))
@ -77,28 +77,28 @@ class SalesOrder(SellingController):
def validate_sales_mntc_quotation(self):
for d in self.get('sales_order_details'):
if d.prevdoc_docname:
res = frappe.db.sql("select name from `tabQuotation` where name=%s and order_type = %s", (d.prevdoc_docname, self.doc.order_type))
res = frappe.db.sql("select name from `tabQuotation` where name=%s and order_type = %s", (d.prevdoc_docname, self.order_type))
if not res:
msgprint("""Order Type (%s) should be same in Quotation: %s \
and current Sales Order""" % (self.doc.order_type, d.prevdoc_docname))
and current Sales Order""" % (self.order_type, d.prevdoc_docname))
def validate_order_type(self):
super(DocType, self).validate_order_type()
def validate_delivery_date(self):
if self.doc.order_type == 'Sales' and not self.doc.delivery_date:
if self.order_type == 'Sales' and not self.delivery_date:
msgprint("Please enter 'Expected Delivery Date'")
raise Exception
self.validate_sales_mntc_quotation()
def validate_proj_cust(self):
if self.doc.project_name and self.doc.customer_name:
if self.project_name and self.customer_name:
res = frappe.db.sql("""select name from `tabProject` where name = %s
and (customer = %s or ifnull(customer,'')='')""",
(self.doc.project_name, self.doc.customer))
(self.project_name, self.customer))
if not res:
msgprint("Customer - %s does not belong to project - %s. \n\nIf you want to use project for multiple customers then please make customer details blank in project - %s."%(self.doc.customer,self.doc.project_name,self.doc.project_name))
msgprint("Customer - %s does not belong to project - %s. \n\nIf you want to use project for multiple customers then please make customer details blank in project - %s."%(self.customer,self.project_name,self.project_name))
raise Exception
def validate(self):
@ -119,15 +119,15 @@ class SalesOrder(SellingController):
self.validate_with_previous_doc()
if not self.doc.status:
self.doc.status = "Draft"
if not self.status:
self.status = "Draft"
from erpnext.utilities import validate_status
validate_status(self.doc.status, ["Draft", "Submitted", "Stopped",
validate_status(self.status, ["Draft", "Submitted", "Stopped",
"Cancelled"])
if not self.doc.billing_status: self.doc.billing_status = 'Not Billed'
if not self.doc.delivery_status: self.doc.delivery_status = 'Not Delivered'
if not self.billing_status: self.billing_status = 'Not Billed'
if not self.delivery_status: self.delivery_status = 'Not Delivered'
def validate_warehouse(self):
from erpnext.stock.utils import validate_warehouse_company
@ -136,7 +136,7 @@ class SalesOrder(SellingController):
self.doclist.get({"doctype": self.tname}) if d.warehouse]))
for w in warehouses:
validate_warehouse_company(w, self.doc.company)
validate_warehouse_company(w, self.company)
def validate_with_previous_doc(self):
super(DocType, self).validate_with_previous_doc(self.tname, {
@ -155,7 +155,7 @@ class SalesOrder(SellingController):
def update_prevdoc_status(self, flag):
for quotation in self.doclist.get_distinct_values("prevdoc_docname"):
bean = frappe.bean("Quotation", quotation)
if bean.doc.docstatus==2:
if bean.docstatus==2:
frappe.throw(quotation + ": " + frappe._("Quotation is cancelled."))
bean.get_controller().set_status(update=True)
@ -163,17 +163,17 @@ class SalesOrder(SellingController):
def on_submit(self):
self.update_stock_ledger(update_stock = 1)
self.check_credit(self.doc.grand_total)
self.check_credit(self.grand_total)
get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.grand_total, self)
get_obj('Authorization Control').validate_approving_authority(self.doctype, self.grand_total, self)
self.update_prevdoc_status('submit')
frappe.db.set(self.doc, 'status', 'Submitted')
def on_cancel(self):
# Cannot cancel stopped SO
if self.doc.status == 'Stopped':
msgprint("Sales Order : '%s' cannot be cancelled as it is Stopped. Unstop it for any further transactions" %(self.doc.name))
if self.status == 'Stopped':
msgprint("Sales Order : '%s' cannot be cancelled as it is Stopped. Unstop it for any further transactions" %(self.name))
raise Exception
self.check_nextdoc_docstatus()
self.update_stock_ledger(update_stock = -1)
@ -184,55 +184,55 @@ class SalesOrder(SellingController):
def check_nextdoc_docstatus(self):
# Checks Delivery Note
submit_dn = frappe.db.sql("select t1.name from `tabDelivery Note` t1,`tabDelivery Note Item` t2 where t1.name = t2.parent and t2.against_sales_order = %s and t1.docstatus = 1", self.doc.name)
submit_dn = frappe.db.sql("select t1.name from `tabDelivery Note` t1,`tabDelivery Note Item` t2 where t1.name = t2.parent and t2.against_sales_order = %s and t1.docstatus = 1", self.name)
if submit_dn:
msgprint("Delivery Note : " + cstr(submit_dn[0][0]) + " has been submitted against " + cstr(self.doc.doctype) + ". Please cancel Delivery Note : " + cstr(submit_dn[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1)
msgprint("Delivery Note : " + cstr(submit_dn[0][0]) + " has been submitted against " + cstr(self.doctype) + ". Please cancel Delivery Note : " + cstr(submit_dn[0][0]) + " first and then cancel "+ cstr(self.doctype), raise_exception = 1)
# Checks Sales Invoice
submit_rv = frappe.db.sql("""select t1.name
from `tabSales Invoice` t1,`tabSales Invoice Item` t2
where t1.name = t2.parent and t2.sales_order = %s and t1.docstatus = 1""",
self.doc.name)
self.name)
if submit_rv:
msgprint("Sales Invoice : " + cstr(submit_rv[0][0]) + " has already been submitted against " +cstr(self.doc.doctype)+ ". Please cancel Sales Invoice : "+ cstr(submit_rv[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1)
msgprint("Sales Invoice : " + cstr(submit_rv[0][0]) + " has already been submitted against " +cstr(self.doctype)+ ". Please cancel Sales Invoice : "+ cstr(submit_rv[0][0]) + " first and then cancel "+ cstr(self.doctype), raise_exception = 1)
#check maintenance schedule
submit_ms = frappe.db.sql("select t1.name from `tabMaintenance Schedule` t1, `tabMaintenance Schedule Item` t2 where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1",self.doc.name)
submit_ms = frappe.db.sql("select t1.name from `tabMaintenance Schedule` t1, `tabMaintenance Schedule Item` t2 where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1",self.name)
if submit_ms:
msgprint("Maintenance Schedule : " + cstr(submit_ms[0][0]) + " has already been submitted against " +cstr(self.doc.doctype)+ ". Please cancel Maintenance Schedule : "+ cstr(submit_ms[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1)
msgprint("Maintenance Schedule : " + cstr(submit_ms[0][0]) + " has already been submitted against " +cstr(self.doctype)+ ". Please cancel Maintenance Schedule : "+ cstr(submit_ms[0][0]) + " first and then cancel "+ cstr(self.doctype), raise_exception = 1)
# check maintenance visit
submit_mv = frappe.db.sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1",self.doc.name)
submit_mv = frappe.db.sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1",self.name)
if submit_mv:
msgprint("Maintenance Visit : " + cstr(submit_mv[0][0]) + " has already been submitted against " +cstr(self.doc.doctype)+ ". Please cancel Maintenance Visit : " + cstr(submit_mv[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1)
msgprint("Maintenance Visit : " + cstr(submit_mv[0][0]) + " has already been submitted against " +cstr(self.doctype)+ ". Please cancel Maintenance Visit : " + cstr(submit_mv[0][0]) + " first and then cancel "+ cstr(self.doctype), raise_exception = 1)
# check production order
pro_order = frappe.db.sql("""select name from `tabProduction Order` where sales_order = %s and docstatus = 1""", self.doc.name)
pro_order = frappe.db.sql("""select name from `tabProduction Order` where sales_order = %s and docstatus = 1""", self.name)
if pro_order:
msgprint("""Production Order: %s exists against this sales order.
Please cancel production order first and then cancel this sales order""" %
pro_order[0][0], raise_exception=1)
def check_modified_date(self):
mod_db = frappe.db.get_value("Sales Order", self.doc.name, "modified")
mod_db = frappe.db.get_value("Sales Order", self.name, "modified")
date_diff = frappe.db.sql("select TIMEDIFF('%s', '%s')" %
( mod_db, cstr(self.doc.modified)))
( mod_db, cstr(self.modified)))
if date_diff and date_diff[0][0]:
msgprint("%s: %s has been modified after you have opened. Please Refresh"
% (self.doc.doctype, self.doc.name), raise_exception=1)
% (self.doctype, self.name), raise_exception=1)
def stop_sales_order(self):
self.check_modified_date()
self.update_stock_ledger(-1)
frappe.db.set(self.doc, 'status', 'Stopped')
msgprint("""%s: %s has been Stopped. To make transactions against this Sales Order
you need to Unstop it.""" % (self.doc.doctype, self.doc.name))
you need to Unstop it.""" % (self.doctype, self.name))
def unstop_sales_order(self):
self.check_modified_date()
self.update_stock_ledger(1)
frappe.db.set(self.doc, 'status', 'Submitted')
msgprint("%s: %s has been Unstopped" % (self.doc.doctype, self.doc.name))
msgprint("%s: %s has been Unstopped" % (self.doctype, self.name))
def update_stock_ledger(self, update_stock):
@ -243,10 +243,10 @@ class SalesOrder(SellingController):
"item_code": d['item_code'],
"warehouse": d['reserved_warehouse'],
"reserved_qty": flt(update_stock) * flt(d['reserved_qty']),
"posting_date": self.doc.transaction_date,
"voucher_type": self.doc.doctype,
"voucher_no": self.doc.name,
"is_amended": self.doc.amended_from and 'Yes' or 'No'
"posting_date": self.transaction_date,
"voucher_type": self.doctype,
"voucher_no": self.name,
"is_amended": self.amended_from and 'Yes' or 'No'
}
update_bin(args)
@ -254,7 +254,7 @@ class SalesOrder(SellingController):
pass
def get_portal_page(self):
return "order" if self.doc.docstatus==1 else None
return "order" if self.docstatus==1 else None
def set_missing_values(source, target):
bean = frappe.bean(target)
@ -327,7 +327,7 @@ def make_delivery_note(source_name, target_doclist=None):
def make_sales_invoice(source_name, target_doclist=None):
def set_missing_values(source, target):
bean = frappe.bean(target)
bean.doc.is_pos = 0
bean.is_pos = 0
bean.run_method("onload_post_render")
def update_item(obj, target, source_parent):

View File

@ -15,11 +15,11 @@ class TestSalesOrder(unittest.TestCase):
so = frappe.bean(copy=test_records[0]).insert()
self.assertRaises(frappe.ValidationError, make_material_request,
so.doc.name)
so.name)
sales_order = frappe.bean("Sales Order", so.doc.name)
sales_order = frappe.bean("Sales Order", so.name)
sales_order.submit()
mr = make_material_request(so.doc.name)
mr = make_material_request(so.name)
self.assertEquals(mr[0]["material_request_type"], "Purchase")
self.assertEquals(len(mr), len(sales_order.doclist))
@ -30,11 +30,11 @@ class TestSalesOrder(unittest.TestCase):
so = frappe.bean(copy=test_records[0]).insert()
self.assertRaises(frappe.ValidationError, make_delivery_note,
so.doc.name)
so.name)
sales_order = frappe.bean("Sales Order", so.doc.name)
sales_order = frappe.bean("Sales Order", so.name)
sales_order.submit()
dn = make_delivery_note(so.doc.name)
dn = make_delivery_note(so.name)
self.assertEquals(dn[0]["doctype"], "Delivery Note")
self.assertEquals(len(dn), len(sales_order.doclist))
@ -45,22 +45,22 @@ class TestSalesOrder(unittest.TestCase):
so = frappe.bean(copy=test_records[0]).insert()
self.assertRaises(frappe.ValidationError, make_sales_invoice,
so.doc.name)
so.name)
sales_order = frappe.bean("Sales Order", so.doc.name)
sales_order = frappe.bean("Sales Order", so.name)
sales_order.submit()
si = make_sales_invoice(so.doc.name)
si = make_sales_invoice(so.name)
self.assertEquals(si[0]["doctype"], "Sales Invoice")
self.assertEquals(len(si), len(sales_order.doclist))
self.assertEquals(len([d for d in si if d["doctype"]=="Sales Invoice Item"]), 1)
si = frappe.bean(si)
si.doc.posting_date = "2013-10-10"
si.posting_date = "2013-10-10"
si.insert()
si.submit()
si1 = make_sales_invoice(so.doc.name)
si1 = make_sales_invoice(so.name)
self.assertEquals(len([d for d in si1 if d["doctype"]=="Sales Invoice Item"]), 0)
@ -82,7 +82,7 @@ class TestSalesOrder(unittest.TestCase):
dn = frappe.bean(frappe.copy_doc(dn_test_records[0]))
dn.doclist[1].item_code = so.doclist[1].item_code
dn.doclist[1].against_sales_order = so.doc.name
dn.doclist[1].against_sales_order = so.name
dn.doclist[1].prevdoc_detail_docname = so.doclist[1].name
if delivered_qty:
dn.doclist[1].qty = delivered_qty
@ -291,9 +291,9 @@ class TestSalesOrder(unittest.TestCase):
from frappe.model.bean import BeanPermissionError
so = frappe.bean(copy = test_records[0])
so.doc.company = "_Test Company 1"
so.doc.conversion_rate = 0.02
so.doc.plc_conversion_rate = 0.02
so.company = "_Test Company 1"
so.conversion_rate = 0.02
so.plc_conversion_rate = 0.02
so.doclist[1].warehouse = "_Test Warehouse 2 - _TC1"
self.assertRaises(BeanPermissionError, so.insert)

View File

@ -13,8 +13,8 @@ class SellingSettings(Document):
def validate(self):
for key in ["cust_master_name", "customer_group", "territory", "maintain_same_sales_rate",
"editable_price_list_rate", "selling_price_list"]:
frappe.db.set_default(key, self.doc.fields.get(key, ""))
frappe.db.set_default(key, self.get(key, ""))
from erpnext.setup.doctype.naming_series.naming_series import set_by_naming_series
set_by_naming_series("Customer", "customer_name",
self.doc.get("cust_master_name")=="Naming Series", hide_name_field=False)
self.get("cust_master_name")=="Naming Series", hide_name_field=False)

View File

@ -14,50 +14,50 @@ class SmsCenter(Document):
def create_receiver_list(self):
rec, where_clause = '', ''
if self.doc.send_to == 'All Customer Contact':
where_clause = self.doc.customer and " and customer = '%s'" % \
self.doc.customer.replace("'", "\'") or " and ifnull(customer, '') != ''"
if self.doc.send_to == 'All Supplier Contact':
where_clause = self.doc.supplier and \
if self.send_to == 'All Customer Contact':
where_clause = self.customer and " and customer = '%s'" % \
self.customer.replace("'", "\'") or " and ifnull(customer, '') != ''"
if self.send_to == 'All Supplier Contact':
where_clause = self.supplier and \
" and ifnull(is_supplier, 0) = 1 and supplier = '%s'" % \
self.doc.supplier.replace("'", "\'") or " and ifnull(supplier, '') != ''"
if self.doc.send_to == 'All Sales Partner Contact':
where_clause = self.doc.sales_partner and \
self.supplier.replace("'", "\'") or " and ifnull(supplier, '') != ''"
if self.send_to == 'All Sales Partner Contact':
where_clause = self.sales_partner and \
" and ifnull(is_sales_partner, 0) = 1 and sales_partner = '%s'" % \
self.doc.sales_partner.replace("'", "\'") or " and ifnull(sales_partner, '') != ''"
self.sales_partner.replace("'", "\'") or " and ifnull(sales_partner, '') != ''"
if self.doc.send_to in ['All Contact', 'All Customer Contact', 'All Supplier Contact', 'All Sales Partner Contact']:
if self.send_to in ['All Contact', 'All Customer Contact', 'All Supplier Contact', 'All Sales Partner Contact']:
rec = frappe.db.sql("""select CONCAT(ifnull(first_name,''), '', ifnull(last_name,'')),
mobile_no from `tabContact` where ifnull(mobile_no,'')!='' and
docstatus != 2 %s""", where_clause)
elif self.doc.send_to == 'All Lead (Open)':
elif self.send_to == 'All Lead (Open)':
rec = frappe.db.sql("""select lead_name, mobile_no from `tabLead` where
ifnull(mobile_no,'')!='' and docstatus != 2 and status='Open'""")
elif self.doc.send_to == 'All Employee (Active)':
where_clause = self.doc.department and " and department = '%s'" % \
self.doc.department.replace("'", "\'") or ""
where_clause += self.doc.branch and " and branch = '%s'" % \
self.doc.branch.replace("'", "\'") or ""
elif self.send_to == 'All Employee (Active)':
where_clause = self.department and " and department = '%s'" % \
self.department.replace("'", "\'") or ""
where_clause += self.branch and " and branch = '%s'" % \
self.branch.replace("'", "\'") or ""
rec = frappe.db.sql("""select employee_name, cell_number from
`tabEmployee` where status = 'Active' and docstatus < 2 and
ifnull(cell_number,'')!='' %s""", where_clause)
elif self.doc.send_to == 'All Sales Person':
elif self.send_to == 'All Sales Person':
rec = frappe.db.sql("""select sales_person_name, mobile_no from
`tabSales Person` where docstatus!=2 and ifnull(mobile_no,'')!=''""")
rec_list = ''
for d in rec:
rec_list += d[0] + ' - ' + d[1] + '\n'
self.doc.receiver_list = rec_list
self.receiver_list = rec_list
def get_receiver_nos(self):
receiver_nos = []
if self.doc.receiver_list:
for d in self.doc.receiver_list.split('\n'):
if self.receiver_list:
for d in self.receiver_list.split('\n'):
receiver_no = d
if '-' in d:
receiver_no = receiver_no.split('-')[1]
@ -69,9 +69,9 @@ class SmsCenter(Document):
return receiver_nos
def send_sms(self):
if not self.doc.message:
if not self.message:
msgprint(_("Please enter message before sending"))
else:
receiver_list = self.get_receiver_nos()
if receiver_list:
msgprint(get_obj('SMS Control', 'SMS Control').send_sms(receiver_list, cstr(self.doc.message)))
msgprint(get_obj('SMS Control', 'SMS Control').send_sms(receiver_list, cstr(self.message)))

View File

@ -36,7 +36,7 @@ class AuthorizationControl(TransactionBase):
if not has_common(appr_roles, frappe.user.get_roles()) and not has_common(appr_users, [session['user']]):
msg, add_msg = '',''
if max_amount:
dcc = get_company_currency(self.doc.company)
dcc = get_company_currency(self.company)
if based_on == 'Grand Total': msg = "since Grand Total exceeds %s. %s" % (dcc, flt(max_amount))
elif based_on == 'Itemwise Discount': msg = "since Discount exceeds %s for Item Code : %s" % (cstr(max_amount)+'%', item)
elif based_on == 'Average Discount' or based_on == 'Customerwise Discount': msg = "since Discount exceeds %s" % (cstr(max_amount)+'%')
@ -81,8 +81,8 @@ class AuthorizationControl(TransactionBase):
if based_on == 'Grand Total': auth_value = total
elif based_on == 'Customerwise Discount':
if doc_obj:
if doc_obj.doc.doctype == 'Sales Invoice': customer = doc_obj.doc.customer
else: customer = doc_obj.doc.customer_name
if doc_obj.doctype == 'Sales Invoice': customer = doc_obj.customer
else: customer = doc_obj.customer_name
add_cond = " and master_name = '"+make_esc("'")(cstr(customer))+"'"
if based_on == 'Itemwise Discount':
if doc_obj:
@ -170,11 +170,11 @@ class AuthorizationControl(TransactionBase):
if doc_obj:
if doctype_name == 'Expense Claim':
rule = self.get_value_based_rule(doctype_name,doc_obj.doc.employee,doc_obj.doc.total_claimed_amount, doc_obj.doc.company)
rule = self.get_value_based_rule(doctype_name,doc_obj.employee,doc_obj.total_claimed_amount, doc_obj.company)
elif doctype_name == 'Appraisal':
rule = frappe.db.sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and company = %s and docstatus!=2",(doctype_name,doc_obj.doc.employee, doc_obj.doc.employee, doc_obj.doc.company),as_dict=1)
rule = frappe.db.sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and company = %s and docstatus!=2",(doctype_name,doc_obj.employee, doc_obj.employee, doc_obj.company),as_dict=1)
if not rule:
rule = frappe.db.sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and ifnull(company,'') = '' and docstatus!=2",(doctype_name,doc_obj.doc.employee, doc_obj.doc.employee),as_dict=1)
rule = frappe.db.sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and ifnull(company,'') = '' and docstatus!=2",(doctype_name,doc_obj.employee, doc_obj.employee),as_dict=1)
if rule:
for m in rule:

View File

@ -17,10 +17,10 @@ class AuthorizationRule(Document):
where transaction = %s and based_on = %s and system_user = %s
and system_role = %s and approving_user = %s and approving_role = %s
and to_emp =%s and to_designation=%s and name != %s""",
(self.doc.transaction, self.doc.based_on, cstr(self.doc.system_user),
cstr(self.doc.system_role), cstr(self.doc.approving_user),
cstr(self.doc.approving_role), cstr(self.doc.to_emp),
cstr(self.doc.to_designation), self.doc.name))
(self.transaction, self.based_on, cstr(self.system_user),
cstr(self.system_role), cstr(self.approving_user),
cstr(self.approving_role), cstr(self.to_emp),
cstr(self.to_designation), self.name))
auth_exists = exists and exists[0][0] or ''
if auth_exists:
if cint(exists[0][1]) == 2:
@ -32,49 +32,49 @@ class AuthorizationRule(Document):
def validate_master_name(self):
if self.doc.based_on == 'Customerwise Discount' and \
if self.based_on == 'Customerwise Discount' and \
not frappe.db.sql("""select name from tabCustomer
where name = %s and docstatus != 2""", (self.doc.master_name)):
where name = %s and docstatus != 2""", (self.master_name)):
msgprint("Please select valid Customer Name for Customerwise Discount",
raise_exception=1)
elif self.doc.based_on == 'Itemwise Discount' and \
elif self.based_on == 'Itemwise Discount' and \
not frappe.db.sql("select name from tabItem where name = %s and docstatus != 2",
(self.doc.master_name)):
(self.master_name)):
msgprint("Please select valid Item Name for Itemwise Discount", raise_exception=1)
elif (self.doc.based_on == 'Grand Total' or \
self.doc.based_on == 'Average Discount') and self.doc.master_name:
elif (self.based_on == 'Grand Total' or \
self.based_on == 'Average Discount') and self.master_name:
msgprint("Please remove Customer/Item Name for %s." %
self.doc.based_on, raise_exception=1)
self.based_on, raise_exception=1)
def validate_rule(self):
if self.doc.transaction != 'Appraisal':
if not self.doc.approving_role and not self.doc.approving_user:
if self.transaction != 'Appraisal':
if not self.approving_role and not self.approving_user:
msgprint("Please enter Approving Role or Approving User", raise_exception=1)
elif self.doc.system_user and self.doc.system_user == self.doc.approving_user:
elif self.system_user and self.system_user == self.approving_user:
msgprint("Approving User cannot be same as user the rule is Applicable To (User)",
raise_exception=1)
elif self.doc.system_role and self.doc.system_role == self.doc.approving_role:
elif self.system_role and self.system_role == self.approving_role:
msgprint("Approving Role cannot be same as user the rule is \
Applicable To (Role).", raise_exception=1)
elif self.doc.system_user and self.doc.approving_role and \
has_common([self.doc.approving_role], [x[0] for x in \
elif self.system_user and self.approving_role and \
has_common([self.approving_role], [x[0] for x in \
frappe.db.sql("select role from `tabUserRole` where parent = %s", \
(self.doc.system_user))]):
(self.system_user))]):
msgprint("System User : %s is assigned role : %s. So rule does not make sense" %
(self.doc.system_user,self.doc.approving_role), raise_exception=1)
elif self.doc.transaction in ['Purchase Order', 'Purchase Receipt', \
'Purchase Invoice', 'Stock Entry'] and self.doc.based_on \
(self.system_user,self.approving_role), raise_exception=1)
elif self.transaction in ['Purchase Order', 'Purchase Receipt', \
'Purchase Invoice', 'Stock Entry'] and self.based_on \
in ['Average Discount', 'Customerwise Discount', 'Itemwise Discount']:
msgprint("You cannot set authorization on basis of Discount for %s" %
self.doc.transaction, raise_exception=1)
elif self.doc.based_on == 'Average Discount' and flt(self.doc.value) > 100.00:
self.transaction, raise_exception=1)
elif self.based_on == 'Average Discount' and flt(self.value) > 100.00:
msgprint("Discount cannot given for more than 100%", raise_exception=1)
elif self.doc.based_on == 'Customerwise Discount' and not self.doc.master_name:
elif self.based_on == 'Customerwise Discount' and not self.master_name:
msgprint("Please enter Customer Name for 'Customerwise Discount'",
raise_exception=1)
else:
if self.doc.transaction == 'Appraisal' and self.doc.based_on != 'Not Applicable':
if self.transaction == 'Appraisal' and self.based_on != 'Not Applicable':
msgprint("Based on should be 'Not Applicable' while setting authorization rule\
for 'Appraisal'", raise_exception=1)
@ -84,4 +84,4 @@ class AuthorizationRule(Document):
self.check_duplicate_entry()
self.validate_rule()
self.validate_master_name()
if not self.doc.value: self.doc.value = 0.0
if not self.value: self.value = 0.0

View File

@ -15,77 +15,77 @@ class Company(Document):
def onload(self):
self.doc.fields["__transactions_exist"] = self.check_if_transactions_exist()
self.set("__transactions_exist", self.check_if_transactions_exist())
def check_if_transactions_exist(self):
exists = False
for doctype in ["Sales Invoice", "Delivery Note", "Sales Order", "Quotation",
"Purchase Invoice", "Purchase Receipt", "Purchase Order", "Supplier Quotation"]:
if frappe.db.sql("""select name from `tab%s` where company=%s and docstatus=1
limit 1""" % (doctype, "%s"), self.doc.name):
limit 1""" % (doctype, "%s"), self.name):
exists = True
break
return exists
def validate(self):
if self.doc.fields.get('__islocal') and len(self.doc.abbr) > 5:
if self.get('__islocal') and len(self.abbr) > 5:
frappe.msgprint("Abbreviation cannot have more than 5 characters",
raise_exception=1)
self.previous_default_currency = frappe.db.get_value("Company", self.doc.name, "default_currency")
if self.doc.default_currency and self.previous_default_currency and \
self.doc.default_currency != self.previous_default_currency and \
self.previous_default_currency = frappe.db.get_value("Company", self.name, "default_currency")
if self.default_currency and self.previous_default_currency and \
self.default_currency != self.previous_default_currency and \
self.check_if_transactions_exist():
msgprint(_("Sorry! You cannot change company's default currency, because there are existing transactions against it. You will need to cancel those transactions if you want to change the default currency."), raise_exception=True)
def on_update(self):
if not frappe.db.sql("""select name from tabAccount
where company=%s and docstatus<2 limit 1""", self.doc.name):
where company=%s and docstatus<2 limit 1""", self.name):
self.create_default_accounts()
self.create_default_warehouses()
self.create_default_web_page()
if not frappe.db.get_value("Cost Center", {"group_or_ledger": "Ledger",
"company": self.doc.name}):
"company": self.name}):
self.create_default_cost_center()
self.set_default_accounts()
if self.doc.default_currency:
frappe.db.set_value("Currency", self.doc.default_currency, "enabled", 1)
if self.default_currency:
frappe.db.set_value("Currency", self.default_currency, "enabled", 1)
def create_default_warehouses(self):
for whname in ("Stores", "Work In Progress", "Finished Goods"):
if not frappe.db.exists("Warehouse", whname + " - " + self.doc.abbr):
if not frappe.db.exists("Warehouse", whname + " - " + self.abbr):
stock_group = frappe.db.get_value("Account", {"account_type": "Stock",
"group_or_ledger": "Group"})
if stock_group:
frappe.bean({
"doctype":"Warehouse",
"warehouse_name": whname,
"company": self.doc.name,
"company": self.name,
"create_account_under": stock_group
}).insert()
def create_default_web_page(self):
if not frappe.db.get_value("Website Settings", None, "home_page") and \
not frappe.db.sql("select name from tabCompany where name!=%s", self.doc.name):
not frappe.db.sql("select name from tabCompany where name!=%s", self.name):
import os
with open(os.path.join(os.path.dirname(__file__), "sample_home_page.html"), "r") as webfile:
webpage = frappe.bean({
"doctype": "Web Page",
"title": self.doc.name + " Home",
"title": self.name + " Home",
"published": 1,
"description": "Standard Home Page for " + self.doc.name,
"main_section": webfile.read() % self.doc.fields
"description": "Standard Home Page for " + self.name,
"main_section": webfile.read() % self.fields
}).insert()
# update in home page in settings
website_settings = frappe.bean("Website Settings", "Website Settings")
website_settings.doc.home_page = webpage.doc.name
website_settings.doc.brand_html = self.doc.name
website_settings.doc.copyright = self.doc.name
website_settings.home_page = webpage.name
website_settings.brand_html = self.name
website_settings.copyright = self.name
website_settings.append("top_bar_items", {
"doctype": "Top Bar Item",
"label":"Contact",
@ -98,21 +98,21 @@ class Company(Document):
})
website_settings.save()
style_settings = frappe.bean("Style Settings", "Style Settings")
style_settings.doc.top_bar_background = "F2F2F2"
style_settings.doc.font_size = "15px"
style_settings.top_bar_background = "F2F2F2"
style_settings.font_size = "15px"
style_settings.save()
def create_default_accounts(self):
if self.doc.chart_of_accounts:
if self.chart_of_accounts:
self.import_chart_of_account()
else:
self.create_standard_accounts()
frappe.db.set(self.doc, "receivables_group", "Accounts Receivable - " + self.doc.abbr)
frappe.db.set(self.doc, "payables_group", "Accounts Payable - " + self.doc.abbr)
frappe.db.set(self.doc, "receivables_group", "Accounts Receivable - " + self.abbr)
frappe.db.set(self.doc, "payables_group", "Accounts Payable - " + self.abbr)
def import_chart_of_account(self):
chart = frappe.bean("Chart of Accounts", self.doc.chart_of_accounts)
chart.make_controller().create_accounts(self.doc.name)
chart = frappe.bean("Chart of Accounts", self.chart_of_accounts)
chart.make_controller().create_accounts(self.name)
def add_acc(self,lst):
account = frappe.bean({
@ -122,16 +122,16 @@ class Company(Document):
})
for d in self.fld_dict.keys():
account.doc.fields[d] = (d == 'parent_account' and lst[self.fld_dict[d]]) and lst[self.fld_dict[d]] +' - '+ self.doc.abbr or lst[self.fld_dict[d]]
account.set(d, (d == 'parent_account' and lst[self.fld_dict[d]]) and lst[self.fld_dict[d]] +' - '+ self.abbr or lst[self.fld_dict[d]])
account.insert()
def set_default_accounts(self):
def _set_default_accounts(accounts):
for field, account_type in accounts.items():
account = frappe.db.get_value("Account", {"account_type": account_type,
"group_or_ledger": "Ledger", "company": self.doc.name})
"group_or_ledger": "Ledger", "company": self.name})
if account and not self.doc.fields.get(field):
if account and not self.get(field):
frappe.db.set(self.doc, field, account)
_set_default_accounts({
@ -149,16 +149,16 @@ class Company(Document):
def create_default_cost_center(self):
cc_list = [
{
'cost_center_name': self.doc.name,
'company':self.doc.name,
'cost_center_name': self.name,
'company':self.name,
'group_or_ledger':'Group',
'parent_cost_center':''
},
{
'cost_center_name':'Main',
'company':self.doc.name,
'company':self.name,
'group_or_ledger':'Ledger',
'parent_cost_center':self.doc.name + ' - ' + self.doc.abbr
'parent_cost_center':self.name + ' - ' + self.abbr
},
]
for cc in cc_list:
@ -166,34 +166,34 @@ class Company(Document):
cc_bean = frappe.bean(cc)
cc_bean.ignore_permissions = True
if cc.get("cost_center_name") == self.doc.name:
if cc.get("cost_center_name") == self.name:
cc_bean.ignore_mandatory = True
cc_bean.insert()
frappe.db.set(self.doc, "cost_center", "Main - " + self.doc.abbr)
frappe.db.set(self.doc, "cost_center", "Main - " + self.abbr)
def on_trash(self):
"""
Trash accounts and cost centers for this company if no gl entry exists
"""
rec = frappe.db.sql("SELECT name from `tabGL Entry` where company = %s", self.doc.name)
rec = frappe.db.sql("SELECT name from `tabGL Entry` where company = %s", self.name)
if not rec:
#delete tabAccount
frappe.db.sql("delete from `tabAccount` where company = %s order by lft desc, rgt desc", self.doc.name)
frappe.db.sql("delete from `tabAccount` where company = %s order by lft desc, rgt desc", self.name)
#delete cost center child table - budget detail
frappe.db.sql("delete bd.* from `tabBudget Detail` bd, `tabCost Center` cc where bd.parent = cc.name and cc.company = %s", self.doc.name)
frappe.db.sql("delete bd.* from `tabBudget Detail` bd, `tabCost Center` cc where bd.parent = cc.name and cc.company = %s", self.name)
#delete cost center
frappe.db.sql("delete from `tabCost Center` WHERE company = %s order by lft desc, rgt desc", self.doc.name)
frappe.db.sql("delete from `tabCost Center` WHERE company = %s order by lft desc, rgt desc", self.name)
if not frappe.db.get_value("Stock Ledger Entry", {"company": self.doc.name}):
frappe.db.sql("""delete from `tabWarehouse` where company=%s""", self.doc.name)
if not frappe.db.get_value("Stock Ledger Entry", {"company": self.name}):
frappe.db.sql("""delete from `tabWarehouse` where company=%s""", self.name)
frappe.defaults.clear_default("company", value=self.doc.name)
frappe.defaults.clear_default("company", value=self.name)
frappe.db.sql("""update `tabSingles` set value=""
where doctype='Global Defaults' and field='default_company'
and value=%s""", self.doc.name)
and value=%s""", self.name)
def before_rename(self, olddn, newdn, merge=False):
if merge:
@ -219,114 +219,114 @@ class Company(Document):
}
acc_list_common = [
['Application of Funds (Assets)','','Group','','Balance Sheet',self.doc.name,''],
['Current Assets','Application of Funds (Assets)','Group','','Balance Sheet',self.doc.name,''],
['Accounts Receivable','Current Assets','Group','','Balance Sheet',self.doc.name,''],
['Bank Accounts','Current Assets','Group','Bank','Balance Sheet',self.doc.name,''],
['Cash In Hand','Current Assets','Group','Cash','Balance Sheet',self.doc.name,''],
['Cash','Cash In Hand','Ledger','Cash','Balance Sheet',self.doc.name,''],
['Loans and Advances (Assets)','Current Assets','Group','','Balance Sheet',self.doc.name,''],
['Securities and Deposits','Current Assets','Group','','Balance Sheet',self.doc.name,''],
['Earnest Money','Securities and Deposits','Ledger','','Balance Sheet',self.doc.name,''],
['Stock Assets','Current Assets','Group','Stock','Balance Sheet',self.doc.name,''],
['Tax Assets','Current Assets','Group','','Balance Sheet',self.doc.name,''],
['Fixed Assets','Application of Funds (Assets)','Group','','Balance Sheet',self.doc.name,''],
['Capital Equipments','Fixed Assets','Ledger','Fixed Asset','Balance Sheet',self.doc.name,''],
['Computers','Fixed Assets','Ledger','Fixed Asset','Balance Sheet',self.doc.name,''],
['Furniture and Fixture','Fixed Assets','Ledger','Fixed Asset','Balance Sheet',self.doc.name,''],
['Office Equipments','Fixed Assets','Ledger','Fixed Asset','Balance Sheet',self.doc.name,''],
['Plant and Machinery','Fixed Assets','Ledger','Fixed Asset','Balance Sheet',self.doc.name,''],
['Investments','Application of Funds (Assets)','Group','','Balance Sheet',self.doc.name,''],
['Temporary Accounts (Assets)','Application of Funds (Assets)','Group','','Balance Sheet',self.doc.name,''],
['Temporary Account (Assets)','Temporary Accounts (Assets)','Ledger','','Balance Sheet',self.doc.name,''],
['Expenses','','Group','Expense Account','Profit and Loss',self.doc.name,''],
['Direct Expenses','Expenses','Group','Expense Account','Profit and Loss',self.doc.name,''],
['Stock Expenses','Direct Expenses','Group','Expense Account','Profit and Loss',self.doc.name,''],
['Cost of Goods Sold','Stock Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Stock Adjustment','Stock Expenses','Ledger','Stock Adjustment','Profit and Loss',self.doc.name,''],
['Expenses Included In Valuation', "Stock Expenses", 'Ledger', 'Expenses Included In Valuation', 'Profit and Loss', self.doc.name, ''],
['Indirect Expenses','Expenses','Group','Expense Account','Profit and Loss',self.doc.name,''],
['Advertising and Publicity','Indirect Expenses','Ledger','Chargeable','Profit and Loss',self.doc.name,''],
['Bad Debts Written Off','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Bank Charges','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Books and Periodicals','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Charity and Donations','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Commission on Sales','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Conveyance Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Customer Entertainment Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Depreciation Account','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Freight and Forwarding Charges','Indirect Expenses','Ledger','Chargeable','Profit and Loss',self.doc.name,''],
['Legal Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Miscellaneous Expenses','Indirect Expenses','Ledger','Chargeable','Profit and Loss',self.doc.name,''],
['Office Maintenance Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Office Rent','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Postal Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Print and Stationary','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Rounded Off','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Salary','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Sales Promotion Expenses','Indirect Expenses','Ledger','Chargeable','Profit and Loss',self.doc.name,''],
['Service Charges Paid','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Staff Welfare Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Telephone Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Travelling Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Water and Electricity Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.doc.name,''],
['Income','','Group','','Profit and Loss',self.doc.name,''],
['Direct Income','Income','Group','Income Account','Profit and Loss',self.doc.name,''],
['Sales','Direct Income','Ledger','Income Account','Profit and Loss',self.doc.name,''],
['Service','Direct Income','Ledger','Income Account','Profit and Loss',self.doc.name,''],
['Indirect Income','Income','Group','Income Account','Profit and Loss',self.doc.name,''],
['Source of Funds (Liabilities)','','Group','','Balance Sheet',self.doc.name,''],
['Capital Account','Source of Funds (Liabilities)','Group','','Balance Sheet',self.doc.name,''],
['Reserves and Surplus','Capital Account','Ledger','','Balance Sheet',self.doc.name,''],
['Shareholders Funds','Capital Account','Ledger','','Balance Sheet',self.doc.name,''],
['Current Liabilities','Source of Funds (Liabilities)','Group','','Balance Sheet',self.doc.name,''],
['Accounts Payable','Current Liabilities','Group','','Balance Sheet',self.doc.name,''],
['Stock Liabilities','Current Liabilities','Group','','Balance Sheet',self.doc.name,''],
['Stock Received But Not Billed', 'Stock Liabilities', 'Ledger', 'Stock Received But Not Billed', 'Balance Sheet', self.doc.name, ''],
['Duties and Taxes','Current Liabilities','Group','','Balance Sheet',self.doc.name,''],
['Loans (Liabilities)','Current Liabilities','Group','','Balance Sheet',self.doc.name,''],
['Secured Loans','Loans (Liabilities)','Group','','Balance Sheet',self.doc.name,''],
['Unsecured Loans','Loans (Liabilities)','Group','','Balance Sheet',self.doc.name,''],
['Bank Overdraft Account','Loans (Liabilities)','Group','','Balance Sheet',self.doc.name,''],
['Temporary Accounts (Liabilities)','Source of Funds (Liabilities)','Group','','Balance Sheet',self.doc.name,''],
['Temporary Account (Liabilities)','Temporary Accounts (Liabilities)','Ledger','','Balance Sheet',self.doc.name,'']
['Application of Funds (Assets)','','Group','','Balance Sheet',self.name,''],
['Current Assets','Application of Funds (Assets)','Group','','Balance Sheet',self.name,''],
['Accounts Receivable','Current Assets','Group','','Balance Sheet',self.name,''],
['Bank Accounts','Current Assets','Group','Bank','Balance Sheet',self.name,''],
['Cash In Hand','Current Assets','Group','Cash','Balance Sheet',self.name,''],
['Cash','Cash In Hand','Ledger','Cash','Balance Sheet',self.name,''],
['Loans and Advances (Assets)','Current Assets','Group','','Balance Sheet',self.name,''],
['Securities and Deposits','Current Assets','Group','','Balance Sheet',self.name,''],
['Earnest Money','Securities and Deposits','Ledger','','Balance Sheet',self.name,''],
['Stock Assets','Current Assets','Group','Stock','Balance Sheet',self.name,''],
['Tax Assets','Current Assets','Group','','Balance Sheet',self.name,''],
['Fixed Assets','Application of Funds (Assets)','Group','','Balance Sheet',self.name,''],
['Capital Equipments','Fixed Assets','Ledger','Fixed Asset','Balance Sheet',self.name,''],
['Computers','Fixed Assets','Ledger','Fixed Asset','Balance Sheet',self.name,''],
['Furniture and Fixture','Fixed Assets','Ledger','Fixed Asset','Balance Sheet',self.name,''],
['Office Equipments','Fixed Assets','Ledger','Fixed Asset','Balance Sheet',self.name,''],
['Plant and Machinery','Fixed Assets','Ledger','Fixed Asset','Balance Sheet',self.name,''],
['Investments','Application of Funds (Assets)','Group','','Balance Sheet',self.name,''],
['Temporary Accounts (Assets)','Application of Funds (Assets)','Group','','Balance Sheet',self.name,''],
['Temporary Account (Assets)','Temporary Accounts (Assets)','Ledger','','Balance Sheet',self.name,''],
['Expenses','','Group','Expense Account','Profit and Loss',self.name,''],
['Direct Expenses','Expenses','Group','Expense Account','Profit and Loss',self.name,''],
['Stock Expenses','Direct Expenses','Group','Expense Account','Profit and Loss',self.name,''],
['Cost of Goods Sold','Stock Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Stock Adjustment','Stock Expenses','Ledger','Stock Adjustment','Profit and Loss',self.name,''],
['Expenses Included In Valuation', "Stock Expenses", 'Ledger', 'Expenses Included In Valuation', 'Profit and Loss', self.name, ''],
['Indirect Expenses','Expenses','Group','Expense Account','Profit and Loss',self.name,''],
['Advertising and Publicity','Indirect Expenses','Ledger','Chargeable','Profit and Loss',self.name,''],
['Bad Debts Written Off','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Bank Charges','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Books and Periodicals','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Charity and Donations','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Commission on Sales','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Conveyance Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Customer Entertainment Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Depreciation Account','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Freight and Forwarding Charges','Indirect Expenses','Ledger','Chargeable','Profit and Loss',self.name,''],
['Legal Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Miscellaneous Expenses','Indirect Expenses','Ledger','Chargeable','Profit and Loss',self.name,''],
['Office Maintenance Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Office Rent','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Postal Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Print and Stationary','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Rounded Off','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Salary','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Sales Promotion Expenses','Indirect Expenses','Ledger','Chargeable','Profit and Loss',self.name,''],
['Service Charges Paid','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Staff Welfare Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Telephone Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Travelling Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Water and Electricity Expenses','Indirect Expenses','Ledger','Expense Account','Profit and Loss',self.name,''],
['Income','','Group','','Profit and Loss',self.name,''],
['Direct Income','Income','Group','Income Account','Profit and Loss',self.name,''],
['Sales','Direct Income','Ledger','Income Account','Profit and Loss',self.name,''],
['Service','Direct Income','Ledger','Income Account','Profit and Loss',self.name,''],
['Indirect Income','Income','Group','Income Account','Profit and Loss',self.name,''],
['Source of Funds (Liabilities)','','Group','','Balance Sheet',self.name,''],
['Capital Account','Source of Funds (Liabilities)','Group','','Balance Sheet',self.name,''],
['Reserves and Surplus','Capital Account','Ledger','','Balance Sheet',self.name,''],
['Shareholders Funds','Capital Account','Ledger','','Balance Sheet',self.name,''],
['Current Liabilities','Source of Funds (Liabilities)','Group','','Balance Sheet',self.name,''],
['Accounts Payable','Current Liabilities','Group','','Balance Sheet',self.name,''],
['Stock Liabilities','Current Liabilities','Group','','Balance Sheet',self.name,''],
['Stock Received But Not Billed', 'Stock Liabilities', 'Ledger', 'Stock Received But Not Billed', 'Balance Sheet', self.name, ''],
['Duties and Taxes','Current Liabilities','Group','','Balance Sheet',self.name,''],
['Loans (Liabilities)','Current Liabilities','Group','','Balance Sheet',self.name,''],
['Secured Loans','Loans (Liabilities)','Group','','Balance Sheet',self.name,''],
['Unsecured Loans','Loans (Liabilities)','Group','','Balance Sheet',self.name,''],
['Bank Overdraft Account','Loans (Liabilities)','Group','','Balance Sheet',self.name,''],
['Temporary Accounts (Liabilities)','Source of Funds (Liabilities)','Group','','Balance Sheet',self.name,''],
['Temporary Account (Liabilities)','Temporary Accounts (Liabilities)','Ledger','','Balance Sheet',self.name,'']
]
acc_list_india = [
['CENVAT Capital Goods','Tax Assets','Ledger','Chargeable','Balance Sheet',self.doc.name,''],
['CENVAT','Tax Assets','Ledger','Chargeable','Balance Sheet',self.doc.name,''],
['CENVAT Service Tax','Tax Assets','Ledger','Chargeable','Balance Sheet',self.doc.name,''],
['CENVAT Service Tax Cess 1','Tax Assets','Ledger','Chargeable','Balance Sheet',self.doc.name,''],
['CENVAT Service Tax Cess 2','Tax Assets','Ledger','Chargeable','Balance Sheet',self.doc.name,''],
['CENVAT Edu Cess','Tax Assets','Ledger','Chargeable','Balance Sheet',self.doc.name,''],
['CENVAT SHE Cess','Tax Assets','Ledger','Chargeable','Balance Sheet',self.doc.name,''],
['Excise Duty 4','Tax Assets','Ledger','Tax','Balance Sheet',self.doc.name,'4.00'],
['Excise Duty 8','Tax Assets','Ledger','Tax','Balance Sheet',self.doc.name,'8.00'],
['Excise Duty 10','Tax Assets','Ledger','Tax','Balance Sheet',self.doc.name,'10.00'],
['Excise Duty 14','Tax Assets','Ledger','Tax','Balance Sheet',self.doc.name,'14.00'],
['Excise Duty Edu Cess 2','Tax Assets','Ledger','Tax','Balance Sheet',self.doc.name,'2.00'],
['Excise Duty SHE Cess 1','Tax Assets','Ledger','Tax','Balance Sheet',self.doc.name,'1.00'],
['P L A','Tax Assets','Ledger','Chargeable','Balance Sheet',self.doc.name,''],
['P L A - Cess Portion','Tax Assets','Ledger','Chargeable','Balance Sheet',self.doc.name,''],
['Edu. Cess on Excise','Duties and Taxes','Ledger','Tax','Balance Sheet',self.doc.name,'2.00'],
['Edu. Cess on Service Tax','Duties and Taxes','Ledger','Tax','Balance Sheet',self.doc.name,'2.00'],
['Edu. Cess on TDS','Duties and Taxes','Ledger','Tax','Balance Sheet',self.doc.name,'2.00'],
['Excise Duty @ 4','Duties and Taxes','Ledger','Tax','Balance Sheet',self.doc.name,'4.00'],
['Excise Duty @ 8','Duties and Taxes','Ledger','Tax','Balance Sheet',self.doc.name,'8.00'],
['Excise Duty @ 10','Duties and Taxes','Ledger','Tax','Balance Sheet',self.doc.name,'10.00'],
['Excise Duty @ 14','Duties and Taxes','Ledger','Tax','Balance Sheet',self.doc.name,'14.00'],
['Service Tax','Duties and Taxes','Ledger','Tax','Balance Sheet',self.doc.name,'10.3'],
['SHE Cess on Excise','Duties and Taxes','Ledger','Tax','Balance Sheet',self.doc.name,'1.00'],
['SHE Cess on Service Tax','Duties and Taxes','Ledger','Tax','Balance Sheet',self.doc.name,'1.00'],
['SHE Cess on TDS','Duties and Taxes','Ledger','Tax','Balance Sheet',self.doc.name,'1.00'],
['Professional Tax','Duties and Taxes','Ledger','Chargeable','Balance Sheet',self.doc.name,''],
['VAT','Duties and Taxes','Ledger','Chargeable','Balance Sheet',self.doc.name,''],
['TDS (Advertisement)','Duties and Taxes','Ledger','Chargeable','Balance Sheet',self.doc.name,''],
['TDS (Commission)','Duties and Taxes','Ledger','Chargeable','Balance Sheet',self.doc.name,''],
['TDS (Contractor)','Duties and Taxes','Ledger','Chargeable','Balance Sheet',self.doc.name,''],
['TDS (Interest)','Duties and Taxes','Ledger','Chargeable','Balance Sheet',self.doc.name,''],
['TDS (Rent)','Duties and Taxes','Ledger','Chargeable','Balance Sheet',self.doc.name,''],
['TDS (Salary)','Duties and Taxes','Ledger','Chargeable','Balance Sheet',self.doc.name,'']
['CENVAT Capital Goods','Tax Assets','Ledger','Chargeable','Balance Sheet',self.name,''],
['CENVAT','Tax Assets','Ledger','Chargeable','Balance Sheet',self.name,''],
['CENVAT Service Tax','Tax Assets','Ledger','Chargeable','Balance Sheet',self.name,''],
['CENVAT Service Tax Cess 1','Tax Assets','Ledger','Chargeable','Balance Sheet',self.name,''],
['CENVAT Service Tax Cess 2','Tax Assets','Ledger','Chargeable','Balance Sheet',self.name,''],
['CENVAT Edu Cess','Tax Assets','Ledger','Chargeable','Balance Sheet',self.name,''],
['CENVAT SHE Cess','Tax Assets','Ledger','Chargeable','Balance Sheet',self.name,''],
['Excise Duty 4','Tax Assets','Ledger','Tax','Balance Sheet',self.name,'4.00'],
['Excise Duty 8','Tax Assets','Ledger','Tax','Balance Sheet',self.name,'8.00'],
['Excise Duty 10','Tax Assets','Ledger','Tax','Balance Sheet',self.name,'10.00'],
['Excise Duty 14','Tax Assets','Ledger','Tax','Balance Sheet',self.name,'14.00'],
['Excise Duty Edu Cess 2','Tax Assets','Ledger','Tax','Balance Sheet',self.name,'2.00'],
['Excise Duty SHE Cess 1','Tax Assets','Ledger','Tax','Balance Sheet',self.name,'1.00'],
['P L A','Tax Assets','Ledger','Chargeable','Balance Sheet',self.name,''],
['P L A - Cess Portion','Tax Assets','Ledger','Chargeable','Balance Sheet',self.name,''],
['Edu. Cess on Excise','Duties and Taxes','Ledger','Tax','Balance Sheet',self.name,'2.00'],
['Edu. Cess on Service Tax','Duties and Taxes','Ledger','Tax','Balance Sheet',self.name,'2.00'],
['Edu. Cess on TDS','Duties and Taxes','Ledger','Tax','Balance Sheet',self.name,'2.00'],
['Excise Duty @ 4','Duties and Taxes','Ledger','Tax','Balance Sheet',self.name,'4.00'],
['Excise Duty @ 8','Duties and Taxes','Ledger','Tax','Balance Sheet',self.name,'8.00'],
['Excise Duty @ 10','Duties and Taxes','Ledger','Tax','Balance Sheet',self.name,'10.00'],
['Excise Duty @ 14','Duties and Taxes','Ledger','Tax','Balance Sheet',self.name,'14.00'],
['Service Tax','Duties and Taxes','Ledger','Tax','Balance Sheet',self.name,'10.3'],
['SHE Cess on Excise','Duties and Taxes','Ledger','Tax','Balance Sheet',self.name,'1.00'],
['SHE Cess on Service Tax','Duties and Taxes','Ledger','Tax','Balance Sheet',self.name,'1.00'],
['SHE Cess on TDS','Duties and Taxes','Ledger','Tax','Balance Sheet',self.name,'1.00'],
['Professional Tax','Duties and Taxes','Ledger','Chargeable','Balance Sheet',self.name,''],
['VAT','Duties and Taxes','Ledger','Chargeable','Balance Sheet',self.name,''],
['TDS (Advertisement)','Duties and Taxes','Ledger','Chargeable','Balance Sheet',self.name,''],
['TDS (Commission)','Duties and Taxes','Ledger','Chargeable','Balance Sheet',self.name,''],
['TDS (Contractor)','Duties and Taxes','Ledger','Chargeable','Balance Sheet',self.name,''],
['TDS (Interest)','Duties and Taxes','Ledger','Chargeable','Balance Sheet',self.name,''],
['TDS (Rent)','Duties and Taxes','Ledger','Chargeable','Balance Sheet',self.name,''],
['TDS (Salary)','Duties and Taxes','Ledger','Chargeable','Balance Sheet',self.name,'']
]
# load common account heads
for d in acc_list_common:

View File

@ -11,10 +11,10 @@ from frappe.model.controller import DocListController
class CurrencyExchange(DocListController):
def autoname(self):
self.doc.name = self.doc.from_currency + "-" + self.doc.to_currency
self.name = self.from_currency + "-" + self.to_currency
def validate(self):
self.validate_value("exchange_rate", ">", 0)
if self.doc.from_currency == self.doc.to_currency:
if self.from_currency == self.to_currency:
msgprint(_("From Currency and To Currency cannot be same"), raise_exception=True)

View File

@ -12,10 +12,10 @@ class CustomerGroup(DocTypeNestedSet):
def validate(self):
if frappe.db.sql("select name from `tabCustomer Group` where name = %s and docstatus = 2",
(self.doc.customer_group_name)):
(self.customer_group_name)):
msgprint("""Another %s record is trashed.
To untrash please go to Setup -> Recycle Bin.""" %
(self.doc.customer_group_name), raise_exception = 1)
(self.customer_group_name), raise_exception = 1)
def on_update(self):
self.validate_name_with_customer()
@ -23,23 +23,23 @@ class CustomerGroup(DocTypeNestedSet):
self.validate_one_root()
def validate_name_with_customer(self):
if frappe.db.exists("Customer", self.doc.name):
if frappe.db.exists("Customer", self.name):
frappe.msgprint("An Customer exists with same name (%s), \
please change the Customer Group name or rename the Customer" %
self.doc.name, raise_exception=1)
self.name, raise_exception=1)
def on_trash(self):
cust = frappe.db.sql("select name from `tabCustomer` where ifnull(customer_group, '') = %s",
self.doc.name)
self.name)
cust = [d[0] for d in cust]
if cust:
msgprint("""Customer Group: %s can not be trashed/deleted \
because it is used in customer: %s.
To trash/delete this, remove/change customer group in customer master""" %
(self.doc.name, cust or ''), raise_exception=1)
(self.name, cust or ''), raise_exception=1)
if frappe.db.sql("select name from `tabCustomer Group` where parent_customer_group = %s \
and docstatus != 2", self.doc.name):
and docstatus != 2", self.name):
msgprint("Child customer group exists for this customer group. \
You can not trash/cancel/delete this customer group.", raise_exception=1)

View File

@ -50,7 +50,7 @@ class EmailDigest(DocListController):
super(EmailDigest, self).__init__(arg1, arg2)
self.from_date, self.to_date = self.get_from_to_date()
self.future_from_date, self.future_to_date = self.get_future_from_to_date()
self.currency = frappe.db.get_value("Company", self.doc.company,
self.currency = frappe.db.get_value("Company", self.company,
"default_currency")
def get_users(self):
@ -61,8 +61,8 @@ class EmailDigest(DocListController):
and user_type != "Website User"
order by enabled desc, name asc""".format(", ".join(["%s"]*len(STANDARD_USERS))), STANDARD_USERS, as_dict=1)
if self.doc.recipient_list:
recipient_list = self.doc.recipient_list.split("\n")
if self.recipient_list:
recipient_list = self.recipient_list.split("\n")
else:
recipient_list = []
for p in user_list:
@ -75,7 +75,7 @@ class EmailDigest(DocListController):
valid_users = [p[0] for p in frappe.db.sql("""select name from `tabUser`
where enabled=1""")]
recipients = filter(lambda r: r in valid_users,
self.doc.recipient_list.split("\n"))
self.recipient_list.split("\n"))
common_msg = self.get_common_content()
if recipients:
@ -85,7 +85,7 @@ class EmailDigest(DocListController):
if msg_for_this_receipient:
sendmail(recipients=user_id,
subject="[ERPNext] [{frequency} Digest] {name}".format(
frequency=self.doc.frequency, name=self.doc.name),
frequency=self.frequency, name=self.name),
msg=msg_for_this_receipient)
def get_digest_msg(self):
@ -97,7 +97,7 @@ class EmailDigest(DocListController):
for module, content in content_sequence:
module_out = []
for ctype in content:
if self.doc.fields.get(ctype) and hasattr(self, "get_"+ctype):
if self.get(ctype) and hasattr(self, "get_"+ctype):
module_out.append(getattr(self, "get_"+ctype)())
if any([m[0] for m in module_out]):
out += [[1, "<h4>" + _(module) + "</h4>"]] + module_out + [[1, "<hr>"]]
@ -114,7 +114,7 @@ class EmailDigest(DocListController):
out = []
for ctype in user_specific_content:
if self.doc.fields.get(ctype) and hasattr(self, "get_"+ctype):
if self.get(ctype) and hasattr(self, "get_"+ctype):
out.append(getattr(self, "get_"+ctype)(user_id))
frappe.session.user = original_session_user
@ -139,16 +139,16 @@ class EmailDigest(DocListController):
if no_value:
no_value = """<h4>No Updates For:</h4>""" + "\n".join(no_value)
date = self.doc.frequency == "Daily" and formatdate(self.from_date) or \
date = self.frequency == "Daily" and formatdate(self.from_date) or \
"%s to %s" % (formatdate(self.from_date), formatdate(self.to_date))
msg = digest_template % {
"digest": self.doc.frequency + " Digest",
"digest": self.frequency + " Digest",
"date": date,
"company": self.doc.company,
"company": self.company,
"with_value": with_value,
"no_value": no_value or "",
"name": self.doc.name
"name": self.name
}
return msg
@ -337,7 +337,7 @@ class EmailDigest(DocListController):
def get_new_count(self, doctype, label, docstatus=0, filter_by_company=True):
if filter_by_company:
company = """and company="%s" """ % self.doc.company.replace('"', '\"')
company = """and company="%s" """ % self.company.replace('"', '\"')
else:
company = ""
count = frappe.db.sql("""select count(*) from `tab%s`
@ -352,7 +352,7 @@ class EmailDigest(DocListController):
count_sum = frappe.db.sql("""select count(*), sum(ifnull(`%s`, 0))
from `tab%s` where docstatus=1 and company = %s and
date(creation)>=%s and date(creation)<=%s""" % (sum_field, doctype, "%s",
"%s", "%s"), (self.doc.company, self.from_date, self.to_date))
"%s", "%s"), (self.company, self.from_date, self.to_date))
count, total = count_sum and count_sum[0] or (0, 0)
return count, self.get_html(label, self.currency,
@ -379,7 +379,7 @@ class EmailDigest(DocListController):
where company=%s
and posting_date <= %s %s""" % ("%s", "%s",
from_date and "and posting_date>='%s'" % from_date or ""),
(self.doc.company, to_date or self.to_date), as_dict=1)
(self.company, to_date or self.to_date), as_dict=1)
# cache if it is the normal cases
if from_date==self.from_date and to_date==self.to_date:
@ -393,17 +393,17 @@ class EmailDigest(DocListController):
root_type, account_type, account_name, master_type
from `tabAccount` where company=%s and docstatus < 2
and group_or_ledger = "Ledger" order by lft""",
(self.doc.company,), as_dict=1)
(self.company,), as_dict=1)
return self.accounts
def get_from_to_date(self):
today = now_datetime().date()
# decide from date based on email digest frequency
if self.doc.frequency == "Daily":
if self.frequency == "Daily":
# from date, to_date is yesterday
from_date = to_date = today - timedelta(days=1)
elif self.doc.frequency == "Weekly":
elif self.frequency == "Weekly":
# from date is the previous week's monday
from_date = today - timedelta(days=today.weekday(), weeks=1)
# to date is sunday i.e. the previous day
@ -420,10 +420,10 @@ class EmailDigest(DocListController):
today = now_datetime().date()
# decide from date based on email digest frequency
if self.doc.frequency == "Daily":
if self.frequency == "Daily":
# from date, to_date is today
from_date = to_date = today
elif self.doc.frequency == "Weekly":
elif self.frequency == "Weekly":
# from date is the current week's monday
from_date = today - timedelta(days=today.weekday())
# to date is the current week's sunday
@ -441,13 +441,13 @@ class EmailDigest(DocListController):
send_date = to_date + timedelta(days=1)
if self.doc.frequency == "Daily":
if self.frequency == "Daily":
next_send_date = send_date + timedelta(days=1)
elif self.doc.frequency == "Weekly":
elif self.frequency == "Weekly":
next_send_date = send_date + timedelta(weeks=1)
else:
next_send_date = send_date + relativedelta(months=1)
self.doc.next_send = formatdate(next_send_date) + " at midnight"
self.next_send = formatdate(next_send_date) + " at midnight"
return send_date

View File

@ -12,6 +12,6 @@ class FeaturesSetup(Document):
"""
from frappe.model import default_fields
from frappe.utils import set_default
for key in self.doc.fields:
for key in self.fields:
if key not in default_fields:
set_default(key, self.doc.fields[key])
set_default(key, self.fields[key])

View File

@ -32,11 +32,11 @@ class GlobalDefaults(Document):
self.update_control_panel()
for key in keydict:
frappe.db.set_default(key, self.doc.fields.get(keydict[key], ''))
frappe.db.set_default(key, self.get(keydict[key], ''))
# update year start date and year end date from fiscal_year
year_start_end_date = frappe.db.sql("""select year_start_date, year_end_date
from `tabFiscal Year` where name=%s""", self.doc.current_fiscal_year)
from `tabFiscal Year` where name=%s""", self.current_fiscal_year)
ysd = year_start_end_date[0][0] or ''
yed = year_start_end_date[0][1] or ''
@ -46,25 +46,25 @@ class GlobalDefaults(Document):
frappe.db.set_default('year_end_date', yed.strftime('%Y-%m-%d'))
# enable default currency
if self.doc.default_currency:
frappe.db.set_value("Currency", self.doc.default_currency, "enabled", 1)
if self.default_currency:
frappe.db.set_value("Currency", self.default_currency, "enabled", 1)
# clear cache
frappe.clear_cache()
def validate_session_expiry(self):
if self.doc.session_expiry:
parts = self.doc.session_expiry.split(":")
if self.session_expiry:
parts = self.session_expiry.split(":")
if len(parts)!=2 or not (cint(parts[0]) or cint(parts[1])):
frappe.msgprint("""Session Expiry must be in format hh:mm""",
raise_exception=1)
def update_control_panel(self):
cp_bean = frappe.bean("Control Panel")
if self.doc.country:
cp_bean.doc.country = self.doc.country
if self.doc.time_zone:
cp_bean.doc.time_zone = self.doc.time_zone
if self.country:
cp_bean.country = self.country
if self.time_zone:
cp_bean.time_zone = self.time_zone
cp_bean.ignore_permissions = True
cp_bean.save()

View File

@ -10,9 +10,9 @@ class ItemGroup(DocTypeNestedSet):
self.nsm_parent_field = 'parent_item_group'
def validate(self):
if not self.doc.parent_website_route:
self.doc.parent_website_route = frappe.get_website_route("Item Group",
self.doc.parent_item_group)
if not self.parent_website_route:
self.parent_website_route = frappe.get_website_route("Item Group",
self.parent_item_group)
def on_update(self):
DocTypeNestedSet.on_update(self)
@ -22,6 +22,6 @@ class ItemGroup(DocTypeNestedSet):
self.validate_one_root()
def validate_name_with_item(self):
if frappe.db.exists("Item", self.doc.name):
if frappe.db.exists("Item", self.name):
frappe.msgprint("An item exists with same name (%s), please change the \
item group name or rename the item" % self.doc.name, raise_exception=1)
item group name or rename the item" % self.name, raise_exception=1)

View File

@ -128,11 +128,11 @@ class TestItem(unittest.TestCase):
def test_recursion(self):
group_b = frappe.bean("Item Group", "_Test Item Group B")
group_b.doc.parent_item_group = "_Test Item Group B - 3"
group_b.parent_item_group = "_Test Item Group B - 3"
self.assertRaises(NestedSetRecursionError, group_b.save)
# cleanup
group_b.doc.parent_item_group = "All Item Groups"
group_b.parent_item_group = "All Item Groups"
group_b.save()
def test_rebuild_tree(self):
@ -141,7 +141,7 @@ class TestItem(unittest.TestCase):
def move_it_back(self):
group_b = frappe.bean("Item Group", "_Test Item Group B")
group_b.doc.parent_item_group = "All Item Groups"
group_b.parent_item_group = "All Item Groups"
group_b.save()
self.test_basic_tree()
@ -151,9 +151,9 @@ class TestItem(unittest.TestCase):
# put B under C
group_b = frappe.bean("Item Group", "_Test Item Group B")
lft, rgt = group_b.doc.lft, group_b.doc.rgt
lft, rgt = group_b.lft, group_b.rgt
group_b.doc.parent_item_group = "_Test Item Group C"
group_b.parent_item_group = "_Test Item Group C"
group_b.save()
self.test_basic_tree()
@ -170,7 +170,7 @@ class TestItem(unittest.TestCase):
def test_move_group_into_root(self):
group_b = frappe.bean("Item Group", "_Test Item Group B")
group_b.doc.parent_item_group = ""
group_b.parent_item_group = ""
self.assertRaises(NestedSetMultipleRootsError, group_b.save)
# trick! works because it hasn't been rolled back :D
@ -187,10 +187,10 @@ class TestItem(unittest.TestCase):
old_lft, old_rgt = frappe.db.get_value("Item Group", "_Test Item Group C", ["lft", "rgt"])
group_b_3 = frappe.bean("Item Group", "_Test Item Group B - 3")
lft, rgt = group_b_3.doc.lft, group_b_3.doc.rgt
lft, rgt = group_b_3.lft, group_b_3.rgt
# child of right sibling is moved into it
group_b_3.doc.parent_item_group = "_Test Item Group C"
group_b_3.parent_item_group = "_Test Item Group C"
group_b_3.save()
self.test_basic_tree()
@ -204,7 +204,7 @@ class TestItem(unittest.TestCase):
# move it back
group_b_3 = frappe.bean("Item Group", "_Test Item Group B - 3")
group_b_3.doc.parent_item_group = "_Test Item Group B"
group_b_3.parent_item_group = "_Test Item Group B"
group_b_3.save()
self.test_basic_tree()
@ -251,7 +251,7 @@ class TestItem(unittest.TestCase):
where parent_item_group='_Test Item Group C'"""):
bean = frappe.bean("Item Group", name)
bean.doc.parent_item_group = "_Test Item Group B"
bean.parent_item_group = "_Test Item Group B"
bean.save()
self.test_basic_tree()

View File

@ -13,8 +13,8 @@ from frappe.model.document import Document
class JobsEmailSettings(Document):
def validate(self):
if cint(self.doc.extract_emails) and not (self.doc.email_id and self.doc.host and \
self.doc.username and self.doc.password):
if cint(self.extract_emails) and not (self.email_id and self.host and \
self.username and self.password):
frappe.msgprint(_("""Host, Email and Password required if emails are to be pulled"""),
raise_exception=True)

View File

@ -31,10 +31,10 @@ class NamingSeries(Document):
def update_series(self, arg=None):
"""update series list"""
self.check_duplicate()
series_list = self.doc.set_options.split("\n")
series_list = self.set_options.split("\n")
# set in doctype
self.set_series_for(self.doc.select_doc_for_series, series_list)
self.set_series_for(self.select_doc_for_series, series_list)
# create series
map(self.insert_series, [d.split('.')[0] for d in series_list])
@ -49,7 +49,7 @@ class NamingSeries(Document):
# validate names
for i in options: self.validate_series_name(i)
if self.doc.user_must_always_select:
if self.user_must_always_select:
options = [''] + options
default = ''
else:
@ -78,7 +78,7 @@ class NamingSeries(Document):
})
ps.save()
self.doc.set_options = "\n".join(options)
self.set_options = "\n".join(options)
frappe.clear_cache(doctype=doctype)
@ -90,17 +90,17 @@ class NamingSeries(Document):
frappe.db.sql_list("""select dt.name
from `tabDocField` df, `tabDocType` dt
where dt.name = df.parent and df.fieldname='naming_series' and dt.name != %s""",
self.doc.select_doc_for_series)
self.select_doc_for_series)
+ frappe.db.sql_list("""select dt.name
from `tabCustom Field` df, `tabDocType` dt
where dt.name = df.dt and df.fieldname='naming_series' and dt.name != %s""",
self.doc.select_doc_for_series)
self.select_doc_for_series)
))
sr = [[frappe.model.doctype.get_property(p, 'options', 'naming_series'), p]
for p in parent]
options = self.scrub_options_list(self.doc.set_options.split("\n"))
options = self.scrub_options_list(self.set_options.split("\n"))
for series in options:
dt.validate_series(series, self.doc.select_doc_for_series)
dt.validate_series(series, self.select_doc_for_series)
for i in sr:
if i[0]:
existing_series = [d.split('.')[0] for d in i[0].split("\n")]
@ -120,15 +120,15 @@ class NamingSeries(Document):
throw('Special Characters except "-" and "/" not allowed in naming series')
def get_options(self, arg=''):
sr = frappe.model.doctype.get_property(self.doc.select_doc_for_series,
sr = frappe.model.doctype.get_property(self.select_doc_for_series,
'options', 'naming_series')
return sr
def get_current(self, arg=None):
"""get series current"""
if self.doc.prefix:
self.doc.current_value = frappe.db.get_value("Series",
self.doc.prefix.split('.')[0], "current")
if self.prefix:
self.current_value = frappe.db.get_value("Series",
self.prefix.split('.')[0], "current")
def insert_series(self, series):
"""insert series if missing"""
@ -136,11 +136,11 @@ class NamingSeries(Document):
frappe.db.sql("insert into tabSeries (name, current) values (%s, 0)", (series))
def update_series_start(self):
if self.doc.prefix:
prefix = self.doc.prefix.split('.')[0]
if self.prefix:
prefix = self.prefix.split('.')[0]
self.insert_series(prefix)
frappe.db.sql("update `tabSeries` set current = %s where name = %s",
(self.doc.current_value, prefix))
(self.current_value, prefix))
msgprint(_("Series Updated Successfully"))
else:
msgprint(_("Please select prefix first"))

View File

@ -18,7 +18,7 @@ class NotificationControl(Document):
return v and v[0][0] or ''
def set_message(self, arg = ''):
fn = self.doc.select_transaction.lower().replace(' ', '_') + '_message'
frappe.db.set(self.doc, fn, self.doc.custom_message)
msgprint("Custom Message for %s updated!" % self.doc.select_transaction)
fn = self.select_transaction.lower().replace(' ', '_') + '_message'
frappe.db.set(self.doc, fn, self.custom_message)
msgprint("Custom Message for %s updated!" % self.select_transaction)

View File

@ -13,8 +13,8 @@ from frappe.model.document import Document
class SalesEmailSettings(Document):
def validate(self):
if cint(self.doc.extract_emails) and not (self.doc.email_id and self.doc.host and \
self.doc.username and self.doc.password):
if cint(self.extract_emails) and not (self.email_id and self.host and \
self.username and self.password):
frappe.msgprint(_("""Host, Email and Password required if emails are to be pulled"""),
raise_exception=True)

View File

@ -8,8 +8,8 @@ from frappe.model.document import Document
class SalesPartner(Document):
def validate(self):
if self.doc.partner_website and not self.doc.partner_website.startswith("http"):
self.doc.partner_website = "http://" + self.doc.partner_website
if self.partner_website and not self.partner_website.startswith("http"):
self.partner_website = "http://" + self.partner_website
def get_contacts(self, nm):
if nm:
@ -21,4 +21,4 @@ class SalesPartner(Document):
return ''
def get_page_title(self):
return self.doc.partner_name
return self.partner_name

View File

@ -20,9 +20,9 @@ class SalesPerson(DocTypeNestedSet):
self.validate_one_root()
def get_email_id(self):
if self.doc.employee:
user = frappe.db.get_value("Employee", self.doc.employee, "user_id")
if self.employee:
user = frappe.db.get_value("Employee", self.employee, "user_id")
if not user:
frappe.throw("User ID not set for Employee %s" % self.doc.employee)
frappe.throw("User ID not set for Employee %s" % self.employee)
else:
return frappe.db.get_value("User", user, "email") or user

View File

@ -114,8 +114,8 @@ def import_defaults():
bean = frappe.bean(r)
# ignore mandatory for root
parent_link_field = ("parent_" + scrub(bean.doc.doctype))
if parent_link_field in bean.doc.fields and not bean.doc.fields.get(parent_link_field):
parent_link_field = ("parent_" + scrub(bean.doctype))
if parent_link_field in bean.fields and not bean.get(parent_link_field):
bean.ignore_mandatory = True
bean.insert()
@ -133,7 +133,7 @@ def feature_setup():
'fs_recurring_invoice', 'fs_pos', 'fs_manufacturing', 'fs_quality',
'fs_page_break', 'fs_more_info', 'fs_pos_view'
]
bean.doc.fields.update(dict(zip(flds, [1]*len(flds))))
bean.update(dict(zip(flds, [1]*len(flds))))
bean.save()
def set_single_defaults():
@ -144,7 +144,7 @@ def set_single_defaults():
try:
b = frappe.bean(dt, dt)
for fieldname, value in default_values:
b.doc.fields[fieldname] = value
b.set(fieldname, value)
b.save()
except frappe.MandatoryError:
pass

View File

@ -117,7 +117,7 @@ def set_defaults(args):
frappe.db.set_value("Currency", args.get("currency"), "enabled", 1)
global_defaults = frappe.bean("Global Defaults", "Global Defaults")
global_defaults.doc.fields.update({
global_defaults.update({
'current_fiscal_year': args.curr_fiscal_year,
'default_currency': args.get('currency'),
'default_company':args.get('company_name'),
@ -129,41 +129,41 @@ def set_defaults(args):
global_defaults.save()
accounts_settings = frappe.bean("Accounts Settings")
accounts_settings.doc.auto_accounting_for_stock = 1
accounts_settings.auto_accounting_for_stock = 1
accounts_settings.save()
stock_settings = frappe.bean("Stock Settings")
stock_settings.doc.item_naming_by = "Item Code"
stock_settings.doc.valuation_method = "FIFO"
stock_settings.doc.stock_uom = "Nos"
stock_settings.doc.auto_indent = 1
stock_settings.item_naming_by = "Item Code"
stock_settings.valuation_method = "FIFO"
stock_settings.stock_uom = "Nos"
stock_settings.auto_indent = 1
stock_settings.save()
selling_settings = frappe.bean("Selling Settings")
selling_settings.doc.cust_master_name = "Customer Name"
selling_settings.doc.so_required = "No"
selling_settings.doc.dn_required = "No"
selling_settings.cust_master_name = "Customer Name"
selling_settings.so_required = "No"
selling_settings.dn_required = "No"
selling_settings.save()
buying_settings = frappe.bean("Buying Settings")
buying_settings.doc.supp_master_name = "Supplier Name"
buying_settings.doc.po_required = "No"
buying_settings.doc.pr_required = "No"
buying_settings.doc.maintain_same_rate = 1
buying_settings.supp_master_name = "Supplier Name"
buying_settings.po_required = "No"
buying_settings.pr_required = "No"
buying_settings.maintain_same_rate = 1
buying_settings.save()
notification_control = frappe.bean("Notification Control")
notification_control.doc.quotation = 1
notification_control.doc.sales_invoice = 1
notification_control.doc.purchase_order = 1
notification_control.quotation = 1
notification_control.sales_invoice = 1
notification_control.purchase_order = 1
notification_control.save()
hr_settings = frappe.bean("HR Settings")
hr_settings.doc.emp_created_by = "Naming Series"
hr_settings.emp_created_by = "Naming Series"
hr_settings.save()
email_settings = frappe.bean("Outgoing Email Settings")
email_settings.doc.send_print_in_body_and_attachment = 1
email_settings.send_print_in_body_and_attachment = 1
email_settings.save()
# control panel
@ -196,14 +196,14 @@ def create_email_digest():
for fieldname in edigest.meta.get_fieldnames({"fieldtype": "Check"}):
if fieldname != "scheduler_errors":
edigest.doc.fields[fieldname] = 1
edigest.set(fieldname, 1)
edigest.insert()
# scheduler errors digest
if companies:
edigest = frappe.new_bean("Email Digest")
edigest.doc.fields.update({
edigest.update({
"name": "Scheduler Errors",
"company": companies[0],
"frequency": "Daily",

View File

@ -11,7 +11,7 @@ def boot_session(bootinfo):
import frappe.model.doc
bootinfo['custom_css'] = frappe.db.get_value('Style Settings', None, 'custom_css') or ''
bootinfo['website_settings'] = frappe.model.doc.getsingle('Website Settings')
bootinfo['website_settings'] = frappe.model.getsingle('Website Settings')
if frappe.session['user']!='Guest':
bootinfo['letter_heads'] = get_letter_heads()

View File

@ -14,19 +14,19 @@ from frappe.model.document import Document
class Bin(Document):
def validate(self):
if self.doc.fields.get("__islocal") or not self.doc.stock_uom:
self.doc.stock_uom = frappe.db.get_value('Item', self.doc.item_code, 'stock_uom')
if self.get("__islocal") or not self.stock_uom:
self.stock_uom = frappe.db.get_value('Item', self.item_code, 'stock_uom')
self.validate_mandatory()
self.doc.projected_qty = flt(self.doc.actual_qty) + flt(self.doc.ordered_qty) + \
flt(self.doc.indented_qty) + flt(self.doc.planned_qty) - flt(self.doc.reserved_qty)
self.projected_qty = flt(self.actual_qty) + flt(self.ordered_qty) + \
flt(self.indented_qty) + flt(self.planned_qty) - flt(self.reserved_qty)
def validate_mandatory(self):
qf = ['actual_qty', 'reserved_qty', 'ordered_qty', 'indented_qty']
for f in qf:
if (not self.doc.fields.has_key(f)) or (not self.doc.fields[f]):
self.doc.fields[f] = 0.0
if (not self.has_key(f)) or (not self.fields[f]):
self.set(f, 0.0)
def update_stock(self, args):
self.update_qty(args)
@ -39,24 +39,24 @@ class Bin(Document):
# update valuation and qty after transaction for post dated entry
update_entries_after({
"item_code": self.doc.item_code,
"warehouse": self.doc.warehouse,
"item_code": self.item_code,
"warehouse": self.warehouse,
"posting_date": args.get("posting_date"),
"posting_time": args.get("posting_time")
})
def update_qty(self, args):
# update the stock values (for current quantities)
self.doc.actual_qty = flt(self.doc.actual_qty) + flt(args.get("actual_qty"))
self.doc.ordered_qty = flt(self.doc.ordered_qty) + flt(args.get("ordered_qty"))
self.doc.reserved_qty = flt(self.doc.reserved_qty) + flt(args.get("reserved_qty"))
self.doc.indented_qty = flt(self.doc.indented_qty) + flt(args.get("indented_qty"))
self.doc.planned_qty = flt(self.doc.planned_qty) + flt(args.get("planned_qty"))
self.actual_qty = flt(self.actual_qty) + flt(args.get("actual_qty"))
self.ordered_qty = flt(self.ordered_qty) + flt(args.get("ordered_qty"))
self.reserved_qty = flt(self.reserved_qty) + flt(args.get("reserved_qty"))
self.indented_qty = flt(self.indented_qty) + flt(args.get("indented_qty"))
self.planned_qty = flt(self.planned_qty) + flt(args.get("planned_qty"))
self.doc.projected_qty = flt(self.doc.actual_qty) + flt(self.doc.ordered_qty) + \
flt(self.doc.indented_qty) + flt(self.doc.planned_qty) - flt(self.doc.reserved_qty)
self.projected_qty = flt(self.actual_qty) + flt(self.ordered_qty) + \
flt(self.indented_qty) + flt(self.planned_qty) - flt(self.reserved_qty)
self.doc.save()
self.save()
def get_first_sle(self):
sle = frappe.db.sql("""
@ -65,5 +65,5 @@ class Bin(Document):
and warehouse = %s
order by timestamp(posting_date, posting_time) asc, name asc
limit 1
""", (self.doc.item_code, self.doc.warehouse), as_dict=1)
""", (self.item_code, self.warehouse), as_dict=1)
return sle and sle[0] or None

Some files were not shown because too many files have changed in this diff Show More