Merge branch 'wsgi' of https://github.com/webnotes/erpnext into i18n
Conflicts: accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js public/js/complete_setup.js selling/doctype/opportunity/opportunity.js selling/doctype/quotation/quotation.js
This commit is contained in:
commit
4b41e5f7f7
@ -7,7 +7,6 @@ import webnotes
|
|||||||
from webnotes.utils import flt, fmt_money, cstr, cint
|
from webnotes.utils import flt, fmt_money, cstr, cint
|
||||||
from webnotes import msgprint, _
|
from webnotes import msgprint, _
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
get_value = webnotes.conn.get_value
|
get_value = webnotes.conn.get_value
|
||||||
|
|
||||||
class DocType:
|
class DocType:
|
||||||
@ -25,17 +24,6 @@ class DocType:
|
|||||||
self.doc.master_name, "address")
|
self.doc.master_name, "address")
|
||||||
}
|
}
|
||||||
|
|
||||||
def validate(self):
|
|
||||||
self.validate_master_name()
|
|
||||||
self.validate_parent()
|
|
||||||
self.validate_duplicate_account()
|
|
||||||
self.validate_root_details()
|
|
||||||
self.validate_mandatory()
|
|
||||||
self.validate_warehouse_account()
|
|
||||||
|
|
||||||
if not self.doc.parent_account:
|
|
||||||
self.doc.parent_account = ''
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_master_name()
|
self.validate_master_name()
|
||||||
self.validate_parent()
|
self.validate_parent()
|
||||||
@ -56,7 +44,7 @@ class DocType:
|
|||||||
def validate_parent(self):
|
def validate_parent(self):
|
||||||
"""Fetch Parent Details and validation for account not to be created under ledger"""
|
"""Fetch Parent Details and validation for account not to be created under ledger"""
|
||||||
if self.doc.parent_account:
|
if self.doc.parent_account:
|
||||||
par = sql("""select name, group_or_ledger, is_pl_account, debit_or_credit
|
par = webnotes.conn.sql("""select name, group_or_ledger, is_pl_account, debit_or_credit
|
||||||
from tabAccount where name =%s""", self.doc.parent_account)
|
from tabAccount where name =%s""", self.doc.parent_account)
|
||||||
if not par:
|
if not par:
|
||||||
msgprint("Parent account does not exists", raise_exception=1)
|
msgprint("Parent account does not exists", raise_exception=1)
|
||||||
@ -84,7 +72,7 @@ class DocType:
|
|||||||
def validate_duplicate_account(self):
|
def validate_duplicate_account(self):
|
||||||
if self.doc.fields.get('__islocal') or not self.doc.name:
|
if self.doc.fields.get('__islocal') or not self.doc.name:
|
||||||
company_abbr = webnotes.conn.get_value("Company", self.doc.company, "abbr")
|
company_abbr = webnotes.conn.get_value("Company", self.doc.company, "abbr")
|
||||||
if sql("""select name from tabAccount where name=%s""",
|
if webnotes.conn.sql("""select name from tabAccount where name=%s""",
|
||||||
(self.doc.account_name + " - " + company_abbr)):
|
(self.doc.account_name + " - " + company_abbr)):
|
||||||
msgprint("Account Name: %s already exists, please rename"
|
msgprint("Account Name: %s already exists, please rename"
|
||||||
% self.doc.account_name, raise_exception=1)
|
% self.doc.account_name, raise_exception=1)
|
||||||
@ -133,7 +121,7 @@ class DocType:
|
|||||||
return webnotes.conn.get_value("GL Entry", {"account": self.doc.name})
|
return webnotes.conn.get_value("GL Entry", {"account": self.doc.name})
|
||||||
|
|
||||||
def check_if_child_exists(self):
|
def check_if_child_exists(self):
|
||||||
return sql("""select name from `tabAccount` where parent_account = %s
|
return webnotes.conn.sql("""select name from `tabAccount` where parent_account = %s
|
||||||
and docstatus != 2""", self.doc.name)
|
and docstatus != 2""", self.doc.name)
|
||||||
|
|
||||||
def validate_mandatory(self):
|
def validate_mandatory(self):
|
||||||
@ -181,7 +169,7 @@ class DocType:
|
|||||||
# Get credit limit
|
# Get credit limit
|
||||||
credit_limit_from = 'Customer'
|
credit_limit_from = 'Customer'
|
||||||
|
|
||||||
cr_limit = sql("""select t1.credit_limit from tabCustomer t1, `tabAccount` t2
|
cr_limit = webnotes.conn.sql("""select t1.credit_limit from tabCustomer t1, `tabAccount` t2
|
||||||
where t2.name=%s and t1.name = t2.master_name""", account)
|
where t2.name=%s and t1.name = t2.master_name""", account)
|
||||||
credit_limit = cr_limit and flt(cr_limit[0][0]) or 0
|
credit_limit = cr_limit and flt(cr_limit[0][0]) or 0
|
||||||
if not credit_limit:
|
if not credit_limit:
|
||||||
@ -221,7 +209,7 @@ class DocType:
|
|||||||
|
|
||||||
# rename account name
|
# rename account name
|
||||||
new_account_name = " - ".join(parts[:-1])
|
new_account_name = " - ".join(parts[:-1])
|
||||||
sql("update `tabAccount` set account_name = %s where name = %s", (new_account_name, old))
|
webnotes.conn.sql("update `tabAccount` set account_name = %s where name = %s", (new_account_name, old))
|
||||||
|
|
||||||
if merge:
|
if merge:
|
||||||
new_name = " - ".join(parts)
|
new_name = " - ".join(parts)
|
||||||
|
@ -10,7 +10,6 @@ from webnotes.model.doc import addchild
|
|||||||
from webnotes.model.bean import getlist, copy_doclist
|
from webnotes.model.bean import getlist, copy_doclist
|
||||||
from webnotes import msgprint
|
from webnotes import msgprint
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -23,7 +22,7 @@ class DocType:
|
|||||||
msgprint("Bank Account, From Date and To Date are Mandatory")
|
msgprint("Bank Account, From Date and To Date are Mandatory")
|
||||||
return
|
return
|
||||||
|
|
||||||
dl = 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 = webnotes.conn.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))
|
||||||
|
|
||||||
self.doclist = self.doc.clear_table(self.doclist, 'entries')
|
self.doclist = self.doc.clear_table(self.doclist, 'entries')
|
||||||
self.doc.total_amount = 0.0
|
self.doc.total_amount = 0.0
|
||||||
@ -47,7 +46,7 @@ class DocType:
|
|||||||
msgprint("Clearance Date can not be before Cheque Date (Row #%s)" %
|
msgprint("Clearance Date can not be before Cheque Date (Row #%s)" %
|
||||||
d.idx, raise_exception=1)
|
d.idx, raise_exception=1)
|
||||||
|
|
||||||
sql("""update `tabJournal Voucher`
|
webnotes.conn.sql("""update `tabJournal Voucher`
|
||||||
set clearance_date = %s, modified = %s where name=%s""",
|
set clearance_date = %s, modified = %s where name=%s""",
|
||||||
(d.clearance_date, nowdate(), d.voucher_id))
|
(d.clearance_date, nowdate(), d.voucher_id))
|
||||||
vouchers.append(d.voucher_id)
|
vouchers.append(d.voucher_id)
|
||||||
|
@ -107,7 +107,7 @@ class DocType:
|
|||||||
_(" does not belong to the company") + ": " + self.doc.company)
|
_(" does not belong to the company") + ": " + self.doc.company)
|
||||||
|
|
||||||
def check_negative_balance(account, adv_adj=False):
|
def check_negative_balance(account, adv_adj=False):
|
||||||
if not adv_adj:
|
if not adv_adj and account:
|
||||||
account_details = webnotes.conn.get_value("Account", account,
|
account_details = webnotes.conn.get_value("Account", account,
|
||||||
["allow_negative_balance", "debit_or_credit"], as_dict=True)
|
["allow_negative_balance", "debit_or_credit"], as_dict=True)
|
||||||
if not account_details["allow_negative_balance"]:
|
if not account_details["allow_negative_balance"]:
|
||||||
@ -161,16 +161,6 @@ def update_outstanding_amt(account, against_voucher_type, against_voucher, on_ca
|
|||||||
webnotes.conn.sql("update `tab%s` set outstanding_amount=%s where name='%s'" %
|
webnotes.conn.sql("update `tab%s` set outstanding_amount=%s where name='%s'" %
|
||||||
(against_voucher_type, bal, against_voucher))
|
(against_voucher_type, bal, against_voucher))
|
||||||
|
|
||||||
def validate_freezed_account(account, adv_adj=False):
|
|
||||||
"""Account has been freezed for other users except account manager"""
|
|
||||||
|
|
||||||
freezed_account = webnotes.conn.get_value("Account", account, "freeze_account")
|
|
||||||
|
|
||||||
if freezed_account == 'Yes' and not adv_adj \
|
|
||||||
and 'Accounts Manager' not in webnotes.user.get_roles():
|
|
||||||
webnotes.throw(_("Account") + ": " + account + _(" has been freezed. \
|
|
||||||
Only Accounts Manager can do transaction against this account"))
|
|
||||||
|
|
||||||
def validate_frozen_account(account, adv_adj):
|
def validate_frozen_account(account, adv_adj):
|
||||||
frozen_account = webnotes.conn.get_value("Account", account, "freeze_account")
|
frozen_account = webnotes.conn.get_value("Account", account, "freeze_account")
|
||||||
if frozen_account == 'Yes' and not adv_adj:
|
if frozen_account == 'Yes' and not adv_adj:
|
||||||
@ -183,4 +173,4 @@ def validate_frozen_account(account, adv_adj):
|
|||||||
elif frozen_accounts_modifier not in webnotes.user.get_roles():
|
elif frozen_accounts_modifier not in webnotes.user.get_roles():
|
||||||
webnotes.throw(account + _(" is a frozen account. ") +
|
webnotes.throw(account + _(" is a frozen account. ") +
|
||||||
_("To create / edit transactions against this account, you need role") + ": " +
|
_("To create / edit transactions against this account, you need role") + ": " +
|
||||||
frozen_accounts_modifier)
|
frozen_accounts_modifier)
|
||||||
|
@ -59,6 +59,50 @@ erpnext.accounts.JournalVoucher = wn.ui.form.Controller.extend({
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
against_voucher: function(doc, cdt, cdn) {
|
||||||
|
var d = wn.model.get_doc(cdt, cdn);
|
||||||
|
if (d.against_voucher && !flt(d.debit)) {
|
||||||
|
this.get_outstanding({
|
||||||
|
'doctype': 'Purchase Invoice',
|
||||||
|
'docname': d.against_voucher
|
||||||
|
}, d)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
against_invoice: function(doc, cdt, cdn) {
|
||||||
|
var d = wn.model.get_doc(cdt, cdn);
|
||||||
|
if (d.against_invoice && !flt(d.credit)) {
|
||||||
|
this.get_outstanding({
|
||||||
|
'doctype': 'Sales Invoice',
|
||||||
|
'docname': d.against_invoice
|
||||||
|
}, d)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
against_jv: function(doc, cdt, cdn) {
|
||||||
|
var d = wn.model.get_doc(cdt, cdn);
|
||||||
|
if (d.against_jv && !flt(d.credit) && !flt(d.debit)) {
|
||||||
|
this.get_outstanding({
|
||||||
|
'doctype': 'Journal Voucher',
|
||||||
|
'docname': d.against_jv,
|
||||||
|
'account': d.account
|
||||||
|
}, d)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
get_outstanding: function(args, child) {
|
||||||
|
var me = this;
|
||||||
|
return this.frm.call({
|
||||||
|
child: child,
|
||||||
|
method: "get_outstanding",
|
||||||
|
args: { args: args},
|
||||||
|
callback: function(r) {
|
||||||
|
cur_frm.cscript.update_totals(me.frm.doc);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
cur_frm.script_manager.make(erpnext.accounts.JournalVoucher);
|
cur_frm.script_manager.make(erpnext.accounts.JournalVoucher);
|
||||||
@ -88,24 +132,6 @@ cur_frm.cscript.is_opening = function(doc, cdt, cdn) {
|
|||||||
if (doc.is_opening == 'Yes') unhide_field('aging_date');
|
if (doc.is_opening == 'Yes') unhide_field('aging_date');
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.cscript.against_voucher = function(doc,cdt,cdn) {
|
|
||||||
var d = locals[cdt][cdn];
|
|
||||||
if (d.against_voucher && !flt(d.debit)) {
|
|
||||||
args = {'doctype': 'Purchase Invoice', 'docname': d.against_voucher }
|
|
||||||
return get_server_fields('get_outstanding',docstring(args),'entries',doc,cdt,cdn,1,function(r,rt) { cur_frm.cscript.update_totals(doc); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript.against_invoice = function(doc,cdt,cdn) {
|
|
||||||
var d = locals[cdt][cdn];
|
|
||||||
if (d.against_invoice && !flt(d.credit)) {
|
|
||||||
args = {'doctype': 'Sales Invoice', 'docname': d.against_invoice }
|
|
||||||
return get_server_fields('get_outstanding',docstring(args),'entries',doc,cdt,cdn,1,function(r,rt) { cur_frm.cscript.update_totals(doc); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update Totals
|
|
||||||
|
|
||||||
cur_frm.cscript.update_totals = function(doc) {
|
cur_frm.cscript.update_totals = function(doc) {
|
||||||
var td=0.0; var tc =0.0;
|
var td=0.0; var tc =0.0;
|
||||||
var el = getchildren('Journal Voucher Detail', doc.name, 'entries');
|
var el = getchildren('Journal Voucher Detail', doc.name, 'entries');
|
||||||
|
@ -260,15 +260,6 @@ class DocType(AccountsController):
|
|||||||
if gl_map:
|
if gl_map:
|
||||||
make_gl_entries(gl_map, cancel=cancel, adv_adj=adv_adj)
|
make_gl_entries(gl_map, cancel=cancel, adv_adj=adv_adj)
|
||||||
|
|
||||||
def get_outstanding(self, args):
|
|
||||||
args = eval(args)
|
|
||||||
o_s = webnotes.conn.sql("""select outstanding_amount from `tab%s` where name = %s""" %
|
|
||||||
(args['doctype'], '%s'), args['docname'])
|
|
||||||
if args['doctype'] == 'Purchase Invoice':
|
|
||||||
return {'debit': o_s and flt(o_s[0][0]) or 0}
|
|
||||||
if args['doctype'] == 'Sales Invoice':
|
|
||||||
return {'credit': o_s and flt(o_s[0][0]) or 0}
|
|
||||||
|
|
||||||
def get_balance(self):
|
def get_balance(self):
|
||||||
if not getlist(self.doclist,'entries'):
|
if not getlist(self.doclist,'entries'):
|
||||||
msgprint("Please enter atleast 1 entry in 'GL Entries' table")
|
msgprint("Please enter atleast 1 entry in 'GL Entries' table")
|
||||||
@ -434,4 +425,31 @@ def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
where jv_detail.parent = jv.name and jv_detail.account = %s and jv.docstatus = 1
|
where jv_detail.parent = jv.name and jv_detail.account = %s and jv.docstatus = 1
|
||||||
and jv.%s like %s order by jv.name desc limit %s, %s""" %
|
and jv.%s like %s order by jv.name desc limit %s, %s""" %
|
||||||
("%s", searchfield, "%s", "%s", "%s"),
|
("%s", searchfield, "%s", "%s", "%s"),
|
||||||
(filters["account"], "%%%s%%" % txt, start, page_len))
|
(filters["account"], "%%%s%%" % txt, start, page_len))
|
||||||
|
|
||||||
|
@webnotes.whitelist()
|
||||||
|
def get_outstanding(args):
|
||||||
|
args = eval(args)
|
||||||
|
if args.get("doctype") == "Journal Voucher" and args.get("account"):
|
||||||
|
against_jv_amount = webnotes.conn.sql("""
|
||||||
|
select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
|
||||||
|
from `tabJournal Voucher Detail` where parent=%s and account=%s
|
||||||
|
and ifnull(against_invoice, '')='' and ifnull(against_voucher, '')=''
|
||||||
|
and ifnull(against_jv, '')=''""", (args['docname'], args['account']))
|
||||||
|
|
||||||
|
against_jv_amount = flt(against_jv_amount[0][0]) if against_jv_amount else 0
|
||||||
|
if against_jv_amount > 0:
|
||||||
|
return {"credit": against_jv_amount}
|
||||||
|
else:
|
||||||
|
return {"debit": -1* against_jv_amount}
|
||||||
|
|
||||||
|
elif args.get("doctype") == "Sales Invoice":
|
||||||
|
return {
|
||||||
|
"credit": flt(webnotes.conn.get_value("Sales Invoice", args["docname"],
|
||||||
|
"outstanding_amount"))
|
||||||
|
}
|
||||||
|
elif args.get("doctype") == "Purchase Invoice":
|
||||||
|
return {
|
||||||
|
"debit": flt(webnotes.conn.get_value("Purchase Invoice", args["docname"],
|
||||||
|
"outstanding_amount"))
|
||||||
|
}
|
||||||
|
@ -11,7 +11,6 @@ from webnotes import session, msgprint
|
|||||||
|
|
||||||
import webnotes.defaults
|
import webnotes.defaults
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
from accounts.utils import get_balance_on, get_fiscal_year
|
from accounts.utils import get_balance_on, get_fiscal_year
|
||||||
|
|
||||||
@ -44,7 +43,7 @@ class DocType:
|
|||||||
ret['company'] = get_companies()
|
ret['company'] = get_companies()
|
||||||
|
|
||||||
#--- to get fiscal year and start_date of that fiscal year -----
|
#--- to get fiscal year and start_date of that fiscal year -----
|
||||||
res = sql("select name, year_start_date from `tabFiscal Year`")
|
res = webnotes.conn.sql("select name, year_start_date from `tabFiscal Year`")
|
||||||
ret['fiscal_year'] = [r[0] for r in res]
|
ret['fiscal_year'] = [r[0] for r in res]
|
||||||
ret['start_dates'] = {}
|
ret['start_dates'] = {}
|
||||||
for r in res:
|
for r in res:
|
||||||
@ -52,7 +51,7 @@ class DocType:
|
|||||||
|
|
||||||
#--- from month and to month (for MIS - Comparison Report) -------
|
#--- from month and to month (for MIS - Comparison Report) -------
|
||||||
month_list = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
|
month_list = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
|
||||||
fiscal_start_month = sql("select MONTH(year_start_date) from `tabFiscal Year` where name = %s",(webnotes.defaults.get_global_default("fiscal_year")))
|
fiscal_start_month = webnotes.conn.sql("select MONTH(year_start_date) from `tabFiscal Year` where name = %s",(webnotes.defaults.get_global_default("fiscal_year")))
|
||||||
fiscal_start_month = fiscal_start_month and fiscal_start_month[0][0] or 1
|
fiscal_start_month = fiscal_start_month and fiscal_start_month[0][0] or 1
|
||||||
mon = ['']
|
mon = ['']
|
||||||
for i in range(fiscal_start_month,13): mon.append(month_list[i-1])
|
for i in range(fiscal_start_month,13): mon.append(month_list[i-1])
|
||||||
@ -107,7 +106,7 @@ class DocType:
|
|||||||
def dates(self,fiscal_year,from_date,to_date):
|
def dates(self,fiscal_year,from_date,to_date):
|
||||||
import datetime
|
import datetime
|
||||||
ret = ''
|
ret = ''
|
||||||
start_date = cstr(sql("select year_start_date from `tabFiscal Year` where name = %s",fiscal_year)[0][0])
|
start_date = cstr(webnotes.conn.sql("select year_start_date from `tabFiscal Year` where name = %s",fiscal_year)[0][0])
|
||||||
st_mon = cint(from_date.split('-')[1])
|
st_mon = cint(from_date.split('-')[1])
|
||||||
ed_mon = cint(to_date.split('-')[1])
|
ed_mon = cint(to_date.split('-')[1])
|
||||||
st_day = cint(from_date.split('-')[2])
|
st_day = cint(from_date.split('-')[2])
|
||||||
@ -152,7 +151,7 @@ class DocType:
|
|||||||
def get_totals(self, args):
|
def get_totals(self, args):
|
||||||
args = eval(args)
|
args = eval(args)
|
||||||
#msgprint(args)
|
#msgprint(args)
|
||||||
totals = sql("SELECT %s FROM %s WHERE %s %s %s %s" %(cstr(args['query_val']), cstr(args['tables']), cstr(args['company']), cstr(args['cond']), cstr(args['add_cond']), cstr(args['fil_cond'])), as_dict = 1)[0]
|
totals = webnotes.conn.sql("SELECT %s FROM %s WHERE %s %s %s %s" %(cstr(args['query_val']), cstr(args['tables']), cstr(args['company']), cstr(args['cond']), cstr(args['add_cond']), cstr(args['fil_cond'])), as_dict = 1)[0]
|
||||||
#msgprint(totals)
|
#msgprint(totals)
|
||||||
tot_keys = totals.keys()
|
tot_keys = totals.keys()
|
||||||
# return in flt because JSON doesn't accept Decimal
|
# return in flt because JSON doesn't accept Decimal
|
||||||
@ -185,7 +184,7 @@ class DocType:
|
|||||||
# Get Children
|
# Get Children
|
||||||
# ------------
|
# ------------
|
||||||
def get_children(self, parent_account, level, pl, company, fy):
|
def get_children(self, parent_account, level, pl, company, fy):
|
||||||
cl = sql("select distinct account_name, name, debit_or_credit, lft, rgt from `tabAccount` where ifnull(parent_account, '') = %s and ifnull(is_pl_account, 'No')=%s and company=%s and docstatus != 2 order by name asc", (parent_account, pl, company))
|
cl = webnotes.conn.sql("select distinct account_name, name, debit_or_credit, lft, rgt from `tabAccount` where ifnull(parent_account, '') = %s and ifnull(is_pl_account, 'No')=%s and company=%s and docstatus != 2 order by name asc", (parent_account, pl, company))
|
||||||
level0_diff = [0 for p in self.period_list]
|
level0_diff = [0 for p in self.period_list]
|
||||||
if pl=='Yes' and level==0: # switch for income & expenses
|
if pl=='Yes' and level==0: # switch for income & expenses
|
||||||
cl = [c for c in cl]
|
cl = [c for c in cl]
|
||||||
@ -238,7 +237,7 @@ class DocType:
|
|||||||
def define_periods(self, year, period):
|
def define_periods(self, year, period):
|
||||||
|
|
||||||
# get year start date
|
# get year start date
|
||||||
ysd = sql("select year_start_date from `tabFiscal Year` where name=%s", year)
|
ysd = webnotes.conn.sql("select year_start_date from `tabFiscal Year` where name=%s", year)
|
||||||
ysd = ysd and ysd[0][0] or ''
|
ysd = ysd and ysd[0][0] or ''
|
||||||
|
|
||||||
self.ysd = ysd
|
self.ysd = ysd
|
||||||
|
@ -69,7 +69,6 @@ class DocType(AccountsController):
|
|||||||
|
|
||||||
def get_pl_balances(self):
|
def get_pl_balances(self):
|
||||||
"""Get balance for pl accounts"""
|
"""Get balance for pl accounts"""
|
||||||
|
|
||||||
return webnotes.conn.sql("""
|
return webnotes.conn.sql("""
|
||||||
select t1.account, sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) as balance
|
select t1.account, sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) as balance
|
||||||
from `tabGL Entry` t1, `tabAccount` t2
|
from `tabGL Entry` t1, `tabAccount` t2
|
||||||
@ -101,4 +100,4 @@ class DocType(AccountsController):
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
from accounts.general_ledger import make_gl_entries
|
from accounts.general_ledger import make_gl_entries
|
||||||
make_gl_entries(gl_entries)
|
make_gl_entries(gl_entries)
|
||||||
|
@ -8,6 +8,9 @@ import webnotes
|
|||||||
|
|
||||||
class TestPeriodClosingVoucher(unittest.TestCase):
|
class TestPeriodClosingVoucher(unittest.TestCase):
|
||||||
def test_closing_entry(self):
|
def test_closing_entry(self):
|
||||||
|
# clear GL Entries
|
||||||
|
webnotes.conn.sql("""delete from `tabGL Entry`""")
|
||||||
|
|
||||||
from accounts.doctype.journal_voucher.test_journal_voucher import test_records as jv_records
|
from accounts.doctype.journal_voucher.test_journal_voucher import test_records as jv_records
|
||||||
jv = webnotes.bean(copy=jv_records[2])
|
jv = webnotes.bean(copy=jv_records[2])
|
||||||
jv.insert()
|
jv.insert()
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-05-24 12:15:51",
|
"creation": "2013-05-24 12:15:51",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-08-28 19:13:42",
|
"modified": "2013-10-15 11:12:02",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -80,16 +80,6 @@
|
|||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"doctype": "DocField",
|
|
||||||
"fieldname": "conversion_rate",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"label": "Conversion Rate",
|
|
||||||
"oldfieldname": "conversion_rate",
|
|
||||||
"oldfieldtype": "Currency",
|
|
||||||
"read_only": 0,
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "selling_price_list",
|
"fieldname": "selling_price_list",
|
||||||
|
@ -8,6 +8,7 @@ cur_frm.cscript.other_fname = "purchase_tax_details";
|
|||||||
wn.provide("erpnext.accounts");
|
wn.provide("erpnext.accounts");
|
||||||
wn.require('app/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js');
|
wn.require('app/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js');
|
||||||
wn.require('app/buying/doctype/purchase_common/purchase_common.js');
|
wn.require('app/buying/doctype/purchase_common/purchase_common.js');
|
||||||
|
wn.require('app/accounts/doctype/sales_invoice/pos.js');
|
||||||
|
|
||||||
erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
||||||
onload: function() {
|
onload: function() {
|
||||||
|
@ -12,7 +12,6 @@ from setup.utils import get_company_currency
|
|||||||
|
|
||||||
import webnotes.defaults
|
import webnotes.defaults
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
from controllers.buying_controller import BuyingController
|
from controllers.buying_controller import BuyingController
|
||||||
class DocType(BuyingController):
|
class DocType(BuyingController):
|
||||||
@ -62,19 +61,23 @@ class DocType(BuyingController):
|
|||||||
"purchase_receipt_details")
|
"purchase_receipt_details")
|
||||||
|
|
||||||
def get_credit_to(self):
|
def get_credit_to(self):
|
||||||
acc_head = sql("""select name, credit_days from `tabAccount`
|
|
||||||
where (name = %s or (master_name = %s and master_type = 'supplier'))
|
|
||||||
and docstatus != 2 and company = %s""",
|
|
||||||
(cstr(self.doc.supplier) + " - " + self.company_abbr,
|
|
||||||
self.doc.supplier, self.doc.company))
|
|
||||||
|
|
||||||
ret = {}
|
ret = {}
|
||||||
if acc_head and acc_head[0][0]:
|
if self.doc.supplier:
|
||||||
ret['credit_to'] = acc_head[0][0]
|
acc_head = webnotes.conn.sql("""select name, credit_days from `tabAccount`
|
||||||
if not self.doc.due_date:
|
where (name = %s or (master_name = %s and master_type = 'supplier'))
|
||||||
ret['due_date'] = add_days(cstr(self.doc.posting_date), acc_head and cint(acc_head[0][1]) or 0)
|
and docstatus != 2 and company = %s""",
|
||||||
elif not acc_head:
|
(cstr(self.doc.supplier) + " - " + self.company_abbr,
|
||||||
msgprint("%s does not have an Account Head in %s. You must first create it from the Supplier Master" % (self.doc.supplier, self.doc.company))
|
self.doc.supplier, self.doc.company))
|
||||||
|
|
||||||
|
if acc_head and acc_head[0][0]:
|
||||||
|
ret['credit_to'] = acc_head[0][0]
|
||||||
|
if not self.doc.due_date:
|
||||||
|
ret['due_date'] = add_days(cstr(self.doc.posting_date),
|
||||||
|
acc_head and cint(acc_head[0][1]) or 0)
|
||||||
|
elif not acc_head:
|
||||||
|
msgprint("%s does not have an Account Head in %s. \
|
||||||
|
You must first create it from the Supplier Master" % \
|
||||||
|
(self.doc.supplier, self.doc.company))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def set_supplier_defaults(self):
|
def set_supplier_defaults(self):
|
||||||
@ -85,18 +88,10 @@ class DocType(BuyingController):
|
|||||||
super(DocType, self).get_advances(self.doc.credit_to,
|
super(DocType, self).get_advances(self.doc.credit_to,
|
||||||
"Purchase Invoice Advance", "advance_allocation_details", "debit")
|
"Purchase Invoice Advance", "advance_allocation_details", "debit")
|
||||||
|
|
||||||
def get_rate(self,arg):
|
|
||||||
return get_obj('Purchase Common').get_rate(arg,self)
|
|
||||||
|
|
||||||
def get_rate1(self,acc):
|
|
||||||
rate = sql("select tax_rate from `tabAccount` where name='%s'"%(acc))
|
|
||||||
ret={'add_tax_rate' :rate and flt(rate[0][0]) or 0 }
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def check_active_purchase_items(self):
|
def check_active_purchase_items(self):
|
||||||
for d in getlist(self.doclist, 'entries'):
|
for d in getlist(self.doclist, 'entries'):
|
||||||
if d.item_code: # extra condn coz item_code is not mandatory in PV
|
if d.item_code: # extra condn coz item_code is not mandatory in PV
|
||||||
valid_item = sql("select docstatus,is_purchase_item from tabItem where name = %s",d.item_code)
|
valid_item = webnotes.conn.sql("select docstatus,is_purchase_item from tabItem where name = %s",d.item_code)
|
||||||
if valid_item[0][0] == 2:
|
if valid_item[0][0] == 2:
|
||||||
msgprint("Item : '%s' is Inactive, you can restore it from Trash" %(d.item_code))
|
msgprint("Item : '%s' is Inactive, you can restore it from Trash" %(d.item_code))
|
||||||
raise Exception
|
raise Exception
|
||||||
@ -116,7 +111,7 @@ class DocType(BuyingController):
|
|||||||
def validate_bill_no(self):
|
def validate_bill_no(self):
|
||||||
if self.doc.bill_no and self.doc.bill_no.lower().strip() \
|
if self.doc.bill_no and self.doc.bill_no.lower().strip() \
|
||||||
not in ['na', 'not applicable', 'none']:
|
not in ['na', 'not applicable', 'none']:
|
||||||
b_no = sql("""select bill_no, name, ifnull(is_opening,'') from `tabPurchase Invoice`
|
b_no = webnotes.conn.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""",
|
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))
|
(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):
|
if b_no and cstr(b_no[0][2]) == cstr(self.doc.is_opening):
|
||||||
@ -132,7 +127,7 @@ class DocType(BuyingController):
|
|||||||
self.doc.remarks = "No Remarks"
|
self.doc.remarks = "No Remarks"
|
||||||
|
|
||||||
def validate_credit_acc(self):
|
def validate_credit_acc(self):
|
||||||
acc = sql("select debit_or_credit, is_pl_account from tabAccount where name = %s",
|
acc = webnotes.conn.sql("select debit_or_credit, is_pl_account from tabAccount where name = %s",
|
||||||
self.doc.credit_to)
|
self.doc.credit_to)
|
||||||
if not acc:
|
if not acc:
|
||||||
msgprint("Account: "+ self.doc.credit_to + "does not exist")
|
msgprint("Account: "+ self.doc.credit_to + "does not exist")
|
||||||
@ -148,7 +143,7 @@ class DocType(BuyingController):
|
|||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
def check_for_acc_head_of_supplier(self):
|
def check_for_acc_head_of_supplier(self):
|
||||||
if self.doc.supplier and self.doc.credit_to:
|
if self.doc.supplier and self.doc.credit_to:
|
||||||
acc_head = sql("select master_name from `tabAccount` where name = %s", self.doc.credit_to)
|
acc_head = webnotes.conn.sql("select master_name from `tabAccount` where name = %s", self.doc.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)):
|
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)
|
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)
|
||||||
@ -160,7 +155,7 @@ class DocType(BuyingController):
|
|||||||
for d in getlist(self.doclist,'entries'):
|
for d in getlist(self.doclist,'entries'):
|
||||||
if d.purchase_order and not d.purchase_order in check_list and not d.purchase_receipt:
|
if d.purchase_order and not d.purchase_order in check_list and not d.purchase_receipt:
|
||||||
check_list.append(d.purhcase_order)
|
check_list.append(d.purhcase_order)
|
||||||
stopped = sql("select name from `tabPurchase Order` where status = 'Stopped' and name = '%s'" % d.purchase_order)
|
stopped = webnotes.conn.sql("select name from `tabPurchase Order` where status = 'Stopped' and name = '%s'" % d.purchase_order)
|
||||||
if stopped:
|
if stopped:
|
||||||
msgprint("One cannot do any transaction against 'Purchase Order' : %s, it's status is 'Stopped'" % (d.purhcase_order))
|
msgprint("One cannot do any transaction against 'Purchase Order' : %s, it's status is 'Stopped'" % (d.purhcase_order))
|
||||||
raise Exception
|
raise Exception
|
||||||
@ -260,11 +255,11 @@ class DocType(BuyingController):
|
|||||||
def check_prev_docstatus(self):
|
def check_prev_docstatus(self):
|
||||||
for d in getlist(self.doclist,'entries'):
|
for d in getlist(self.doclist,'entries'):
|
||||||
if d.purchase_order:
|
if d.purchase_order:
|
||||||
submitted = sql("select name from `tabPurchase Order` where docstatus = 1 and name = '%s'" % d.purchase_order)
|
submitted = webnotes.conn.sql("select name from `tabPurchase Order` where docstatus = 1 and name = '%s'" % d.purchase_order)
|
||||||
if not submitted:
|
if not submitted:
|
||||||
webnotes.throw("Purchase Order : "+ cstr(d.purchase_order) +" is not submitted")
|
webnotes.throw("Purchase Order : "+ cstr(d.purchase_order) +" is not submitted")
|
||||||
if d.purchase_receipt:
|
if d.purchase_receipt:
|
||||||
submitted = sql("select name from `tabPurchase Receipt` where docstatus = 1 and name = '%s'" % d.purchase_receipt)
|
submitted = webnotes.conn.sql("select name from `tabPurchase Receipt` where docstatus = 1 and name = '%s'" % d.purchase_receipt)
|
||||||
if not submitted:
|
if not submitted:
|
||||||
webnotes.throw("Purchase Receipt : "+ cstr(d.purchase_receipt) +" is not submitted")
|
webnotes.throw("Purchase Receipt : "+ cstr(d.purchase_receipt) +" is not submitted")
|
||||||
|
|
||||||
@ -334,7 +329,7 @@ class DocType(BuyingController):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# tax table gl entries
|
# tax table gl entries
|
||||||
valuation_tax = 0
|
valuation_tax = {}
|
||||||
for tax in self.doclist.get({"parentfield": "purchase_tax_details"}):
|
for tax in self.doclist.get({"parentfield": "purchase_tax_details"}):
|
||||||
if tax.category in ("Total", "Valuation and Total") and flt(tax.tax_amount):
|
if tax.category in ("Total", "Valuation and Total") and flt(tax.tax_amount):
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
@ -349,8 +344,11 @@ class DocType(BuyingController):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# accumulate valuation tax
|
# accumulate valuation tax
|
||||||
if tax.category in ("Valuation", "Valuation and Total") and flt(tax.tax_amount):
|
if tax.category in ("Valuation", "Valuation and Total") and flt(tax.tax_amount) \
|
||||||
valuation_tax += (tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.tax_amount)
|
and tax.cost_center:
|
||||||
|
valuation_tax.setdefault(tax.cost_center, 0)
|
||||||
|
valuation_tax[tax.cost_center] += \
|
||||||
|
(tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.tax_amount)
|
||||||
|
|
||||||
# item gl entries
|
# item gl entries
|
||||||
stock_item_and_auto_accounting_for_stock = False
|
stock_item_and_auto_accounting_for_stock = False
|
||||||
@ -391,15 +389,19 @@ class DocType(BuyingController):
|
|||||||
if stock_item_and_auto_accounting_for_stock and valuation_tax:
|
if stock_item_and_auto_accounting_for_stock and valuation_tax:
|
||||||
# credit valuation tax amount in "Expenses Included In Valuation"
|
# credit valuation tax amount in "Expenses Included In Valuation"
|
||||||
# this will balance out valuation amount included in cost of goods sold
|
# this will balance out valuation amount included in cost of goods sold
|
||||||
gl_entries.append(
|
expenses_included_in_valuation = \
|
||||||
self.get_gl_dict({
|
self.get_company_default("expenses_included_in_valuation")
|
||||||
"account": self.get_company_default("expenses_included_in_valuation"),
|
|
||||||
"cost_center": self.get_company_default("cost_center"),
|
for cost_center, amount in valuation_tax.items():
|
||||||
"against": self.doc.credit_to,
|
gl_entries.append(
|
||||||
"credit": valuation_tax,
|
self.get_gl_dict({
|
||||||
"remarks": self.doc.remarks or "Accounting Entry for Stock"
|
"account": expenses_included_in_valuation,
|
||||||
})
|
"cost_center": cost_center,
|
||||||
)
|
"against": self.doc.credit_to,
|
||||||
|
"credit": amount,
|
||||||
|
"remarks": self.doc.remarks or "Accounting Entry for Stock"
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
# writeoff account includes petty difference in the invoice amount
|
# writeoff account includes petty difference in the invoice amount
|
||||||
# and the amount that is paid
|
# and the amount that is paid
|
||||||
@ -432,7 +434,7 @@ class DocType(BuyingController):
|
|||||||
def update_raw_material_cost(self):
|
def update_raw_material_cost(self):
|
||||||
if self.sub_contracted_items:
|
if self.sub_contracted_items:
|
||||||
for d in self.doclist.get({"parentfield": "entries"}):
|
for d in self.doclist.get({"parentfield": "entries"}):
|
||||||
rm_cost = webnotes.conn.sql(""" select raw_material_cost / quantity
|
rm_cost = webnotes.conn.sql("""select raw_material_cost / quantity
|
||||||
from `tabBOM` where item = %s and is_default = 1 and docstatus = 1
|
from `tabBOM` where item = %s and is_default = 1 and docstatus = 1
|
||||||
and is_active = 1 """, (d.item_code,))
|
and is_active = 1 """, (d.item_code,))
|
||||||
rm_cost = rm_cost and flt(rm_cost[0][0]) or 0
|
rm_cost = rm_cost and flt(rm_cost[0][0]) or 0
|
||||||
|
@ -2,12 +2,13 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-05-21 16:16:39",
|
"creation": "2013-05-21 16:16:39",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-08-09 14:45:35",
|
"modified": "2013-10-02 14:24:55",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_attach": 1,
|
"allow_attach": 1,
|
||||||
|
"allow_import": 1,
|
||||||
"autoname": "naming_series:",
|
"autoname": "naming_series:",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"icon": "icon-file-text",
|
"icon": "icon-file-text",
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
//--------- ONLOAD -------------
|
//--------- ONLOAD -------------
|
||||||
|
wn.require("app/js/controllers/accounts.js");
|
||||||
|
|
||||||
cur_frm.cscript.onload = function(doc, cdt, cdn) {
|
cur_frm.cscript.onload = function(doc, cdt, cdn) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -134,6 +136,7 @@ cur_frm.fields_dict['purchase_tax_details'].grid.get_field("cost_center").get_qu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
cur_frm.cscript.account_head = function(doc, cdt, cdn) {
|
cur_frm.cscript.account_head = function(doc, cdt, cdn) {
|
||||||
var d = locals[cdt][cdn];
|
var d = locals[cdt][cdn];
|
||||||
if(!d.charge_type && d.account_head){
|
if(!d.charge_type && d.account_head){
|
||||||
@ -148,6 +151,8 @@ cur_frm.cscript.account_head = function(doc, cdt, cdn) {
|
|||||||
refresh_field('account_head',d.name,'purchase_tax_details');
|
refresh_field('account_head',d.name,'purchase_tax_details');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> f146e8b7f52a3e46e335c0fefd92c347717b370b
|
||||||
cur_frm.cscript.rate = function(doc, cdt, cdn) {
|
cur_frm.cscript.rate = function(doc, cdt, cdn) {
|
||||||
var d = locals[cdt][cdn];
|
var d = locals[cdt][cdn];
|
||||||
if(!d.charge_type && d.rate) {
|
if(!d.charge_type && d.rate) {
|
||||||
|
@ -8,16 +8,10 @@ from webnotes.model import db_exists
|
|||||||
from webnotes.model.bean import copy_doclist
|
from webnotes.model.bean import copy_doclist
|
||||||
from webnotes.model.code import get_obj
|
from webnotes.model.code import get_obj
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DocType:
|
class DocType:
|
||||||
def __init__(self, doc, doclist=[]):
|
def __init__(self, doc, doclist=[]):
|
||||||
self.doc = doc
|
self.doc = doc
|
||||||
self.doclist = doclist
|
self.doclist = doclist
|
||||||
|
|
||||||
# Get Tax Rate if account type is Tax
|
|
||||||
# ===================================================================
|
|
||||||
def get_rate(self, arg):
|
|
||||||
return get_obj('Purchase Common').get_rate(arg, self)
|
|
@ -7,7 +7,7 @@ erpnext.POS = Class.extend({
|
|||||||
this.frm = frm;
|
this.frm = frm;
|
||||||
this.wrapper.html('<div class="container">\
|
this.wrapper.html('<div class="container">\
|
||||||
<div class="row">\
|
<div class="row">\
|
||||||
<div class="customer-area col-sm-3 col-xs-6"></div>\
|
<div class="party-area col-sm-3 col-xs-6"></div>\
|
||||||
<div class="barcode-area col-sm-3 col-xs-6"></div>\
|
<div class="barcode-area col-sm-3 col-xs-6"></div>\
|
||||||
<div class="search-area col-sm-3 col-xs-6"></div>\
|
<div class="search-area col-sm-3 col-xs-6"></div>\
|
||||||
<div class="item-group-area col-sm-3 col-xs-6"></div>\
|
<div class="item-group-area col-sm-3 col-xs-6"></div>\
|
||||||
@ -71,7 +71,18 @@ erpnext.POS = Class.extend({
|
|||||||
</div>\
|
</div>\
|
||||||
</div>\
|
</div>\
|
||||||
</div></div>');
|
</div></div>');
|
||||||
|
|
||||||
|
if (wn.meta.has_field(cur_frm.doc.doctype, "customer")) {
|
||||||
|
this.party = "Customer";
|
||||||
|
this.price_list = this.frm.doc.selling_price_list;
|
||||||
|
this.sales_or_purchase = "Sales";
|
||||||
|
}
|
||||||
|
else if (wn.meta.has_field(cur_frm.doc.doctype, "supplier")) {
|
||||||
|
this.party = "Supplier";
|
||||||
|
this.price_list = this.frm.doc.buying_price_list;
|
||||||
|
this.sales_or_purchase = "Purchase";
|
||||||
|
}
|
||||||
|
|
||||||
this.make();
|
this.make();
|
||||||
|
|
||||||
var me = this;
|
var me = this;
|
||||||
@ -88,28 +99,29 @@ erpnext.POS = Class.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
make: function() {
|
make: function() {
|
||||||
this.make_customer();
|
this.make_party();
|
||||||
this.make_item_group();
|
this.make_item_group();
|
||||||
this.make_search();
|
this.make_search();
|
||||||
this.make_barcode();
|
this.make_barcode();
|
||||||
this.make_item_list();
|
this.make_item_list();
|
||||||
},
|
},
|
||||||
make_customer: function() {
|
make_party: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
this.customer = wn.ui.form.make_control({
|
this.party_field = wn.ui.form.make_control({
|
||||||
df: {
|
df: {
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Customer",
|
"options": this.party,
|
||||||
"label": "Customer",
|
"label": this.party,
|
||||||
"fieldname": "pos_customer",
|
"fieldname": "pos_party",
|
||||||
"placeholder": "Customer"
|
"placeholder": this.party
|
||||||
},
|
},
|
||||||
parent: this.wrapper.find(".customer-area")
|
parent: this.wrapper.find(".party-area")
|
||||||
});
|
});
|
||||||
this.customer.make_input();
|
this.party_field.make_input();
|
||||||
this.customer.$input.on("change", function() {
|
this.party_field.$input.on("change", function() {
|
||||||
if(!me.customer.autocomplete_open)
|
if(!me.party_field.autocomplete_open)
|
||||||
wn.model.set_value("Sales Invoice", me.frm.docname, "customer", this.value);
|
wn.model.set_value(me.frm.doctype, me.frm.docname,
|
||||||
|
me.party.toLowerCase(), this.value);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
make_item_group: function() {
|
make_item_group: function() {
|
||||||
@ -120,7 +132,7 @@ erpnext.POS = Class.extend({
|
|||||||
"options": "Item Group",
|
"options": "Item Group",
|
||||||
"label": "Item Group",
|
"label": "Item Group",
|
||||||
"fieldname": "pos_item_group",
|
"fieldname": "pos_item_group",
|
||||||
"placeholder": "Filter by Item Group"
|
"placeholder": "Item Group"
|
||||||
},
|
},
|
||||||
parent: this.wrapper.find(".item-group-area")
|
parent: this.wrapper.find(".item-group-area")
|
||||||
});
|
});
|
||||||
@ -138,7 +150,7 @@ erpnext.POS = Class.extend({
|
|||||||
"options": "Item",
|
"options": "Item",
|
||||||
"label": "Item",
|
"label": "Item",
|
||||||
"fieldname": "pos_item",
|
"fieldname": "pos_item",
|
||||||
"placeholder": "Select Item"
|
"placeholder": "Item"
|
||||||
},
|
},
|
||||||
parent: this.wrapper.find(".search-area")
|
parent: this.wrapper.find(".search-area")
|
||||||
});
|
});
|
||||||
@ -155,7 +167,7 @@ erpnext.POS = Class.extend({
|
|||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Barcode",
|
"label": "Barcode",
|
||||||
"fieldname": "pos_barcode",
|
"fieldname": "pos_barcode",
|
||||||
"placeholder": "Select Barcode"
|
"placeholder": "Barcode"
|
||||||
},
|
},
|
||||||
parent: this.wrapper.find(".barcode-area")
|
parent: this.wrapper.find(".barcode-area")
|
||||||
});
|
});
|
||||||
@ -171,7 +183,8 @@ erpnext.POS = Class.extend({
|
|||||||
wn.call({
|
wn.call({
|
||||||
method: 'accounts.doctype.sales_invoice.pos.get_items',
|
method: 'accounts.doctype.sales_invoice.pos.get_items',
|
||||||
args: {
|
args: {
|
||||||
price_list: cur_frm.doc.selling_price_list,
|
sales_or_purchase: this.sales_or_purchase,
|
||||||
|
price_list: this.price_list,
|
||||||
item_group: this.item_group.$input.val(),
|
item_group: this.item_group.$input.val(),
|
||||||
item: this.search.$input.val()
|
item: this.search.$input.val()
|
||||||
},
|
},
|
||||||
@ -200,15 +213,18 @@ erpnext.POS = Class.extend({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// if form is local then allow this function
|
// if form is local then allow this function
|
||||||
if (cur_frm.doc.docstatus===0) {
|
$(me.wrapper).find("div.pos-item").on("click", function() {
|
||||||
$("div.pos-item").on("click", function() {
|
if(me.frm.doc.docstatus==0) {
|
||||||
if(!cur_frm.doc.customer) {
|
if(!me.frm.doc[me.party.toLowerCase()] && ((me.frm.doctype == "Quotation" &&
|
||||||
msgprint("Please select customer first.");
|
me.frm.doc.quotation_to == "Customer")
|
||||||
|
|| me.frm.doctype != "Quotation")) {
|
||||||
|
msgprint("Please select " + me.party + " first.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
me.add_to_cart($(this).attr("data-item_code"));
|
else
|
||||||
});
|
me.add_to_cart($(this).attr("data-item_code"));
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -217,12 +233,12 @@ erpnext.POS = Class.extend({
|
|||||||
var caught = false;
|
var caught = false;
|
||||||
|
|
||||||
// get no_of_items
|
// get no_of_items
|
||||||
no_of_items = me.wrapper.find("#cart tbody").length;
|
var no_of_items = me.wrapper.find("#cart tbody tr").length;
|
||||||
|
|
||||||
// check whether the item is already added
|
// check whether the item is already added
|
||||||
if (no_of_items != 0) {
|
if (no_of_items != 0) {
|
||||||
$.each(wn.model.get_children("Sales Invoice Item", this.frm.doc.name, "entries",
|
$.each(wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name,
|
||||||
"Sales Invoice"), function(i, d) {
|
this.frm.cscript.fname, this.frm.doctype), function(i, d) {
|
||||||
if (d.item_code == item_code)
|
if (d.item_code == item_code)
|
||||||
caught = true;
|
caught = true;
|
||||||
});
|
});
|
||||||
@ -233,15 +249,16 @@ erpnext.POS = Class.extend({
|
|||||||
me.update_qty(item_code, 1);
|
me.update_qty(item_code, 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var child = wn.model.add_child(me.frm.doc, "Sales Invoice Item", "entries");
|
var child = wn.model.add_child(me.frm.doc, this.frm.doctype + " Item",
|
||||||
|
this.frm.cscript.fname);
|
||||||
child.item_code = item_code;
|
child.item_code = item_code;
|
||||||
me.frm.cscript.item_code(me.frm.doc, child.doctype, child.name);
|
me.frm.cscript.item_code(me.frm.doc, child.doctype, child.name);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
update_qty: function(item_code, qty, textbox_qty) {
|
update_qty: function(item_code, qty, textbox_qty) {
|
||||||
var me = this;
|
var me = this;
|
||||||
$.each(wn.model.get_children("Sales Invoice Item", this.frm.doc.name, "entries",
|
$.each(wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name,
|
||||||
"Sales Invoice"), function(i, d) {
|
this.frm.cscript.fname, this.frm.doctype), function(i, d) {
|
||||||
if (d.item_code == item_code) {
|
if (d.item_code == item_code) {
|
||||||
if (textbox_qty) {
|
if (textbox_qty) {
|
||||||
if (qty == 0 && d.item_code == item_code)
|
if (qty == 0 && d.item_code == item_code)
|
||||||
@ -259,14 +276,24 @@ erpnext.POS = Class.extend({
|
|||||||
},
|
},
|
||||||
refresh: function() {
|
refresh: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
this.customer.set_input(this.frm.doc.customer);
|
this.party_field.set_input(this.frm.doc[this.party.toLowerCase()]);
|
||||||
this.barcode.set_input("");
|
this.barcode.set_input("");
|
||||||
|
|
||||||
// add items
|
// add items
|
||||||
var $items = me.wrapper.find("#cart tbody").empty();
|
var $items = me.wrapper.find("#cart tbody").empty();
|
||||||
|
|
||||||
$.each(wn.model.get_children("Sales Invoice Item", this.frm.doc.name, "entries",
|
$.each(wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name,
|
||||||
"Sales Invoice"), function(i, d) {
|
this.frm.cscript.fname, this.frm.doctype), function(i, d) {
|
||||||
|
|
||||||
|
if (me.sales_or_purchase == "Sales") {
|
||||||
|
item_amount = d.export_amount;
|
||||||
|
rate = d.export_rate;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
item_amount = d.import_amount;
|
||||||
|
rate = d.import_rate;
|
||||||
|
}
|
||||||
|
|
||||||
$(repl('<tr id="%(item_code)s" data-selected="false">\
|
$(repl('<tr id="%(item_code)s" data-selected="false">\
|
||||||
<td>%(item_code)s%(item_name)s</td>\
|
<td>%(item_code)s%(item_name)s</td>\
|
||||||
<td><input type="text" value="%(qty)s" \
|
<td><input type="text" value="%(qty)s" \
|
||||||
@ -277,16 +304,16 @@ erpnext.POS = Class.extend({
|
|||||||
item_code: d.item_code,
|
item_code: d.item_code,
|
||||||
item_name: d.item_name===d.item_code ? "" : ("<br>" + d.item_name),
|
item_name: d.item_name===d.item_code ? "" : ("<br>" + d.item_name),
|
||||||
qty: d.qty,
|
qty: d.qty,
|
||||||
rate: format_currency(d.ref_rate, cur_frm.doc.price_list_currency),
|
rate: format_currency(rate, me.frm.doc.currency),
|
||||||
amount: format_currency(d.export_amount, cur_frm.doc.price_list_currency)
|
amount: format_currency(item_amount, me.frm.doc.currency)
|
||||||
}
|
}
|
||||||
)).appendTo($items);
|
)).appendTo($items);
|
||||||
});
|
});
|
||||||
|
|
||||||
// taxes
|
// taxes
|
||||||
var taxes = wn.model.get_children("Sales Taxes and Charges", this.frm.doc.name, "other_charges",
|
var taxes = wn.model.get_children(this.sales_or_purchase + " Taxes and Charges",
|
||||||
"Sales Invoice");
|
this.frm.doc.name, this.frm.cscript.other_fname, this.frm.doctype);
|
||||||
$(".tax-table")
|
$(this.wrapper).find(".tax-table")
|
||||||
.toggle((taxes && taxes.length) ? true : false)
|
.toggle((taxes && taxes.length) ? true : false)
|
||||||
.find("tbody").empty();
|
.find("tbody").empty();
|
||||||
|
|
||||||
@ -297,30 +324,39 @@ erpnext.POS = Class.extend({
|
|||||||
<tr>', {
|
<tr>', {
|
||||||
description: d.description,
|
description: d.description,
|
||||||
rate: d.rate,
|
rate: d.rate,
|
||||||
tax_amount: format_currency(d.tax_amount, me.frm.doc.price_list_currency)
|
tax_amount: format_currency(flt(d.tax_amount)/flt(me.frm.doc.conversion_rate),
|
||||||
|
me.frm.doc.currency)
|
||||||
})).appendTo(".tax-table tbody");
|
})).appendTo(".tax-table tbody");
|
||||||
});
|
});
|
||||||
|
|
||||||
// set totals
|
// set totals
|
||||||
this.wrapper.find(".net-total").text(format_currency(this.frm.doc.net_total_export,
|
if (this.sales_or_purchase == "Sales") {
|
||||||
cur_frm.doc.price_list_currency));
|
this.wrapper.find(".net-total").text(format_currency(this.frm.doc.net_total_export,
|
||||||
this.wrapper.find(".grand-total").text(format_currency(this.frm.doc.grand_total_export,
|
me.frm.doc.currency));
|
||||||
cur_frm.doc.price_list_currency));
|
this.wrapper.find(".grand-total").text(format_currency(this.frm.doc.grand_total_export,
|
||||||
|
me.frm.doc.currency));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.wrapper.find(".net-total").text(format_currency(this.frm.doc.net_total_import,
|
||||||
|
me.frm.doc.currency));
|
||||||
|
this.wrapper.find(".grand-total").text(format_currency(this.frm.doc.grand_total_import,
|
||||||
|
me.frm.doc.currency));
|
||||||
|
}
|
||||||
|
|
||||||
// if form is local then only run all these functions
|
// if form is local then only run all these functions
|
||||||
if (cur_frm.doc.docstatus===0) {
|
if (this.frm.doc.docstatus===0) {
|
||||||
$("input.qty").on("focus", function() {
|
$(this.wrapper).find("input.qty").on("focus", function() {
|
||||||
$(this).select();
|
$(this).select();
|
||||||
});
|
});
|
||||||
|
|
||||||
// append quantity to the respective item after change from input box
|
// append quantity to the respective item after change from input box
|
||||||
$("input.qty").on("change", function() {
|
$(this.wrapper).find("input.qty").on("change", function() {
|
||||||
var item_code = $(this).closest("tr")[0].id;
|
var item_code = $(this).closest("tr")[0].id;
|
||||||
me.update_qty(item_code, $(this).val(), true);
|
me.update_qty(item_code, $(this).val(), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
// on td click toggle the highlighting of row
|
// on td click toggle the highlighting of row
|
||||||
$("#cart tbody tr td").on("click", function() {
|
$(this.wrapper).find("#cart tbody tr td").on("click", function() {
|
||||||
var row = $(this).closest("tr");
|
var row = $(this).closest("tr");
|
||||||
if (row.attr("data-selected") == "false") {
|
if (row.attr("data-selected") == "false") {
|
||||||
row.attr("class", "warning");
|
row.attr("class", "warning");
|
||||||
@ -335,20 +371,37 @@ erpnext.POS = Class.extend({
|
|||||||
});
|
});
|
||||||
|
|
||||||
me.refresh_delete_btn();
|
me.refresh_delete_btn();
|
||||||
cur_frm.pos.barcode.$input.focus();
|
this.barcode.$input.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if form is submitted & cancelled then disable all input box & buttons
|
// if form is submitted & cancelled then disable all input box & buttons
|
||||||
if (cur_frm.doc.docstatus>=1 && cint(cur_frm.doc.is_pos)) {
|
if (this.frm.doc.docstatus>=1) {
|
||||||
me.wrapper.find('input, button').each(function () {
|
$(this.wrapper).find('input, button').each(function () {
|
||||||
$(this).prop('disabled', true);
|
$(this).prop('disabled', true);
|
||||||
});
|
});
|
||||||
$(".delete-items").hide();
|
$(this.wrapper).find(".delete-items").hide();
|
||||||
$(".make-payment").hide();
|
$(this.wrapper).find(".make-payment").hide();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$(this.wrapper).find('input, button').each(function () {
|
||||||
|
$(this).prop('disabled', false);
|
||||||
|
});
|
||||||
|
$(this.wrapper).find(".make-payment").show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show Make Payment button only in Sales Invoice
|
||||||
|
if (this.frm.doctype != "Sales Invoice")
|
||||||
|
$(this.wrapper).find(".make-payment").hide();
|
||||||
|
|
||||||
|
// If quotation to is not Customer then remove party
|
||||||
|
if (this.frm.doctype == "Quotation") {
|
||||||
|
this.party_field.$wrapper.remove();
|
||||||
|
if (this.frm.doc.quotation_to == "Customer")
|
||||||
|
this.make_party();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
refresh_delete_btn: function() {
|
refresh_delete_btn: function() {
|
||||||
$(".delete-items").toggle($(".item-cart .warning").length ? true : false);
|
$(this.wrapper).find(".delete-items").toggle($(".item-cart .warning").length ? true : false);
|
||||||
},
|
},
|
||||||
add_item_thru_barcode: function() {
|
add_item_thru_barcode: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
@ -370,32 +423,32 @@ erpnext.POS = Class.extend({
|
|||||||
remove_selected_item: function() {
|
remove_selected_item: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
var selected_items = [];
|
var selected_items = [];
|
||||||
var no_of_items = $("#cart tbody tr").length;
|
var no_of_items = $(this.wrapper).find("#cart tbody tr").length;
|
||||||
for(var x=0; x<=no_of_items - 1; x++) {
|
for(var x=0; x<=no_of_items - 1; x++) {
|
||||||
var row = $("#cart tbody tr:eq(" + x + ")");
|
var row = $(this.wrapper).find("#cart tbody tr:eq(" + x + ")");
|
||||||
if(row.attr("data-selected") == "true") {
|
if(row.attr("data-selected") == "true") {
|
||||||
selected_items.push(row.attr("id"));
|
selected_items.push(row.attr("id"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var child = wn.model.get_children("Sales Invoice Item", this.frm.doc.name, "entries",
|
var child = wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name,
|
||||||
"Sales Invoice");
|
this.frm.cscript.fname, this.frm.doctype);
|
||||||
|
|
||||||
$.each(child, function(i, d) {
|
$.each(child, function(i, d) {
|
||||||
for (var i in selected_items) {
|
for (var i in selected_items) {
|
||||||
if (d.item_code == selected_items[i]) {
|
if (d.item_code == selected_items[i]) {
|
||||||
// cur_frm.fields_dict["entries"].grid.grid_rows[d.idx].remove();
|
|
||||||
wn.model.clear_doc(d.doctype, d.name);
|
wn.model.clear_doc(d.doctype, d.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
cur_frm.fields_dict["entries"].grid.refresh();
|
this.frm.fields_dict[this.frm.cscript.fname].grid.refresh();
|
||||||
cur_frm.script_manager.trigger("calculate_taxes_and_totals");
|
this.frm.script_manager.trigger("calculate_taxes_and_totals");
|
||||||
me.frm.dirty();
|
me.frm.dirty();
|
||||||
me.refresh();
|
me.refresh();
|
||||||
},
|
},
|
||||||
make_payment: function() {
|
make_payment: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
var no_of_items = $("#cart tbody tr").length;
|
var no_of_items = $(this.wrapper).find("#cart tbody tr").length;
|
||||||
var mode_of_payment = [];
|
var mode_of_payment = [];
|
||||||
|
|
||||||
if (no_of_items == 0)
|
if (no_of_items == 0)
|
||||||
@ -423,15 +476,15 @@ erpnext.POS = Class.extend({
|
|||||||
"total_amount": $(".grand-total").text()
|
"total_amount": $(".grand-total").text()
|
||||||
});
|
});
|
||||||
dialog.show();
|
dialog.show();
|
||||||
cur_frm.pos.barcode.$input.focus();
|
me.barcode.$input.focus();
|
||||||
|
|
||||||
dialog.get_input("total_amount").prop("disabled", true);
|
dialog.get_input("total_amount").prop("disabled", true);
|
||||||
|
|
||||||
dialog.fields_dict.pay.input.onclick = function() {
|
dialog.fields_dict.pay.input.onclick = function() {
|
||||||
cur_frm.set_value("mode_of_payment", dialog.get_values().mode_of_payment);
|
me.frm.set_value("mode_of_payment", dialog.get_values().mode_of_payment);
|
||||||
cur_frm.set_value("paid_amount", dialog.get_values().total_amount);
|
me.frm.set_value("paid_amount", dialog.get_values().total_amount);
|
||||||
cur_frm.cscript.mode_of_payment(cur_frm.doc);
|
me.frm.cscript.mode_of_payment(me.frm.doc);
|
||||||
cur_frm.save();
|
me.frm.save();
|
||||||
dialog.hide();
|
dialog.hide();
|
||||||
me.refresh();
|
me.refresh();
|
||||||
};
|
};
|
||||||
|
@ -3,17 +3,21 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import webnotes
|
import webnotes
|
||||||
from webnotes import msgprint
|
|
||||||
|
|
||||||
@webnotes.whitelist()
|
@webnotes.whitelist()
|
||||||
def get_items(price_list, item=None, item_group=None):
|
def get_items(price_list, sales_or_purchase, item=None, item_group=None):
|
||||||
condition = ""
|
condition = ""
|
||||||
|
|
||||||
|
if sales_or_purchase == "Sales":
|
||||||
|
condition = "i.is_sales_item='Yes'"
|
||||||
|
else:
|
||||||
|
condition = "i.is_purchase_item='Yes'"
|
||||||
|
|
||||||
if item_group and item_group != "All Item Groups":
|
if item_group and item_group != "All Item Groups":
|
||||||
condition = "and i.item_group='%s'" % item_group
|
condition += " and i.item_group='%s'" % item_group
|
||||||
|
|
||||||
if item:
|
if item:
|
||||||
condition = "and i.name='%s'" % item
|
condition += " and i.name='%s'" % item
|
||||||
|
|
||||||
return webnotes.conn.sql("""select i.name, i.item_name, i.image,
|
return webnotes.conn.sql("""select i.name, i.item_name, i.image,
|
||||||
pl_items.ref_rate, pl_items.currency
|
pl_items.ref_rate, pl_items.currency
|
||||||
@ -24,13 +28,18 @@ def get_items(price_list, item=None, item_group=None):
|
|||||||
ON
|
ON
|
||||||
pl_items.item_code=i.name
|
pl_items.item_code=i.name
|
||||||
where
|
where
|
||||||
i.is_sales_item='Yes'%s""" % ('%s', condition), (price_list), as_dict=1)
|
%s""" % ('%s', condition), (price_list), as_dict=1)
|
||||||
|
|
||||||
@webnotes.whitelist()
|
@webnotes.whitelist()
|
||||||
def get_item_from_barcode(barcode):
|
def get_item_from_barcode(barcode):
|
||||||
return webnotes.conn.sql("""select name from `tabItem` where barcode=%s""",
|
return webnotes.conn.sql("""select name from `tabItem` where barcode=%s""",
|
||||||
(barcode), as_dict=1)
|
(barcode), as_dict=1)
|
||||||
|
|
||||||
|
@webnotes.whitelist()
|
||||||
|
def get_item_from_serial_no(serial_no):
|
||||||
|
return webnotes.conn.sql("""select name, item_code from `tabSerial No` where
|
||||||
|
name=%s""", (serial_no), as_dict=1)
|
||||||
|
|
||||||
@webnotes.whitelist()
|
@webnotes.whitelist()
|
||||||
def get_mode_of_payment():
|
def get_mode_of_payment():
|
||||||
return webnotes.conn.sql("""select name from `tabMode of Payment`""", as_dict=1)
|
return webnotes.conn.sql("""select name from `tabMode of Payment`""", as_dict=1)
|
@ -1,15 +0,0 @@
|
|||||||
.pos-item {
|
|
||||||
height: 200px;
|
|
||||||
overflow: hidden;
|
|
||||||
cursor: pointer;
|
|
||||||
padding-left: 5px !important;
|
|
||||||
padding-right: 5px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pos-bill {
|
|
||||||
padding: 20px 5px;
|
|
||||||
font-family: Monospace;
|
|
||||||
border: 1px solid #eee;
|
|
||||||
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
|
|
||||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
|
|
||||||
}
|
|
@ -29,9 +29,10 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
// toggle to pos view if is_pos is 1 in user_defaults
|
// toggle to pos view if is_pos is 1 in user_defaults
|
||||||
if ((cint(wn.defaults.get_user_defaults("is_pos"))===1 || cur_frm.doc.is_pos) &&
|
if ((cint(wn.defaults.get_user_defaults("is_pos"))===1 || cur_frm.doc.is_pos) &&
|
||||||
cint(wn.defaults.get_user_defaults("fs_pos_view"))===1) {
|
cint(wn.defaults.get_user_defaults("fs_pos_view"))===1) {
|
||||||
this.frm.set_value("is_pos", 1);
|
if(this.frm.doc.__islocal && !this.frm.doc.amended_from) {
|
||||||
this.is_pos();
|
this.frm.set_value("is_pos", 1);
|
||||||
cur_frm.cscript.toggle_pos(true);
|
this.is_pos(function() {cur_frm.cscript.toggle_pos(true);});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if document is POS then change default print format to "POS Invoice"
|
// if document is POS then change default print format to "POS Invoice"
|
||||||
@ -78,14 +79,11 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
cur_frm.add_custom_button(wn._('Make Payment Entry'), cur_frm.cscript.make_bank_voucher);
|
cur_frm.add_custom_button(wn._('Make Payment Entry'), cur_frm.cscript.make_bank_voucher);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doc.docstatus===0) {
|
// Show buttons only when pos view is active
|
||||||
|
if (doc.docstatus===0 && !this.pos_active) {
|
||||||
cur_frm.cscript.sales_order_btn();
|
cur_frm.cscript.sales_order_btn();
|
||||||
cur_frm.cscript.delivery_note_btn();
|
cur_frm.cscript.delivery_note_btn();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show POS button only if it enabled from features setup
|
|
||||||
if(cint(sys_defaults.fs_pos_view)===1)
|
|
||||||
cur_frm.cscript.pos_btn();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
sales_order_btn: function() {
|
sales_order_btn: function() {
|
||||||
@ -124,62 +122,13 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
pos_btn: function() {
|
|
||||||
if(cur_frm.$pos_btn)
|
|
||||||
cur_frm.$pos_btn.remove();
|
|
||||||
|
|
||||||
if(!cur_frm.pos_active) {
|
|
||||||
var btn_label = wn._("POS View"),
|
|
||||||
icon = "icon-desktop";
|
|
||||||
|
|
||||||
cur_frm.cscript.sales_order_btn();
|
|
||||||
cur_frm.cscript.delivery_note_btn();
|
|
||||||
} else {
|
|
||||||
var btn_label = wn._("Invoice View"),
|
|
||||||
icon = "icon-file-text";
|
|
||||||
|
|
||||||
if (cur_frm.doc.docstatus===0) {
|
|
||||||
this.$delivery_note_btn.remove();
|
|
||||||
this.$sales_order_btn.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.$pos_btn = cur_frm.add_custom_button(btn_label, function() {
|
|
||||||
cur_frm.cscript.toggle_pos();
|
|
||||||
cur_frm.cscript.pos_btn();
|
|
||||||
}, icon);
|
|
||||||
},
|
|
||||||
|
|
||||||
toggle_pos: function(show) {
|
|
||||||
if (!this.frm.doc.selling_price_list)
|
|
||||||
msgprint(wn._("Please select Price List"))
|
|
||||||
else {
|
|
||||||
if((show===true && cur_frm.pos_active) || (show===false && !cur_frm.pos_active)) return;
|
|
||||||
|
|
||||||
// make pos
|
|
||||||
if(!cur_frm.pos) {
|
|
||||||
cur_frm.layout.add_view("pos");
|
|
||||||
cur_frm.pos = new erpnext.POS(cur_frm.layout.views.pos, cur_frm);
|
|
||||||
}
|
|
||||||
|
|
||||||
// toggle view
|
|
||||||
cur_frm.layout.set_view(cur_frm.pos_active ? "" : "pos");
|
|
||||||
cur_frm.pos_active = !cur_frm.pos_active;
|
|
||||||
|
|
||||||
// refresh
|
|
||||||
if(cur_frm.pos_active)
|
|
||||||
cur_frm.pos.refresh();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
tc_name: function() {
|
tc_name: function() {
|
||||||
this.get_terms();
|
this.get_terms();
|
||||||
},
|
},
|
||||||
|
|
||||||
is_pos: function() {
|
is_pos: function(callback_fn) {
|
||||||
cur_frm.cscript.hide_fields(this.frm.doc);
|
cur_frm.cscript.hide_fields(this.frm.doc);
|
||||||
|
|
||||||
if(cint(this.frm.doc.is_pos)) {
|
if(cint(this.frm.doc.is_pos)) {
|
||||||
if(!this.frm.doc.company) {
|
if(!this.frm.doc.company) {
|
||||||
this.frm.set_value("is_pos", 0);
|
this.frm.set_value("is_pos", 0);
|
||||||
@ -192,6 +141,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if(!r.exc) {
|
if(!r.exc) {
|
||||||
me.frm.script_manager.trigger("update_stock");
|
me.frm.script_manager.trigger("update_stock");
|
||||||
|
if(callback_fn) callback_fn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -256,7 +206,6 @@ cur_frm.cscript.hide_fields = function(doc) {
|
|||||||
'total_commission', 'advances'];
|
'total_commission', 'advances'];
|
||||||
|
|
||||||
item_flds_normal = ['sales_order', 'delivery_note']
|
item_flds_normal = ['sales_order', 'delivery_note']
|
||||||
item_flds_pos = ['serial_no', 'batch_no', 'actual_qty', 'expense_account']
|
|
||||||
|
|
||||||
if(cint(doc.is_pos) == 1) {
|
if(cint(doc.is_pos) == 1) {
|
||||||
hide_field(par_flds);
|
hide_field(par_flds);
|
||||||
@ -271,7 +220,9 @@ cur_frm.cscript.hide_fields = function(doc) {
|
|||||||
cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_normal, true);
|
cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_normal, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_pos, (cint(doc.update_stock)==1?true:false));
|
item_flds_stock = ['serial_no', 'batch_no', 'actual_qty', 'expense_account', 'warehouse']
|
||||||
|
cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_stock,
|
||||||
|
(cint(doc.update_stock)==1 ? true : false));
|
||||||
|
|
||||||
// India related fields
|
// India related fields
|
||||||
var cp = wn.control_panel;
|
var cp = wn.control_panel;
|
||||||
|
@ -83,7 +83,6 @@ class DocType(SellingController):
|
|||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
if cint(self.doc.update_stock) == 1:
|
if cint(self.doc.update_stock) == 1:
|
||||||
self.update_stock_ledger()
|
self.update_stock_ledger()
|
||||||
self.update_serial_nos()
|
|
||||||
else:
|
else:
|
||||||
# Check for Approving Authority
|
# Check for Approving Authority
|
||||||
if not self.doc.recurring_id:
|
if not self.doc.recurring_id:
|
||||||
@ -111,7 +110,6 @@ class DocType(SellingController):
|
|||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
if cint(self.doc.update_stock) == 1:
|
if cint(self.doc.update_stock) == 1:
|
||||||
self.update_stock_ledger()
|
self.update_stock_ledger()
|
||||||
self.update_serial_nos(cancel = True)
|
|
||||||
|
|
||||||
sales_com_obj = get_obj(dt = 'Sales Common')
|
sales_com_obj = get_obj(dt = 'Sales Common')
|
||||||
sales_com_obj.check_stop_sales_order(self)
|
sales_com_obj.check_stop_sales_order(self)
|
||||||
@ -195,7 +193,7 @@ class DocType(SellingController):
|
|||||||
pos = get_pos_settings(self.doc.company)
|
pos = get_pos_settings(self.doc.company)
|
||||||
|
|
||||||
if pos:
|
if pos:
|
||||||
if not for_validate:
|
if not for_validate and not self.doc.customer:
|
||||||
self.doc.customer = pos.customer
|
self.doc.customer = pos.customer
|
||||||
self.set_customer_defaults()
|
self.set_customer_defaults()
|
||||||
|
|
||||||
@ -266,13 +264,7 @@ class DocType(SellingController):
|
|||||||
|
|
||||||
def get_adj_percent(self, arg=''):
|
def get_adj_percent(self, arg=''):
|
||||||
"""Fetch ref rate from item master as per selected price list"""
|
"""Fetch ref rate from item master as per selected price list"""
|
||||||
get_obj('Sales Common').get_adj_percent(self)
|
get_obj('Sales Common').get_adj_percent(self)
|
||||||
|
|
||||||
|
|
||||||
def get_rate(self,arg):
|
|
||||||
"""Get tax rate if account type is tax"""
|
|
||||||
get_obj('Sales Common').get_rate(arg)
|
|
||||||
|
|
||||||
|
|
||||||
def get_comm_rate(self, sales_partner):
|
def get_comm_rate(self, sales_partner):
|
||||||
"""Get Commission rate of Sales Partner"""
|
"""Get Commission rate of Sales Partner"""
|
||||||
@ -965,8 +957,7 @@ def make_delivery_note(source_name, target_doclist=None):
|
|||||||
"doctype": "Delivery Note Item",
|
"doctype": "Delivery Note Item",
|
||||||
"field_map": {
|
"field_map": {
|
||||||
"name": "prevdoc_detail_docname",
|
"name": "prevdoc_detail_docname",
|
||||||
"parent": "prevdoc_docname",
|
"parent": "against_sales_invoice",
|
||||||
"parenttype": "prevdoc_doctype",
|
|
||||||
"serial_no": "serial_no"
|
"serial_no": "serial_no"
|
||||||
},
|
},
|
||||||
"postprocess": update_item
|
"postprocess": update_item
|
||||||
|
@ -2,12 +2,13 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-05-24 19:29:05",
|
"creation": "2013-05-24 19:29:05",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-09-01 05:26:13",
|
"modified": "2013-10-11 13:12:38",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_attach": 1,
|
"allow_attach": 1,
|
||||||
|
"allow_import": 1,
|
||||||
"autoname": "naming_series:",
|
"autoname": "naming_series:",
|
||||||
"default_print_format": "Standard",
|
"default_print_format": "Standard",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
@ -225,7 +226,6 @@
|
|||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "1.00",
|
|
||||||
"description": "Rate at which Customer Currency is converted to customer's base currency",
|
"description": "Rate at which Customer Currency is converted to customer's base currency",
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "conversion_rate",
|
"fieldname": "conversion_rate",
|
||||||
@ -411,7 +411,7 @@
|
|||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "other_charges",
|
"fieldname": "other_charges",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"label": "Taxes and Charges1",
|
"label": "Sales Taxes and Charges",
|
||||||
"oldfieldname": "other_charges",
|
"oldfieldname": "other_charges",
|
||||||
"oldfieldtype": "Table",
|
"oldfieldtype": "Table",
|
||||||
"options": "Sales Taxes and Charges",
|
"options": "Sales Taxes and Charges",
|
||||||
|
@ -641,8 +641,8 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
return new_si
|
return new_si
|
||||||
|
|
||||||
# if yearly, test 3 repetitions, else test 13 repetitions
|
# if yearly, test 1 repetition, else test 5 repetitions
|
||||||
count = 3 if no_of_months == 12 else 13
|
count = 1 if (no_of_months == 12) else 5
|
||||||
for i in xrange(count):
|
for i in xrange(count):
|
||||||
base_si = _test(i)
|
base_si = _test(i)
|
||||||
|
|
||||||
@ -653,7 +653,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
def test_serialized(self):
|
def test_serialized(self):
|
||||||
from stock.doctype.stock_entry.test_stock_entry import make_serialized_item
|
from stock.doctype.stock_entry.test_stock_entry import make_serialized_item
|
||||||
from stock.doctype.stock_ledger_entry.stock_ledger_entry import get_serial_nos
|
from stock.doctype.serial_no.serial_no import get_serial_nos
|
||||||
|
|
||||||
se = make_serialized_item()
|
se = make_serialized_item()
|
||||||
serial_nos = get_serial_nos(se.doclist[1].serial_no)
|
serial_nos = get_serial_nos(se.doclist[1].serial_no)
|
||||||
@ -674,7 +674,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
return si
|
return si
|
||||||
|
|
||||||
def test_serialized_cancel(self):
|
def test_serialized_cancel(self):
|
||||||
from stock.doctype.stock_ledger_entry.stock_ledger_entry import get_serial_nos
|
from stock.doctype.serial_no.serial_no import get_serial_nos
|
||||||
si = self.test_serialized()
|
si = self.test_serialized()
|
||||||
si.cancel()
|
si.cancel()
|
||||||
|
|
||||||
@ -686,7 +686,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
"delivery_document_no"))
|
"delivery_document_no"))
|
||||||
|
|
||||||
def test_serialize_status(self):
|
def test_serialize_status(self):
|
||||||
from stock.doctype.stock_ledger_entry.stock_ledger_entry import SerialNoStatusError, get_serial_nos
|
from stock.doctype.serial_no.serial_no import SerialNoStatusError, get_serial_nos
|
||||||
from stock.doctype.stock_entry.test_stock_entry import make_serialized_item
|
from stock.doctype.stock_entry.test_stock_entry import make_serialized_item
|
||||||
|
|
||||||
se = make_serialized_item()
|
se = make_serialized_item()
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
// License: GNU General Public License v3. See license.txt
|
// License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
//--------- ONLOAD -------------
|
//--------- ONLOAD -------------
|
||||||
|
|
||||||
|
wn.require("app/js/controllers/accounts.js");
|
||||||
|
|
||||||
cur_frm.cscript.onload = function(doc, cdt, cdn) {
|
cur_frm.cscript.onload = function(doc, cdt, cdn) {
|
||||||
if(doc.doctype === "Sales Taxes and Charges Master")
|
if(doc.doctype === "Sales Taxes and Charges Master")
|
||||||
erpnext.add_for_territory();
|
erpnext.add_for_territory();
|
||||||
@ -142,6 +145,7 @@ cur_frm.fields_dict['other_charges'].grid.get_field("cost_center").get_query = f
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
|
||||||
cur_frm.cscript.account_head = function(doc, cdt, cdn) {
|
cur_frm.cscript.account_head = function(doc, cdt, cdn) {
|
||||||
var d = locals[cdt][cdn];
|
var d = locals[cdt][cdn];
|
||||||
@ -157,6 +161,8 @@ cur_frm.cscript.account_head = function(doc, cdt, cdn) {
|
|||||||
refresh_field('account_head',d.name,'other_charges');
|
refresh_field('account_head',d.name,'other_charges');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> f146e8b7f52a3e46e335c0fefd92c347717b370b
|
||||||
cur_frm.cscript.rate = function(doc, cdt, cdn) {
|
cur_frm.cscript.rate = function(doc, cdt, cdn) {
|
||||||
var d = locals[cdt][cdn];
|
var d = locals[cdt][cdn];
|
||||||
if(!d.charge_type && d.rate) {
|
if(!d.charge_type && d.rate) {
|
||||||
|
@ -6,11 +6,7 @@ import webnotes
|
|||||||
from webnotes.utils import cint
|
from webnotes.utils import cint
|
||||||
from webnotes.model.controller import DocListController
|
from webnotes.model.controller import DocListController
|
||||||
|
|
||||||
class DocType(DocListController):
|
class DocType(DocListController):
|
||||||
def get_rate(self, arg):
|
|
||||||
from webnotes.model.code import get_obj
|
|
||||||
return get_obj('Sales Common').get_rate(arg)
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
if self.doc.is_default == 1:
|
if self.doc.is_default == 1:
|
||||||
webnotes.conn.sql("""update `tabSales Taxes and Charges Master` set is_default = 0
|
webnotes.conn.sql("""update `tabSales Taxes and Charges Master` set is_default = 0
|
||||||
|
@ -15,7 +15,7 @@ def get_companies():
|
|||||||
|
|
||||||
@webnotes.whitelist()
|
@webnotes.whitelist()
|
||||||
def get_children():
|
def get_children():
|
||||||
args = webnotes.form_dict
|
args = webnotes.local.form_dict
|
||||||
ctype, company = args['ctype'], args['comp']
|
ctype, company = args['ctype'], args['comp']
|
||||||
|
|
||||||
# root
|
# root
|
||||||
|
@ -64,10 +64,10 @@ def upload():
|
|||||||
|
|
||||||
data, start_idx = get_data(rows, company_abbr, rows[0][0])
|
data, start_idx = get_data(rows, company_abbr, rows[0][0])
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
err_msg = webnotes.message_log and "<br>".join(webnotes.message_log) or cstr(e)
|
err_msg = webnotes.local.message_log and "<br>".join(webnotes.local.message_log) or cstr(e)
|
||||||
messages.append("""<p style='color: red'>%s</p>""" % (err_msg or "No message"))
|
messages.append("""<p style='color: red'>%s</p>""" % (err_msg or "No message"))
|
||||||
webnotes.errprint(webnotes.getTraceback())
|
webnotes.errprint(webnotes.getTraceback())
|
||||||
webnotes.message_log = []
|
webnotes.local.message_log = []
|
||||||
return messages
|
return messages
|
||||||
|
|
||||||
return import_vouchers(common_values, data, start_idx, rows[0][0])
|
return import_vouchers(common_values, data, start_idx, rows[0][0])
|
||||||
@ -117,11 +117,11 @@ def import_vouchers(common_values, data, start_idx, import_type):
|
|||||||
|
|
||||||
d = data[i][0]
|
d = data[i][0]
|
||||||
if import_type == "Voucher Import: Two Accounts" and flt(d.get("amount")) == 0:
|
if import_type == "Voucher Import: Two Accounts" and flt(d.get("amount")) == 0:
|
||||||
webnotes.message_log = ["Amount not specified"]
|
webnotes.local.message_log = ["Amount not specified"]
|
||||||
raise Exception
|
raise Exception
|
||||||
elif import_type == "Voucher Import: Multiple Accounts" and \
|
elif import_type == "Voucher Import: Multiple Accounts" and \
|
||||||
(flt(d.get("total_debit")) == 0 or flt(d.get("total_credit")) == 0):
|
(flt(d.get("total_debit")) == 0 or flt(d.get("total_credit")) == 0):
|
||||||
webnotes.message_log = ["Total Debit and Total Credit amount can not be zero"]
|
webnotes.local.message_log = ["Total Debit and Total Credit amount can not be zero"]
|
||||||
raise Exception
|
raise Exception
|
||||||
else:
|
else:
|
||||||
d.posting_date = parse_date(d.posting_date)
|
d.posting_date = parse_date(d.posting_date)
|
||||||
@ -174,7 +174,7 @@ def import_vouchers(common_values, data, start_idx, import_type):
|
|||||||
details.append(detail)
|
details.append(detail)
|
||||||
|
|
||||||
if not details:
|
if not details:
|
||||||
webnotes.message_log = ["""No accounts found.
|
webnotes.local.message_log = ["""No accounts found.
|
||||||
If you entered accounts correctly, please check template once"""]
|
If you entered accounts correctly, please check template once"""]
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
@ -193,12 +193,12 @@ def import_vouchers(common_values, data, start_idx, import_type):
|
|||||||
webnotes.conn.commit()
|
webnotes.conn.commit()
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
webnotes.conn.rollback()
|
webnotes.conn.rollback()
|
||||||
err_msg = webnotes.message_log and "<br>".join(webnotes.message_log) or cstr(e)
|
err_msg = webnotes.local.message_log and "<br>".join(webnotes.local.message_log) or cstr(e)
|
||||||
messages.append("""<p style='color: red'>[row #%s] %s failed: %s</p>"""
|
messages.append("""<p style='color: red'>[row #%s] %s failed: %s</p>"""
|
||||||
% ((start_idx + 1) + i, jv.name or "", err_msg or "No message"))
|
% ((start_idx + 1) + i, jv.name or "", err_msg or "No message"))
|
||||||
messages.append("<p style='color: red'>All transactions rolled back</p>")
|
messages.append("<p style='color: red'>All transactions rolled back</p>")
|
||||||
webnotes.errprint(webnotes.getTraceback())
|
webnotes.errprint(webnotes.getTraceback())
|
||||||
webnotes.message_log = []
|
webnotes.local.message_log = []
|
||||||
|
|
||||||
return messages
|
return messages
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ def get_stock_ledger_entries(filters):
|
|||||||
from `tabStock Ledger Entry`"""
|
from `tabStock Ledger Entry`"""
|
||||||
|
|
||||||
if filters.get("company"):
|
if filters.get("company"):
|
||||||
query += """ and company=%(company)s"""
|
query += """ where company=%(company)s"""
|
||||||
|
|
||||||
query += " order by item_code desc, warehouse desc, posting_date desc, posting_time desc, name desc"
|
query += " order by item_code desc, warehouse desc, posting_date desc, posting_time desc, name desc"
|
||||||
|
|
||||||
|
@ -81,12 +81,12 @@ def get_tax_accounts(item_list, columns):
|
|||||||
if account_head not in tax_accounts:
|
if account_head not in tax_accounts:
|
||||||
tax_accounts.append(account_head)
|
tax_accounts.append(account_head)
|
||||||
|
|
||||||
invoice = item_tax.setdefault(parent, {})
|
|
||||||
if item_wise_tax_detail:
|
if item_wise_tax_detail:
|
||||||
try:
|
try:
|
||||||
item_wise_tax_detail = json.loads(item_wise_tax_detail)
|
item_wise_tax_detail = json.loads(item_wise_tax_detail)
|
||||||
for item, tax_amount in item_wise_tax_detail.items():
|
for item, tax_amount in item_wise_tax_detail.items():
|
||||||
invoice.setdefault(item, {})[account_head] = flt(tax_amount)
|
item_tax.setdefault(parent, {}).setdefault(item, {})[account_head] = \
|
||||||
|
flt(tax_amount[1])
|
||||||
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
continue
|
continue
|
||||||
|
@ -9,7 +9,7 @@ def execute(filters=None):
|
|||||||
if not filters: filters = {}
|
if not filters: filters = {}
|
||||||
columns = get_columns()
|
columns = get_columns()
|
||||||
last_col = len(columns)
|
last_col = len(columns)
|
||||||
|
|
||||||
item_list = get_items(filters)
|
item_list = get_items(filters)
|
||||||
item_tax, tax_accounts = get_tax_accounts(item_list, columns)
|
item_tax, tax_accounts = get_tax_accounts(item_list, columns)
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ def execute(filters=None):
|
|||||||
|
|
||||||
for tax in tax_accounts:
|
for tax in tax_accounts:
|
||||||
row.append(item_tax.get(d.parent, {}).get(d.item_code, {}).get(tax, 0))
|
row.append(item_tax.get(d.parent, {}).get(d.item_code, {}).get(tax, 0))
|
||||||
|
|
||||||
total_tax = sum(row[last_col:])
|
total_tax = sum(row[last_col:])
|
||||||
row += [total_tax, d.amount + total_tax]
|
row += [total_tax, d.amount + total_tax]
|
||||||
|
|
||||||
@ -71,19 +71,19 @@ def get_tax_accounts(item_list, columns):
|
|||||||
tax_details = webnotes.conn.sql("""select parent, account_head, item_wise_tax_detail
|
tax_details = webnotes.conn.sql("""select parent, account_head, item_wise_tax_detail
|
||||||
from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice'
|
from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice'
|
||||||
and docstatus = 1 and ifnull(account_head, '') != ''
|
and docstatus = 1 and ifnull(account_head, '') != ''
|
||||||
and parent in (%s)""" % ', '.join(['%s']*len(item_list)), tuple([item.parent for item in item_list]))
|
and parent in (%s)""" % ', '.join(['%s']*len(item_list)),
|
||||||
|
tuple([item.parent for item in item_list]))
|
||||||
|
|
||||||
for parent, account_head, item_wise_tax_detail in tax_details:
|
for parent, account_head, item_wise_tax_detail in tax_details:
|
||||||
if account_head not in tax_accounts:
|
if account_head not in tax_accounts:
|
||||||
tax_accounts.append(account_head)
|
tax_accounts.append(account_head)
|
||||||
|
|
||||||
invoice = item_tax.setdefault(parent, {})
|
|
||||||
if item_wise_tax_detail:
|
if item_wise_tax_detail:
|
||||||
try:
|
try:
|
||||||
item_wise_tax_detail = json.loads(item_wise_tax_detail)
|
item_wise_tax_detail = json.loads(item_wise_tax_detail)
|
||||||
for item, tax_amount in item_wise_tax_detail.items():
|
for item, tax_amount in item_wise_tax_detail.items():
|
||||||
invoice.setdefault(item, {})[account_head] = flt(tax_amount)
|
item_tax.setdefault(parent, {}).setdefault(item, {})[account_head] = \
|
||||||
|
flt(tax_amount[1])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ def get_balance_on(account=None, date=None):
|
|||||||
@webnotes.whitelist()
|
@webnotes.whitelist()
|
||||||
def add_ac(args=None):
|
def add_ac(args=None):
|
||||||
if not args:
|
if not args:
|
||||||
args = webnotes.form_dict
|
args = webnotes.local.form_dict
|
||||||
args.pop("cmd")
|
args.pop("cmd")
|
||||||
|
|
||||||
ac = webnotes.bean(args)
|
ac = webnotes.bean(args)
|
||||||
@ -121,7 +121,7 @@ def add_ac(args=None):
|
|||||||
@webnotes.whitelist()
|
@webnotes.whitelist()
|
||||||
def add_cc(args=None):
|
def add_cc(args=None):
|
||||||
if not args:
|
if not args:
|
||||||
args = webnotes.form_dict
|
args = webnotes.local.form_dict
|
||||||
args.pop("cmd")
|
args.pop("cmd")
|
||||||
|
|
||||||
cc = webnotes.bean(args)
|
cc = webnotes.bean(args)
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
wn.provide("erpnext.buying");
|
wn.provide("erpnext.buying");
|
||||||
wn.require("app/js/transaction.js");
|
wn.require("app/js/transaction.js");
|
||||||
|
wn.require("app/js/controllers/accounts.js");
|
||||||
|
|
||||||
erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||||
onload: function() {
|
onload: function() {
|
||||||
@ -108,8 +109,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
|||||||
var item = wn.model.get_doc(cdt, cdn);
|
var item = wn.model.get_doc(cdt, cdn);
|
||||||
if(item.item_code) {
|
if(item.item_code) {
|
||||||
if(!this.validate_company_and_party("supplier")) {
|
if(!this.validate_company_and_party("supplier")) {
|
||||||
item.item_code = null;
|
cur_frm.fields_dict[me.frm.cscript.fname].grid.grid_rows[item.idx - 1].remove();
|
||||||
refresh_field("item_code", item.name, item.parentfield);
|
|
||||||
} else {
|
} else {
|
||||||
return this.frm.call({
|
return this.frm.call({
|
||||||
method: "buying.utils.get_item_details",
|
method: "buying.utils.get_item_details",
|
||||||
|
@ -10,7 +10,6 @@ from webnotes import msgprint, _
|
|||||||
|
|
||||||
from buying.utils import get_last_purchase_details
|
from buying.utils import get_last_purchase_details
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
from controllers.buying_controller import BuyingController
|
from controllers.buying_controller import BuyingController
|
||||||
class DocType(BuyingController):
|
class DocType(BuyingController):
|
||||||
@ -23,27 +22,20 @@ class DocType(BuyingController):
|
|||||||
msgprint(_("You need to put at least one item in the item table."), raise_exception=True)
|
msgprint(_("You need to put at least one item in the item table."), raise_exception=True)
|
||||||
|
|
||||||
def get_supplier_details(self, name = ''):
|
def get_supplier_details(self, name = ''):
|
||||||
details = sql("select supplier_name,address from `tabSupplier` where name = '%s' and docstatus != 2" %(name), as_dict = 1)
|
details = webnotes.conn.sql("select supplier_name,address from `tabSupplier` where name = '%s' and docstatus != 2" %(name), as_dict = 1)
|
||||||
if details:
|
if details:
|
||||||
ret = {
|
ret = {
|
||||||
'supplier_name' : details and details[0]['supplier_name'] or '',
|
'supplier_name' : details and details[0]['supplier_name'] or '',
|
||||||
'supplier_address' : details and details[0]['address'] or ''
|
'supplier_address' : details and details[0]['address'] or ''
|
||||||
}
|
}
|
||||||
# ********** get primary contact details (this is done separately coz. , in case there is no primary contact thn it would not be able to fetch customer details in case of join query)
|
# ********** get primary contact details (this is done separately coz. , in case there is no primary contact thn it would not be able to fetch customer details in case of join query)
|
||||||
contact_det = sql("select contact_name, contact_no, email_id from `tabContact` where supplier = '%s' and is_supplier = 1 and is_primary_contact = 'Yes' and docstatus != 2" %(name), as_dict = 1)
|
contact_det = webnotes.conn.sql("select contact_name, contact_no, email_id from `tabContact` where supplier = '%s' and is_supplier = 1 and is_primary_contact = 'Yes' and docstatus != 2" %(name), as_dict = 1)
|
||||||
ret['contact_person'] = contact_det and contact_det[0]['contact_name'] or ''
|
ret['contact_person'] = contact_det and contact_det[0]['contact_name'] or ''
|
||||||
return ret
|
return ret
|
||||||
else:
|
else:
|
||||||
msgprint("Supplier : %s does not exists" % (name))
|
msgprint("Supplier : %s does not exists" % (name))
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
# Get Available Qty at Warehouse
|
|
||||||
def get_bin_details( self, arg = ''):
|
|
||||||
arg = eval(arg)
|
|
||||||
bin = sql("select projected_qty from `tabBin` where item_code = %s and warehouse = %s", (arg['item_code'], arg['warehouse']), as_dict=1)
|
|
||||||
ret = { 'projected_qty' : bin and flt(bin[0]['projected_qty']) or 0 }
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def update_last_purchase_rate(self, obj, is_submit):
|
def update_last_purchase_rate(self, obj, is_submit):
|
||||||
"""updates last_purchase_rate in item table for each item"""
|
"""updates last_purchase_rate in item table for each item"""
|
||||||
|
|
||||||
@ -70,7 +62,7 @@ class DocType(BuyingController):
|
|||||||
|
|
||||||
# update last purchsae rate
|
# update last purchsae rate
|
||||||
if last_purchase_rate:
|
if last_purchase_rate:
|
||||||
sql("update `tabItem` set last_purchase_rate = %s where name = %s",
|
webnotes.conn.sql("update `tabItem` set last_purchase_rate = %s where name = %s",
|
||||||
(flt(last_purchase_rate),d.item_code))
|
(flt(last_purchase_rate),d.item_code))
|
||||||
|
|
||||||
def get_last_purchase_rate(self, obj):
|
def get_last_purchase_rate(self, obj):
|
||||||
@ -107,7 +99,7 @@ class DocType(BuyingController):
|
|||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
# udpate with latest quantities
|
# udpate with latest quantities
|
||||||
bin = sql("select projected_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1)
|
bin = webnotes.conn.sql("select projected_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1)
|
||||||
|
|
||||||
f_lst ={'projected_qty': bin and flt(bin[0]['projected_qty']) or 0, 'ordered_qty': 0, 'received_qty' : 0}
|
f_lst ={'projected_qty': bin and flt(bin[0]['projected_qty']) or 0, 'ordered_qty': 0, 'received_qty' : 0}
|
||||||
if d.doctype == 'Purchase Receipt Item':
|
if d.doctype == 'Purchase Receipt Item':
|
||||||
@ -116,7 +108,7 @@ class DocType(BuyingController):
|
|||||||
if d.fields.has_key(x):
|
if d.fields.has_key(x):
|
||||||
d.fields[x] = f_lst[x]
|
d.fields[x] = f_lst[x]
|
||||||
|
|
||||||
item = sql("select is_stock_item, is_purchase_item, is_sub_contracted_item, end_of_life from tabItem where name=%s",
|
item = webnotes.conn.sql("select is_stock_item, is_purchase_item, is_sub_contracted_item, end_of_life from tabItem where name=%s",
|
||||||
d.item_code)
|
d.item_code)
|
||||||
if not item:
|
if not item:
|
||||||
msgprint("Item %s does not exist in Item Master." % cstr(d.item_code), raise_exception=True)
|
msgprint("Item %s does not exist in Item Master." % cstr(d.item_code), raise_exception=True)
|
||||||
@ -139,7 +131,7 @@ class DocType(BuyingController):
|
|||||||
# if is not stock item
|
# if is not stock item
|
||||||
f = [d.schedule_date, d.item_code, d.description]
|
f = [d.schedule_date, d.item_code, d.description]
|
||||||
|
|
||||||
ch = sql("select is_stock_item from `tabItem` where name = '%s'"%d.item_code)
|
ch = webnotes.conn.sql("select is_stock_item from `tabItem` where name = '%s'"%d.item_code)
|
||||||
|
|
||||||
if ch and ch[0][0] == 'Yes':
|
if ch and ch[0][0] == 'Yes':
|
||||||
# check for same items
|
# check for same items
|
||||||
@ -165,18 +157,18 @@ class DocType(BuyingController):
|
|||||||
# but if in Material Request uom KG it can change in PO
|
# but if in Material Request uom KG it can change in PO
|
||||||
|
|
||||||
get_qty = (transaction == 'Material Request - Purchase Order') and 'qty * conversion_factor' or 'qty'
|
get_qty = (transaction == 'Material Request - Purchase Order') and 'qty * conversion_factor' or 'qty'
|
||||||
qty = sql("select sum(%s) from `tab%s` where %s = '%s' and docstatus = 1 and parent != '%s'"% ( get_qty, curr_doctype, ref_tab_fname, ref_tab_dn, curr_parent_name))
|
qty = webnotes.conn.sql("select sum(%s) from `tab%s` where %s = '%s' and docstatus = 1 and parent != '%s'"% ( get_qty, curr_doctype, ref_tab_fname, ref_tab_dn, curr_parent_name))
|
||||||
qty = qty and flt(qty[0][0]) or 0
|
qty = qty and flt(qty[0][0]) or 0
|
||||||
|
|
||||||
# get total qty of ref doctype
|
# get total qty of ref doctype
|
||||||
#--------------------
|
#--------------------
|
||||||
max_qty = sql("select qty from `tab%s` where name = '%s' and docstatus = 1"% (ref_doc_tname, ref_tab_dn))
|
max_qty = webnotes.conn.sql("select qty from `tab%s` where name = '%s' and docstatus = 1"% (ref_doc_tname, ref_tab_dn))
|
||||||
max_qty = max_qty and flt(max_qty[0][0]) or 0
|
max_qty = max_qty and flt(max_qty[0][0]) or 0
|
||||||
|
|
||||||
return cstr(qty)+'~~~'+cstr(max_qty)
|
return cstr(qty)+'~~~'+cstr(max_qty)
|
||||||
|
|
||||||
def check_for_stopped_status(self, doctype, docname):
|
def check_for_stopped_status(self, doctype, docname):
|
||||||
stopped = sql("select name from `tab%s` where name = '%s' and status = 'Stopped'" %
|
stopped = webnotes.conn.sql("select name from `tab%s` where name = '%s' and status = 'Stopped'" %
|
||||||
( doctype, docname))
|
( doctype, docname))
|
||||||
if stopped:
|
if stopped:
|
||||||
msgprint("One cannot do any transaction against %s : %s, it's status is 'Stopped'" %
|
msgprint("One cannot do any transaction against %s : %s, it's status is 'Stopped'" %
|
||||||
@ -184,7 +176,7 @@ class DocType(BuyingController):
|
|||||||
|
|
||||||
def check_docstatus(self, check, doctype, docname , detail_doctype = ''):
|
def check_docstatus(self, check, doctype, docname , detail_doctype = ''):
|
||||||
if check == 'Next':
|
if check == 'Next':
|
||||||
submitted = sql("""select t1.name from `tab%s` t1,`tab%s` t2
|
submitted = webnotes.conn.sql("""select t1.name from `tab%s` t1,`tab%s` t2
|
||||||
where t1.name = t2.parent and t2.prevdoc_docname = %s and t1.docstatus = 1"""
|
where t1.name = t2.parent and t2.prevdoc_docname = %s and t1.docstatus = 1"""
|
||||||
% (doctype, detail_doctype, '%s'), docname)
|
% (doctype, detail_doctype, '%s'), docname)
|
||||||
if submitted:
|
if submitted:
|
||||||
@ -192,23 +184,8 @@ class DocType(BuyingController):
|
|||||||
+ _(" has already been submitted."), raise_exception=1)
|
+ _(" has already been submitted."), raise_exception=1)
|
||||||
|
|
||||||
if check == 'Previous':
|
if check == 'Previous':
|
||||||
submitted = sql("""select name from `tab%s`
|
submitted = webnotes.conn.sql("""select name from `tab%s`
|
||||||
where docstatus = 1 and name = %s"""% (doctype, '%s'), docname)
|
where docstatus = 1 and name = %s"""% (doctype, '%s'), docname)
|
||||||
if not submitted:
|
if not submitted:
|
||||||
msgprint(cstr(doctype) + ": " + cstr(submitted[0][0])
|
msgprint(cstr(doctype) + ": " + cstr(submitted[0][0])
|
||||||
+ _(" not submitted"), raise_exception=1)
|
+ _(" not submitted"), raise_exception=1)
|
||||||
|
|
||||||
def get_rate(self, arg, obj):
|
|
||||||
arg = eval(arg)
|
|
||||||
rate = sql("select account_type, tax_rate from `tabAccount` where name = %s"
|
|
||||||
, (arg['account_head']), as_dict=1)
|
|
||||||
|
|
||||||
return {'rate': rate and (rate[0]['account_type'] == 'Tax' \
|
|
||||||
and not arg['charge_type'] == 'Actual') and flt(rate[0]['tax_rate']) or 0 }
|
|
||||||
|
|
||||||
def get_prevdoc_date(self, obj):
|
|
||||||
for d in getlist(obj.doclist, obj.fname):
|
|
||||||
if d.prevdoc_doctype and d.prevdoc_docname:
|
|
||||||
dt = sql("select transaction_date from `tab%s` where name = %s"
|
|
||||||
% (d.prevdoc_doctype, '%s'), (d.prevdoc_docname))
|
|
||||||
d.prevdoc_date = dt and dt[0][0].strftime('%Y-%m-%d') or ''
|
|
@ -10,6 +10,7 @@ cur_frm.cscript.other_fname = "purchase_tax_details";
|
|||||||
wn.require('app/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js');
|
wn.require('app/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js');
|
||||||
wn.require('app/utilities/doctype/sms_control/sms_control.js');
|
wn.require('app/utilities/doctype/sms_control/sms_control.js');
|
||||||
wn.require('app/buying/doctype/purchase_common/purchase_common.js');
|
wn.require('app/buying/doctype/purchase_common/purchase_common.js');
|
||||||
|
wn.require('app/accounts/doctype/sales_invoice/pos.js');
|
||||||
|
|
||||||
erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend({
|
erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend({
|
||||||
refresh: function(doc, cdt, cdn) {
|
refresh: function(doc, cdt, cdn) {
|
||||||
@ -184,9 +185,9 @@ cur_frm.pformat.indent_no = function(doc, cdt, cdn){
|
|||||||
if(cl[i].prevdoc_doctype == 'Material Request' && cl[i].prevdoc_docname && prevdoc_list.indexOf(cl[i].prevdoc_docname) == -1) {
|
if(cl[i].prevdoc_doctype == 'Material Request' && cl[i].prevdoc_docname && prevdoc_list.indexOf(cl[i].prevdoc_docname) == -1) {
|
||||||
prevdoc_list.push(cl[i].prevdoc_docname);
|
prevdoc_list.push(cl[i].prevdoc_docname);
|
||||||
if(prevdoc_list.length ==1)
|
if(prevdoc_list.length ==1)
|
||||||
out += make_row(cl[i].prevdoc_doctype, cl[i].prevdoc_docname, cl[i].prevdoc_date,0);
|
out += make_row(cl[i].prevdoc_doctype, cl[i].prevdoc_docname, null,0);
|
||||||
else
|
else
|
||||||
out += make_row('', cl[i].prevdoc_docname, cl[i].prevdoc_date,0);
|
out += make_row('', cl[i].prevdoc_docname,null,0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ from webnotes.model.bean import getlist
|
|||||||
from webnotes.model.code import get_obj
|
from webnotes.model.code import get_obj
|
||||||
from webnotes import msgprint
|
from webnotes import msgprint
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
from controllers.buying_controller import BuyingController
|
from controllers.buying_controller import BuyingController
|
||||||
class DocType(BuyingController):
|
class DocType(BuyingController):
|
||||||
@ -42,7 +41,6 @@ class DocType(BuyingController):
|
|||||||
|
|
||||||
pc_obj = get_obj(dt='Purchase Common')
|
pc_obj = get_obj(dt='Purchase Common')
|
||||||
pc_obj.validate_for_items(self)
|
pc_obj.validate_for_items(self)
|
||||||
pc_obj.get_prevdoc_date(self)
|
|
||||||
self.check_for_stopped_status(pc_obj)
|
self.check_for_stopped_status(pc_obj)
|
||||||
|
|
||||||
self.validate_uom_is_integer("uom", "qty")
|
self.validate_uom_is_integer("uom", "qty")
|
||||||
@ -66,10 +64,6 @@ class DocType(BuyingController):
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
# get available qty at warehouse
|
|
||||||
def get_bin_details(self, arg = ''):
|
|
||||||
return get_obj(dt='Purchase Common').get_bin_details(arg)
|
|
||||||
|
|
||||||
def get_schedule_dates(self):
|
def get_schedule_dates(self):
|
||||||
for d in getlist(self.doclist, 'po_details'):
|
for d in getlist(self.doclist, 'po_details'):
|
||||||
if d.prevdoc_detail_docname and not d.schedule_date:
|
if d.prevdoc_detail_docname and not d.schedule_date:
|
||||||
@ -133,8 +127,8 @@ class DocType(BuyingController):
|
|||||||
update_bin(args)
|
update_bin(args)
|
||||||
|
|
||||||
def check_modified_date(self):
|
def check_modified_date(self):
|
||||||
mod_db = sql("select modified from `tabPurchase Order` where name = '%s'" % self.doc.name)
|
mod_db = webnotes.conn.sql("select modified from `tabPurchase Order` where name = '%s'" % self.doc.name)
|
||||||
date_diff = sql("select TIMEDIFF('%s', '%s')" % ( mod_db[0][0],cstr(self.doc.modified)))
|
date_diff = webnotes.conn.sql("select TIMEDIFF('%s', '%s')" % ( mod_db[0][0],cstr(self.doc.modified)))
|
||||||
|
|
||||||
if date_diff and date_diff[0][0]:
|
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.doc.doctype) +" => "+ cstr(self.doc.name) +" has been modified. Please Refresh. ")
|
||||||
@ -173,7 +167,7 @@ class DocType(BuyingController):
|
|||||||
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.doc.name, detail_doctype = 'Purchase Receipt Item')
|
||||||
|
|
||||||
# Check if Purchase Invoice has been submitted against current Purchase Order
|
# Check if Purchase Invoice has been submitted against current Purchase Order
|
||||||
submitted = 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)
|
submitted = webnotes.conn.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)
|
||||||
if submitted:
|
if submitted:
|
||||||
msgprint("Purchase Invoice : " + cstr(submitted[0][0]) + " has already been submitted !")
|
msgprint("Purchase Invoice : " + cstr(submitted[0][0]) + " has already been submitted !")
|
||||||
raise Exception
|
raise Exception
|
||||||
@ -186,9 +180,6 @@ class DocType(BuyingController):
|
|||||||
def on_update(self):
|
def on_update(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_rate(self,arg):
|
|
||||||
return get_obj('Purchase Common').get_rate(arg,self)
|
|
||||||
|
|
||||||
@webnotes.whitelist()
|
@webnotes.whitelist()
|
||||||
def make_purchase_receipt(source_name, target_doclist=None):
|
def make_purchase_receipt(source_name, target_doclist=None):
|
||||||
from webnotes.model.mapper import get_mapped_doclist
|
from webnotes.model.mapper import get_mapped_doclist
|
||||||
|
@ -2,12 +2,13 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-05-21 16:16:39",
|
"creation": "2013-05-21 16:16:39",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-09-12 18:34:54",
|
"modified": "2013-10-02 14:24:49",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_attach": 1,
|
"allow_attach": 1,
|
||||||
|
"allow_import": 1,
|
||||||
"autoname": "naming_series:",
|
"autoname": "naming_series:",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Transaction",
|
"document_type": "Transaction",
|
||||||
@ -132,7 +133,6 @@
|
|||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
"label": "Purchase Order Date",
|
"label": "Purchase Order Date",
|
||||||
"no_copy": 1,
|
|
||||||
"oldfieldname": "transaction_date",
|
"oldfieldname": "transaction_date",
|
||||||
"oldfieldtype": "Date",
|
"oldfieldtype": "Date",
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
|
@ -98,11 +98,11 @@ class TestPurchaseOrder(unittest.TestCase):
|
|||||||
self.assertEquals(len(po.doclist.get({"parentfield": "po_raw_material_details"})), 2)
|
self.assertEquals(len(po.doclist.get({"parentfield": "po_raw_material_details"})), 2)
|
||||||
|
|
||||||
def test_warehouse_company_validation(self):
|
def test_warehouse_company_validation(self):
|
||||||
from controllers.buying_controller import WrongWarehouseCompany
|
from stock.utils import InvalidWarehouseCompany
|
||||||
po = webnotes.bean(copy=test_records[0])
|
po = webnotes.bean(copy=test_records[0])
|
||||||
po.doc.company = "_Test Company 1"
|
po.doc.company = "_Test Company 1"
|
||||||
po.doc.conversion_rate = 0.0167
|
po.doc.conversion_rate = 0.0167
|
||||||
self.assertRaises(WrongWarehouseCompany, po.insert)
|
self.assertRaises(InvalidWarehouseCompany, po.insert)
|
||||||
|
|
||||||
def test_uom_integer_validation(self):
|
def test_uom_integer_validation(self):
|
||||||
from utilities.transaction_base import UOMMustBeIntegerError
|
from utilities.transaction_base import UOMMustBeIntegerError
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-05-24 19:29:06",
|
"creation": "2013-05-24 19:29:06",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-08-07 14:44:12",
|
"modified": "2013-10-10 17:01:57",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -306,21 +306,6 @@
|
|||||||
"search_index": 1,
|
"search_index": 1,
|
||||||
"width": "120px"
|
"width": "120px"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"doctype": "DocField",
|
|
||||||
"fieldname": "prevdoc_date",
|
|
||||||
"fieldtype": "Date",
|
|
||||||
"hidden": 1,
|
|
||||||
"in_filter": 1,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Material Request Date",
|
|
||||||
"no_copy": 1,
|
|
||||||
"oldfieldname": "prevdoc_date",
|
|
||||||
"oldfieldtype": "Date",
|
|
||||||
"print_hide": 1,
|
|
||||||
"read_only": 1,
|
|
||||||
"search_index": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "prevdoc_detail_docname",
|
"fieldname": "prevdoc_detail_docname",
|
||||||
|
@ -9,7 +9,6 @@ from webnotes.utils import cint
|
|||||||
from webnotes import msgprint, _
|
from webnotes import msgprint, _
|
||||||
from webnotes.model.doc import make_autoname
|
from webnotes.model.doc import make_autoname
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
from utilities.transaction_base import TransactionBase
|
from utilities.transaction_base import TransactionBase
|
||||||
|
|
||||||
@ -29,7 +28,7 @@ class DocType(TransactionBase):
|
|||||||
self.doc.name = make_autoname(self.doc.naming_series + '.#####')
|
self.doc.name = make_autoname(self.doc.naming_series + '.#####')
|
||||||
|
|
||||||
def update_credit_days_limit(self):
|
def update_credit_days_limit(self):
|
||||||
sql("""update tabAccount set credit_days = %s where name = %s""",
|
webnotes.conn.sql("""update tabAccount set credit_days = %s where name = %s""",
|
||||||
(cint(self.doc.credit_days), self.doc.name + " - " + self.get_company_abbr()))
|
(cint(self.doc.credit_days), self.doc.name + " - " + self.get_company_abbr()))
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
@ -43,7 +42,7 @@ class DocType(TransactionBase):
|
|||||||
self.update_credit_days_limit()
|
self.update_credit_days_limit()
|
||||||
|
|
||||||
def get_payables_group(self):
|
def get_payables_group(self):
|
||||||
g = sql("select payables_group from tabCompany where name=%s", self.doc.company)
|
g = webnotes.conn.sql("select payables_group from tabCompany where name=%s", self.doc.company)
|
||||||
g = g and g[0][0] or ''
|
g = g and g[0][0] or ''
|
||||||
if not g:
|
if not g:
|
||||||
msgprint("Update Company master, assign a default group for Payables")
|
msgprint("Update Company master, assign a default group for Payables")
|
||||||
@ -65,14 +64,14 @@ class DocType(TransactionBase):
|
|||||||
msgprint(_("Created Group ") + ac)
|
msgprint(_("Created Group ") + ac)
|
||||||
|
|
||||||
def get_company_abbr(self):
|
def get_company_abbr(self):
|
||||||
return sql("select abbr from tabCompany where name=%s", self.doc.company)[0][0]
|
return webnotes.conn.sql("select abbr from tabCompany where name=%s", self.doc.company)[0][0]
|
||||||
|
|
||||||
def get_parent_account(self, abbr):
|
def get_parent_account(self, abbr):
|
||||||
if (not self.doc.supplier_type):
|
if (not self.doc.supplier_type):
|
||||||
msgprint("Supplier Type is mandatory")
|
msgprint("Supplier Type is mandatory")
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
if not sql("select name from tabAccount where name=%s and debit_or_credit = 'Credit' and ifnull(is_pl_account, 'No') = 'No'", (self.doc.supplier_type + " - " + abbr)):
|
if not webnotes.conn.sql("select name from tabAccount where name=%s and debit_or_credit = 'Credit' and ifnull(is_pl_account, 'No') = 'No'", (self.doc.supplier_type + " - " + abbr)):
|
||||||
|
|
||||||
# if not group created , create it
|
# if not group created , create it
|
||||||
self.add_account(self.doc.supplier_type, self.get_payables_group(), abbr)
|
self.add_account(self.doc.supplier_type, self.get_payables_group(), abbr)
|
||||||
@ -90,7 +89,7 @@ class DocType(TransactionBase):
|
|||||||
abbr = self.get_company_abbr()
|
abbr = self.get_company_abbr()
|
||||||
parent_account = self.get_parent_account(abbr)
|
parent_account = self.get_parent_account(abbr)
|
||||||
|
|
||||||
if not sql("select name from tabAccount where name=%s", (self.doc.name + " - " + abbr)):
|
if not webnotes.conn.sql("select name from tabAccount where name=%s", (self.doc.name + " - " + abbr)):
|
||||||
ac_bean = webnotes.bean({
|
ac_bean = webnotes.bean({
|
||||||
"doctype": "Account",
|
"doctype": "Account",
|
||||||
'account_name': self.doc.name,
|
'account_name': self.doc.name,
|
||||||
@ -121,15 +120,15 @@ class DocType(TransactionBase):
|
|||||||
|
|
||||||
def get_contacts(self,nm):
|
def get_contacts(self,nm):
|
||||||
if nm:
|
if nm:
|
||||||
contact_details =webnotes.conn.convert_to_lists(sql("select name, CONCAT(IFNULL(first_name,''),' ',IFNULL(last_name,'')),contact_no,email_id from `tabContact` where supplier = '%s'"%nm))
|
contact_details =webnotes.conn.convert_to_lists(webnotes.conn.sql("select name, CONCAT(IFNULL(first_name,''),' ',IFNULL(last_name,'')),contact_no,email_id from `tabContact` where supplier = '%s'"%nm))
|
||||||
|
|
||||||
return contact_details
|
return contact_details
|
||||||
else:
|
else:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def delete_supplier_address(self):
|
def delete_supplier_address(self):
|
||||||
for rec in sql("select * from `tabAddress` where supplier=%s", (self.doc.name,), as_dict=1):
|
for rec in webnotes.conn.sql("select * from `tabAddress` where supplier=%s", (self.doc.name,), as_dict=1):
|
||||||
sql("delete from `tabAddress` where name=%s",(rec['name']))
|
webnotes.conn.sql("delete from `tabAddress` where name=%s",(rec['name']))
|
||||||
|
|
||||||
def delete_supplier_contact(self):
|
def delete_supplier_contact(self):
|
||||||
for contact in webnotes.conn.sql_list("""select name from `tabContact`
|
for contact in webnotes.conn.sql_list("""select name from `tabContact`
|
||||||
@ -138,7 +137,7 @@ class DocType(TransactionBase):
|
|||||||
|
|
||||||
def delete_supplier_account(self):
|
def delete_supplier_account(self):
|
||||||
"""delete supplier's ledger if exist and check balance before deletion"""
|
"""delete supplier's ledger if exist and check balance before deletion"""
|
||||||
acc = sql("select name from `tabAccount` where master_type = 'Supplier' \
|
acc = webnotes.conn.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.doc.name)
|
||||||
if acc:
|
if acc:
|
||||||
from webnotes.model import delete_doc
|
from webnotes.model import delete_doc
|
||||||
@ -161,7 +160,7 @@ class DocType(TransactionBase):
|
|||||||
('Purchase Receipt', 'supplier'),
|
('Purchase Receipt', 'supplier'),
|
||||||
('Serial No', 'supplier')]
|
('Serial No', 'supplier')]
|
||||||
for rec in update_fields:
|
for rec in update_fields:
|
||||||
sql("update `tab%s` set supplier_name = %s where `%s` = %s" % \
|
webnotes.conn.sql("update `tab%s` set supplier_name = %s where `%s` = %s" % \
|
||||||
(rec[0], '%s', rec[1], '%s'), (new, old))
|
(rec[0], '%s', rec[1], '%s'), (new, old))
|
||||||
|
|
||||||
for account in webnotes.conn.sql("""select name, account_name from
|
for account in webnotes.conn.sql("""select name, account_name from
|
||||||
|
@ -9,6 +9,7 @@ cur_frm.cscript.other_fname = "purchase_tax_details";
|
|||||||
// attach required files
|
// attach required files
|
||||||
wn.require('app/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js');
|
wn.require('app/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js');
|
||||||
wn.require('app/buying/doctype/purchase_common/purchase_common.js');
|
wn.require('app/buying/doctype/purchase_common/purchase_common.js');
|
||||||
|
wn.require('app/accounts/doctype/sales_invoice/pos.js');
|
||||||
|
|
||||||
erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.extend({
|
erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.extend({
|
||||||
refresh: function() {
|
refresh: function() {
|
||||||
|
@ -54,7 +54,6 @@ class DocType(BuyingController):
|
|||||||
def validate_common(self):
|
def validate_common(self):
|
||||||
pc = get_obj('Purchase Common')
|
pc = get_obj('Purchase Common')
|
||||||
pc.validate_for_items(self)
|
pc.validate_for_items(self)
|
||||||
pc.get_prevdoc_date(self)
|
|
||||||
|
|
||||||
@webnotes.whitelist()
|
@webnotes.whitelist()
|
||||||
def make_purchase_order(source_name, target_doclist=None):
|
def make_purchase_order(source_name, target_doclist=None):
|
||||||
|
@ -2,12 +2,13 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-05-21 16:16:45",
|
"creation": "2013-05-21 16:16:45",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-08-09 14:45:58",
|
"modified": "2013-10-02 14:24:44",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_attach": 1,
|
"allow_attach": 1,
|
||||||
|
"allow_import": 1,
|
||||||
"autoname": "naming_series:",
|
"autoname": "naming_series:",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Transaction",
|
"document_type": "Transaction",
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-05-22 12:43:10",
|
"creation": "2013-05-22 12:43:10",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-08-07 14:44:18",
|
"modified": "2013-10-10 17:02:11",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -259,21 +259,6 @@
|
|||||||
"search_index": 1,
|
"search_index": 1,
|
||||||
"width": "120px"
|
"width": "120px"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"doctype": "DocField",
|
|
||||||
"fieldname": "prevdoc_date",
|
|
||||||
"fieldtype": "Date",
|
|
||||||
"hidden": 1,
|
|
||||||
"in_filter": 1,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Material Request Date",
|
|
||||||
"no_copy": 1,
|
|
||||||
"oldfieldname": "prevdoc_date",
|
|
||||||
"oldfieldtype": "Date",
|
|
||||||
"print_hide": 1,
|
|
||||||
"read_only": 1,
|
|
||||||
"search_index": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "prevdoc_detail_docname",
|
"fieldname": "prevdoc_detail_docname",
|
||||||
|
@ -145,6 +145,11 @@ wn.module_page["Buying"] = [
|
|||||||
route: "query-report/Purchase Order Trends",
|
route: "query-report/Purchase Order Trends",
|
||||||
doctype: "Purchase Order"
|
doctype: "Purchase Order"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label":wn._("Supplier Addresses And Contacts"),
|
||||||
|
route: "query-report/Supplier Addresses and Contacts",
|
||||||
|
doctype: "Supplier"
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"creation": "2013-10-09 10:38:40",
|
||||||
|
"docstatus": 0,
|
||||||
|
"modified": "2013-10-09 10:53:52",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"owner": "Administrator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Report",
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"name": "__common__",
|
||||||
|
"query": "SELECT\n `tabSupplier`.name as \"Supplier:Link/Supplier:120\",\n\t`tabSupplier`.supplier_name as \"Supplier Name::120\",\n\t`tabSupplier`.supplier_type as \"Supplier Type:Link/Supplier Type:120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2), \n\t\ttabAddress.state, tabAddress.pincode, tabAddress.country\n\t) as 'Address::180',\n concat_ws(', ', `tabContact`.first_name, `tabContact`.last_name) as 'Contact Name::180',\n\t`tabContact`.phone as \"Phone\",\n\t`tabContact`.mobile_no as \"Mobile No\",\n\t`tabContact`.email_id as \"Email Id::120\",\n\t`tabContact`.is_primary_contact as \"Is Primary Contact::120\"\nFROM\n\t`tabSupplier`\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.supplier=`tabSupplier`.name\n\t)\n\tleft join `tabContact` on (\n\t\t`tabContact`.supplier=`tabSupplier`.name\n\t)\nWHERE\n\t`tabSupplier`.docstatus<2\nORDER BY\n\t`tabSupplier`.name asc",
|
||||||
|
"ref_doctype": "Supplier",
|
||||||
|
"report_name": "Supplier Addresses and Contacts",
|
||||||
|
"report_type": "Query Report"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Report",
|
||||||
|
"name": "Supplier Addresses and Contacts"
|
||||||
|
}
|
||||||
|
]
|
@ -65,7 +65,7 @@ def _get_basic_details(args, item_bean):
|
|||||||
|
|
||||||
out = webnotes._dict({
|
out = webnotes._dict({
|
||||||
"description": item.description_html or item.description,
|
"description": item.description_html or item.description,
|
||||||
"qty": 0.0,
|
"qty": 1.0,
|
||||||
"uom": item.stock_uom,
|
"uom": item.stock_uom,
|
||||||
"conversion_factor": 1.0,
|
"conversion_factor": 1.0,
|
||||||
"warehouse": args.warehouse or item.default_warehouse,
|
"warehouse": args.warehouse or item.default_warehouse,
|
||||||
|
@ -52,7 +52,7 @@ class AccountsController(TransactionBase):
|
|||||||
msgprint(_("Account for this ") + fieldname + _(" has been freezed. ") +
|
msgprint(_("Account for this ") + fieldname + _(" has been freezed. ") +
|
||||||
self.doc.doctype + _(" can not be made."), raise_exception=1)
|
self.doc.doctype + _(" can not be made."), raise_exception=1)
|
||||||
|
|
||||||
def set_price_list_currency(self, buying_or_selling):
|
def set_price_list_currency(self, buying_or_selling, for_validate=False):
|
||||||
if self.meta.get_field("currency"):
|
if self.meta.get_field("currency"):
|
||||||
company_currency = get_company_currency(self.doc.company)
|
company_currency = get_company_currency(self.doc.company)
|
||||||
|
|
||||||
@ -60,14 +60,13 @@ class AccountsController(TransactionBase):
|
|||||||
fieldname = "selling_price_list" if buying_or_selling.lower() == "selling" \
|
fieldname = "selling_price_list" if buying_or_selling.lower() == "selling" \
|
||||||
else "buying_price_list"
|
else "buying_price_list"
|
||||||
if self.meta.get_field(fieldname) and self.doc.fields.get(fieldname):
|
if self.meta.get_field(fieldname) and self.doc.fields.get(fieldname):
|
||||||
if not self.doc.price_list_currency:
|
self.doc.price_list_currency = webnotes.conn.get_value("Price List",
|
||||||
self.doc.price_list_currency = webnotes.conn.get_value("Price List",
|
self.doc.fields.get(fieldname), "currency")
|
||||||
self.doc.fields.get(fieldname), "currency")
|
|
||||||
|
|
||||||
if self.doc.price_list_currency == company_currency:
|
if self.doc.price_list_currency == company_currency:
|
||||||
self.doc.plc_conversion_rate = 1.0
|
self.doc.plc_conversion_rate = 1.0
|
||||||
|
|
||||||
elif not self.doc.plc_conversion_rate:
|
elif not self.doc.plc_conversion_rate or not for_validate:
|
||||||
self.doc.plc_conversion_rate = self.get_exchange_rate(
|
self.doc.plc_conversion_rate = self.get_exchange_rate(
|
||||||
self.doc.price_list_currency, company_currency)
|
self.doc.price_list_currency, company_currency)
|
||||||
|
|
||||||
@ -77,7 +76,7 @@ class AccountsController(TransactionBase):
|
|||||||
self.doc.conversion_rate = self.doc.plc_conversion_rate
|
self.doc.conversion_rate = self.doc.plc_conversion_rate
|
||||||
elif self.doc.currency == company_currency:
|
elif self.doc.currency == company_currency:
|
||||||
self.doc.conversion_rate = 1.0
|
self.doc.conversion_rate = 1.0
|
||||||
elif not self.doc.conversion_rate:
|
elif not self.doc.conversion_rate or not for_validate:
|
||||||
self.doc.conversion_rate = self.get_exchange_rate(self.doc.currency,
|
self.doc.conversion_rate = self.get_exchange_rate(self.doc.currency,
|
||||||
company_currency)
|
company_currency)
|
||||||
|
|
||||||
@ -423,3 +422,7 @@ class AccountsController(TransactionBase):
|
|||||||
self._abbr = webnotes.conn.get_value("Company", self.doc.company, "abbr")
|
self._abbr = webnotes.conn.get_value("Company", self.doc.company, "abbr")
|
||||||
|
|
||||||
return self._abbr
|
return self._abbr
|
||||||
|
|
||||||
|
@webnotes.whitelist()
|
||||||
|
def get_tax_rate(account_head):
|
||||||
|
return webnotes.conn.get_value("Account", account_head, "tax_rate")
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import webnotes
|
import webnotes, json
|
||||||
from webnotes import _, msgprint
|
from webnotes import _, msgprint
|
||||||
from webnotes.utils import flt, _round
|
from webnotes.utils import flt, _round
|
||||||
|
|
||||||
@ -11,9 +11,8 @@ from setup.utils import get_company_currency
|
|||||||
|
|
||||||
from controllers.stock_controller import StockController
|
from controllers.stock_controller import StockController
|
||||||
|
|
||||||
class WrongWarehouseCompany(Exception): pass
|
|
||||||
|
|
||||||
class BuyingController(StockController):
|
class BuyingController(StockController):
|
||||||
|
|
||||||
def onload_post_render(self):
|
def onload_post_render(self):
|
||||||
# contact, address, item details
|
# contact, address, item details
|
||||||
self.set_missing_values()
|
self.set_missing_values()
|
||||||
@ -24,13 +23,13 @@ class BuyingController(StockController):
|
|||||||
self.doc.supplier_name = webnotes.conn.get_value("Supplier",
|
self.doc.supplier_name = webnotes.conn.get_value("Supplier",
|
||||||
self.doc.supplier, "supplier_name")
|
self.doc.supplier, "supplier_name")
|
||||||
self.validate_stock_or_nonstock_items()
|
self.validate_stock_or_nonstock_items()
|
||||||
self.validate_warehouse_belongs_to_company()
|
self.validate_warehouse()
|
||||||
|
|
||||||
def set_missing_values(self, for_validate=False):
|
def set_missing_values(self, for_validate=False):
|
||||||
super(BuyingController, self).set_missing_values(for_validate)
|
super(BuyingController, self).set_missing_values(for_validate)
|
||||||
|
|
||||||
self.set_supplier_from_item_default()
|
self.set_supplier_from_item_default()
|
||||||
self.set_price_list_currency("Buying")
|
self.set_price_list_currency("Buying", for_validate)
|
||||||
|
|
||||||
# set contact and address details for supplier, if they are not mentioned
|
# set contact and address details for supplier, if they are not mentioned
|
||||||
if self.doc.supplier and not (self.doc.contact_person and self.doc.supplier_address):
|
if self.doc.supplier and not (self.doc.contact_person and self.doc.supplier_address):
|
||||||
@ -49,17 +48,20 @@ class BuyingController(StockController):
|
|||||||
if supplier:
|
if supplier:
|
||||||
self.doc.supplier = supplier
|
self.doc.supplier = supplier
|
||||||
break
|
break
|
||||||
|
|
||||||
|
def validate_warehouse(self):
|
||||||
|
from stock.utils import validate_warehouse_user, validate_warehouse_company
|
||||||
|
|
||||||
|
warehouses = list(set([d.warehouse for d in
|
||||||
|
self.doclist.get({"doctype": self.tname}) if d.warehouse]))
|
||||||
|
|
||||||
|
for w in warehouses:
|
||||||
|
validate_warehouse_user(w)
|
||||||
|
validate_warehouse_company(w, self.doc.company)
|
||||||
|
|
||||||
def get_purchase_tax_details(self):
|
def get_purchase_tax_details(self):
|
||||||
self.doclist = self.doc.clear_table(self.doclist, "purchase_tax_details")
|
self.doclist = self.doc.clear_table(self.doclist, "purchase_tax_details")
|
||||||
self.set_taxes("purchase_tax_details", "purchase_other_charges")
|
self.set_taxes("purchase_tax_details", "purchase_other_charges")
|
||||||
|
|
||||||
def validate_warehouse_belongs_to_company(self):
|
|
||||||
for warehouse, company in webnotes.conn.get_values("Warehouse",
|
|
||||||
self.doclist.get_distinct_values("warehouse"), "company").items():
|
|
||||||
if company and company != self.doc.company:
|
|
||||||
webnotes.msgprint(_("Company mismatch for Warehouse") + (": %s" % (warehouse,)),
|
|
||||||
raise_exception=WrongWarehouseCompany)
|
|
||||||
|
|
||||||
def validate_stock_or_nonstock_items(self):
|
def validate_stock_or_nonstock_items(self):
|
||||||
if not self.get_stock_items():
|
if not self.get_stock_items():
|
||||||
|
@ -14,13 +14,16 @@ class SellingController(StockController):
|
|||||||
def onload_post_render(self):
|
def onload_post_render(self):
|
||||||
# contact, address, item details and pos details (if applicable)
|
# contact, address, item details and pos details (if applicable)
|
||||||
self.set_missing_values()
|
self.set_missing_values()
|
||||||
|
|
||||||
|
def get_sender(self, comm):
|
||||||
|
return webnotes.conn.get_value('Sales Email Settings', None, 'email_id')
|
||||||
|
|
||||||
def set_missing_values(self, for_validate=False):
|
def set_missing_values(self, for_validate=False):
|
||||||
super(SellingController, self).set_missing_values(for_validate)
|
super(SellingController, self).set_missing_values(for_validate)
|
||||||
|
|
||||||
# set contact and address details for customer, if they are not mentioned
|
# set contact and address details for customer, if they are not mentioned
|
||||||
self.set_missing_lead_customer_details()
|
self.set_missing_lead_customer_details()
|
||||||
self.set_price_list_and_item_details()
|
self.set_price_list_and_item_details(for_validate)
|
||||||
if self.doc.fields.get("__islocal"):
|
if self.doc.fields.get("__islocal"):
|
||||||
self.set_taxes("other_charges", "charge")
|
self.set_taxes("other_charges", "charge")
|
||||||
|
|
||||||
@ -38,8 +41,8 @@ class SellingController(StockController):
|
|||||||
if not self.doc.fields.get(fieldname) and self.meta.get_field(fieldname):
|
if not self.doc.fields.get(fieldname) and self.meta.get_field(fieldname):
|
||||||
self.doc.fields[fieldname] = val
|
self.doc.fields[fieldname] = val
|
||||||
|
|
||||||
def set_price_list_and_item_details(self):
|
def set_price_list_and_item_details(self, for_validate=False):
|
||||||
self.set_price_list_currency("Selling")
|
self.set_price_list_currency("Selling", for_validate)
|
||||||
self.set_missing_item_details(get_item_details)
|
self.set_missing_item_details(get_item_details)
|
||||||
|
|
||||||
def get_other_charges(self):
|
def get_other_charges(self):
|
||||||
@ -233,34 +236,4 @@ class SellingController(StockController):
|
|||||||
self.doc.order_type = "Sales"
|
self.doc.order_type = "Sales"
|
||||||
elif self.doc.order_type not in valid_types:
|
elif self.doc.order_type not in valid_types:
|
||||||
msgprint(_(self.meta.get_label("order_type")) + " " +
|
msgprint(_(self.meta.get_label("order_type")) + " " +
|
||||||
_("must be one of") + ": " + comma_or(valid_types),
|
_("must be one of") + ": " + comma_or(valid_types), raise_exception=True)
|
||||||
raise_exception=True)
|
|
||||||
|
|
||||||
def update_serial_nos(self, cancel=False):
|
|
||||||
from stock.doctype.stock_ledger_entry.stock_ledger_entry import update_serial_nos_after_submit, get_serial_nos
|
|
||||||
update_serial_nos_after_submit(self, self.doc.doctype, self.fname)
|
|
||||||
update_serial_nos_after_submit(self, self.doc.doctype, "packing_details")
|
|
||||||
|
|
||||||
for table_fieldname in (self.fname, "packing_details"):
|
|
||||||
for d in self.doclist.get({"parentfield": table_fieldname}):
|
|
||||||
for serial_no in get_serial_nos(d.serial_no):
|
|
||||||
sr = webnotes.bean("Serial No", serial_no)
|
|
||||||
if cancel:
|
|
||||||
sr.doc.status = "Available"
|
|
||||||
for fieldname in ("warranty_expiry_date", "delivery_document_type",
|
|
||||||
"delivery_document_no", "delivery_date", "delivery_time", "customer",
|
|
||||||
"customer_name"):
|
|
||||||
sr.doc.fields[fieldname] = None
|
|
||||||
else:
|
|
||||||
sr.doc.delivery_document_type = self.doc.doctype
|
|
||||||
sr.doc.delivery_document_no = self.doc.name
|
|
||||||
sr.doc.delivery_date = self.doc.posting_date
|
|
||||||
sr.doc.delivery_time = self.doc.posting_time
|
|
||||||
sr.doc.customer = self.doc.customer
|
|
||||||
sr.doc.customer_name = self.doc.customer_name
|
|
||||||
if sr.doc.warranty_period:
|
|
||||||
sr.doc.warranty_expiry_date = add_days(cstr(self.doc.posting_date),
|
|
||||||
cint(sr.doc.warranty_period))
|
|
||||||
sr.doc.status = 'Delivered'
|
|
||||||
|
|
||||||
sr.save()
|
|
||||||
|
@ -8,6 +8,51 @@ from webnotes import msgprint
|
|||||||
|
|
||||||
from webnotes.model.controller import DocListController
|
from webnotes.model.controller import DocListController
|
||||||
|
|
||||||
|
status_map = {
|
||||||
|
"Contact": [
|
||||||
|
["Replied", "communication_sent"],
|
||||||
|
["Open", "communication_received"]
|
||||||
|
],
|
||||||
|
"Job Applicant": [
|
||||||
|
["Replied", "communication_sent"],
|
||||||
|
["Open", "communication_received"]
|
||||||
|
],
|
||||||
|
"Lead": [
|
||||||
|
["Replied", "communication_sent"],
|
||||||
|
["Converted", "has_customer"],
|
||||||
|
["Opportunity", "has_opportunity"],
|
||||||
|
["Open", "communication_received"],
|
||||||
|
],
|
||||||
|
"Opportunity": [
|
||||||
|
["Draft", None],
|
||||||
|
["Submitted", "eval:self.doc.docstatus==1"],
|
||||||
|
["Lost", "eval:self.doc.status=='Lost'"],
|
||||||
|
["Quotation", "has_quotation"],
|
||||||
|
["Replied", "communication_sent"],
|
||||||
|
["Cancelled", "eval:self.doc.docstatus==2"],
|
||||||
|
["Open", "communication_received"],
|
||||||
|
],
|
||||||
|
"Quotation": [
|
||||||
|
["Draft", None],
|
||||||
|
["Submitted", "eval:self.doc.docstatus==1"],
|
||||||
|
["Lost", "eval:self.doc.status=='Lost'"],
|
||||||
|
["Ordered", "has_sales_order"],
|
||||||
|
["Replied", "communication_sent"],
|
||||||
|
["Cancelled", "eval:self.doc.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"],
|
||||||
|
],
|
||||||
|
"Support Ticket": [
|
||||||
|
["Replied", "communication_sent"],
|
||||||
|
["Open", "communication_received"]
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
class StatusUpdater(DocListController):
|
class StatusUpdater(DocListController):
|
||||||
"""
|
"""
|
||||||
Updates the status of the calling records
|
Updates the status of the calling records
|
||||||
@ -20,6 +65,45 @@ class StatusUpdater(DocListController):
|
|||||||
self.update_qty()
|
self.update_qty()
|
||||||
self.validate_qty()
|
self.validate_qty()
|
||||||
|
|
||||||
|
def set_status(self, update=False):
|
||||||
|
if self.doc.get("__islocal"):
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.doc.doctype in status_map:
|
||||||
|
sl = status_map[self.doc.doctype][:]
|
||||||
|
sl.reverse()
|
||||||
|
for s in sl:
|
||||||
|
if not s[1]:
|
||||||
|
self.doc.status = s[0]
|
||||||
|
break
|
||||||
|
elif s[1].startswith("eval:"):
|
||||||
|
if eval(s[1][5:]):
|
||||||
|
self.doc.status = s[0]
|
||||||
|
break
|
||||||
|
elif getattr(self, s[1])():
|
||||||
|
self.doc.status = s[0]
|
||||||
|
break
|
||||||
|
|
||||||
|
if update:
|
||||||
|
webnotes.conn.set_value(self.doc.doctype, self.doc.name, "status", self.doc.status)
|
||||||
|
|
||||||
|
def on_communication(self):
|
||||||
|
self.communication_set = True
|
||||||
|
self.set_status(update=True)
|
||||||
|
del self.communication_set
|
||||||
|
|
||||||
|
def communication_received(self):
|
||||||
|
if getattr(self, "communication_set", False):
|
||||||
|
last_comm = self.doclist.get({"doctype":"Communication"})
|
||||||
|
if last_comm:
|
||||||
|
return last_comm[-1].sent_or_received == "Received"
|
||||||
|
|
||||||
|
def communication_sent(self):
|
||||||
|
if getattr(self, "communication_set", False):
|
||||||
|
last_comm = self.doclist.get({"doctype":"Communication"})
|
||||||
|
if last_comm:
|
||||||
|
return last_comm[-1].sent_or_received == "Sent"
|
||||||
|
|
||||||
def validate_qty(self):
|
def validate_qty(self):
|
||||||
"""
|
"""
|
||||||
Validates qty at row level
|
Validates qty at row level
|
||||||
|
@ -13,33 +13,34 @@ You can make a Sales Invoice of type POS by checking on “Is POS”. When you c
|
|||||||
|
|
||||||
- Update Stock: If this is checked, Stock Ledger Entries will be made when you “Submit” this Sales Invoice thereby eliminating the need for a separate Delivery Note.
|
- Update Stock: If this is checked, Stock Ledger Entries will be made when you “Submit” this Sales Invoice thereby eliminating the need for a separate Delivery Note.
|
||||||
- In your Items table, update inventory information like Warehouse (saved as default), Serial Number, or Batch Number if applicable.
|
- In your Items table, update inventory information like Warehouse (saved as default), Serial Number, or Batch Number if applicable.
|
||||||
- Update Payment Details like your Bank / Cash Account, paid amount etc.
|
- Update Payment Details like your Bank / Cash Account, Paid amount etc.
|
||||||
- If you are writing off certain amount. For example when you receive extra cash as a result of not having exact denomination of change, check on ‘Write off Outstanding Amount’ and set the Account.
|
- If you are writing off certain amount. For example when you receive extra cash as a result of not having exact denomination of change, check on ‘Write off Outstanding Amount’ and set the Account.
|
||||||
|
|
||||||
Setup [POS Setting](docs.user.setup.pos_setting.html)
|
|
||||||
|
|
||||||
#### Enable POS View
|
#### Enable POS View
|
||||||
|
|
||||||
Sales Invoice has 2 different interfaces, Invoice View and POS View. The current view used by most users is the Invoice View. This view is preferred by non-retailing companies.The POS view is used by retailing companies. For retailers it is very important to provide bill or sales invoice at the point of sale. Their customers cannot wait to receive the bill by post. The customers want an immediate bill for the payment which they make. In such cases, the POS View is preferred.
|
- Every Sales & Purchase documents has 2 different interfaces, Invoice View and POS View. The current view used by most users is the Invoice View. This view is preferred by non-retailing companies.The POS view is used by retailing companies. For retailers it is very important to provide bill or sales invoice at the point of sale. Their customers cannot wait to receive the bill by post. The customers want an immediate bill for the payment which they make. In such cases, the POS View is preferred.
|
||||||
|
|
||||||
> Setup > Show/Hide Features
|
> Setup > Show/Hide Features
|
||||||
|
|
||||||
![POS View](img/pos-features-setup.png)
|
![POS View](img/pos-features-setup.png)
|
||||||
|
|
||||||
|
- Setup [POS Setting](docs.user.setup.pos_setting.html)
|
||||||
|
|
||||||
### Adding an Item
|
### Adding an Item
|
||||||
|
|
||||||
At the billing counter, the retailer needs to select Items which the consumer buys. In the POS interface you can select an Item by two methods. One, is by clicking on the Item image and the other, is through the Barcode.
|
At the billing counter, the retailer needs to select Items which the consumer buys. In the POS interface you can select an Item by two methods. One, is by clicking on the Item image and the other, is through the Barcode / Serial No.
|
||||||
|
|
||||||
**Select Item** - To select a product click on the Item image and add it into the cart. A cart is an area that prepares a customer for checkout by allowing to edit product information, adjust taxes and add discounts.
|
**Select Item** - To select a product click on the Item image and add it into the cart. A cart is an area that prepares a customer for checkout by allowing to edit product information, adjust taxes and add discounts.
|
||||||
|
|
||||||
**Barcode** - A Barcode is an optical machine-readable representation of data relating to the object to which it is attached. Enter Barcode in the barcode box and pause for a second. The Item will be automatically added to the cart.
|
**Barcode / Serial No** - A Barcode / Serial No is an optical machine-readable representation of data relating to the object to which it is attached. Enter Barcode / Serial No in the box as shown in the image below and pause for a second, the item will be automatically added to the cart.
|
||||||
|
|
||||||
![POS](img/pos-add-item.png)
|
![POS](img/pos-add-item.png)
|
||||||
|
|
||||||
> Tip: To change the quantity of an Item, enter your desired quantity in the quantity box. These are mostly used if the same Item is purchased in bulk.
|
> Tip: To change the quantity of an Item, enter your desired quantity in the quantity box. These are mostly used if the same Item is purchased in bulk.
|
||||||
|
|
||||||
|
|
||||||
If your product list is very long use the universal search field, to type the product name and select faster.
|
If your product list is very long use the Search field, type the product name in Search box.
|
||||||
|
|
||||||
### Removing an Item
|
### Removing an Item
|
||||||
|
|
||||||
@ -48,7 +49,7 @@ There are two ways to remove an Item.
|
|||||||
- Select an Item by clicking on the row of that Item from Item cart. Then click on “Del” button. OR
|
- Select an Item by clicking on the row of that Item from Item cart. Then click on “Del” button. OR
|
||||||
|
|
||||||
|
|
||||||
- Type 0 in the ‘select quantity’ field to delete the record.
|
- Enter 0(zero) quantity of any item to delete that item.
|
||||||
|
|
||||||
To remove multiple Items together, select multiple rows & click on “Del” button.
|
To remove multiple Items together, select multiple rows & click on “Del” button.
|
||||||
|
|
||||||
@ -62,11 +63,11 @@ After all the Items and their quantities are added into the cart, you are ready
|
|||||||
|
|
||||||
1. Click on “Make Payment” to get the Payment window.
|
1. Click on “Make Payment” to get the Payment window.
|
||||||
1. Select your “Mode of Payment”.
|
1. Select your “Mode of Payment”.
|
||||||
1. Click on “Pay” button to Save the Sales Invoice.
|
1. Click on “Pay” button to Save the document.
|
||||||
|
|
||||||
![POS Payment](img/pos-make-payment.png)
|
![POS Payment](img/pos-make-payment.png)
|
||||||
|
|
||||||
Submit the document to finalise the record. After the Invoice is submitted, you can either print an invoice or email it directly to the customer.
|
Submit the document to finalise the record. After the document is submitted, you can either print or email it directly to the customer.
|
||||||
|
|
||||||
#### Accounting entries (GL Entry) for a Point of Sale:
|
#### Accounting entries (GL Entry) for a Point of Sale:
|
||||||
|
|
||||||
|
@ -20,7 +20,15 @@ You can create a new Supplier via:
|
|||||||
|
|
||||||
> Tip: When you select a Supplier in any transaction, one Contact and Address gets pre-selected. This is the “Default Contact or Address”. So make sure you set your defaults correctly!
|
> Tip: When you select a Supplier in any transaction, one Contact and Address gets pre-selected. This is the “Default Contact or Address”. So make sure you set your defaults correctly!
|
||||||
|
|
||||||
|
### Integration with Accounts
|
||||||
|
|
||||||
|
In ERPNext, there is a separate Account record for each Supplier, of Each company.
|
||||||
|
|
||||||
|
When you create a new Supplier, ERPNext will automatically create an Account Ledger for the Supplier under “Accounts Receivable” in the Company set in the Supplier record.
|
||||||
|
|
||||||
|
> Advanced Tip: If you want to change the Account Group under which the Supplier Account is created, you can set it in the Company master.
|
||||||
|
|
||||||
|
If you want to create an Account in another Company, just change the Company value and “Save” the Supplier again.
|
||||||
|
|
||||||
|
|
||||||
> Buying > Contact > New Contact
|
> Buying > Contact > New Contact
|
||||||
|
@ -3,9 +3,11 @@
|
|||||||
"_label": "Supplier Type"
|
"_label": "Supplier Type"
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
|
A supplier may be distinguished from a contractor or subcontractor, who commonly adds specialized input to deliverables. A supplier is also known as a vendor. There are different types of suppliers based on their goods and products.
|
||||||
|
|
||||||
Based on what the suppliers supply, they are classified into different categories called Supplier Type.
|
ERPNext allows you to create your own categories of suppliers. These categories are known as Supplier Type. For Example, if your suppliers are mainly pharmaceutical companies and FMCG distributors, You can create a new Type for them and name them accordingly.
|
||||||
There can be different types of suppliers. You can create your own category of Supplier Type.
|
|
||||||
|
Based on what the suppliers supply, they are classified into different categories called Supplier Type. There can be different types of suppliers. You can create your own category of Supplier Type.
|
||||||
|
|
||||||
> Buying > Supplier Type > New Supplier Type
|
> Buying > Supplier Type > New Supplier Type
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
"_label": "User Guide",
|
"_label": "User Guide",
|
||||||
"_toc": [
|
"_toc": [
|
||||||
"docs.user.intro",
|
"docs.user.intro",
|
||||||
|
"docs.user.five_day_setup",
|
||||||
"docs.user.implement",
|
"docs.user.implement",
|
||||||
"docs.user.setup",
|
"docs.user.setup",
|
||||||
"docs.user.selling",
|
"docs.user.selling",
|
||||||
@ -17,7 +18,7 @@
|
|||||||
"docs.user.tools",
|
"docs.user.tools",
|
||||||
"docs.user.customize",
|
"docs.user.customize",
|
||||||
"docs.user.knowledge"
|
"docs.user.knowledge"
|
||||||
],
|
],
|
||||||
"_no_toc": 1
|
"_no_toc": 1
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
@ -29,6 +30,12 @@ Contents
|
|||||||
1. [Open Source](docs.user.intro.open_source.html)
|
1. [Open Source](docs.user.intro.open_source.html)
|
||||||
1. [Ways to get started](docs.user.intro.try.html)
|
1. [Ways to get started](docs.user.intro.try.html)
|
||||||
1. [Getting Help](docs.user.help.html)
|
1. [Getting Help](docs.user.help.html)
|
||||||
|
1. [Five-Day-Setup](docs.user.five_day_setup.html)
|
||||||
|
1. [Day-1: Setup Customer,Item, and Supplier](docs.user.five_day_setup.day_1.html)
|
||||||
|
1. [Day-2: Setup Chart of Accounts, Opening Accounts, and HR](docs.user.five_day_setup.day_2.html)
|
||||||
|
1. [Day-3: Sales Cycle and Purchase Cycle](docs.user.five_day_setup.day_3.html)
|
||||||
|
1. [Day-4: Manufacturing Cycle and Accounting Reports](docs.user.five_day_setup.day_4.html)
|
||||||
|
1. [Day-5: Projects, Calendar, and Website](docs.user.five_day_setup.day_5.html)
|
||||||
1. [Implementation](docs.user.implement.html)
|
1. [Implementation](docs.user.implement.html)
|
||||||
1. [Implementation Strategy](docs.user.implement.strategy.html)
|
1. [Implementation Strategy](docs.user.implement.strategy.html)
|
||||||
1. [Concepts](docs.user.implement.concepts.html)
|
1. [Concepts](docs.user.implement.concepts.html)
|
||||||
@ -151,3 +158,6 @@ Contents
|
|||||||
1. [Fiscal Year](docs.user.knowledge.fiscal_year.html)
|
1. [Fiscal Year](docs.user.knowledge.fiscal_year.html)
|
||||||
1. [Accounting Knowledge](docs.user.knowledge.accounting.html)
|
1. [Accounting Knowledge](docs.user.knowledge.accounting.html)
|
||||||
1. [Accounting Entries](docs.user.knowledge.accounting_entries.html)
|
1. [Accounting Entries](docs.user.knowledge.accounting_entries.html)
|
||||||
|
1. [DocType Definitions](docs.user.knowledge.doctype.html)
|
||||||
|
1. [Attachment and CSV Files](docs.user.knowledge.attachment_csv.html)
|
||||||
|
1. [Format using Markdown](docs.user.knowledge.markdown.html)
|
||||||
|
81
docs/user/five_day_setup/docs.user.five_day_setup.day_1.md
Normal file
81
docs/user/five_day_setup/docs.user.five_day_setup.day_1.md
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Day-1: Setup Customer, Item, and Supplier"
|
||||||
|
}
|
||||||
|
---
|
||||||
|
Login to your ERPNext account with the User ID and Password sent through the mail.
|
||||||
|
|
||||||
|
After logging into your account you will receive a pop-up form to fill. Please fill this form. Select the abbreviation you would wish to have for your company. The abbreviation selected here will be used in naming most of the business documents.
|
||||||
|
|
||||||
|
#### Form Part I
|
||||||
|
|
||||||
|
![1st Form](img/firstdaysetup-1.png)
|
||||||
|
<br><br>
|
||||||
|
#### Form Part II
|
||||||
|
To understand about Company Financial Year or Fiscal Year visit [Fiscal Year](docs.user.knowledge.fiscal_year.html)
|
||||||
|
|
||||||
|
|
||||||
|
![1st Form](img/firstdaysetup-2.png)
|
||||||
|
|
||||||
|
After filling this form, you will get a pop-up message for completing the set-up process. Click on the Setup button. The Setup page will appear.
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Setup Page - Customer
|
||||||
|
|
||||||
|
The Organisation details are updated in ERPNext, after filling the first form. Go directly to the Customer Icon.
|
||||||
|
|
||||||
|
![Customer](img/firstdaysetup-customer.png)
|
||||||
|
<br>
|
||||||
|
|
||||||
|
|
||||||
|
After clicking on Customer, a new form will appear.
|
||||||
|
<br>
|
||||||
|
|
||||||
|
![Customer](img/firstdaysetup-customer-1.png)
|
||||||
|
|
||||||
|
To see how customer details are added, visit [Customer](docs.user.selling.customer.html). Create 5 new customer records in the system.
|
||||||
|
|
||||||
|
Now proceed to make an Item. To go to the main menu, click on erpnext icon which is on the left hand corner of the page. On the main menu page, click on Setup
|
||||||
|
|
||||||
|
![Main Menu](img/firstdaysetup-main-menu.png)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
#### Setup Page - Item
|
||||||
|
|
||||||
|
On the setup page go to Item.
|
||||||
|
|
||||||
|
|
||||||
|
![Item](img/firstdaysetup-item.png)
|
||||||
|
|
||||||
|
|
||||||
|
Create a new Item. An Item is your company's product or a service.The term Item is applicable to your core products as well as your raw materials. It can be a product or service that you buy/sell from your customers/ suppliers.
|
||||||
|
|
||||||
|
Filling Item details is an important step in ERPNext. Do not postpone this step. After clicking on Item, make a new Item.
|
||||||
|
|
||||||
|
![Item](img/firstdaysetup-item-1.png)
|
||||||
|
|
||||||
|
To understand how to fill an Item in detail, visit [Item](docs.user.stock.item.html). Add 5 item records to ERPnext. After adding these records, go back to the Setup Page and add Suppliers.
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Setup Page - Suppliers
|
||||||
|
On the Setup page go to Supplier.
|
||||||
|
|
||||||
|
![Supplier](img/firstdaysetup-supplier.png)
|
||||||
|
<br>
|
||||||
|
|
||||||
|
Suppliers are companies or individuals who provide you with products or services. They are treated in exactly the same manner as Customers in ERPNext. Create a new Supplier record.
|
||||||
|
|
||||||
|
![Supplier](img/firstdaysetup-supplier-1.png)
|
||||||
|
|
||||||
|
|
||||||
|
To understand how to fill Supplier details, visit [Supplier](docs.user.buying.supplier.html).
|
||||||
|
|
||||||
|
If you wish to import your list of customers and suppliers directly to ERPNext, you can do that via the Data Import Tool.
|
||||||
|
|
||||||
|
To upload Customers or suppliers in bulk, go to the Data Import Tool.
|
||||||
|
|
||||||
|
> Note: The data import format is case-sensitive. The file will not be processed if there are any spelling mistakes or deviations from the default values.
|
||||||
|
|
||||||
|
To understand how to import data, visit [Importing Data](docs.user.setup.data_import.html).
|
||||||
|
|
54
docs/user/five_day_setup/docs.user.five_day_setup.day_2.md
Normal file
54
docs/user/five_day_setup/docs.user.five_day_setup.day_2.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Day-2: Setup Chart of Accounts, Opening Accounts, and HR"
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Setup Page - Accounts
|
||||||
|
<br>
|
||||||
|
Go to the Accounts icon and make ledgers under Chart of Accounts.
|
||||||
|
|
||||||
|
![Accounts](img/seconddaysetup-accounts.png)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
|
||||||
|
Create acccounting ledgers.
|
||||||
|
|
||||||
|
![Tree](img/seconddaysetup-tree.png)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
To begin Opening Entries, go to 'Opening Accounts and Stock' on the Setup Page.
|
||||||
|
|
||||||
|
![Ledger](img/seconddaysetup-accounts-jv.png)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
|
||||||
|
To understand how to create opening entries in detail visit [Opening Entry](docs.user.setup.opening.html).
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
#### Opening Stock
|
||||||
|
|
||||||
|
You can upload your opening stock in the system using Stock Reconciliation. Stock Reconciliation will update your stock for any given Item.
|
||||||
|
|
||||||
|
![Stock Opening](img/seconddaysetup-stock-opening.png)
|
||||||
|
<br>
|
||||||
|
|
||||||
|
|
||||||
|
To understand Stock Opening in detail visit [Opening Stock](docs.user.accounts.opening_stock.html).
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
#### Setup Page - HR Setup
|
||||||
|
|
||||||
|
To setup HR, begin by creating individual employee records.
|
||||||
|
|
||||||
|
|
||||||
|
![Employee](img/seconddaysetup-hr.png)
|
||||||
|
|
||||||
|
To fill the Employee Form, refer to [Employee](docs.user.hr.employee.html)
|
||||||
|
|
||||||
|
To complete the remaining HR-Setup, see [Human Resources](docs.user.hr.html)
|
139
docs/user/five_day_setup/docs.user.five_day_setup.day_3.md
Normal file
139
docs/user/five_day_setup/docs.user.five_day_setup.day_3.md
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Day-3: Sales Cycle and Purchase Cycle"
|
||||||
|
}
|
||||||
|
---
|
||||||
|
After completing the set-up and account opening process, it is advisable to complete a few cycles of sales, purchase, and manufacturing process.
|
||||||
|
|
||||||
|
|
||||||
|
### Sales Cycle
|
||||||
|
|
||||||
|
Complete a standard Sales Cycle.
|
||||||
|
> Lead > Opportunity > Quotation > Sales Order > Delivery Note > Sales Invoice > Payment (Journal Voucher)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Lead
|
||||||
|
|
||||||
|
To begin the sales cycle, go to the Selling Icon. On the selling page, click on Lead.
|
||||||
|
|
||||||
|
![Lead](img/thirddaysetup-lead.png)
|
||||||
|
|
||||||
|
Fill the Lead form.
|
||||||
|
|
||||||
|
> To understand Lead in detail, visit [Lead](docs.user.selling.lead.html)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Opportunity
|
||||||
|
|
||||||
|
After completing the Lead form, assume that, this same lead is getting converted into an Opportunity. Thus, to create an Opportunity from the existing lead, click on Create Opportunity, on the Lead page.
|
||||||
|
|
||||||
|
##### Step 1: Go to 'Lead List' Page and open the Lead that shows interested status.
|
||||||
|
|
||||||
|
![Opportunity](img/thirddaysetup-opportunity-1.png)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
##### Step 2: Generate Opportunity from the selected Lead
|
||||||
|
|
||||||
|
![Opportunity](img/thirddaysetup-opportunity.png)
|
||||||
|
|
||||||
|
You can also generate an Opportunity directly from the Selling Page.
|
||||||
|
|
||||||
|
> To understand Opportunity in detail visit [Opportunity](docs.user.selling.opportunity.html).
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Quotation
|
||||||
|
|
||||||
|
Imagine that your Opportunity has shown interest and asked for a Quotation. To generate a Quotation from the same Opportunity, open the submitted Opportunity and click on Create Quotation.
|
||||||
|
|
||||||
|
![Quotation](img/thirddaysetup-quotation.png)
|
||||||
|
|
||||||
|
You can also generate a Quotation directly from the Selling Page.
|
||||||
|
|
||||||
|
> To understand Quotation in detail visit [Quotation](docs.user.selling.quotation.html)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Sales Order
|
||||||
|
|
||||||
|
Imagine that the Quotation which you sent was accepted by the prospect. You are now reequired to send him a Sales Order. To make a sales order from this same Quotation, go to that Quotation page and click on Make Sales Order.
|
||||||
|
|
||||||
|
![Sales Order](img/thirddaysetup-sales-order.png)
|
||||||
|
|
||||||
|
You can also generate a Sales Order directly from the Selling Page.
|
||||||
|
|
||||||
|
> To understand Sales Order in detail visit [Sales Order](docs.user.selling.sales_order.html).
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Delivery Note
|
||||||
|
|
||||||
|
If your organisation has the practice of sending Delivery Note, this section will be helpful. To create a Delivery Note from the a Sales Order, go to that Sales Order and click on Make Delivery.
|
||||||
|
|
||||||
|
|
||||||
|
![Delivery Note](img/thirddaysetup-delivery-note.png)
|
||||||
|
|
||||||
|
> To understand Delivery Note in detail, visit [Delivery Note](docs.user.stock.delivery_note.html)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Sales Invoice
|
||||||
|
|
||||||
|
Save and Submit your Delivery Note to generate a Sales Invoice. You can also generate an Invoice from Sales Order.
|
||||||
|
|
||||||
|
![Sales Invoice](img/thirddaysetup-sales-invoice.png)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
#### Payment (Journal Voucher)
|
||||||
|
|
||||||
|
|
||||||
|
A Journal Voucher or a payment entry can be generated directly from the Sales Invoice.
|
||||||
|
|
||||||
|
![Payment Entry](img/thirddaysetup-payment-entry.png)
|
||||||
|
|
||||||
|
> To understand a Journal Voucher in detail, visit [Journal Voucher](docs.user.accounts.journal_voucher.html)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
### Purchase Cycle
|
||||||
|
|
||||||
|
Complete a standard Purchase Cycle.
|
||||||
|
> Material Request > Purchase Order > Purchase Receipt > Payment (Journal Voucher).
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Material Request
|
||||||
|
|
||||||
|
To create a Material Request, go to Stock/Buying and Click on Material Request.
|
||||||
|
|
||||||
|
![Material Request](img/thirddaysetup-material-request.png)
|
||||||
|
|
||||||
|
> To understand Material Request in detail, visit [Material Request](docs.user.buying.material_request.html)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Purchase Order
|
||||||
|
|
||||||
|
To create a Purchase Order go to Buying and click on Purchase Order
|
||||||
|
|
||||||
|
![Purchase Order](img/thirddaysetup-purchase-order.png)
|
||||||
|
|
||||||
|
> To understand Purchase Order in detail, visit [Purchase Order](docs.user.buying.purchase_order.html)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Purchase Receipt
|
||||||
|
|
||||||
|
To create a Purchase Receipt from an existing Purchase Order, open that purchase order and click on Make Purchase Receipt.
|
||||||
|
|
||||||
|
![Purchase Receipt](img/thirddaysetup-purchase-receipt.png)
|
||||||
|
<br>
|
||||||
|
|
||||||
|
>To understand Purchase Receipt in detail, visit [Purchase Receipt](docs.user.stock.purchase_receipt.html)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
#### Payment (Journal Voucher)
|
||||||
|
|
||||||
|
Payments made against Sales Invoices or Purchase Invoices can be made by clicking on “Make Payment Entry” button on “Submitted” invoices.
|
||||||
|
|
||||||
|
|
||||||
|
![Payment Entry](img/thirddaysetup-payment-entry.png)
|
||||||
|
<br>
|
||||||
|
|
||||||
|
> To understand Payment Entry in detail, visit [Payment Entry](docs.user.accounts.payments.html).
|
86
docs/user/five_day_setup/docs.user.five_day_setup.day_4.md
Normal file
86
docs/user/five_day_setup/docs.user.five_day_setup.day_4.md
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Day-4: Manufacturing Cycle and Accounting Reports"
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
### Manufacturing Cycle
|
||||||
|
|
||||||
|
Complete a manufacturing cycle (if applicable).
|
||||||
|
> BOM > Production Planning Tool > Production Order > Stock Entry (Material Issue) > Stock Entry (Sales Return)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Bill of Materials
|
||||||
|
|
||||||
|
To go to Bill of Materials, Click on Manufacturing. On the Manufacturing page, click on Bill of Materials.
|
||||||
|
|
||||||
|
![Bill of Materials](img/fourthdaysetup-bom.png)
|
||||||
|
|
||||||
|
> To understand BOM in detail, visit [Bill of Materials](docs.user.mfg.bom.html)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Production Planning Tool
|
||||||
|
|
||||||
|
To go to Production Planning Tool, click on the Manufacturing Icon. On the Manufacturing Page, click on Production Planning Tool to go to that page.
|
||||||
|
|
||||||
|
![Production Planning Page](img/fourthdaysetup-ppt.png)
|
||||||
|
|
||||||
|
> To understand Production Planning Tool in detail, visit [Production Planning](docs.user.mfg.planning.html)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Production Order
|
||||||
|
|
||||||
|
To go to Production Order click on the Manufacturing Icon. On the Manufacturing Page, click on Production Order.
|
||||||
|
|
||||||
|
![Production Order](img/fourthdaysetup-po.png)
|
||||||
|
|
||||||
|
> To understand Production Order in detail, visit [Production Order](docs.user.mfg.production_order.html)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Stock Entry
|
||||||
|
|
||||||
|
To go to Stock Entry, click on the Stock Icon and go to Stock Entry.
|
||||||
|
|
||||||
|
![Stock Entry](img/fourthdaysetup-stock.png)
|
||||||
|
|
||||||
|
> To understand Material Issue, visit [Material Issue](docs.user.stock.material_issue.html).
|
||||||
|
|
||||||
|
> To understand Sales Return, visit [Sales Return](docs.user.stock.sales_return.html).
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Delivery Note
|
||||||
|
|
||||||
|
To go to Delivery Note, click on Stock. On the Stock Page, click on Delivery Note.
|
||||||
|
|
||||||
|
![Delivery Note](img/fourthdaysetup-delivery-note.png)
|
||||||
|
|
||||||
|
> To understand Delivery Note in detail, visit [Delivery Note](docs.user.stock.delivery_note.html)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Warehouse
|
||||||
|
|
||||||
|
To go to Warehouse, Click on Stock. On the Stock Page, go to Warehouse.
|
||||||
|
|
||||||
|
![Warehouse](img/fourthdaysetup-warehouse.png)
|
||||||
|
|
||||||
|
> To understand Warehouse in detail, visit [Warehouse](docs.user.stock.warehouse.html)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Accounts
|
||||||
|
|
||||||
|
Make a few Journal Vouchers. Generate some Accounting Reports.
|
||||||
|
|
||||||
|
#### Journal Voucher
|
||||||
|
|
||||||
|
To go to a Journal Voucher, click on Accounts. On the Accounts page, click on Journal Voucher.
|
||||||
|
|
||||||
|
![Journal Voucher](img/fourthdaysetup-jv.png)
|
||||||
|
|
||||||
|
> To understand Journal Voucher in detail, visit [Journal Voucher](docs.user.accounts.journal_voucher.html)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
### Accounting Reports
|
||||||
|
|
||||||
|
Some of the major Accounting Reports are General Ledger, Trial Balance, Accounts Payable and Accounts Receivables, and Sales and Purchase Register.
|
||||||
|
|
||||||
|
> To be able to generate these accounts, visti [Accounting Reports](docs.user.accounts.report.html)
|
32
docs/user/five_day_setup/docs.user.five_day_setup.day_5.md
Normal file
32
docs/user/five_day_setup/docs.user.five_day_setup.day_5.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Day-5: Projects, Calendar, and Website"
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Projects
|
||||||
|
|
||||||
|
ERPNext helps you to manage your Projects by breaking them into Tasks and allocating them to different people.
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Tasks
|
||||||
|
|
||||||
|
Project is divided into Tasks and each Task is allocated to a resource. In ERPNext, you can also create and allocate a Task independently of a Project.
|
||||||
|
|
||||||
|
To create a Task, go to Project and click on Task.
|
||||||
|
|
||||||
|
![Tasks](img/fifthdaysetup-tasks.png)
|
||||||
|
|
||||||
|
> To understand Projects in detail, visit [Projects](docs.user.projects.html).
|
||||||
|
|
||||||
|
> To understand Task in detail, visit [Tasks](docs.user.projects.tasks.html)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Calendar
|
||||||
|
|
||||||
|
> To understand Calendar in detail, visit [Calendar](docs.user.tools.calendar.html)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Website
|
||||||
|
|
||||||
|
> To understand Website in detail, visit [Website](docs.user.website.html)
|
48
docs/user/five_day_setup/docs.user.five_day_setup.md
Normal file
48
docs/user/five_day_setup/docs.user.five_day_setup.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Five-Day Setup",
|
||||||
|
"_toc": [
|
||||||
|
"docs.user.five_day_setup.day_1",
|
||||||
|
"docs.user.five_day_setup.day_2",
|
||||||
|
"docs.user.five_day_setup.day_3",
|
||||||
|
"docs.user.five_day_setup.day_4",
|
||||||
|
"docs.user.five_day_setup.day_5"
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
---
|
||||||
|
Welcome to ERPNext. To be able to setup ERPNext account successfully, a five-day-setup process is recommended. Perform the 5-days-setup instructions and sail through the ERPNext implementation.
|
||||||
|
|
||||||
|
The setup help is divided into day-wise instructions for 5 consecutive days.
|
||||||
|
|
||||||
|
#### Day 1
|
||||||
|
|
||||||
|
- Company Setup
|
||||||
|
- Customer Setup
|
||||||
|
- Item Setup
|
||||||
|
- Supplier Setup
|
||||||
|
- Data Import Tool
|
||||||
|
|
||||||
|
#### Day 2
|
||||||
|
|
||||||
|
- Opening Accounts
|
||||||
|
- Opening Stock
|
||||||
|
- HR Setup
|
||||||
|
|
||||||
|
#### Day 3
|
||||||
|
|
||||||
|
- Sales Cycle
|
||||||
|
- Purchase Cycle
|
||||||
|
|
||||||
|
|
||||||
|
#### Day 4
|
||||||
|
|
||||||
|
- Manufacturing Cycle
|
||||||
|
- Delivery Note and Warehouse
|
||||||
|
- Accounts
|
||||||
|
|
||||||
|
#### Day 5
|
||||||
|
|
||||||
|
- Projects
|
||||||
|
- Calendar
|
||||||
|
- Website
|
@ -10,11 +10,12 @@ Before you start managing your Operations in EPRNext, you must first become fami
|
|||||||
### Test Phase
|
### Test Phase
|
||||||
|
|
||||||
- Read the Manual
|
- Read the Manual
|
||||||
|
- Follow the Five-Day-Setup Module or the instructions given below.
|
||||||
- Create your first Customer, Supplier and Item. Add a few more so you get familiar with them.
|
- Create your first Customer, Supplier and Item. Add a few more so you get familiar with them.
|
||||||
- Create Customer Groups, Item Groups, Warehouses, Supplier Groups, so that you can classify your Items.
|
- Create Customer Groups, Item Groups, Warehouses, Supplier Groups, so that you can classify your Items.
|
||||||
- Complete a standard sales cycle - Lead > Opportunity > Quotation > Sales Order > Delivery Note > Sales Invoice > Payment (Journal Voucher)
|
- Complete a standard sales cycle - Lead > Opportunity > Quotation > Sales Order > Delivery Note > Sales Invoice > Payment (Journal Voucher)
|
||||||
- Complete a standard purchase cycle - Purchase Request > Purchase Order > Purchase Receipt > Payment (Journal Voucher).
|
- Complete a standard purchase cycle - Material Request > Purchase Order > Purchase Receipt > Payment (Journal Voucher).
|
||||||
- Complete a manufacturing cycle (if applicable) - BOM > Production Planning Tool > Production Order > Stock Entry (issue) > Stock Entry (back-flush)
|
- Complete a manufacturing cycle (if applicable) - BOM > Production Planning Tool > Production Order > Material Issue > Sales Return
|
||||||
|
|
||||||
> Tip: Use the 30-day free trial at [erpnext.com](https://erpnext.com) to take your test drive.
|
> Tip: Use the 30-day free trial at [erpnext.com](https://erpnext.com) to take your test drive.
|
||||||
|
|
||||||
|
@ -22,34 +22,34 @@ Accounting Entries
|
|||||||
|
|
||||||
The balance of account can be increased / decreased, depending on account type and transaction type.
|
The balance of account can be increased / decreased, depending on account type and transaction type.
|
||||||
|
|
||||||
<table class="table table-bordered">
|
<table class="table table-bordered text-center">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="active">
|
<tr class="active">
|
||||||
<td style="text-align: center;">Account Type</td>
|
<td>Account Type</td>
|
||||||
<td style="text-align: center;">Transaction Type</td>
|
<td>Transaction Type</td>
|
||||||
<td style="text-align: center;">Effect on account balance</td>
|
<td>Effect on account balance</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center;">Debit</td>
|
<td>Debit</td>
|
||||||
<td style="text-align: center;">Debit</td>
|
<td>Debit</td>
|
||||||
<td style="text-align: center;">Increases</td>
|
<td>Increases</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center;">Debit</td>
|
<td>Debit</td>
|
||||||
<td style="text-align: center;">Credit</td>
|
<td>Credit</td>
|
||||||
<td style="text-align: center;">Decreases</td>
|
<td>Decreases</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center;">Credit</td>
|
<td>Credit</td>
|
||||||
<td style="text-align: center;">Credit</td>
|
<td>Credit</td>
|
||||||
<td style="text-align: center;">Increases</td>
|
<td>Increases</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center;">Credit</td>
|
<td>Credit</td>
|
||||||
<td style="text-align: center;">Debit</td>
|
<td>Debit</td>
|
||||||
<td style="text-align: center;">Decreases</td>
|
<td>Decreases</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -62,48 +62,48 @@ This means that every accounting entry has two parts, one debit and one credit a
|
|||||||
|
|
||||||
As the company will receive a payment from customer, the customer is considered as an asset account. For booking income, company maintains an account called "Sales of Laptop". So, entries will be done in the following manner:
|
As the company will receive a payment from customer, the customer is considered as an asset account. For booking income, company maintains an account called "Sales of Laptop". So, entries will be done in the following manner:
|
||||||
|
|
||||||
<table class="table table-bordered">
|
<table class="table table-bordered text-center">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="active">
|
<tr class="active">
|
||||||
<td style="text-align: center;">Account</td>
|
<td>Account</td>
|
||||||
<td style="text-align: center;">Debit</td>
|
<td>Debit</td>
|
||||||
<td style="text-align: center;">Credit</td>
|
<td>Credit</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center;">Customer A</td>
|
<td>Customer A</td>
|
||||||
<td style="text-align: center;">50000</td>
|
<td>50000</td>
|
||||||
<td style="text-align: center;"></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center;">Sales of Laptop</td>
|
<td>Sales of Laptop</td>
|
||||||
<td style="text-align: center;"></td>
|
<td></td>
|
||||||
<td style="text-align: center;">50000</td>
|
<td>50000</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
Customer A has made the payment, so customer balance should decreased based on the paid amount, which will increase "Cash" balance.
|
Customer A has made the payment, so customer balance should decreased based on the paid amount, which will increase "Cash" balance.
|
||||||
|
|
||||||
<table class="table table-bordered">
|
<table class="table table-bordered text-center">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="active">
|
<tr class="active">
|
||||||
<td style="text-align: center;">Account</td>
|
<td>Account</td>
|
||||||
<td style="text-align: center;">Debit</td>
|
<td>Debit</td>
|
||||||
<td style="text-align: center;">Credit</td>
|
<td>Credit</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center;">Customer A</td>
|
<td>Customer A</td>
|
||||||
<td style="text-align: center;"></td>
|
<td></td>
|
||||||
<td style="text-align: center;">50000</td>
|
<td>50000</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center;">Cash</td>
|
<td>Cash</td>
|
||||||
<td style="text-align: center;">50000</td>
|
<td>50000</td>
|
||||||
<td style="text-align: center;"></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
16
docs/user/knowledge/docs.user.knowledge.attachment_csv.md
Normal file
16
docs/user/knowledge/docs.user.knowledge.attachment_csv.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Attachment and CSV files"
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
#### How to Attach files?
|
||||||
|
|
||||||
|
When you open a form, on the right sidebar, you will see a section to attach files. Click on “Add” and select the file you want to attach. Click on “Upload” and you are set.
|
||||||
|
|
||||||
|
#### What is a CSV file?
|
||||||
|
|
||||||
|
A CSV (Comma Separated Value) file is a data file that you can upload into ERPNext to update various data. Any spreadsheet file from popular spreadsheet applications like MS Excel or Open Office Spreadsheet can be saved as a CSV file.
|
||||||
|
|
||||||
|
If you are using Microsoft Excel and using non-English characters, make sure to save your file encoded as UTF-8. For older versions of Excel, there is no clear way of saving as UTF-8. So save your file as a CSV, then open it in Notepad, and save as “UTF-8”. (Sorry blame Microsoft for this!)
|
||||||
|
|
267
docs/user/knowledge/docs.user.knowledge.doctype.md
Normal file
267
docs/user/knowledge/docs.user.knowledge.doctype.md
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "DocType"
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ERPNext is a based on a “metadata” (data about data) framework that helps define all the different types of documents in the system. The basic building block of ERPNext is a DocType.
|
||||||
|
|
||||||
|
A DocType represents both a table in the database and a form from which a user can enter data.
|
||||||
|
|
||||||
|
Many DocTypes are single tables, but some work in groups. For example, Quotation has a “Quotation” DocType and a “Quotation Item” doctype for the Items table, among others. DocTypes contain a collection of fields called DocFields that form the basis of the columns in the database and the layout of the form.
|
||||||
|
|
||||||
|
<table class="table table-bordered text-left">
|
||||||
|
<thead>
|
||||||
|
<tr class="active">
|
||||||
|
<td width="30%">Column</td>
|
||||||
|
<td>Description</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Name</td>
|
||||||
|
<td>Name of the record</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Owner</td>
|
||||||
|
<td>Creator and Owner of the record</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Created on</td>
|
||||||
|
<td>Date and Time of Creation</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Modified On </td>
|
||||||
|
<td>Date and Time of Modification</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Docstatus</td>
|
||||||
|
<td>Status of the record<br>
|
||||||
|
0 = Saved/Draft<br>
|
||||||
|
1 = Submitted<br>
|
||||||
|
2 = Cancelled/Deleted
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Parent</td>
|
||||||
|
<td>Name of the Parent</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Parent Type</td>
|
||||||
|
<td>Type of Parent</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Parent Field</td>
|
||||||
|
<td>Specifying the relationship with the parent (there can be multiple child relationships with the same DocType).</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Index(idx)</td>
|
||||||
|
<td>Index (sequence) of the record in the child table.</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
#### Single DocType
|
||||||
|
|
||||||
|
There are a certain type of DocTypes that are “Single”, i.e. they have no table associated and have only one record of its fields. DocTypes such as Global Defaults, Production Planning Tool are “Single” DocTypes.
|
||||||
|
|
||||||
|
#### Field Columns
|
||||||
|
|
||||||
|
In the fields table, there are many columns, here is an explanation of the columns of the field table.
|
||||||
|
|
||||||
|
<table class="table table-bordered text-left">
|
||||||
|
<thead>
|
||||||
|
<tr class="active">
|
||||||
|
<td width="30%">Column</td>
|
||||||
|
<td>Description</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Label</td>
|
||||||
|
<td>Field Label (that appears in the form).</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Type</td>
|
||||||
|
<td>Field Type</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Name</td>
|
||||||
|
<td>Column name in the database, must be code friendly with no white spaces, special characters and capital letters.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>options</td>
|
||||||
|
<td>Field settings:<br>
|
||||||
|
For Select: List of options (each on a new line).<br>
|
||||||
|
For Link: DocType that is “linked”.<br>
|
||||||
|
For HTML: HTML Content
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Perm Level</td>
|
||||||
|
<td>Permission level (number) of the field. You can group fields by numbers, called levels, and apply rules on the levels.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Width</td>
|
||||||
|
<td>Width of the field (in pixels) - useful for “Table” types.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Reqd</td>
|
||||||
|
<td>Checked if field is mandatory (required).</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>In Filter</td>
|
||||||
|
<td>Checked if field appears as a standard filter in old style reports.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Hidden</td>
|
||||||
|
<td>Checked if field is hidden.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Print Hide</td>
|
||||||
|
<td>Checked if field is hidden in Print Formats.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Report Hide</td>
|
||||||
|
<td>Checked if field is hidden in old style reports.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Allow on Submit</td>
|
||||||
|
<td>Checked if this field can be edited after the document is “Submitted”.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Depends On</td>
|
||||||
|
<td>The fieldname of the field that will decide whether this field will be shown or hidden. It is useful to hide un-necessary fields.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Description</td>
|
||||||
|
<td>Description of the field</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Default</td>
|
||||||
|
<td>Default value when a new record is created.<br>
|
||||||
|
Note: “user” will set the current user as default and “today” will set today’s date (if the field is a Date field).</td>
|
||||||
|
</tr>
|
||||||
|
<tbody>
|
||||||
|
<table>
|
||||||
|
|
||||||
|
#### Field Types and Options
|
||||||
|
|
||||||
|
Here is a list of the different types of fields used to make / customize forms in ERPNext.
|
||||||
|
|
||||||
|
<table class="table table-bordered text-left">
|
||||||
|
<thead>
|
||||||
|
<tr class="active">
|
||||||
|
<td width="30%">Type</td>
|
||||||
|
<td>Description</td>
|
||||||
|
<td>Options/Setting</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Data</td>
|
||||||
|
<td>Single line text field with 180 characters</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Select</td>
|
||||||
|
<td>Select from a pre-determined items in a drop-down.</td>
|
||||||
|
<td>The “Options” contains the drop-down items, each on a new row</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Link</td>
|
||||||
|
<td>Link an existing document / record</td>
|
||||||
|
<td>Options contains the name of the type of document (DocType)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Currency</td>
|
||||||
|
<td>Number with 2 decimal places, that will be shown separated by commas for thousands etc. in Print.</td>
|
||||||
|
<td>e.g. 1,000,000.00</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Float</td>
|
||||||
|
<td>Number with 6 decimal places.</td>
|
||||||
|
<td>e.g. 3.141593</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Int</td>
|
||||||
|
<td>Integer (no decimals)</td>
|
||||||
|
<td>e.g. 100</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Date</td>
|
||||||
|
<td>Date</td>
|
||||||
|
<td>Format can be selected in Global Defaults</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Time</td>
|
||||||
|
<td>Time</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3" class="active">Text</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Text</td>
|
||||||
|
<td>Multi-line text box without formatting features</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Text editor</td>
|
||||||
|
<td>Multi-line text box with formatting toolbar etc</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Code</td>
|
||||||
|
<td>Code Editor</td>
|
||||||
|
<td>Options can include the type of language for syntax formatting.
|
||||||
|
Eg JS / Python / HTML</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3" class="active">Table (Grid)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Table</td>
|
||||||
|
<td>Table of child items linked to the record.</td>
|
||||||
|
<td>Options contains the name of the DocType of the child table. For example “Sales Invoice Item” for “Sales Invoice”</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3" class="active">Layout</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Section Break</td>
|
||||||
|
<td>Break into a new horizontal section.</td>
|
||||||
|
<td>The layout in ERPNext is evaluated from top to bottom.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Column Break</td>
|
||||||
|
<td>Break into a new vertical column.</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>HTML</td>
|
||||||
|
<td>Add a static text / help / link etc in HTML</td>
|
||||||
|
<td>Options contains the HTML.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3" class="active">Action</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Button</td>
|
||||||
|
<td>Button</td>
|
||||||
|
<td>[for developers only]</td>
|
||||||
|
</tr>
|
||||||
|
<tbody>
|
||||||
|
<table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
84
docs/user/knowledge/docs.user.knowledge.markdown.md
Normal file
84
docs/user/knowledge/docs.user.knowledge.markdown.md
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Format Using Markdown"
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
Markdown is a simple way of writing text to format your content. Markdown allows you easy ways to format.
|
||||||
|
|
||||||
|
1. Headings (h1 (largest), h2, h3, h4 and so on)
|
||||||
|
1. Paragraphs
|
||||||
|
1. Lists (numbered or bulleted)
|
||||||
|
1. Hyper links (links to other pages)
|
||||||
|
1. Images
|
||||||
|
1. Code
|
||||||
|
1. Embed HTML (HTML tags within your text)
|
||||||
|
|
||||||
|
#### Headings
|
||||||
|
|
||||||
|
Headings are specified by adding a `#` (hash) at the beginning of the line. The more the number of hashes, the smaller the heading:
|
||||||
|
|
||||||
|
# This is a large heading.
|
||||||
|
|
||||||
|
### This is a smaller heading.
|
||||||
|
|
||||||
|
#### Paragraphs
|
||||||
|
|
||||||
|
To start a new paragraph, just make sure that there is an empty line at the beginning and end of the paragraph.
|
||||||
|
|
||||||
|
To format text as **bold** or with _italics_ format as follows:
|
||||||
|
|
||||||
|
**This text** is **bold** and _this one_ is with _italics_
|
||||||
|
|
||||||
|
#### Lists
|
||||||
|
|
||||||
|
To define numbered lists, start your link with a number and a dot (.) and ensure there is a blank line before and after the list. The numbers are automatically generated so it does not matter what number you put:
|
||||||
|
|
||||||
|
1. list 1st item
|
||||||
|
1. second item
|
||||||
|
1. and so on
|
||||||
|
1. and so forth
|
||||||
|
|
||||||
|
To define bulleted lists, start your items with a hyphen (-)
|
||||||
|
|
||||||
|
- item 1
|
||||||
|
- item 2
|
||||||
|
- item 3
|
||||||
|
|
||||||
|
To nest lists within one another, put four spaces to indent your inner list as follows:
|
||||||
|
|
||||||
|
1. item 1
|
||||||
|
1. item 2
|
||||||
|
- sub item 1
|
||||||
|
- sub item 2
|
||||||
|
1. item 3
|
||||||
|
|
||||||
|
#### Links (to other pages)
|
||||||
|
|
||||||
|
Links to other pages can be defined by adding your text in box brackets [] followed by the link in round brackets ()
|
||||||
|
|
||||||
|
[This is an external link](http://example.com)
|
||||||
|
[A link within the site](my-page.html)
|
||||||
|
|
||||||
|
#### Images
|
||||||
|
|
||||||
|
Images can be added by adding an exclamation ! before the link.
|
||||||
|
|
||||||
|
![A flower](files/flower.gif)
|
||||||
|
|
||||||
|
|
||||||
|
#### Code
|
||||||
|
|
||||||
|
To add a code block, just leave a blank line before and after the block and make sure all code line are indented by four spaces:
|
||||||
|
|
||||||
|
This is normal text
|
||||||
|
|
||||||
|
This is a code block
|
||||||
|
|
||||||
|
#### HTML
|
||||||
|
|
||||||
|
You can embed any kind of HTML tags within your code. Any content written within HTML tags will not be formatted.
|
||||||
|
|
||||||
|
[Detailed description of the markdown format](http://daringfireball.net/projects/markdown/syntax)
|
||||||
|
|
||||||
|
|
@ -4,8 +4,12 @@
|
|||||||
"_toc": [
|
"_toc": [
|
||||||
"docs.user.knowledge.fiscal_year",
|
"docs.user.knowledge.fiscal_year",
|
||||||
"docs.user.knowledge.accounting",
|
"docs.user.knowledge.accounting",
|
||||||
"docs.user.knowledge.accounting_entries"
|
"docs.user.knowledge.accounting_entries",
|
||||||
|
"docs.user.knowledge.doctype",
|
||||||
|
"docs.user.knowledge.attachment_csv",
|
||||||
|
"docs.user.knowledge.markdown"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
Knowledge Library contains definitions and explanations of various management concepts. This page is created for users who wish to elaborate their conceptual knowledge.
|
Knowledge Library contains definitions and explanations of various management concepts. This page is created for users who wish to elaborate their conceptual knowledge.
|
||||||
|
|
||||||
|
@ -4,7 +4,9 @@
|
|||||||
"_title_image": "img/customers.png"
|
"_title_image": "img/customers.png"
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
You can either directly create your Customers via
|
A customer, who is sometimes known as a client, buyer, or purchaser is the one who receives goods, services, products, or ideas, from a seller for a monetary consideration. A customer can also receive goods or services from a vendor or a supplier for other valuable considerations.
|
||||||
|
|
||||||
|
You can either directly create your Customers via
|
||||||
|
|
||||||
> Selling > Customer
|
> Selling > Customer
|
||||||
|
|
||||||
|
@ -45,6 +45,14 @@ ERPNext will help you set and manage budgets on your Cost Centers. This is usefu
|
|||||||
Budgets are also great for planning purposes. When you are making plans for the next financial year, you would typically target a revenue based on which you would set your expenses. Setting a budget will ensure that your expenses do not get out of hand, at any point, as per your plans.
|
Budgets are also great for planning purposes. When you are making plans for the next financial year, you would typically target a revenue based on which you would set your expenses. Setting a budget will ensure that your expenses do not get out of hand, at any point, as per your plans.
|
||||||
|
|
||||||
You can define it in the Cost Center. If you have seasonal sales you can also define a budget distribution that the budget will follow.
|
You can define it in the Cost Center. If you have seasonal sales you can also define a budget distribution that the budget will follow.
|
||||||
|
|
||||||
|
> Accounts > Budget Distribution > New Budget Distribution
|
||||||
|
|
||||||
|
|
||||||
|
![Budget Distribution](img/budgeting.png)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
#### Budget Actions
|
#### Budget Actions
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"_label": "Data Import Tool"
|
"_label": "Data Import Tool"
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
The Data Import Tool is a great way to upload (or edit) bulk data, specially master data, into the system. To start the tool go to:
|
The Data Import Tool is a great way to upload (or edit) bulk data, specially master data, into the system.
|
||||||
|
|
||||||
To Open the data import tool, you either go to Setup or go to the Transaction you want to Import. If Data Import is allowed, you will see an Import Button:
|
To Open the data import tool, you either go to Setup or go to the Transaction you want to Import. If Data Import is allowed, you will see an Import Button:
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ The tool has two sections, one to download a template and the second to upload t
|
|||||||
|
|
||||||
### 1. Downloading The Template
|
### 1. Downloading The Template
|
||||||
|
|
||||||
Data in ERPNext is stored in tables, much like a spreadsheet with columns and rows of data. Each entity in ERPNext can have multiple child tables associated with it too. The child tables are linked to the parent tables and are implemented where are multiple values for any property. For example an Item can have multiple prices, An Invoice has multiple Items and so on.
|
Data in ERPNext is stored in tables, much like a spreadsheet with columns and rows of data. Each entity in ERPNext can have multiple child tables associated with it too. The child tables are linked to the parent tables and are implemented where there are multiple values for any property. For example an Item can have multiple prices, An Invoice has multiple Items and so on.
|
||||||
|
|
||||||
You can import each table separately, or all at a time. In the child table, you must mention the parent of the row in the “parent” column so that ERPNext knows which Item’s price or tax you are trying to set if you are importing separately.
|
You can import each table separately, or all at a time. In the child table, you must mention the parent of the row in the “parent” column so that ERPNext knows which Item’s price or tax you are trying to set if you are importing separately.
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ Then export your template or save it as a **Comma Separated Values** (CSV) file.
|
|||||||
|
|
||||||
### 3. Upload the .csv File
|
### 3. Upload the .csv File
|
||||||
|
|
||||||
Finally attach the .csv file in the section section click on the "Upload and Import" button.
|
Finally attach the .csv file in the section. Click on the "Upload and Import" button.
|
||||||
|
|
||||||
![Attach and Upload](img/import-5.png)
|
![Attach and Upload](img/import-5.png)
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
"docs.user.setup.email",
|
"docs.user.setup.email",
|
||||||
"docs.user.setup.sms",
|
"docs.user.setup.sms",
|
||||||
"docs.user.setup.taxes",
|
"docs.user.setup.taxes",
|
||||||
"docs.user.setup.price_lists",
|
"docs.user.setup.price_list",
|
||||||
"docs.user.setup.opening",
|
"docs.user.setup.opening",
|
||||||
"docs.user.setup.pos_setting",
|
"docs.user.setup.pos_setting",
|
||||||
"docs.user.setup.third_party_backups"
|
"docs.user.setup.third_party_backups"
|
||||||
|
@ -7,7 +7,7 @@ A Price List is a place where different rate plans can be stored. It’s a name
|
|||||||
|
|
||||||
An Item can have multiple prices based on customer, currency, region, shipping cost etc, which can be stored as different rate plans. In ERPNext, you are required to store all the lists seperately. Buying Price List is different from Selling Price List and thus is stored separately.
|
An Item can have multiple prices based on customer, currency, region, shipping cost etc, which can be stored as different rate plans. In ERPNext, you are required to store all the lists seperately. Buying Price List is different from Selling Price List and thus is stored separately.
|
||||||
|
|
||||||
> Selling > Price List
|
> Setup > Price List
|
||||||
|
|
||||||
|
|
||||||
![Price-List](img/price-lists.png)
|
![Price-List](img/price-lists.png)
|
||||||
@ -15,7 +15,14 @@ An Item can have multiple prices based on customer, currency, region, shipping c
|
|||||||
|
|
||||||
> For multiple currencies, maintain multiple Price Lists.
|
> For multiple currencies, maintain multiple Price Lists.
|
||||||
|
|
||||||
|
<br>
|
||||||
|
### Add Item in Price List
|
||||||
|
|
||||||
To add a new Item to the Price List, add the Item Code and its rate in the Item Prices table.
|
> Setup > Item Price
|
||||||
|
|
||||||
You can also import Item Prices via [Data Import Tool](docs.user.setup.data_import.html)
|
- Enter Price List and Item Code, Valid for Buying or Selling, Item Name & Item Description will be automatically fetched.
|
||||||
|
- Enter Rate and save the document.
|
||||||
|
|
||||||
|
![Item-Price](img/item-price.png)
|
||||||
|
|
||||||
|
For bulk upload of Item Prices, use [Data Import Tool](docs.user.setup.data_import.html)
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
ERPNext has a role-based permission system, which means that you can assign Roles to Users, and permissions on Roles.Each ERPNext user has a Profile. The Profile contains the user’s email and authentication and can be set from:
|
ERPNext has a role-based permission system, which means that you can assign Roles to Users, and permissions on Roles.Each ERPNext user has a Profile. The Profile contains the user’s email and authentication and can be set from:
|
||||||
|
|
||||||
> Setup > Users and Permissions > Users
|
> Setup > Profile
|
||||||
|
|
||||||
#### Step 1: Adding a new User
|
#### Step 1: Adding a new User
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ ERPNext is optimized for itemized management of your sales and purchase. If you
|
|||||||
|
|
||||||
- **Item Name:** Item name is the actual name of your product or service.
|
- **Item Name:** Item name is the actual name of your product or service.
|
||||||
- **Item Code:** Item Code is a short-form to denote your Item. If you have very few Items, it is advisable to keep the Item Name and the Item Code same. This helps new users to recognise and update Item details in all transactions. In case you have lot of Items with long names and the list runs in hundreds, it is advisable to code. To understand naming Item codes see [Item Codification](docs.user.setup.codification.html)
|
- **Item Code:** Item Code is a short-form to denote your Item. If you have very few Items, it is advisable to keep the Item Name and the Item Code same. This helps new users to recognise and update Item details in all transactions. In case you have lot of Items with long names and the list runs in hundreds, it is advisable to code. To understand naming Item codes see [Item Codification](docs.user.setup.codification.html)
|
||||||
- **Item Group:** Item Group is used to categorize an Item under various criterias like products, raw materials, services, sub-assemblies, consumables or all Item groups. Create your default Item Group list under Setup> Item Group and pre-select the option while filling your New Item details under Item Group.
|
- **Item Group:** Item Group is used to categorize an Item under various criterias like products, raw materials, services, sub-assemblies, consumables or all Item groups. Create your default Item Group list under Setup> Item Group and pre-select the option while filling your New Item details under [Item Group](docs.user.stock.item_group.html)
|
||||||
- **Default Unit of Measure:** This is the default measuring unit that you will use for your product. It could be in nos, kgs, meters, etc. You can store all the UOM’s that your product will require under Set Up> Master Data > UOM. These can be preselected while filling New Item by using % sign to get a pop up of the UOM list.
|
- **Default Unit of Measure:** This is the default measuring unit that you will use for your product. It could be in nos, kgs, meters, etc. You can store all the UOM’s that your product will require under Set Up> Master Data > UOM. These can be preselected while filling New Item by using % sign to get a pop up of the UOM list.
|
||||||
- **Brand:** If you have more than one brand save them under Set Up> Master Data> Brand and pre-select them while filling a New Item.
|
- **Brand:** If you have more than one brand save them under Set Up> Master Data> Brand and pre-select them while filling a New Item.
|
||||||
|
|
||||||
@ -27,11 +27,7 @@ To upload an image for your icon that will appear in all transactions, save the
|
|||||||
|
|
||||||
![Item Properties](img/item-add-image.png)
|
![Item Properties](img/item-add-image.png)
|
||||||
|
|
||||||
### Item Pricing
|
### Inventory : Warehouse and Stock Setting
|
||||||
|
|
||||||
Item Price and Price Lists: ERPNext lets you maintain multiple selling prices for an Item using Price Lists. A Price List is a place where different rate plans can be stored. It’s a name you can give to a set of Item prices. In case you have different zones (based on the shipping costs), for different currencies etc, you can maintain different Price Lists. A Price List is formed when you create different Item Prices. To import Item Price see [Importing Data](docs.user.data_import.md).
|
|
||||||
|
|
||||||
## Inventory : Warehouse and Stock Setting
|
|
||||||
|
|
||||||
In ERPNext, you can select different type of Warehouses to stock your different Items. This can be selected based on Item types. It could be Fixed Asset Item, Stock Item or even Manufacturing Item.
|
In ERPNext, you can select different type of Warehouses to stock your different Items. This can be selected based on Item types. It could be Fixed Asset Item, Stock Item or even Manufacturing Item.
|
||||||
|
|
||||||
@ -95,3 +91,59 @@ Inspection Criteria: If a Quality Inspection is prepared for this Item, then thi
|
|||||||
|
|
||||||
|
|
||||||
Visit [Manufacturing](docs.user.mfg.html) and [Website](docs.user.website.html) to understand these topics in detail.
|
Visit [Manufacturing](docs.user.mfg.html) and [Website](docs.user.website.html) to understand these topics in detail.
|
||||||
|
|
||||||
|
### Listing Item on Website
|
||||||
|
|
||||||
|
To list your Item on the Website, fill the Item details and save the file. Once the file is saved, a plus (+) button will appear next to the Image icon. Click on the plus button and add your Item image. The html code will be generated automatically.
|
||||||
|
|
||||||
|
##### Step 1: Save Image
|
||||||
|
|
||||||
|
![Webimage](img/item-webimage.png)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
##### Step 2: Check the 'Show in Website' box.
|
||||||
|
|
||||||
|
Under the Website section, please check the box that says 'show in Website'. Once the box is checked, the page will display other fields for entering information.
|
||||||
|
|
||||||
|
![Webimage](img/item-webimage-1.png)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
|
||||||
|
##### Step 3: Enter Website Details
|
||||||
|
|
||||||
|
![Webimage](img/item-webimage-2.png)
|
||||||
|
|
||||||
|
|
||||||
|
The page name will be generated automatically. Mention the Item-Group under which the Item will be displayed.
|
||||||
|
|
||||||
|
#### Item Groups
|
||||||
|
|
||||||
|
Mention the Item Group under this column. If you wish to list your Item under the broad category products, name your Item Group as Products. In case you have various varieties of Item and want to classify them under different names, make Item Groups with those names and check the box that says 'show in Website'. For Example, if you wish to create a category called 'Bags', create a Item Group named Bags.
|
||||||
|
|
||||||
|
|
||||||
|
![Item Group](img/itemgroup-webimage-bags.png)
|
||||||
|
|
||||||
|
Once the Item Group is created go to the Website Settings page under Website. Enter the Label, Url, and Parent Label.
|
||||||
|
|
||||||
|
|
||||||
|
![Item Group](img/itemgroup-website-settings.png)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
#### Webpage labels
|
||||||
|
|
||||||
|
![Webpage](img/webpage-labels.png)
|
||||||
|
|
||||||
|
Add more Items under a particular Item Group.
|
||||||
|
|
||||||
|
To add more Items under a certain Label, mention the Item Group on the Item Page. The Items will be added automatically on the Webpage, under the Item Group Label. For Example, To add Item-Kiddies Bag and Butterfly Print Bag, check the 'Show in Website'box. The Items will be placed under the Label Bags on the Webpage.
|
||||||
|
|
||||||
|
![Item Group](img/itemgroup-websettings.png)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
Item Group Display
|
||||||
|
|
||||||
|
![Item Group Display](img/webpage-itemgroup-display.png)
|
@ -15,6 +15,11 @@ To create a new blog, just create a new Blog from:
|
|||||||
![Blog](img/blog.png)
|
![Blog](img/blog.png)
|
||||||
|
|
||||||
|
|
||||||
You can format the blog using the same Markdown format
|
You can format a blog using the Markdown format.You can also access your blog by going to the page “blog.html”.
|
||||||
|
|
||||||
|
|
||||||
|
#### A sample blog-page.
|
||||||
|
|
||||||
|
|
||||||
|
![Blog](img/blog-look.png)
|
||||||
|
|
||||||
You can access your blog by going to the page “blog.html”
|
|
||||||
|
@ -29,11 +29,36 @@ To define the Top Bar Menus, Brand, Footers and Home Page, go to:
|
|||||||
|
|
||||||
> Website > Website Settings
|
> Website > Website Settings
|
||||||
|
|
||||||
|
#### Step 1: Landing Page Details
|
||||||
|
|
||||||
![Website Setting](img/website-settings.png)
|
![Website Setting](img/website-settings.png)
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
#### Step 2: Banner Details
|
||||||
|
|
||||||
|
![Website Setting](img/website-settings-1.png)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
#### Step 3: Top Bar Labels
|
||||||
|
|
||||||
|
![Website Setting](img/website-settings-2.png)
|
||||||
|
|
||||||
|
> Note: Create seperate web pages which will be linked to the main web-icons like company, contact, products etc.
|
||||||
|
|
||||||
|
<br>
|
||||||
|
#### Step 4: Footer Details
|
||||||
|
|
||||||
|
![Website Setting](img/website-settings-3.png)
|
||||||
|
|
||||||
|
A website can be generated once all the settings and style requirements are added.
|
||||||
|
|
||||||
|
A sample website generated by ERPNext would look like this.
|
||||||
|
|
||||||
|
![Website](img/website-settings-4.png)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
#### Top Menu
|
#### Top Menu
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ import webnotes
|
|||||||
from webnotes.model import db_exists
|
from webnotes.model import db_exists
|
||||||
from webnotes.model.bean import copy_doclist
|
from webnotes.model.bean import copy_doclist
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ import webnotes
|
|||||||
from webnotes.utils import getdate, nowdate
|
from webnotes.utils import getdate, nowdate
|
||||||
from webnotes import msgprint, _
|
from webnotes import msgprint, _
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
class DocType:
|
class DocType:
|
||||||
def __init__(self, doc, doclist=[]):
|
def __init__(self, doc, doclist=[]):
|
||||||
@ -15,7 +14,7 @@ class DocType:
|
|||||||
self.doclist = doclist
|
self.doclist = doclist
|
||||||
|
|
||||||
def validate_duplicate_record(self):
|
def validate_duplicate_record(self):
|
||||||
res = sql("""select name from `tabAttendance` where employee = %s and att_date = %s
|
res = webnotes.conn.sql("""select name from `tabAttendance` where employee = %s and att_date = %s
|
||||||
and name != %s and docstatus = 1""",
|
and name != %s and docstatus = 1""",
|
||||||
(self.doc.employee, self.doc.att_date, self.doc.name))
|
(self.doc.employee, self.doc.att_date, self.doc.name))
|
||||||
if res:
|
if res:
|
||||||
@ -24,7 +23,7 @@ class DocType:
|
|||||||
|
|
||||||
def check_leave_record(self):
|
def check_leave_record(self):
|
||||||
if self.doc.status == 'Present':
|
if self.doc.status == 'Present':
|
||||||
leave = sql("""select name from `tabLeave Application`
|
leave = webnotes.conn.sql("""select name from `tabLeave Application`
|
||||||
where employee = %s and %s between from_date and to_date and status = 'Approved'
|
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.doc.employee, self.doc.att_date))
|
||||||
|
|
||||||
@ -42,7 +41,7 @@ class DocType:
|
|||||||
msgprint(_("Attendance can not be marked for future dates"), raise_exception=1)
|
msgprint(_("Attendance can not be marked for future dates"), raise_exception=1)
|
||||||
|
|
||||||
def validate_employee(self):
|
def validate_employee(self):
|
||||||
emp = sql("select name from `tabEmployee` where name = %s and status = 'Active'",
|
emp = webnotes.conn.sql("select name from `tabEmployee` where name = %s and status = 'Active'",
|
||||||
self.doc.employee)
|
self.doc.employee)
|
||||||
if not emp:
|
if not emp:
|
||||||
msgprint(_("Employee: ") + self.doc.employee +
|
msgprint(_("Employee: ") + self.doc.employee +
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
wn.provide("erpnext.hr");
|
wn.provide("erpnext.hr");
|
||||||
erpnext.hr.EmployeeController = wn.ui.form.Controller.extend({
|
erpnext.hr.EmployeeController = wn.ui.form.Controller.extend({
|
||||||
setup: function() {
|
setup: function() {
|
||||||
this.setup_leave_approver_select();
|
|
||||||
this.frm.fields_dict.user_id.get_query = function(doc,cdt,cdn) {
|
this.frm.fields_dict.user_id.get_query = function(doc,cdt,cdn) {
|
||||||
return { query:"core.doctype.profile.profile.profile_query"} }
|
return { query:"core.doctype.profile.profile.profile_query"} }
|
||||||
this.frm.fields_dict.reports_to.get_query = function(doc,cdt,cdn) {
|
this.frm.fields_dict.reports_to.get_query = function(doc,cdt,cdn) {
|
||||||
@ -12,6 +11,7 @@ erpnext.hr.EmployeeController = wn.ui.form.Controller.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onload: function() {
|
onload: function() {
|
||||||
|
this.setup_leave_approver_select();
|
||||||
this.frm.toggle_display(["esic_card_no", "gratuity_lic_id", "pan_number", "pf_number"],
|
this.frm.toggle_display(["esic_card_no", "gratuity_lic_id", "pan_number", "pf_number"],
|
||||||
wn.control_panel.country==="India");
|
wn.control_panel.country==="India");
|
||||||
if(this.frm.doc.__islocal) this.frm.set_value("employee_name", "");
|
if(this.frm.doc.__islocal) this.frm.set_value("employee_name", "");
|
||||||
|
@ -4,11 +4,10 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import webnotes
|
import webnotes
|
||||||
|
|
||||||
from webnotes.utils import getdate, validate_email_add, cstr
|
from webnotes.utils import getdate, validate_email_add, cstr, cint
|
||||||
from webnotes.model.doc import make_autoname
|
from webnotes.model.doc import make_autoname
|
||||||
from webnotes import msgprint, _
|
from webnotes import msgprint, _
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
class DocType:
|
class DocType:
|
||||||
def __init__(self,doc,doclist=[]):
|
def __init__(self,doc,doclist=[]):
|
||||||
@ -40,12 +39,12 @@ class DocType:
|
|||||||
self.validate_email()
|
self.validate_email()
|
||||||
self.validate_status()
|
self.validate_status()
|
||||||
self.validate_employee_leave_approver()
|
self.validate_employee_leave_approver()
|
||||||
|
self.update_dob_event()
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
if self.doc.user_id:
|
if self.doc.user_id:
|
||||||
self.update_user_default()
|
self.update_user_default()
|
||||||
self.update_profile()
|
self.update_profile()
|
||||||
self.update_dob_event()
|
|
||||||
|
|
||||||
def update_user_default(self):
|
def update_user_default(self):
|
||||||
webnotes.conn.set_default("employee", self.doc.name, self.doc.user_id)
|
webnotes.conn.set_default("employee", self.doc.name, self.doc.user_id)
|
||||||
@ -156,10 +155,11 @@ class DocType:
|
|||||||
raise_exception=InvalidLeaveApproverError)
|
raise_exception=InvalidLeaveApproverError)
|
||||||
|
|
||||||
def update_dob_event(self):
|
def update_dob_event(self):
|
||||||
if self.doc.status == "Active" and self.doc.date_of_birth:
|
if self.doc.status == "Active" and self.doc.date_of_birth \
|
||||||
|
and not cint(webnotes.conn.get_value("HR Settings", None, "stop_birthday_reminders")):
|
||||||
birthday_event = webnotes.conn.sql("""select name from `tabEvent` where repeat_on='Every Year'
|
birthday_event = webnotes.conn.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.doc.name)
|
||||||
|
|
||||||
starts_on = self.doc.date_of_birth + " 00:00:00"
|
starts_on = self.doc.date_of_birth + " 00:00:00"
|
||||||
ends_on = self.doc.date_of_birth + " 00:15:00"
|
ends_on = self.doc.date_of_birth + " 00:15:00"
|
||||||
|
|
||||||
|
@ -2,12 +2,13 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-03-07 09:04:18",
|
"creation": "2013-03-07 09:04:18",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-08-08 14:22:11",
|
"modified": "2013-10-11 10:52:53",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_attach": 1,
|
"allow_attach": 1,
|
||||||
|
"allow_rename": 1,
|
||||||
"autoname": "naming_series:",
|
"autoname": "naming_series:",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Master",
|
"document_type": "Master",
|
||||||
|
@ -10,7 +10,6 @@ from webnotes.model.doc import addchild, make_autoname
|
|||||||
from webnotes.model.bean import copy_doclist
|
from webnotes.model.bean import copy_doclist
|
||||||
from webnotes import msgprint
|
from webnotes import msgprint
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
@ -6,6 +6,24 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import webnotes
|
import webnotes
|
||||||
|
|
||||||
|
from webnotes.utils import cint
|
||||||
|
|
||||||
class DocType:
|
class DocType:
|
||||||
def __init__(self, d, dl):
|
def __init__(self, d, dl):
|
||||||
self.doc, self.doclist = d, dl
|
self.doc, self.doclist = d, dl
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
self.original_stop_birthday_reminders = cint(webnotes.conn.get_value("HR Settings",
|
||||||
|
None, "stop_birthday_reminders"))
|
||||||
|
|
||||||
|
def on_update(self):
|
||||||
|
# reset birthday reminders
|
||||||
|
if cint(self.doc.stop_birthday_reminders) != self.original_stop_birthday_reminders:
|
||||||
|
webnotes.conn.sql("""delete from `tabEvent` where repeat_on='Every Year' and ref_type='Employee'""")
|
||||||
|
|
||||||
|
if not self.doc.stop_birthday_reminders:
|
||||||
|
for employee in webnotes.conn.sql_list("""select name from `tabEmployee` where status='Active' and
|
||||||
|
ifnull(date_of_birth, '')!=''"""):
|
||||||
|
webnotes.get_obj("Employee", employee).update_dob_event()
|
||||||
|
|
||||||
|
webnotes.msgprint(webnotes._("Updated Birthday Reminders"))
|
@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-08-02 13:45:23",
|
"creation": "2013-08-02 13:45:23",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-08-02 14:22:26",
|
"modified": "2013-10-02 15:44:38",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -38,6 +38,12 @@
|
|||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"name": "HR Settings"
|
"name": "HR Settings"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"doctype": "DocField",
|
||||||
|
"fieldname": "employee_settings",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Employee Settings"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "Employee record is created using selected field. ",
|
"description": "Employee record is created using selected field. ",
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
@ -46,6 +52,19 @@
|
|||||||
"label": "Employee Records to be created by",
|
"label": "Employee Records to be created by",
|
||||||
"options": "Naming Series\nEmployee Number"
|
"options": "Naming Series\nEmployee Number"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"description": "Don't send Employee Birthday Reminders",
|
||||||
|
"doctype": "DocField",
|
||||||
|
"fieldname": "stop_birthday_reminders",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Stop Birthday Reminders"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "DocField",
|
||||||
|
"fieldname": "payroll_settings",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Payroll Settings"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "If checked, Total no. of Working Days will include holidays, and this will reduce the value of Salary Per Day",
|
"description": "If checked, Total no. of Working Days will include holidays, and this will reduce the value of Salary Per Day",
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
|
@ -37,7 +37,7 @@ class JobsMailbox(POP3Mailbox):
|
|||||||
mail.save_attachments_in_doc(applicant.doc)
|
mail.save_attachments_in_doc(applicant.doc)
|
||||||
|
|
||||||
make(content=mail.content, sender=mail.from_email,
|
make(content=mail.content, sender=mail.from_email,
|
||||||
doctype="Job Applicant", name=applicant.doc.name)
|
doctype="Job Applicant", name=applicant.doc.name, sent_or_received="Received")
|
||||||
|
|
||||||
def get_job_applications():
|
def get_job_applications():
|
||||||
if cint(webnotes.conn.get_value('Jobs Email Settings', None, 'extract_emails')):
|
if cint(webnotes.conn.get_value('Jobs Email Settings', None, 'extract_emails')):
|
||||||
|
@ -11,14 +11,9 @@ from webnotes.utils import extract_email_id
|
|||||||
class DocType(TransactionBase):
|
class DocType(TransactionBase):
|
||||||
def __init__(self, d, dl):
|
def __init__(self, d, dl):
|
||||||
self.doc, self.doclist = d, dl
|
self.doc, self.doclist = d, dl
|
||||||
|
|
||||||
def get_sender(self, comm):
|
def get_sender(self, comm):
|
||||||
return webnotes.conn.get_value('Jobs Email Settings',None,'email_id')
|
return webnotes.conn.get_value('Jobs Email Settings',None,'email_id')
|
||||||
|
|
||||||
def on_communication(self, comm):
|
def validate(self):
|
||||||
if webnotes.conn.get_value("Profile", extract_email_id(comm.sender), "user_type")=="System User":
|
self.set_status()
|
||||||
status = "Replied"
|
|
||||||
else:
|
|
||||||
status = "Open"
|
|
||||||
|
|
||||||
webnotes.conn.set(self.doc, 'status', status)
|
|
@ -5,7 +5,6 @@ from __future__ import unicode_literals
|
|||||||
import webnotes
|
import webnotes
|
||||||
from webnotes.utils import cint, flt
|
from webnotes.utils import cint, flt
|
||||||
from webnotes import msgprint
|
from webnotes import msgprint
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
class DocType:
|
class DocType:
|
||||||
def __init__(self, doc, doclist):
|
def __init__(self, doc, doclist):
|
||||||
@ -37,7 +36,7 @@ class DocType:
|
|||||||
|
|
||||||
def check_existing_leave_allocation(self):
|
def check_existing_leave_allocation(self):
|
||||||
"""check whether leave for same type is already allocated or not"""
|
"""check whether leave for same type is already allocated or not"""
|
||||||
leave_allocation = sql("""select name from `tabLeave Allocation`
|
leave_allocation = webnotes.conn.sql("""select name from `tabLeave Allocation`
|
||||||
where employee=%s and leave_type=%s and fiscal_year=%s and docstatus=1""",
|
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.doc.employee, self.doc.leave_type, self.doc.fiscal_year))
|
||||||
if leave_allocation:
|
if leave_allocation:
|
||||||
@ -64,14 +63,14 @@ class DocType:
|
|||||||
return self.get_leaves_allocated(prev_fyear) - self.get_leaves_applied(prev_fyear)
|
return self.get_leaves_allocated(prev_fyear) - self.get_leaves_applied(prev_fyear)
|
||||||
|
|
||||||
def get_leaves_applied(self, fiscal_year):
|
def get_leaves_applied(self, fiscal_year):
|
||||||
leaves_applied = sql("""select SUM(ifnull(total_leave_days, 0))
|
leaves_applied = webnotes.conn.sql("""select SUM(ifnull(total_leave_days, 0))
|
||||||
from `tabLeave Application` where employee=%s and leave_type=%s
|
from `tabLeave Application` where employee=%s and leave_type=%s
|
||||||
and fiscal_year=%s and docstatus=1""",
|
and fiscal_year=%s and docstatus=1""",
|
||||||
(self.doc.employee, self.doc.leave_type, fiscal_year))
|
(self.doc.employee, self.doc.leave_type, fiscal_year))
|
||||||
return leaves_applied and flt(leaves_applied[0][0]) or 0
|
return leaves_applied and flt(leaves_applied[0][0]) or 0
|
||||||
|
|
||||||
def get_leaves_allocated(self, fiscal_year):
|
def get_leaves_allocated(self, fiscal_year):
|
||||||
leaves_allocated = sql("""select SUM(ifnull(total_leaves_allocated, 0))
|
leaves_allocated = webnotes.conn.sql("""select SUM(ifnull(total_leaves_allocated, 0))
|
||||||
from `tabLeave Allocation` where employee=%s and leave_type=%s
|
from `tabLeave Allocation` where employee=%s and leave_type=%s
|
||||||
and fiscal_year=%s and docstatus=1 and name!=%s""",
|
and fiscal_year=%s and docstatus=1 and name!=%s""",
|
||||||
(self.doc.employee, self.doc.leave_type, fiscal_year, self.doc.name))
|
(self.doc.employee, self.doc.leave_type, fiscal_year, self.doc.name))
|
||||||
@ -79,7 +78,7 @@ class DocType:
|
|||||||
|
|
||||||
def allow_carry_forward(self):
|
def allow_carry_forward(self):
|
||||||
"""check whether carry forward is allowed or not for this leave type"""
|
"""check whether carry forward is allowed or not for this leave type"""
|
||||||
cf = sql("""select is_carry_forward from `tabLeave Type` where name = %s""",
|
cf = webnotes.conn.sql("""select is_carry_forward from `tabLeave Type` where name = %s""",
|
||||||
self.doc.leave_type)
|
self.doc.leave_type)
|
||||||
cf = cf and cint(cf[0][0]) or 0
|
cf = cf and cint(cf[0][0]) or 0
|
||||||
if not cf:
|
if not cf:
|
||||||
@ -110,7 +109,7 @@ class DocType:
|
|||||||
webnotes.conn.set(self.doc,'total_leaves_allocated',flt(leave_det['total_leaves_allocated']))
|
webnotes.conn.set(self.doc,'total_leaves_allocated',flt(leave_det['total_leaves_allocated']))
|
||||||
|
|
||||||
def check_for_leave_application(self):
|
def check_for_leave_application(self):
|
||||||
exists = sql("""select name from `tabLeave Application`
|
exists = webnotes.conn.sql("""select name from `tabLeave Application`
|
||||||
where employee=%s and leave_type=%s and fiscal_year=%s and docstatus=1""",
|
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.doc.employee, self.doc.leave_type, self.doc.fiscal_year))
|
||||||
if exists:
|
if exists:
|
||||||
|
@ -7,6 +7,9 @@ import unittest
|
|||||||
from hr.doctype.leave_application.leave_application import LeaveDayBlockedError, OverlapError
|
from hr.doctype.leave_application.leave_application import LeaveDayBlockedError, OverlapError
|
||||||
|
|
||||||
class TestLeaveApplication(unittest.TestCase):
|
class TestLeaveApplication(unittest.TestCase):
|
||||||
|
def tearDown(self):
|
||||||
|
webnotes.session.user = "Administrator"
|
||||||
|
|
||||||
def _clear_roles(self):
|
def _clear_roles(self):
|
||||||
webnotes.conn.sql("""delete from `tabUserRole` where parent in
|
webnotes.conn.sql("""delete from `tabUserRole` where parent in
|
||||||
("test@example.com", "test1@example.com", "test2@example.com")""")
|
("test@example.com", "test1@example.com", "test2@example.com")""")
|
||||||
@ -15,6 +18,7 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
webnotes.conn.sql("""delete from `tabLeave Application`""")
|
webnotes.conn.sql("""delete from `tabLeave Application`""")
|
||||||
|
|
||||||
def _add_employee_leave_approver(self, employee, leave_approver):
|
def _add_employee_leave_approver(self, employee, leave_approver):
|
||||||
|
temp_session_user = webnotes.session.user
|
||||||
webnotes.session.user = "Administrator"
|
webnotes.session.user = "Administrator"
|
||||||
employee = webnotes.bean("Employee", employee)
|
employee = webnotes.bean("Employee", employee)
|
||||||
employee.doclist.append({
|
employee.doclist.append({
|
||||||
@ -23,6 +27,7 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
"leave_approver": leave_approver
|
"leave_approver": leave_approver
|
||||||
})
|
})
|
||||||
employee.save()
|
employee.save()
|
||||||
|
webnotes.session.user = temp_session_user
|
||||||
|
|
||||||
def get_application(self, doclist):
|
def get_application(self, doclist):
|
||||||
application = webnotes.bean(copy=doclist)
|
application = webnotes.bean(copy=doclist)
|
||||||
@ -31,7 +36,6 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
return application
|
return application
|
||||||
|
|
||||||
def test_block_list(self):
|
def test_block_list(self):
|
||||||
webnotes.session.user = "Administrator"
|
|
||||||
self._clear_roles()
|
self._clear_roles()
|
||||||
|
|
||||||
from webnotes.profile import add_role
|
from webnotes.profile import add_role
|
||||||
@ -54,7 +58,6 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
self.assertTrue(application.insert())
|
self.assertTrue(application.insert())
|
||||||
|
|
||||||
def test_overlap(self):
|
def test_overlap(self):
|
||||||
webnotes.session.user = "Administrator"
|
|
||||||
self._clear_roles()
|
self._clear_roles()
|
||||||
self._clear_applications()
|
self._clear_applications()
|
||||||
|
|
||||||
@ -72,7 +75,6 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
self.assertRaises(OverlapError, application.insert)
|
self.assertRaises(OverlapError, application.insert)
|
||||||
|
|
||||||
def test_global_block_list(self):
|
def test_global_block_list(self):
|
||||||
webnotes.session.user = "Administrator"
|
|
||||||
self._clear_roles()
|
self._clear_roles()
|
||||||
|
|
||||||
from webnotes.profile import add_role
|
from webnotes.profile import add_role
|
||||||
@ -98,7 +100,6 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
"applies_to_all_departments", 0)
|
"applies_to_all_departments", 0)
|
||||||
|
|
||||||
def test_leave_approval(self):
|
def test_leave_approval(self):
|
||||||
webnotes.session.user = "Administrator"
|
|
||||||
self._clear_roles()
|
self._clear_roles()
|
||||||
|
|
||||||
from webnotes.profile import add_role
|
from webnotes.profile import add_role
|
||||||
|
@ -7,6 +7,9 @@ import unittest
|
|||||||
from hr.doctype.leave_block_list.leave_block_list import get_applicable_block_dates
|
from hr.doctype.leave_block_list.leave_block_list import get_applicable_block_dates
|
||||||
|
|
||||||
class TestLeaveBlockList(unittest.TestCase):
|
class TestLeaveBlockList(unittest.TestCase):
|
||||||
|
def tearDown(self):
|
||||||
|
webnotes.session.user = "Administrator"
|
||||||
|
|
||||||
def test_get_applicable_block_dates(self):
|
def test_get_applicable_block_dates(self):
|
||||||
webnotes.session.user = "test@example.com"
|
webnotes.session.user = "test@example.com"
|
||||||
webnotes.conn.set_value("Department", "_Test Department", "leave_block_list",
|
webnotes.conn.set_value("Department", "_Test Department", "leave_block_list",
|
||||||
|
@ -9,7 +9,6 @@ from webnotes.model.doc import Document
|
|||||||
from webnotes.model.code import get_obj
|
from webnotes.model.code import get_obj
|
||||||
from webnotes import msgprint
|
from webnotes import msgprint
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -34,7 +33,7 @@ class DocType:
|
|||||||
emp_query = "select name from `tabEmployee` "
|
emp_query = "select name from `tabEmployee` "
|
||||||
if flag == 1:
|
if flag == 1:
|
||||||
emp_query += condition
|
emp_query += condition
|
||||||
e = sql(emp_query)
|
e = webnotes.conn.sql(emp_query)
|
||||||
return e
|
return e
|
||||||
|
|
||||||
# ----------------
|
# ----------------
|
||||||
|
@ -11,7 +11,6 @@ from webnotes.model.bean import getlist, copy_doclist
|
|||||||
from webnotes.model.code import get_obj
|
from webnotes.model.code import get_obj
|
||||||
from webnotes import msgprint
|
from webnotes import msgprint
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -30,7 +29,7 @@ class DocType:
|
|||||||
cond = self.get_filter_condition()
|
cond = self.get_filter_condition()
|
||||||
cond += self.get_joining_releiving_condition()
|
cond += self.get_joining_releiving_condition()
|
||||||
|
|
||||||
emp_list = sql("""
|
emp_list = webnotes.conn.sql("""
|
||||||
select t1.name
|
select t1.name
|
||||||
from `tabEmployee` t1, `tabSalary Structure` t2
|
from `tabEmployee` t1, `tabSalary Structure` t2
|
||||||
where t1.docstatus!=2 and t2.docstatus != 2
|
where t1.docstatus!=2 and t2.docstatus != 2
|
||||||
@ -68,7 +67,7 @@ class DocType:
|
|||||||
|
|
||||||
|
|
||||||
def get_month_details(self, year, month):
|
def get_month_details(self, year, month):
|
||||||
ysd = sql("select year_start_date from `tabFiscal Year` where name ='%s'"%year)[0][0]
|
ysd = webnotes.conn.sql("select year_start_date from `tabFiscal Year` where name ='%s'"%year)[0][0]
|
||||||
if ysd:
|
if ysd:
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
import calendar, datetime
|
import calendar, datetime
|
||||||
@ -96,7 +95,7 @@ class DocType:
|
|||||||
emp_list = self.get_emp_list()
|
emp_list = self.get_emp_list()
|
||||||
ss_list = []
|
ss_list = []
|
||||||
for emp in emp_list:
|
for emp in emp_list:
|
||||||
if not sql("""select name from `tabSalary Slip`
|
if not webnotes.conn.sql("""select name from `tabSalary Slip`
|
||||||
where docstatus!= 2 and employee = %s and month = %s and fiscal_year = %s and company = %s
|
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.doc.month, self.doc.fiscal_year, self.doc.company)):
|
||||||
ss = webnotes.bean({
|
ss = webnotes.bean({
|
||||||
@ -127,7 +126,7 @@ class DocType:
|
|||||||
which are not submitted
|
which are not submitted
|
||||||
"""
|
"""
|
||||||
cond = self.get_filter_condition()
|
cond = self.get_filter_condition()
|
||||||
ss_list = sql("""
|
ss_list = webnotes.conn.sql("""
|
||||||
select t1.name from `tabSalary Slip` t1
|
select t1.name from `tabSalary Slip` t1
|
||||||
where t1.docstatus = 0 and month = '%s' and fiscal_year = '%s' %s
|
where t1.docstatus = 0 and month = '%s' and fiscal_year = '%s' %s
|
||||||
""" % (self.doc.month, self.doc.fiscal_year, cond))
|
""" % (self.doc.month, self.doc.fiscal_year, cond))
|
||||||
@ -189,7 +188,7 @@ class DocType:
|
|||||||
Get total salary amount from submitted salary slip based on selected criteria
|
Get total salary amount from submitted salary slip based on selected criteria
|
||||||
"""
|
"""
|
||||||
cond = self.get_filter_condition()
|
cond = self.get_filter_condition()
|
||||||
tot = sql("""
|
tot = webnotes.conn.sql("""
|
||||||
select sum(rounded_total) from `tabSalary Slip` t1
|
select sum(rounded_total) from `tabSalary Slip` t1
|
||||||
where t1.docstatus = 1 and month = '%s' and fiscal_year = '%s' %s
|
where t1.docstatus = 1 and month = '%s' and fiscal_year = '%s' %s
|
||||||
""" % (self.doc.month, self.doc.fiscal_year, cond))
|
""" % (self.doc.month, self.doc.fiscal_year, cond))
|
||||||
@ -202,7 +201,7 @@ class DocType:
|
|||||||
get default bank account,default salary acount from company
|
get default bank account,default salary acount from company
|
||||||
"""
|
"""
|
||||||
amt = self.get_total_salary()
|
amt = self.get_total_salary()
|
||||||
com = sql("select default_bank_account from `tabCompany` where name = '%s'" % self.doc.company)
|
com = webnotes.conn.sql("select default_bank_account from `tabCompany` where name = '%s'" % self.doc.company)
|
||||||
|
|
||||||
if not com[0][0] or not com[0][1]:
|
if not com[0][0] or not com[0][1]:
|
||||||
msgprint("You can set Default Bank Account in Company master.")
|
msgprint("You can set Default Bank Account in Company master.")
|
||||||
|
@ -9,7 +9,7 @@ test_records = []
|
|||||||
|
|
||||||
# from webnotes.model.doc import Document
|
# from webnotes.model.doc import Document
|
||||||
# from webnotes.model.code import get_obj
|
# from webnotes.model.code import get_obj
|
||||||
# sql = webnotes.conn.sql
|
# webnotes.conn.sql = webnotes.conn.sql
|
||||||
#
|
#
|
||||||
# class TestSalaryManager(unittest.TestCase):
|
# class TestSalaryManager(unittest.TestCase):
|
||||||
# def setUp(self):
|
# def setUp(self):
|
||||||
@ -20,15 +20,15 @@ test_records = []
|
|||||||
# ss1[0].employee = emp1.name
|
# ss1[0].employee = emp1.name
|
||||||
# for s in ss1: s.save(1)
|
# for s in ss1: s.save(1)
|
||||||
# for s in ss1[1:]:
|
# for s in ss1[1:]:
|
||||||
# sql("update `tabSalary Structure Earning` set parent = '%s' where name = '%s'" % (ss1[0].name, s.name))
|
# webnotes.conn.sql("update `tabSalary Structure Earning` set parent = '%s' where name = '%s'" % (ss1[0].name, s.name))
|
||||||
# sql("update `tabSalary Structure Deduction` set parent = '%s' where name = '%s'" % (ss1[0].name, s.name))
|
# webnotes.conn.sql("update `tabSalary Structure Deduction` set parent = '%s' where name = '%s'" % (ss1[0].name, s.name))
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# ss2[0].employee = emp2.name
|
# ss2[0].employee = emp2.name
|
||||||
# for s in ss2: s.save(1)
|
# for s in ss2: s.save(1)
|
||||||
# for s in ss2[1:]:
|
# for s in ss2[1:]:
|
||||||
# sql("update `tabSalary Structure Earning` set parent = '%s' where name = '%s'" % (ss2[0].name, s.name))
|
# webnotes.conn.sql("update `tabSalary Structure Earning` set parent = '%s' where name = '%s'" % (ss2[0].name, s.name))
|
||||||
# sql("update `tabSalary Structure Deduction` set parent = '%s' where name = '%s'" % (ss2[0].name, s.name))
|
# webnotes.conn.sql("update `tabSalary Structure Deduction` set parent = '%s' where name = '%s'" % (ss2[0].name, s.name))
|
||||||
#
|
#
|
||||||
# sman.save()
|
# sman.save()
|
||||||
# self.sm = get_obj('Salary Manager')
|
# self.sm = get_obj('Salary Manager')
|
||||||
@ -36,7 +36,7 @@ test_records = []
|
|||||||
# self.sm.create_sal_slip()
|
# self.sm.create_sal_slip()
|
||||||
#
|
#
|
||||||
# def test_creation(self):
|
# def test_creation(self):
|
||||||
# ssid = sql("""
|
# ssid = webnotes.conn.sql("""
|
||||||
# select name, department
|
# select name, department
|
||||||
# from `tabSalary Slip`
|
# from `tabSalary Slip`
|
||||||
# where month = '08' and fiscal_year='2011-2012'""")
|
# where month = '08' and fiscal_year='2011-2012'""")
|
||||||
@ -46,7 +46,7 @@ test_records = []
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
# def test_lwp_calc(self):
|
# def test_lwp_calc(self):
|
||||||
# ss = sql("""
|
# ss = webnotes.conn.sql("""
|
||||||
# select payment_days
|
# select payment_days
|
||||||
# from `tabSalary Slip`
|
# from `tabSalary Slip`
|
||||||
# where month = '08' and fiscal_year='2011-2012' and employee = '%s'
|
# where month = '08' and fiscal_year='2011-2012' and employee = '%s'
|
||||||
|
@ -11,7 +11,6 @@ from webnotes.model.code import get_obj
|
|||||||
from webnotes import msgprint, _
|
from webnotes import msgprint, _
|
||||||
from setup.utils import get_company_currency
|
from setup.utils import get_company_currency
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
from utilities.transaction_base import TransactionBase
|
from utilities.transaction_base import TransactionBase
|
||||||
|
|
||||||
@ -32,7 +31,7 @@ class DocType(TransactionBase):
|
|||||||
|
|
||||||
|
|
||||||
def check_sal_struct(self):
|
def check_sal_struct(self):
|
||||||
struct = sql("select name from `tabSalary Structure` where employee ='%s' and is_active = 'Yes' "%self.doc.employee)
|
struct = webnotes.conn.sql("select name from `tabSalary Structure` where employee ='%s' and is_active = 'Yes' "%self.doc.employee)
|
||||||
if not struct:
|
if not struct:
|
||||||
msgprint("Please create Salary Structure for employee '%s'"%self.doc.employee)
|
msgprint("Please create Salary Structure for employee '%s'"%self.doc.employee)
|
||||||
self.doc.employee = ''
|
self.doc.employee = ''
|
||||||
@ -100,13 +99,13 @@ class DocType(TransactionBase):
|
|||||||
return payment_days
|
return payment_days
|
||||||
|
|
||||||
def get_holidays_for_employee(self, m):
|
def get_holidays_for_employee(self, m):
|
||||||
holidays = sql("""select t1.holiday_date
|
holidays = webnotes.conn.sql("""select t1.holiday_date
|
||||||
from `tabHoliday` t1, tabEmployee t2
|
from `tabHoliday` t1, tabEmployee t2
|
||||||
where t1.parent = t2.holiday_list and t2.name = %s
|
where t1.parent = t2.holiday_list and t2.name = %s
|
||||||
and t1.holiday_date between %s and %s""",
|
and t1.holiday_date between %s and %s""",
|
||||||
(self.doc.employee, m['month_start_date'], m['month_end_date']))
|
(self.doc.employee, m['month_start_date'], m['month_end_date']))
|
||||||
if not holidays:
|
if not holidays:
|
||||||
holidays = sql("""select t1.holiday_date
|
holidays = webnotes.conn.sql("""select t1.holiday_date
|
||||||
from `tabHoliday` t1, `tabHoliday List` t2
|
from `tabHoliday` t1, `tabHoliday List` t2
|
||||||
where t1.parent = t2.name and ifnull(t2.is_default, 0) = 1
|
where t1.parent = t2.name and ifnull(t2.is_default, 0) = 1
|
||||||
and t2.fiscal_year = %s
|
and t2.fiscal_year = %s
|
||||||
@ -120,7 +119,7 @@ class DocType(TransactionBase):
|
|||||||
for d in range(m['month_days']):
|
for d in range(m['month_days']):
|
||||||
dt = add_days(cstr(m['month_start_date']), d)
|
dt = add_days(cstr(m['month_start_date']), d)
|
||||||
if dt not in holidays:
|
if dt not in holidays:
|
||||||
leave = sql("""
|
leave = webnotes.conn.sql("""
|
||||||
select t1.name, t1.half_day
|
select t1.name, t1.half_day
|
||||||
from `tabLeave Application` t1, `tabLeave Type` t2
|
from `tabLeave Application` t1, `tabLeave Type` t2
|
||||||
where t2.name = t1.leave_type
|
where t2.name = t1.leave_type
|
||||||
@ -134,7 +133,7 @@ class DocType(TransactionBase):
|
|||||||
return lwp
|
return lwp
|
||||||
|
|
||||||
def check_existing(self):
|
def check_existing(self):
|
||||||
ret_exist = sql("""select name from `tabSalary Slip`
|
ret_exist = webnotes.conn.sql("""select name from `tabSalary Slip`
|
||||||
where month = %s and fiscal_year = %s and docstatus != 2
|
where month = %s and fiscal_year = %s and docstatus != 2
|
||||||
and employee = %s and name != %s""",
|
and employee = %s and name != %s""",
|
||||||
(self.doc.month, self.doc.fiscal_year, self.doc.employee, self.doc.name))
|
(self.doc.month, self.doc.fiscal_year, self.doc.employee, self.doc.name))
|
||||||
@ -201,9 +200,9 @@ class DocType(TransactionBase):
|
|||||||
receiver = webnotes.conn.get_value("Employee", self.doc.employee, "company_email")
|
receiver = webnotes.conn.get_value("Employee", self.doc.employee, "company_email")
|
||||||
if receiver:
|
if receiver:
|
||||||
subj = 'Salary Slip - ' + cstr(self.doc.month) +'/'+cstr(self.doc.fiscal_year)
|
subj = 'Salary Slip - ' + cstr(self.doc.month) +'/'+cstr(self.doc.fiscal_year)
|
||||||
earn_ret=sql("""select e_type, e_modified_amount from `tabSalary Slip Earning`
|
earn_ret=webnotes.conn.sql("""select e_type, e_modified_amount from `tabSalary Slip Earning`
|
||||||
where parent = %s""", self.doc.name)
|
where parent = %s""", self.doc.name)
|
||||||
ded_ret=sql("""select d_type, d_modified_amount from `tabSalary Slip Deduction`
|
ded_ret=webnotes.conn.sql("""select d_type, d_modified_amount from `tabSalary Slip Deduction`
|
||||||
where parent = %s""", self.doc.name)
|
where parent = %s""", self.doc.name)
|
||||||
|
|
||||||
earn_table = ''
|
earn_table = ''
|
||||||
|
@ -8,7 +8,6 @@ from webnotes.utils import cstr, flt
|
|||||||
from webnotes.model.doc import addchild, make_autoname
|
from webnotes.model.doc import addchild, make_autoname
|
||||||
from webnotes import msgprint, _
|
from webnotes import msgprint, _
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
class DocType:
|
class DocType:
|
||||||
def __init__(self,doc,doclist=[]):
|
def __init__(self,doc,doclist=[]):
|
||||||
@ -20,7 +19,7 @@ class DocType:
|
|||||||
|
|
||||||
def get_employee_details(self):
|
def get_employee_details(self):
|
||||||
ret = {}
|
ret = {}
|
||||||
det = sql("""select employee_name, branch, designation, department, grade
|
det = webnotes.conn.sql("""select employee_name, branch, designation, department, grade
|
||||||
from `tabEmployee` where name = %s""", self.doc.employee)
|
from `tabEmployee` where name = %s""", self.doc.employee)
|
||||||
if det:
|
if det:
|
||||||
ret = {
|
ret = {
|
||||||
@ -34,7 +33,7 @@ class DocType:
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
def get_ss_values(self,employee):
|
def get_ss_values(self,employee):
|
||||||
basic_info = sql("""select bank_name, bank_ac_no, esic_card_no, pf_number
|
basic_info = webnotes.conn.sql("""select bank_name, bank_ac_no, esic_card_no, pf_number
|
||||||
from `tabEmployee` where name =%s""", employee)
|
from `tabEmployee` where name =%s""", employee)
|
||||||
ret = {'bank_name': basic_info and basic_info[0][0] or '',
|
ret = {'bank_name': basic_info and basic_info[0][0] or '',
|
||||||
'bank_ac_no': basic_info and basic_info[0][1] or '',
|
'bank_ac_no': basic_info and basic_info[0][1] or '',
|
||||||
@ -43,7 +42,7 @@ class DocType:
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
def make_table(self, doct_name, tab_fname, tab_name):
|
def make_table(self, doct_name, tab_fname, tab_name):
|
||||||
list1 = sql("select name from `tab%s` where docstatus != 2" % doct_name)
|
list1 = webnotes.conn.sql("select name from `tab%s` where docstatus != 2" % doct_name)
|
||||||
for li in list1:
|
for li in list1:
|
||||||
child = addchild(self.doc, tab_fname, tab_name, self.doclist)
|
child = addchild(self.doc, tab_fname, tab_name, self.doclist)
|
||||||
if(tab_fname == 'earning_details'):
|
if(tab_fname == 'earning_details'):
|
||||||
@ -58,7 +57,7 @@ class DocType:
|
|||||||
self.make_table('Deduction Type','deduction_details', 'Salary Structure Deduction')
|
self.make_table('Deduction Type','deduction_details', 'Salary Structure Deduction')
|
||||||
|
|
||||||
def check_existing(self):
|
def check_existing(self):
|
||||||
ret = sql("""select name from `tabSalary Structure` where is_active = 'Yes'
|
ret = webnotes.conn.sql("""select name from `tabSalary Structure` where is_active = 'Yes'
|
||||||
and employee = %s and name!=%s""", (self.doc.employee,self.doc.name))
|
and employee = %s and name!=%s""", (self.doc.employee,self.doc.name))
|
||||||
if ret and self.doc.is_active=='Yes':
|
if ret and self.doc.is_active=='Yes':
|
||||||
msgprint(_("""Another Salary Structure '%s' is active for employee '%s'.
|
msgprint(_("""Another Salary Structure '%s' is active for employee '%s'.
|
||||||
|
@ -9,7 +9,8 @@ from webnotes.utils import cstr, add_days, date_diff
|
|||||||
from webnotes import msgprint, _
|
from webnotes import msgprint, _
|
||||||
from webnotes.utils.datautils import UnicodeWriter
|
from webnotes.utils.datautils import UnicodeWriter
|
||||||
|
|
||||||
doclist = None
|
# doclist = None
|
||||||
|
doclist = webnotes.local('uploadattendance_doclist')
|
||||||
|
|
||||||
class DocType():
|
class DocType():
|
||||||
def __init__(self, doc, doclist=[]):
|
def __init__(self, doc, doclist=[]):
|
||||||
@ -21,9 +22,8 @@ def get_template():
|
|||||||
if not webnotes.has_permission("Attendance", "create"):
|
if not webnotes.has_permission("Attendance", "create"):
|
||||||
raise webnotes.PermissionError
|
raise webnotes.PermissionError
|
||||||
|
|
||||||
args = webnotes.form_dict
|
args = webnotes.local.form_dict
|
||||||
global doclist
|
webnotes.local.uploadattendance_doclist = webnotes.model.doctype.get("Attendance")
|
||||||
doclist = webnotes.model.doctype.get("Attendance")
|
|
||||||
|
|
||||||
w = UnicodeWriter()
|
w = UnicodeWriter()
|
||||||
w = add_header(w)
|
w = add_header(w)
|
||||||
@ -144,4 +144,4 @@ def upload():
|
|||||||
webnotes.conn.rollback()
|
webnotes.conn.rollback()
|
||||||
else:
|
else:
|
||||||
webnotes.conn.commit()
|
webnotes.conn.commit()
|
||||||
return {"messages": ret, "error": error}
|
return {"messages": ret, "error": error}
|
||||||
|
@ -9,7 +9,6 @@ from webnotes.model.bean import getlist
|
|||||||
from webnotes.model.code import get_obj
|
from webnotes.model.code import get_obj
|
||||||
from webnotes import msgprint, _
|
from webnotes import msgprint, _
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
|
|
||||||
class DocType:
|
class DocType:
|
||||||
@ -18,7 +17,7 @@ class DocType:
|
|||||||
self.doclist = doclist
|
self.doclist = doclist
|
||||||
|
|
||||||
def autoname(self):
|
def autoname(self):
|
||||||
last_name = sql("""select max(name) from `tabBOM`
|
last_name = webnotes.conn.sql("""select max(name) from `tabBOM`
|
||||||
where name like "BOM/%s/%%" """ % cstr(self.doc.item).replace('"', '\\"'))
|
where name like "BOM/%s/%%" """ % cstr(self.doc.item).replace('"', '\\"'))
|
||||||
if last_name:
|
if last_name:
|
||||||
idx = cint(cstr(last_name[0][0]).split('/')[-1].split('-')[0]) + 1
|
idx = cint(cstr(last_name[0][0]).split('/')[-1].split('-')[0]) + 1
|
||||||
@ -144,7 +143,7 @@ class DocType:
|
|||||||
webnotes.bean(self.doclist).update_after_submit()
|
webnotes.bean(self.doclist).update_after_submit()
|
||||||
|
|
||||||
def get_bom_unitcost(self, bom_no):
|
def get_bom_unitcost(self, bom_no):
|
||||||
bom = sql("""select name, total_cost/quantity as unit_cost from `tabBOM`
|
bom = webnotes.conn.sql("""select name, total_cost/quantity as unit_cost from `tabBOM`
|
||||||
where is_active = 1 and name = %s""", bom_no, as_dict=1)
|
where is_active = 1 and name = %s""", bom_no, as_dict=1)
|
||||||
return bom and bom[0]['unit_cost'] or 0
|
return bom and bom[0]['unit_cost'] or 0
|
||||||
|
|
||||||
@ -156,7 +155,7 @@ class DocType:
|
|||||||
from stock.utils import get_incoming_rate
|
from stock.utils import get_incoming_rate
|
||||||
dt = self.doc.costing_date or nowdate()
|
dt = self.doc.costing_date or nowdate()
|
||||||
time = self.doc.costing_date == nowdate() and now().split()[1] or '23:59'
|
time = self.doc.costing_date == nowdate() and now().split()[1] or '23:59'
|
||||||
warehouse = sql("select warehouse from `tabBin` where item_code = %s", args['item_code'])
|
warehouse = webnotes.conn.sql("select warehouse from `tabBin` where item_code = %s", args['item_code'])
|
||||||
rate = []
|
rate = []
|
||||||
for wh in warehouse:
|
for wh in warehouse:
|
||||||
r = get_incoming_rate({
|
r = get_incoming_rate({
|
||||||
@ -184,7 +183,7 @@ class DocType:
|
|||||||
if not self.doc.is_active:
|
if not self.doc.is_active:
|
||||||
webnotes.conn.set(self.doc, "is_default", 0)
|
webnotes.conn.set(self.doc, "is_default", 0)
|
||||||
|
|
||||||
sql("update `tabItem` set default_bom = null where name = %s and default_bom = %s",
|
webnotes.conn.sql("update `tabItem` set default_bom = null where name = %s and default_bom = %s",
|
||||||
(self.doc.item, self.doc.name))
|
(self.doc.item, self.doc.name))
|
||||||
|
|
||||||
def clear_operations(self):
|
def clear_operations(self):
|
||||||
@ -250,7 +249,7 @@ class DocType:
|
|||||||
|
|
||||||
def validate_bom_no(self, item, bom_no, idx):
|
def validate_bom_no(self, item, bom_no, idx):
|
||||||
"""Validate BOM No of sub-contracted items"""
|
"""Validate BOM No of sub-contracted items"""
|
||||||
bom = sql("""select name from `tabBOM` where name = %s and item = %s
|
bom = webnotes.conn.sql("""select name from `tabBOM` where name = %s and item = %s
|
||||||
and is_active=1 and docstatus=1""",
|
and is_active=1 and docstatus=1""",
|
||||||
(bom_no, item), as_dict =1)
|
(bom_no, item), as_dict =1)
|
||||||
if not bom:
|
if not bom:
|
||||||
@ -272,7 +271,7 @@ class DocType:
|
|||||||
for d in check_list:
|
for d in check_list:
|
||||||
bom_list, count = [self.doc.name], 0
|
bom_list, count = [self.doc.name], 0
|
||||||
while (len(bom_list) > count ):
|
while (len(bom_list) > count ):
|
||||||
boms = sql(" select %s from `tabBOM Item` where %s = '%s' " %
|
boms = webnotes.conn.sql(" select %s from `tabBOM Item` where %s = '%s' " %
|
||||||
(d[0], d[1], cstr(bom_list[count])))
|
(d[0], d[1], cstr(bom_list[count])))
|
||||||
count = count + 1
|
count = count + 1
|
||||||
for b in boms:
|
for b in boms:
|
||||||
@ -333,6 +332,7 @@ class DocType:
|
|||||||
d.amount = flt(d.rate) * flt(d.qty)
|
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.doc.quantity)
|
||||||
total_rm_cost += d.amount
|
total_rm_cost += d.amount
|
||||||
|
|
||||||
self.doc.raw_material_cost = total_rm_cost
|
self.doc.raw_material_cost = total_rm_cost
|
||||||
|
|
||||||
def update_exploded_items(self):
|
def update_exploded_items(self):
|
||||||
@ -364,7 +364,7 @@ class DocType:
|
|||||||
def get_child_exploded_items(self, bom_no, qty):
|
def get_child_exploded_items(self, bom_no, qty):
|
||||||
""" Add all items from Flat BOM of child BOM"""
|
""" Add all items from Flat BOM of child BOM"""
|
||||||
|
|
||||||
child_fb_items = sql("""select item_code, description, stock_uom, qty, rate,
|
child_fb_items = webnotes.conn.sql("""select item_code, description, stock_uom, qty, rate,
|
||||||
qty_consumed_per_unit from `tabBOM Explosion Item`
|
qty_consumed_per_unit from `tabBOM Explosion Item`
|
||||||
where parent = %s and docstatus = 1""", bom_no, as_dict = 1)
|
where parent = %s and docstatus = 1""", bom_no, as_dict = 1)
|
||||||
|
|
||||||
@ -390,12 +390,12 @@ class DocType:
|
|||||||
ch.save(1)
|
ch.save(1)
|
||||||
|
|
||||||
def get_parent_bom_list(self, bom_no):
|
def get_parent_bom_list(self, bom_no):
|
||||||
p_bom = sql("select parent from `tabBOM Item` where bom_no = '%s'" % bom_no)
|
p_bom = webnotes.conn.sql("select parent from `tabBOM Item` where bom_no = '%s'" % bom_no)
|
||||||
return p_bom and [i[0] for i in p_bom] or []
|
return p_bom and [i[0] for i in p_bom] or []
|
||||||
|
|
||||||
def validate_bom_links(self):
|
def validate_bom_links(self):
|
||||||
if not self.doc.is_active:
|
if not self.doc.is_active:
|
||||||
act_pbom = sql("""select distinct bom_item.parent from `tabBOM Item` bom_item
|
act_pbom = webnotes.conn.sql("""select distinct bom_item.parent from `tabBOM Item` bom_item
|
||||||
where bom_item.bom_no = %s and bom_item.docstatus = 1
|
where bom_item.bom_no = %s and bom_item.docstatus = 1
|
||||||
and exists (select * from `tabBOM` where name = bom_item.parent
|
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.doc.name)
|
||||||
@ -403,4 +403,53 @@ class DocType:
|
|||||||
if act_pbom and act_pbom[0][0]:
|
if act_pbom and act_pbom[0][0]:
|
||||||
action = self.doc.docstatus < 2 and _("deactivate") or _("cancel")
|
action = self.doc.docstatus < 2 and _("deactivate") or _("cancel")
|
||||||
msgprint(_("Cannot ") + action + _(": It is linked to other active BOM(s)"),
|
msgprint(_("Cannot ") + action + _(": It is linked to other active BOM(s)"),
|
||||||
raise_exception=1)
|
raise_exception=1)
|
||||||
|
|
||||||
|
def get_bom_items_as_dict(bom, qty=1, fetch_exploded=1):
|
||||||
|
item_dict = {}
|
||||||
|
|
||||||
|
query = """select
|
||||||
|
bom_item.item_code,
|
||||||
|
ifnull(sum(bom_item.qty_consumed_per_unit),0) * %(qty)s as qty,
|
||||||
|
item.description,
|
||||||
|
item.stock_uom,
|
||||||
|
item.default_warehouse
|
||||||
|
from
|
||||||
|
`tab%(table)s` bom_item, `tabItem` item
|
||||||
|
where
|
||||||
|
bom_item.docstatus < 2
|
||||||
|
and bom_item.parent = "%(bom)s"
|
||||||
|
and item.name = bom_item.item_code
|
||||||
|
%(conditions)s
|
||||||
|
group by item_code, stock_uom"""
|
||||||
|
|
||||||
|
if fetch_exploded:
|
||||||
|
items = webnotes.conn.sql(query % {
|
||||||
|
"qty": qty,
|
||||||
|
"table": "BOM Explosion Item",
|
||||||
|
"bom": bom,
|
||||||
|
"conditions": """and ifnull(item.is_pro_applicable, 'No') = 'No'
|
||||||
|
and ifnull(item.is_sub_contracted_item, 'No') = 'No' """
|
||||||
|
}, as_dict=True)
|
||||||
|
else:
|
||||||
|
items = webnotes.conn.sql(query % {
|
||||||
|
"qty": qty,
|
||||||
|
"table": "BOM Item",
|
||||||
|
"bom": bom,
|
||||||
|
"conditions": ""
|
||||||
|
}, as_dict=True)
|
||||||
|
|
||||||
|
# make unique
|
||||||
|
for item in items:
|
||||||
|
if item_dict.has_key(item.item_code):
|
||||||
|
item_dict[item.item_code]["qty"] += flt(item.qty)
|
||||||
|
else:
|
||||||
|
item_dict[item.item_code] = item
|
||||||
|
|
||||||
|
return item_dict
|
||||||
|
|
||||||
|
@webnotes.whitelist()
|
||||||
|
def get_bom_items(bom, qty=1, fetch_exploded=1):
|
||||||
|
items = get_bom_items_as_dict(bom, qty, fetch_exploded).values()
|
||||||
|
items.sort(lambda a, b: a.item_code > b.item_code and 1 or -1)
|
||||||
|
return items
|
@ -7,6 +7,35 @@ import unittest
|
|||||||
import webnotes
|
import webnotes
|
||||||
|
|
||||||
test_records = [
|
test_records = [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"doctype": "BOM",
|
||||||
|
"item": "_Test Item Home Desktop Manufactured",
|
||||||
|
"quantity": 1.0,
|
||||||
|
"is_active": 1,
|
||||||
|
"is_default": 1,
|
||||||
|
"docstatus": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "BOM Item",
|
||||||
|
"item_code": "_Test Serialized Item With Series",
|
||||||
|
"parentfield": "bom_materials",
|
||||||
|
"qty": 1.0,
|
||||||
|
"rate": 5000.0,
|
||||||
|
"amount": 5000.0,
|
||||||
|
"stock_uom": "_Test UOM"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "BOM Item",
|
||||||
|
"item_code": "_Test Item 2",
|
||||||
|
"parentfield": "bom_materials",
|
||||||
|
"qty": 2.0,
|
||||||
|
"rate": 1000.0,
|
||||||
|
"amount": 2000.0,
|
||||||
|
"stock_uom": "_Test UOM"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"doctype": "BOM",
|
"doctype": "BOM",
|
||||||
@ -34,5 +63,57 @@ test_records = [
|
|||||||
"amount": 2000.0,
|
"amount": 2000.0,
|
||||||
"stock_uom": "_Test UOM"
|
"stock_uom": "_Test UOM"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
]
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"doctype": "BOM",
|
||||||
|
"item": "_Test FG Item 2",
|
||||||
|
"quantity": 1.0,
|
||||||
|
"is_active": 1,
|
||||||
|
"is_default": 1,
|
||||||
|
"docstatus": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "BOM Item",
|
||||||
|
"item_code": "_Test Item",
|
||||||
|
"parentfield": "bom_materials",
|
||||||
|
"qty": 1.0,
|
||||||
|
"rate": 5000.0,
|
||||||
|
"amount": 5000.0,
|
||||||
|
"stock_uom": "_Test UOM"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "BOM Item",
|
||||||
|
"item_code": "_Test Item Home Desktop Manufactured",
|
||||||
|
"bom_no": "BOM/_Test Item Home Desktop Manufactured/001",
|
||||||
|
"parentfield": "bom_materials",
|
||||||
|
"qty": 2.0,
|
||||||
|
"rate": 1000.0,
|
||||||
|
"amount": 2000.0,
|
||||||
|
"stock_uom": "_Test UOM"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
]
|
||||||
|
|
||||||
|
class TestBOM(unittest.TestCase):
|
||||||
|
def test_get_items(self):
|
||||||
|
from manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
||||||
|
items_dict = get_bom_items_as_dict(bom="BOM/_Test FG Item 2/001", qty=1, fetch_exploded=0)
|
||||||
|
self.assertTrue(test_records[2][1]["item_code"] in items_dict)
|
||||||
|
self.assertTrue(test_records[2][2]["item_code"] in items_dict)
|
||||||
|
self.assertEquals(len(items_dict.values()), 2)
|
||||||
|
|
||||||
|
def test_get_items_exploded(self):
|
||||||
|
from manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
||||||
|
items_dict = get_bom_items_as_dict(bom="BOM/_Test FG Item 2/001", qty=1, fetch_exploded=1)
|
||||||
|
self.assertTrue(test_records[2][1]["item_code"] in items_dict)
|
||||||
|
self.assertFalse(test_records[2][2]["item_code"] in items_dict)
|
||||||
|
self.assertTrue(test_records[0][1]["item_code"] in items_dict)
|
||||||
|
self.assertTrue(test_records[0][2]["item_code"] in items_dict)
|
||||||
|
self.assertEquals(len(items_dict.values()), 3)
|
||||||
|
|
||||||
|
def test_get_items_list(self):
|
||||||
|
from manufacturing.doctype.bom.bom import get_bom_items
|
||||||
|
self.assertEquals(len(get_bom_items(bom="BOM/_Test FG Item 2/001", qty=1, fetch_exploded=1)), 3)
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ from webnotes.utils import cstr, flt, nowdate
|
|||||||
from webnotes.model.code import get_obj
|
from webnotes.model.code import get_obj
|
||||||
from webnotes import msgprint, _
|
from webnotes import msgprint, _
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
class OverProductionError(webnotes.ValidationError): pass
|
class OverProductionError(webnotes.ValidationError): pass
|
||||||
|
|
||||||
@ -18,19 +17,23 @@ class DocType:
|
|||||||
self.doclist = doclist
|
self.doclist = doclist
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
if self.doc.docstatus == 0:
|
||||||
|
self.doc.status = "Draft"
|
||||||
|
|
||||||
import utilities
|
import utilities
|
||||||
utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped",
|
utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped",
|
||||||
"In Process", "Completed", "Cancelled"])
|
"In Process", "Completed", "Cancelled"])
|
||||||
|
|
||||||
if self.doc.production_item :
|
self.validate_bom_no()
|
||||||
item_detail = sql("select name from `tabItem` where name = '%s' and docstatus != 2"
|
self.validate_sales_order()
|
||||||
% self.doc.production_item, as_dict = 1)
|
self.validate_warehouse()
|
||||||
if not item_detail:
|
|
||||||
msgprint("Item '%s' does not exist or cancelled in the system."
|
from utilities.transaction_base import validate_uom_is_integer
|
||||||
% cstr(self.doc.production_item), raise_exception=1)
|
validate_uom_is_integer(self.doclist, "stock_uom", ["qty", "produced_qty"])
|
||||||
|
|
||||||
|
def validate_bom_no(self):
|
||||||
if self.doc.bom_no:
|
if self.doc.bom_no:
|
||||||
bom = sql("""select name from `tabBOM` where name=%s and docstatus=1
|
bom = webnotes.conn.sql("""select name from `tabBOM` where name=%s and docstatus=1
|
||||||
and is_active=1 and item=%s"""
|
and is_active=1 and item=%s"""
|
||||||
, (self.doc.bom_no, self.doc.production_item), as_dict =1)
|
, (self.doc.bom_no, self.doc.production_item), as_dict =1)
|
||||||
if not bom:
|
if not bom:
|
||||||
@ -38,16 +41,20 @@ class DocType:
|
|||||||
May be BOM not exists or inactive or not submitted
|
May be BOM not exists or inactive or not submitted
|
||||||
or for some other item.""" % cstr(self.doc.bom_no), raise_exception=1)
|
or for some other item.""" % cstr(self.doc.bom_no), raise_exception=1)
|
||||||
|
|
||||||
|
def validate_sales_order(self):
|
||||||
if self.doc.sales_order:
|
if self.doc.sales_order:
|
||||||
if not webnotes.conn.sql("""select name from `tabSales Order`
|
if not webnotes.conn.sql("""select name from `tabSales Order`
|
||||||
where name=%s and docstatus = 1""", self.doc.sales_order):
|
where name=%s and docstatus = 1""", self.doc.sales_order):
|
||||||
msgprint("Sales Order: %s is not valid" % self.doc.sales_order, raise_exception=1)
|
msgprint("Sales Order: %s is not valid" % self.doc.sales_order, raise_exception=1)
|
||||||
|
|
||||||
self.validate_production_order_against_so()
|
self.validate_production_order_against_so()
|
||||||
|
|
||||||
from utilities.transaction_base import validate_uom_is_integer
|
def validate_warehouse(self):
|
||||||
validate_uom_is_integer(self.doclist, "stock_uom", ["qty", "produced_qty"])
|
from stock.utils import validate_warehouse_user, validate_warehouse_company
|
||||||
|
|
||||||
|
for w in [self.doc.fg_warehouse, self.doc.wip_warehouse]:
|
||||||
|
validate_warehouse_user(w)
|
||||||
|
validate_warehouse_company(w, self.doc.company)
|
||||||
|
|
||||||
def validate_production_order_against_so(self):
|
def validate_production_order_against_so(self):
|
||||||
# already ordered qty
|
# already ordered qty
|
||||||
@ -104,7 +111,7 @@ class DocType:
|
|||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
# Check whether any stock entry exists against this Production Order
|
# Check whether any stock entry exists against this Production Order
|
||||||
stock_entry = sql("""select name from `tabStock Entry`
|
stock_entry = webnotes.conn.sql("""select name from `tabStock Entry`
|
||||||
where production_order = %s and docstatus = 1""", self.doc.name)
|
where production_order = %s and docstatus = 1""", self.doc.name)
|
||||||
if stock_entry:
|
if stock_entry:
|
||||||
msgprint("""Submitted Stock Entry %s exists against this production order.
|
msgprint("""Submitted Stock Entry %s exists against this production order.
|
||||||
@ -144,12 +151,6 @@ def get_item_details(item):
|
|||||||
@webnotes.whitelist()
|
@webnotes.whitelist()
|
||||||
def make_stock_entry(production_order_id, purpose):
|
def make_stock_entry(production_order_id, purpose):
|
||||||
production_order = webnotes.bean("Production Order", production_order_id)
|
production_order = webnotes.bean("Production Order", production_order_id)
|
||||||
|
|
||||||
# validate already existing
|
|
||||||
ste = webnotes.conn.get_value("Stock Entry", {
|
|
||||||
"production_order":production_order_id,
|
|
||||||
"purpose": purpose
|
|
||||||
}, "name")
|
|
||||||
|
|
||||||
stock_entry = webnotes.new_bean("Stock Entry")
|
stock_entry = webnotes.new_bean("Stock Entry")
|
||||||
stock_entry.doc.purpose = purpose
|
stock_entry.doc.purpose = purpose
|
||||||
|
@ -2,11 +2,12 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-01-10 16:34:16",
|
"creation": "2013-01-10 16:34:16",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-08-08 14:22:12",
|
"modified": "2013-10-02 14:25:03",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_import": 1,
|
||||||
"autoname": "naming_series:",
|
"autoname": "naming_series:",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"icon": "icon-cogs",
|
"icon": "icon-cogs",
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import unittest
|
||||||
|
import webnotes
|
||||||
|
from stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
||||||
|
from manufacturing.doctype.production_order.production_order import make_stock_entry
|
||||||
|
|
||||||
|
|
||||||
|
class TestProductionOrder(unittest.TestCase):
|
||||||
|
def test_planned_qty(self):
|
||||||
|
set_perpetual_inventory(0)
|
||||||
|
webnotes.conn.sql("delete from `tabStock Ledger Entry`")
|
||||||
|
webnotes.conn.sql("""delete from `tabBin`""")
|
||||||
|
webnotes.conn.sql("""delete from `tabGL Entry`""")
|
||||||
|
|
||||||
|
pro_bean = webnotes.bean(copy = test_records[0])
|
||||||
|
pro_bean.insert()
|
||||||
|
pro_bean.submit()
|
||||||
|
|
||||||
|
from stock.doctype.stock_entry.test_stock_entry import test_records as se_test_records
|
||||||
|
mr1 = webnotes.bean(copy = se_test_records[0])
|
||||||
|
mr1.insert()
|
||||||
|
mr1.submit()
|
||||||
|
|
||||||
|
mr2 = webnotes.bean(copy = se_test_records[0])
|
||||||
|
mr2.doclist[1].item_code = "_Test Item Home Desktop 100"
|
||||||
|
mr2.insert()
|
||||||
|
mr2.submit()
|
||||||
|
|
||||||
|
stock_entry = make_stock_entry(pro_bean.doc.name, "Manufacture/Repack")
|
||||||
|
stock_entry = webnotes.bean(stock_entry)
|
||||||
|
|
||||||
|
stock_entry.doc.fg_completed_qty = 4
|
||||||
|
stock_entry.run_method("get_items")
|
||||||
|
stock_entry.submit()
|
||||||
|
|
||||||
|
self.assertEqual(webnotes.conn.get_value("Production Order", pro_bean.doc.name,
|
||||||
|
"produced_qty"), 4)
|
||||||
|
self.assertEqual(webnotes.conn.get_value("Bin", {"item_code": "_Test FG Item",
|
||||||
|
"warehouse": "_Test Warehouse 1 - _TC"}, "planned_qty"), 6)
|
||||||
|
|
||||||
|
return pro_bean.doc.name
|
||||||
|
|
||||||
|
def test_over_production(self):
|
||||||
|
from stock.doctype.stock_entry.stock_entry import StockOverProductionError
|
||||||
|
pro_order = self.test_planned_qty()
|
||||||
|
|
||||||
|
stock_entry = make_stock_entry(pro_order, "Manufacture/Repack")
|
||||||
|
stock_entry = webnotes.bean(stock_entry)
|
||||||
|
|
||||||
|
stock_entry.doc.fg_completed_qty = 15
|
||||||
|
stock_entry.run_method("get_items")
|
||||||
|
stock_entry.insert()
|
||||||
|
|
||||||
|
self.assertRaises(StockOverProductionError, stock_entry.submit)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
test_records = [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"bom_no": "BOM/_Test FG Item/001",
|
||||||
|
"company": "_Test Company",
|
||||||
|
"doctype": "Production Order",
|
||||||
|
"production_item": "_Test FG Item",
|
||||||
|
"qty": 10.0,
|
||||||
|
"fg_warehouse": "_Test Warehouse 1 - _TC",
|
||||||
|
"wip_warehouse": "_Test Warehouse - _TC",
|
||||||
|
"stock_uom": "Nos"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
@ -9,7 +9,6 @@ from webnotes.model.bean import getlist
|
|||||||
from webnotes.model.code import get_obj
|
from webnotes.model.code import get_obj
|
||||||
from webnotes import msgprint, _
|
from webnotes import msgprint, _
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
class DocType:
|
class DocType:
|
||||||
def __init__(self, doc, doclist=[]):
|
def __init__(self, doc, doclist=[]):
|
||||||
@ -19,7 +18,7 @@ class DocType:
|
|||||||
|
|
||||||
def get_so_details(self, so):
|
def get_so_details(self, so):
|
||||||
"""Pull other details from so"""
|
"""Pull other details from so"""
|
||||||
so = sql("""select transaction_date, customer, grand_total
|
so = webnotes.conn.sql("""select transaction_date, customer, grand_total
|
||||||
from `tabSales Order` where name = %s""", so, as_dict = 1)
|
from `tabSales Order` where name = %s""", so, as_dict = 1)
|
||||||
ret = {
|
ret = {
|
||||||
'sales_order_date': so and so[0]['transaction_date'] or '',
|
'sales_order_date': so and so[0]['transaction_date'] or '',
|
||||||
@ -31,7 +30,7 @@ class DocType:
|
|||||||
def get_item_details(self, item_code):
|
def get_item_details(self, item_code):
|
||||||
""" Pull other item details from item master"""
|
""" Pull other item details from item master"""
|
||||||
|
|
||||||
item = sql("""select description, stock_uom, default_bom
|
item = webnotes.conn.sql("""select description, stock_uom, default_bom
|
||||||
from `tabItem` where name = %s""", item_code, as_dict =1)
|
from `tabItem` where name = %s""", item_code, as_dict =1)
|
||||||
ret = {
|
ret = {
|
||||||
'description' : item and item[0]['description'],
|
'description' : item and item[0]['description'],
|
||||||
@ -63,7 +62,7 @@ class DocType:
|
|||||||
if self.doc.fg_item:
|
if self.doc.fg_item:
|
||||||
item_filter += ' and item.name = "' + self.doc.fg_item + '"'
|
item_filter += ' and item.name = "' + self.doc.fg_item + '"'
|
||||||
|
|
||||||
open_so = sql("""
|
open_so = webnotes.conn.sql("""
|
||||||
select distinct so.name, so.transaction_date, so.customer, so.grand_total
|
select distinct so.name, so.transaction_date, so.customer, so.grand_total
|
||||||
from `tabSales Order` so, `tabSales Order Item` so_item
|
from `tabSales Order` so, `tabSales Order Item` so_item
|
||||||
where so_item.parent = so.name
|
where so_item.parent = so.name
|
||||||
@ -108,7 +107,7 @@ class DocType:
|
|||||||
msgprint("Please enter sales order in the above table")
|
msgprint("Please enter sales order in the above table")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
items = sql("""select distinct parent, item_code, reserved_warehouse,
|
items = webnotes.conn.sql("""select distinct parent, item_code, reserved_warehouse,
|
||||||
(qty - ifnull(delivered_qty, 0)) as pending_qty
|
(qty - ifnull(delivered_qty, 0)) as pending_qty
|
||||||
from `tabSales Order Item` so_item
|
from `tabSales Order Item` so_item
|
||||||
where parent in (%s) and docstatus = 1 and ifnull(qty, 0) > ifnull(delivered_qty, 0)
|
where parent in (%s) and docstatus = 1 and ifnull(qty, 0) > ifnull(delivered_qty, 0)
|
||||||
@ -117,7 +116,7 @@ class DocType:
|
|||||||
or ifnull(item.is_sub_contracted_item, 'No') = 'Yes'))""" % \
|
or ifnull(item.is_sub_contracted_item, 'No') = 'Yes'))""" % \
|
||||||
(", ".join(["%s"] * len(so_list))), tuple(so_list), as_dict=1)
|
(", ".join(["%s"] * len(so_list))), tuple(so_list), as_dict=1)
|
||||||
|
|
||||||
dnpi_items = sql("""select distinct dnpi.parent, dnpi.item_code, dnpi.warehouse as reserved_warhouse,
|
dnpi_items = webnotes.conn.sql("""select distinct dnpi.parent, dnpi.item_code, dnpi.warehouse as reserved_warhouse,
|
||||||
(((so_item.qty - ifnull(so_item.delivered_qty, 0)) * dnpi.qty) / so_item.qty)
|
(((so_item.qty - ifnull(so_item.delivered_qty, 0)) * dnpi.qty) / so_item.qty)
|
||||||
as pending_qty
|
as pending_qty
|
||||||
from `tabSales Order Item` so_item, `tabDelivery Note Packing Item` dnpi
|
from `tabSales Order Item` so_item, `tabDelivery Note Packing Item` dnpi
|
||||||
@ -136,7 +135,7 @@ class DocType:
|
|||||||
self.clear_item_table()
|
self.clear_item_table()
|
||||||
|
|
||||||
for p in items:
|
for p in items:
|
||||||
item_details = sql("""select description, stock_uom, default_bom
|
item_details = webnotes.conn.sql("""select description, stock_uom, default_bom
|
||||||
from tabItem where name=%s""", p['item_code'])
|
from tabItem where name=%s""", p['item_code'])
|
||||||
pi = addchild(self.doc, 'pp_details', 'Production Plan Item', self.doclist)
|
pi = addchild(self.doc, 'pp_details', 'Production Plan Item', self.doclist)
|
||||||
pi.sales_order = p['parent']
|
pi.sales_order = p['parent']
|
||||||
@ -162,7 +161,7 @@ class DocType:
|
|||||||
msgprint("Please enter bom no for item: %s at row no: %s" %
|
msgprint("Please enter bom no for item: %s at row no: %s" %
|
||||||
(d.item_code, d.idx), raise_exception=1)
|
(d.item_code, d.idx), raise_exception=1)
|
||||||
else:
|
else:
|
||||||
bom = sql("""select name from `tabBOM` where name = %s and item = %s
|
bom = webnotes.conn.sql("""select name from `tabBOM` where name = %s and item = %s
|
||||||
and docstatus = 1 and is_active = 1""",
|
and docstatus = 1 and is_active = 1""",
|
||||||
(d.bom_no, d.item_code), as_dict = 1)
|
(d.bom_no, d.item_code), as_dict = 1)
|
||||||
if not bom:
|
if not bom:
|
||||||
@ -216,14 +215,14 @@ class DocType:
|
|||||||
pro = webnotes.new_bean("Production Order")
|
pro = webnotes.new_bean("Production Order")
|
||||||
pro.doc.fields.update(items[key])
|
pro.doc.fields.update(items[key])
|
||||||
|
|
||||||
webnotes.mute_messages = True
|
webnotes.flags.mute_messages = True
|
||||||
try:
|
try:
|
||||||
pro.insert()
|
pro.insert()
|
||||||
pro_list.append(pro.doc.name)
|
pro_list.append(pro.doc.name)
|
||||||
except OverProductionError, e:
|
except OverProductionError, e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
webnotes.mute_messages = False
|
webnotes.flags.mute_messages = False
|
||||||
|
|
||||||
return pro_list
|
return pro_list
|
||||||
|
|
||||||
@ -243,7 +242,7 @@ class DocType:
|
|||||||
for bom in bom_dict:
|
for bom in bom_dict:
|
||||||
if self.doc.use_multi_level_bom:
|
if self.doc.use_multi_level_bom:
|
||||||
# get all raw materials with sub assembly childs
|
# get all raw materials with sub assembly childs
|
||||||
fl_bom_items = sql("""select fb.item_code,
|
fl_bom_items = webnotes.conn.sql("""select fb.item_code,
|
||||||
ifnull(sum(fb.qty_consumed_per_unit), 0)*%s as qty,
|
ifnull(sum(fb.qty_consumed_per_unit), 0)*%s as qty,
|
||||||
fb.description, fb.stock_uom, it.min_order_qty
|
fb.description, fb.stock_uom, it.min_order_qty
|
||||||
from `tabBOM Explosion Item` fb,`tabItem` it
|
from `tabBOM Explosion Item` fb,`tabItem` it
|
||||||
@ -254,7 +253,7 @@ class DocType:
|
|||||||
else:
|
else:
|
||||||
# Get all raw materials considering SA items as raw materials,
|
# Get all raw materials considering SA items as raw materials,
|
||||||
# so no childs of SA items
|
# so no childs of SA items
|
||||||
fl_bom_items = sql("""select bom_item.item_code,
|
fl_bom_items = webnotes.conn.sql("""select bom_item.item_code,
|
||||||
ifnull(sum(bom_item.qty_consumed_per_unit), 0) * %s,
|
ifnull(sum(bom_item.qty_consumed_per_unit), 0) * %s,
|
||||||
bom_item.description, bom_item.stock_uom, item.min_order_qty
|
bom_item.description, bom_item.stock_uom, item.min_order_qty
|
||||||
from `tabBOM Item` bom_item, tabItem item
|
from `tabBOM Item` bom_item, tabItem item
|
||||||
@ -274,7 +273,7 @@ class DocType:
|
|||||||
'Quantity Requested for Purchase', 'Ordered Qty', 'Actual Qty']]
|
'Quantity Requested for Purchase', 'Ordered Qty', 'Actual Qty']]
|
||||||
for d in self.item_dict:
|
for d in self.item_dict:
|
||||||
item_list.append([d, self.item_dict[d][1], self.item_dict[d][2], self.item_dict[d][0]])
|
item_list.append([d, self.item_dict[d][1], self.item_dict[d][2], self.item_dict[d][0]])
|
||||||
item_qty= sql("""select warehouse, indented_qty, ordered_qty, actual_qty
|
item_qty= webnotes.conn.sql("""select warehouse, indented_qty, ordered_qty, actual_qty
|
||||||
from `tabBin` where item_code = %s""", d)
|
from `tabBin` where item_code = %s""", d)
|
||||||
i_qty, o_qty, a_qty = 0, 0, 0
|
i_qty, o_qty, a_qty = 0, 0, 0
|
||||||
for w in item_qty:
|
for w in item_qty:
|
||||||
|
@ -8,7 +8,6 @@ from webnotes.utils import flt
|
|||||||
from webnotes.model import db_exists
|
from webnotes.model import db_exists
|
||||||
from webnotes.model.bean import copy_doclist
|
from webnotes.model.bean import copy_doclist
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -18,9 +17,9 @@ class DocType:
|
|||||||
self.doclist = doclist
|
self.doclist = doclist
|
||||||
|
|
||||||
def update_bom_operation(self):
|
def update_bom_operation(self):
|
||||||
bom_list = sql(" select DISTINCT parent from `tabBOM Operation` where workstation = '%s'" % self.doc.name)
|
bom_list = webnotes.conn.sql(" select DISTINCT parent from `tabBOM Operation` where workstation = '%s'" % self.doc.name)
|
||||||
for bom_no in bom_list:
|
for bom_no in bom_list:
|
||||||
sql("update `tabBOM Operation` set hour_rate = '%s' where parent = '%s' and workstation = '%s'"%( self.doc.hour_rate, bom_no[0], self.doc.name))
|
webnotes.conn.sql("update `tabBOM Operation` set hour_rate = '%s' where parent = '%s' and workstation = '%s'"%( self.doc.hour_rate, bom_no[0], self.doc.name))
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
webnotes.conn.set(self.doc, 'overhead', flt(self.doc.hour_rate_electricity) + flt(self.doc.hour_rate_consumable) + flt(self.doc.hour_rate_rent))
|
webnotes.conn.set(self.doc, 'overhead', flt(self.doc.hour_rate_electricity) + flt(self.doc.hour_rate_consumable) + flt(self.doc.hour_rate_rent))
|
||||||
|
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