Replaced doc, doc.fields frappe/frappe#478
This commit is contained in:
parent
67d6a4e3aa
commit
f78d1aee28
@ -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"""))
|
||||
|
@ -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()
|
||||
|
@ -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 = []
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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)
|
@ -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:
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}))
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 = ""
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
@ -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")
|
||||
|
@ -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 = [
|
||||
[
|
||||
|
@ -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):
|
||||
|
@ -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]
|
||||
|
@ -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")
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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 = ''
|
||||
|
@ -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()
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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])
|
||||
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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')
|
||||
|
@ -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)
|
@ -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)
|
@ -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):
|
||||
|
@ -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'):
|
||||
|
@ -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,))
|
||||
|
@ -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()
|
||||
|
@ -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')):
|
||||
|
@ -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
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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""",
|
||||
|
@ -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:
|
||||
|
@ -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])
|
||||
|
@ -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.")
|
||||
|
@ -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:
|
||||
|
@ -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"]
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)]
|
@ -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]
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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
|
||||
})
|
||||
|
||||
|
@ -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()
|
@ -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()
|
@ -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()
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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),
|
||||
|
@ -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 = [[
|
||||
{
|
||||
|
@ -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()
|
@ -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 = ''
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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:
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)))
|
@ -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:
|
||||
|
@ -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
|
@ -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:
|
||||
|
@ -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)
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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])
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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)
|
@ -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"))
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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()
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user