[fix] [minor] auto accounting for stock transactions

This commit is contained in:
Nabin Hait 2013-08-29 18:19:37 +05:30
parent d85d63bb81
commit bb77756069
18 changed files with 134 additions and 247 deletions

View File

@ -12,19 +12,6 @@ class DocType:
def __init__(self, d, dl):
self.doc, self.doclist = d, dl
def validate(self):
self.validate_auto_accounting_for_stock()
def validate_auto_accounting_for_stock(self):
if cint(self.doc.auto_accounting_for_stock) == 1:
previous_val = cint(webnotes.conn.get_value("Accounts Settings",
None, "auto_accounting_for_stock"))
if cint(self.doc.auto_accounting_for_stock) != previous_val:
from accounts.utils import validate_stock_and_account_balance, \
create_stock_in_hand_jv
validate_stock_and_account_balance()
create_stock_in_hand_jv(reverse=cint(self.doc.auto_accounting_for_stock) < previous_val)
def on_update(self):
for key in ["auto_accounting_for_stock"]:
webnotes.conn.set_default(key, self.doc.fields.get(key, ''))

View File

@ -32,6 +32,18 @@ class TestJournalVoucher(unittest.TestCase):
self.assertTrue(not webnotes.conn.sql("""select name from `tabJournal Voucher Detail`
where against_jv=%s""", jv_invoice.doc.name))
def test_jv_against_stock_account(self):
webnotes.defaults.set_global_default("auto_accounting_for_stock", 1)
jv = webnotes.bean(copy=test_records[0])
jv.doclist[1].account = "_Test Account Stock in Hand - _TC"
jv.insert()
from accounts.general_ledger import StockAccountInvalidTransaction
self.assertRaises(StockAccountInvalidTransaction, jv.submit)
webnotes.defaults.set_global_default("auto_accounting_for_stock", 0)
def test_monthly_budget_crossed_ignore(self):
webnotes.conn.set_value("Company", "_Test Company", "monthly_bgt_flag", "Ignore")

View File

@ -90,7 +90,6 @@ class DocType(SellingController):
get_obj('Authorization Control').validate_approving_authority(self.doc.doctype,
self.doc.company, self.doc.grand_total, self)
self.set_buying_amount()
self.check_prev_docstatus()
self.update_status_updater_args()

View File

@ -330,13 +330,12 @@ class TestSalesInvoice(unittest.TestCase):
self.assertFalse(gle)
def atest_pos_gl_entry_with_aii(self):
def test_pos_gl_entry_with_aii(self):
webnotes.conn.sql("delete from `tabStock Ledger Entry`")
webnotes.conn.sql("delete from `tabGL Entry`")
webnotes.conn.sql("delete from `tabBin`")
webnotes.defaults.set_global_default("auto_accounting_for_stock", 1)
old_default_company = webnotes.conn.get_default("company")
webnotes.conn.set_default("company", "_Test Company")
self._insert_purchase_receipt()
self._insert_pos_settings()
@ -360,20 +359,18 @@ class TestSalesInvoice(unittest.TestCase):
["_Test Item", "_Test Warehouse - _TC", -1.0])
# check gl entries
stock_in_hand_account = webnotes.conn.get_value("Company", "_Test Company",
"stock_in_hand_account")
gl_entries = webnotes.conn.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
order by account asc, debit asc""", si.doc.name, as_dict=1)
self.assertTrue(gl_entries)
expected_gl_entries = sorted([
[si.doc.debit_to, 630.0, 0.0],
[pos[1]["income_account"], 0.0, 500.0],
[pos[2]["account_head"], 0.0, 80.0],
[pos[3]["account_head"], 0.0, 50.0],
[stock_in_hand_account, 0.0, 75.0],
["_Test Account Stock In Hand - _TC", 0.0, 75.0],
[pos[1]["expense_account"], 75.0, 0.0],
[si.doc.debit_to, 0.0, 600.0],
["_Test Account Bank Account - _TC", 600.0, 0.0]
@ -383,6 +380,8 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEquals(expected_gl_entries[i][1], gle.debit)
self.assertEquals(expected_gl_entries[i][2], gle.credit)
# cancel
si.cancel()
gle = webnotes.conn.sql("""select * from `tabGL Entry`
@ -390,12 +389,11 @@ class TestSalesInvoice(unittest.TestCase):
self.assertFalse(gle)
self.assertFalse(get_stock_and_account_difference([si.doclist[1].warehouse]))
self.assertFalse(get_stock_and_account_difference(["_Test Account Stock In Hand - _TC"]))
webnotes.defaults.set_global_default("auto_accounting_for_stock", 0)
webnotes.conn.set_default("company", old_default_company)
def atest_sales_invoice_gl_entry_with_aii_no_item_code(self):
def test_sales_invoice_gl_entry_with_aii_no_item_code(self):
webnotes.defaults.set_global_default("auto_accounting_for_stock", 1)
si_copy = webnotes.copy_doclist(test_records[1])
@ -422,7 +420,7 @@ class TestSalesInvoice(unittest.TestCase):
webnotes.defaults.set_global_default("auto_accounting_for_stock", 0)
def atest_sales_invoice_gl_entry_with_aii_non_stock_item(self):
def test_sales_invoice_gl_entry_with_aii_non_stock_item(self):
webnotes.defaults.set_global_default("auto_accounting_for_stock", 1)
si_copy = webnotes.copy_doclist(test_records[1])
@ -641,7 +639,7 @@ class TestSalesInvoice(unittest.TestCase):
return new_si
# if yearly, test 3 repetitions, else test 13 repetitions
count = no_of_months == 12 and 3 or 13
count = 3 if no_of_months == 12 else 13
for i in xrange(count):
base_si = _test(i)

View File

@ -2,7 +2,7 @@
{
"creation": "2013-06-04 11:02:19",
"docstatus": 0,
"modified": "2013-07-25 16:32:10",
"modified": "2013-08-29 16:58:56",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -416,17 +416,6 @@
"print_hide": 1,
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "buying_amount",
"fieldtype": "Currency",
"hidden": 1,
"label": "Buying Amount",
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1
},
{
"allow_on_submit": 1,
"doctype": "DocField",

View File

@ -5,8 +5,12 @@ from __future__ import unicode_literals
import webnotes
from webnotes.utils import flt, cstr, now
from webnotes.model.doc import Document
from webnotes import msgprint, _
from accounts.utils import validate_expense_against_budget
class StockAccountInvalidTransaction(webnotes.ValidationError): pass
def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True,
update_outstanding='Yes'):
if gl_map:
@ -47,8 +51,8 @@ def merge_similar_entries(gl_map):
merged_gl_map = filter(lambda x: flt(x.debit)!=0 or flt(x.credit)!=0, merged_gl_map)
return merged_gl_map
def check_if_in_list(gle, gl_mqp):
for e in gl_mqp:
def check_if_in_list(gle, gl_map):
for e in gl_map:
if e.account == gle.account and \
cstr(e.get('against_voucher'))==cstr(gle.get('against_voucher')) \
and cstr(e.get('against_voucher_type')) == \
@ -57,11 +61,14 @@ def check_if_in_list(gle, gl_mqp):
return e
def save_entries(gl_map, adv_adj, update_outstanding):
validate_account_for_auto_accounting_for_stock(gl_map)
total_debit = total_credit = 0.0
for entry in gl_map:
make_entry(entry, adv_adj, update_outstanding)
# check against budget
validate_expense_against_budget(entry)
# update total debit / credit
total_debit += flt(entry.debit)
@ -79,8 +86,20 @@ def make_entry(args, adv_adj, update_outstanding):
def validate_total_debit_credit(total_debit, total_credit):
if abs(total_debit - total_credit) > 0.005:
webnotes.throw(webnotes._("Debit and Credit not equal for this voucher: Diff (Debit) is ") +
webnotes.throw(_("Debit and Credit not equal for this voucher: Diff (Debit) is ") +
cstr(total_debit - total_credit))
def validate_account_for_auto_accounting_for_stock(gl_map):
if gl_map[0].voucher_type=="Journal Voucher":
aii_accounts = [d[0] for d in webnotes.conn.sql("""select account from tabWarehouse
where ifnull(account, '')!=''""")]
for entry in gl_map:
if entry.account in aii_accounts:
webnotes.throw(_("Account") + ": " + entry.account +
_(" can only be debited/credited through Stock transactions"),
StockAccountInvalidTransaction)
def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
adv_adj=False, update_outstanding="Yes"):

View File

@ -246,79 +246,6 @@ def get_company_default(company, fieldname):
_("' in Company: ") + company), raise_exception=True)
return value
def create_stock_in_hand_jv(reverse=False):
from webnotes.utils import nowdate
today = nowdate()
fiscal_year = get_fiscal_year(today)[0]
jv_list = []
for company in webnotes.conn.sql_list("select name from `tabCompany`"):
stock_rbnb_value = get_stock_rbnb_value(company)
stock_rbnb_value = reverse and -1*stock_rbnb_value or stock_rbnb_value
if stock_rbnb_value:
jv = webnotes.bean([
{
"doctype": "Journal Voucher",
"naming_series": "JV-AUTO-",
"company": company,
"posting_date": today,
"fiscal_year": fiscal_year,
"voucher_type": "Journal Entry",
"user_remark": (_("Perpetual Accounting") + ": " +
(_("Disabled") if reverse else _("Enabled")) + ". " +
_("Journal Entry for inventory that is received but not yet invoiced"))
},
{
"doctype": "Journal Voucher Detail",
"parentfield": "entries",
"account": get_company_default(company, "stock_received_but_not_billed"),
(stock_rbnb_value > 0 and "credit" or "debit"): abs(stock_rbnb_value)
},
{
"doctype": "Journal Voucher Detail",
"parentfield": "entries",
"account": get_company_default(company, "stock_adjustment_account"),
(stock_rbnb_value > 0 and "debit" or "credit"): abs(stock_rbnb_value),
"cost_center": get_company_default(company, "stock_adjustment_cost_center")
},
])
jv.insert()
jv_list.append(jv.doc.name)
if jv_list:
msgprint(_("Following Journal Vouchers have been created automatically") + \
":\n%s" % ("\n".join([("<a href=\"#Form/Journal Voucher/%s\">%s</a>" % (jv, jv)) for jv in jv_list]),))
msgprint(_("""These adjustment vouchers book the difference between \
the total value of received items and the total value of invoiced items, \
as a required step to use Perpetual Accounting.
This is an approximation to get you started.
You will need to submit these vouchers after checking if the values are correct.
For more details, read: \
<a href="http://erpnext.com/auto-inventory-accounting" target="_blank">\
Perpetual Accounting</a>"""))
webnotes.msgprint("""Please refresh the system to get effect of Perpetual Accounting""")
def get_stock_rbnb_value(company):
total_received_amount = webnotes.conn.sql("""select sum(valuation_rate*qty*conversion_factor)
from `tabPurchase Receipt Item` pr_item where docstatus=1
and exists(select name from `tabItem` where name = pr_item.item_code
and is_stock_item='Yes')
and exists(select name from `tabPurchase Receipt`
where name = pr_item.parent and company = %s)""", company)
total_billed_amount = webnotes.conn.sql("""select sum(valuation_rate*qty*conversion_factor)
from `tabPurchase Invoice Item` pi_item where docstatus=1
and exists(select name from `tabItem` where name = pi_item.item_code
and is_stock_item='Yes')
and exists(select name from `tabPurchase Invoice`
where name = pi_item.parent and company = %s)""", company)
return flt(total_received_amount[0][0]) - flt(total_billed_amount[0][0])
def fix_total_debit_credit():
vouchers = webnotes.conn.sql("""select voucher_type, voucher_no,
@ -335,14 +262,6 @@ def fix_total_debit_credit():
where voucher_type = %s and voucher_no = %s and %s > 0 limit 1""" %
(dr_or_cr, dr_or_cr, '%s', '%s', '%s', dr_or_cr),
(d.diff, d.voucher_type, d.voucher_no))
def validate_stock_and_account_balance():
difference = get_stock_and_account_difference()
if difference:
msgprint(_("Account balance must be synced with stock balance, \
to enable perpetual accounting." +
_(" Following accounts are not synced with stock balance") + ": \n" +
"\n".join(difference.keys())), raise_exception=1)
def get_stock_and_account_difference(account_list=None, posting_date=None):
from stock.utils import get_stock_balance_on

View File

@ -83,29 +83,6 @@ class SellingController(StockController):
if self.meta.get_field("in_words_export"):
self.doc.in_words_export = money_in_words(disable_rounded_total and
self.doc.grand_total_export or self.doc.rounded_total_export, self.doc.currency)
def set_buying_amount(self, stock_ledger_entries = None):
from stock.utils import get_buying_amount
if not stock_ledger_entries:
stock_ledger_entries = self.get_stock_ledger_entries()
item_sales_bom = {}
for d in self.doclist.get({"parentfield": "packing_details"}):
new_d = webnotes._dict(d.fields.copy())
new_d.total_qty = -1 * d.qty
item_sales_bom.setdefault(d.parent_item, []).append(new_d)
if stock_ledger_entries:
stock_items = self.get_stock_items()
for item in self.doclist.get({"parentfield": self.fname}):
if item.item_code in stock_items or \
(item_sales_bom and item_sales_bom.get(item.item_code)):
buying_amount = get_buying_amount(item.item_code, self.doc.doctype, self.doc.name, item.name,
stock_ledger_entries.get((item.item_code, item.warehouse), []),
item_sales_bom)
item.buying_amount = buying_amount >= 0.01 and buying_amount or 0
webnotes.conn.set_value(item.doctype, item.name, "buying_amount",
item.buying_amount)
def calculate_taxes_and_totals(self):
self.other_fname = "other_charges"

View File

@ -1,33 +0,0 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
# License: GNU General Public License v3. See license.txt
import webnotes
from webnotes.utils import now_datetime
def execute():
webnotes.reload_doc("stock", "doctype", "delivery_note_item")
webnotes.reload_doc("accounts", "doctype", "sales_invoice_item")
webnotes.conn.auto_commit_on_many_writes = True
for company in webnotes.conn.sql("select name from `tabCompany`"):
stock_ledger_entries = webnotes.conn.sql("""select item_code, voucher_type, voucher_no,
voucher_detail_no, posting_date, posting_time, stock_value,
warehouse, actual_qty as qty from `tabStock Ledger Entry`
where ifnull(`is_cancelled`, "No") = "No" and company = %s
order by item_code desc, warehouse desc,
posting_date desc, posting_time desc, name desc""", company[0], as_dict=True)
dn_list = webnotes.conn.sql("""select name from `tabDelivery Note`
where docstatus < 2 and company = %s""", company[0])
for dn in dn_list:
dn = webnotes.get_obj("Delivery Note", dn[0], with_children = 1)
dn.set_buying_amount(stock_ledger_entries)
si_list = webnotes.conn.sql("""select name from `tabSales Invoice`
where docstatus < 2 and company = %s""", company[0])
for si in si_list:
si = webnotes.get_obj("Sales Invoice", si[0], with_children = 1)
si.set_buying_amount(stock_ledger_entries)
webnotes.conn.auto_commit_on_many_writes = False

View File

@ -186,7 +186,6 @@ class DocType(SellingController):
self.credit_limit()
self.set_buying_amount()
self.make_gl_entries()
# set DN status

View File

@ -2,7 +2,7 @@
{
"creation": "2013-04-22 13:15:44",
"docstatus": 0,
"modified": "2013-08-07 14:45:30",
"modified": "2013-08-29 16:58:16",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -420,17 +420,6 @@
"print_hide": 1,
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "buying_amount",
"fieldtype": "Currency",
"hidden": 1,
"label": "Buying Amount",
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1
},
{
"allow_on_submit": 1,
"doctype": "DocField",

View File

@ -7,10 +7,7 @@ from webnotes.utils import cint, cstr, flt
from webnotes.model.doc import addchild
from webnotes.model.bean import getlist
from webnotes.model.code import get_obj
from webnotes import msgprint
sql = webnotes.conn.sql
from webnotes import msgprint, _
class DocType:
def __init__(self, doc, doclist=[]):
@ -18,47 +15,66 @@ class DocType:
self.doclist = doclist
self.prwise_cost = {}
def check_mandatory(self):
""" Check mandatory fields """
if not self.doc.from_pr_date or not self.doc.to_pr_date:
msgprint("Please enter From and To PR Date", raise_exception=1)
webnotes.throw(_("Please enter From and To PR Date"))
if not self.doc.currency:
msgprint("Please enter Currency.", raise_exception=1)
webnotes.throw(_("Please enter Currency"))
def update_landed_cost(self):
"""
Add extra cost and recalculate all values in pr,
Recalculate valuation rate in all sle after pr posting date
"""
self.get_selected_pr()
self.validate_selected_pr()
self.add_charges_in_pr()
self.cal_charges_and_item_tax_amt()
self.update_sle()
msgprint("Landed Cost updated successfully")
def get_selected_pr(self):
""" Get selected purchase receipt no """
self.selected_pr = [d.purchase_receipt for d in \
self.doclist.get({"parentfield": "lc_pr_details"}) if d.select_pr]
if not self.selected_pr:
webnotes.throw(_("Please select atleast one PR to proceed."))
def get_purchase_receipts(self):
""" Get purchase receipts for given period """
self.doclist = self.doc.clear_table(self.doclist,'lc_pr_details',1)
self.doclist = self.doc.clear_table(self.doclist,'lc_pr_details')
self.check_mandatory()
pr = sql("select name from `tabPurchase Receipt` where docstatus = 1 and posting_date >= '%s' and posting_date <= '%s' and currency = '%s' order by name " % (self.doc.from_pr_date, self.doc.to_pr_date, self.doc.currency), as_dict = 1)
if len(pr)>200:
msgprint("Please enter date of shorter duration as there are too many purchase receipt, hence it cannot be loaded.", raise_exception=1)
pr = webnotes.conn.sql("""select name from `tabPurchase Receipt` where docstatus = 1
and posting_date>=%s and posting_date<=%s and currency=%s order by name """,
(self.doc.from_pr_date, self.doc.to_pr_date, self.doc.currency), as_dict = 1)
if len(pr) > 200:
webnotes.throw(_("Please enter date of shorter duration as there are too many \
purchase receipt, hence it cannot be loaded."))
for i in pr:
ch = addchild(self.doc, 'lc_pr_details', 'Landed Cost Purchase Receipt',
self.doclist)
ch.purchase_receipt = i and i['name'] or ''
ch.save()
def get_selected_pr(self):
""" Get selected purchase receipt no """
self.selected_pr = [d.purchase_receipt for d in getlist(self.doclist, 'lc_pr_details') if d.select_pr]
if not self.selected_pr:
msgprint("Please select atleast one PR to proceed.", raise_exception=1)
ch.purchase_receipt = i.name
def validate_selected_pr(self):
"""Validate selected PR as submitted"""
invalid_pr = sql("SELECT name FROM `tabPurchase Receipt` WHERE docstatus != 1 and name in (%s)" % ("'" + "', '".join(self.selected_pr) + "'"))
invalid_pr = webnotes.conn.sql("""SELECT name FROM `tabPurchase Receipt`
WHERE docstatus!=1 and name in (%s)""" %
', '.join(['%s']*len(self.selected_pr)), tuple(self.selected_pr))
if invalid_pr:
msgprint("Selected purchase receipts must be submitted. Following PR are not submitted: %s" % invalid_pr, raise_exception=1)
webnotes.throw(_("Selected purchase receipts must be submitted. \
Following PR are not submitted") + ": " + invalid_pr)
def get_total_amt(self):
""" Get sum of net total of all selected PR"""
return sql("SELECT SUM(net_total) FROM `tabPurchase Receipt` WHERE name in (%s)" % ("'" + "', '".join(self.selected_pr) + "'"))[0][0]
return webnotes.conn.sql("""SELECT SUM(net_total) FROM `tabPurchase Receipt`
WHERE name in (%s)""" % ', '.join(['%s']*len(self.selected_pr)),
tuple(self.selected_pr))[0][0]
def add_charges_in_pr(self):
@ -74,7 +90,9 @@ class DocType:
self.prwise_cost[pr] = self.prwise_cost.get(pr, 0) + amt
cumulative_grand_total += amt
pr_oc_row = sql("select name from `tabPurchase Taxes and Charges` where parent = %s and category = 'Valuation' and add_deduct_tax = 'Add' and charge_type = 'Actual' and account_head = %s",(pr, lc.account_head))
pr_oc_row = webnotes.conn.sql("""select name from `tabPurchase Taxes and Charges`
where parent = %s and category = 'Valuation' and add_deduct_tax = 'Add'
and charge_type = 'Actual' and account_head = %s""",(pr, lc.account_head))
if not pr_oc_row: # add if not exists
ch = addchild(pr_obj.doc, 'purchase_tax_details', 'Purchase Taxes and Charges')
ch.category = 'Valuation'
@ -89,7 +107,9 @@ class DocType:
ch.idx = 500 # add at the end
ch.save(1)
else: # overwrite if exists
sql("update `tabPurchase Taxes and Charges` set rate = %s, tax_amount = %s where name = %s and parent = %s ", (amt, amt, pr_oc_row[0][0], pr))
webnotes.conn.sql("""update `tabPurchase Taxes and Charges`
set rate = %s, tax_amount = %s where name = %s and parent = %s""",
(amt, amt, pr_oc_row[0][0], pr))
def reset_other_charges(self, pr_obj):
@ -201,9 +221,9 @@ class DocType:
d.save()
if d.serial_no:
self.update_serial_no(d.serial_no, d.valuation_rate)
sql("update `tabStock Ledger Entry` set incoming_rate = '%s' where voucher_detail_no = '%s'"%(flt(d.valuation_rate), d.name))
webnotes.conn.sql("update `tabStock Ledger Entry` set incoming_rate = '%s' where voucher_detail_no = '%s'"%(flt(d.valuation_rate), d.name))
res = sql("""select item_code, warehouse, posting_date, posting_time
res = webnotes.conn.sql("""select item_code, warehouse, posting_date, posting_time
from `tabStock Ledger Entry` where voucher_detail_no = %s LIMIT 1""",
d.name, as_dict=1)
@ -211,22 +231,9 @@ class DocType:
if res:
update_entries_after(res[0])
def update_serial_no(self, sr_no, rate):
""" update valuation rate in serial no"""
sr_no = map(lambda x: x.strip(), cstr(sr_no).split('\n'))
webnotes.conn.sql("""update `tabSerial No` set purchase_rate = %s where name in (%s)""" %
('%s', ', '.join(['%s']*len(sr_no))), tuple([rate] + sr_no))
def update_landed_cost(self):
"""
Add extra cost and recalculate all values in pr,
Recalculate valuation rate in all sle after pr posting date
"""
self.get_selected_pr()
self.validate_selected_pr()
self.add_charges_in_pr()
self.cal_charges_and_item_tax_amt()
self.update_sle()
msgprint("Landed Cost updated successfully")
('%s', ', '.join(['%s']*len(sr_no))), tuple([rate] + sr_no))

View File

@ -39,9 +39,9 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
};
if(cint(wn.defaults.get_default("auto_accounting_for_stock"))) {
this.frm.add_fetch("company", "stock_adjustment_account", "expense_adjustment_account");
this.frm.fields_dict["expense_adjustment_account"].get_query = function() {
this.frm.add_fetch("company", "stock_adjustment_account", "expense_account");
this.frm.fields_dict.mtn_details.grid.get_field('expense_account').get_query =
function() {
return {
filters: {
"company": me.frm.doc.company,
@ -88,7 +88,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
set_default_account: function() {
var me = this;
if (cint(wn.defaults.get_default("auto_inventory_accounting")) && !this.frm.doc.expense_adjustment_account) {
if(cint(wn.defaults.get_default("auto_accounting_for_stock")) {
var account_for = "stock_adjustment_account";
if (this.frm.doc.purpose == "Sales Return")
account_for = "stock_in_hand_account";
@ -102,12 +102,22 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
"company": this.frm.doc.company
},
callback: function(r) {
if (!r.exc) me.frm.set_value("expense_adjustment_account", r.message);
if (!r.exc) {
for(d in getchildren('Stock Entry Detail',doc.name,'mtn_details')) {
if(!d.expense_account) d.expense_account = r.message;
}
}
}
});
}
},
entries_add: function(doc, cdt, cdn) {
var row = wn.model.get_doc(cdt, cdn);
this.frm.script_manager.copy_from_first_row("mtn_details", row,
["expense_account", "cost_center"]);
},
clean_up: function() {
// Clear Production Order record from locals, because it is updated via Stock Entry
if(this.frm.doc.production_order &&

View File

@ -2,7 +2,7 @@
{
"creation": "2013-03-29 18:22:12",
"docstatus": 0,
"modified": "2013-08-28 19:15:55",
"modified": "2013-08-28 19:25:38",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -149,7 +149,7 @@
"doctype": "DocField",
"fieldname": "expense_account",
"fieldtype": "Link",
"label": "Expense/Adjustment Account",
"label": "Difference Account",
"options": "Account",
"print_hide": 1
},

View File

@ -2,7 +2,7 @@
{
"creation": "2013-03-28 10:35:31",
"docstatus": 0,
"modified": "2013-08-07 18:16:18",
"modified": "2013-08-29 16:46:33",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -102,11 +102,11 @@
"reqd": 1
},
{
"depends_on": "eval:sys_defaults.auto_inventory_accounting",
"depends_on": "eval:sys_defaults.auto_accounting_for_stock",
"doctype": "DocField",
"fieldname": "expense_account",
"fieldtype": "Link",
"label": "Expense Account",
"label": "Difference Account",
"options": "Account"
},
{

View File

@ -22,7 +22,6 @@ cur_frm.set_query("account", function() {
filters: {
"company": cur_frm.doc.company,
"debit_or_credit": "Debit",
"is_pl_account": "No",
'group_or_ledger': "Ledger"
}
}

View File

@ -4,7 +4,7 @@
from __future__ import unicode_literals
import webnotes
from webnotes.utils import flt, validate_email_add
from webnotes.utils import cint, flt, validate_email_add
from webnotes.model.code import get_obj
from webnotes import msgprint
@ -23,6 +23,21 @@ class DocType:
def validate(self):
if self.doc.email_id and not validate_email_add(self.doc.email_id):
msgprint("Please enter valid Email Id", raise_exception=1)
self.account_mandatory()
def account_mandatory(self):
if cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")):
sle_exists = webnotes.conn.get_value("Stock Ledger Entry", {"warehouse": self.doc.name})
if not self.doc.account and (self.doc.__islocal or not sle_exists):
webnotes.throw(_("Asset/Expense Account mandatory"))
if not self.doc.__islocal and sle_exists:
old_account = webnotes.conn.get_value("Warehouse", self.doc.name, "account")
if old_account != self.doc.account:
webnotes.throw(_("Account can not be changed/assigned/removed as \
stock transactions exist for this warehouse"))
def merge_warehouses(self):
webnotes.conn.auto_commit_on_many_writes = 1

View File

@ -82,7 +82,7 @@ def update_entries_after(args, verbose=1):
valuation_method = get_valuation_method(args["item_code"])
stock_value_difference = 0.0
for sle in entries_to_fix:
if sle.serial_no or not cint(webnotes.conn.get_default("allow_negative_stock")):
# validate negative stock for serialized items, fifo valuation
@ -90,7 +90,7 @@ def update_entries_after(args, verbose=1):
if not validate_negative_stock(qty_after_transaction, sle):
qty_after_transaction += flt(sle.actual_qty)
continue
if sle.serial_no:
valuation_rate = get_serialized_values(qty_after_transaction, sle, valuation_rate)
elif valuation_method == "Moving Average":
@ -172,6 +172,7 @@ def get_stock_ledger_entries(args, conditions=None, order="desc", limit=None, fo
return webnotes.conn.sql("""select * from `tabStock Ledger Entry`
where item_code = %%(item_code)s
and warehouse = %%(warehouse)s
and ifnull(is_cancelled, 'No')='No'
%(conditions)s
order by timestamp(posting_date, posting_time) %(order)s, name %(order)s
%(limit)s %(for_update)s""" % {