[fix] [minor] perpetual inventory: account for each warehouse

This commit is contained in:
Nabin Hait
2013-09-17 10:21:20 +05:30
parent 87eb4b99a8
commit 7a75e10a61
18 changed files with 241 additions and 171 deletions

View File

@@ -32,10 +32,10 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) {
} else {
// credit days and type if customer or supplier
cur_frm.set_intro(null);
cur_frm.toggle_display(['credit_days', 'credit_limit', 'master_name'],
in_list(['Customer', 'Supplier'], doc.master_type));
// hide tax_rate
cur_frm.toggle_display(['credit_days', 'credit_limit'], in_list(['Customer', 'Supplier'],
doc.master_type));
cur_frm.cscript.master_type(doc, cdt, cdn);
cur_frm.cscript.account_type(doc, cdt, cdn);
// show / hide convert buttons
@@ -44,7 +44,10 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) {
}
cur_frm.cscript.master_type = function(doc, cdt, cdn) {
cur_frm.toggle_display(['credit_days', 'credit_limit', 'master_name'],
cur_frm.toggle_display(['credit_days', 'credit_limit'], in_list(['Customer', 'Supplier'],
doc.master_type));
cur_frm.toggle_display('master_name', doc.account_type=='Warehouse' ||
in_list(['Customer', 'Supplier'], doc.master_type));
}
@@ -58,10 +61,10 @@ cur_frm.add_fetch('parent_account', 'is_pl_account', 'is_pl_account');
// -----------------------------------------
cur_frm.cscript.account_type = function(doc, cdt, cdn) {
if(doc.group_or_ledger=='Ledger') {
cur_frm.toggle_display(['tax_rate'],
doc.account_type == 'Tax');
cur_frm.toggle_display(['master_type', 'master_name'],
cstr(doc.account_type)=='');
cur_frm.toggle_display(['tax_rate'], doc.account_type == 'Tax');
cur_frm.toggle_display('master_type', cstr(doc.account_type)=='');
cur_frm.toggle_display('master_name', doc.account_type=='Warehouse' ||
in_list(['Customer', 'Supplier'], doc.master_type));
}
}
@@ -109,11 +112,15 @@ cur_frm.cscript.convert_to_group = function(doc, cdt, cdn) {
}
cur_frm.fields_dict['master_name'].get_query = function(doc) {
if (doc.master_type) {
if (doc.master_type || doc.account_type=="Warehouse") {
var dt = doc.master_type || "Warehouse";
return {
doctype: doc.master_type,
doctype: dt,
query: "accounts.doctype.account.account.get_master_name",
filters: { "master_type": doc.master_type }
filters: {
"master_type": dt,
"company": doc.company
}
}
}
}

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import webnotes
from webnotes.utils import flt, fmt_money
from webnotes.utils import flt, fmt_money, cstr, cint
from webnotes import msgprint, _
sql = webnotes.conn.sql
@@ -16,13 +16,25 @@ class DocType:
self.nsm_parent_field = 'parent_account'
def autoname(self):
"""Append abbreviation to company on naming"""
self.doc.name = self.doc.account_name.strip() + ' - ' + \
webnotes.conn.get_value("Company", self.doc.company, "abbr")
def get_address(self):
address = webnotes.conn.get_value(self.doc.master_type, self.doc.master_name, "address")
return {'address': address}
return {
'address': webnotes.conn.get_value(self.doc.master_type,
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_master_name(self):
"""Remind to add master name"""
@@ -109,16 +121,26 @@ class DocType:
msgprint("Debit or Credit field is mandatory", raise_exception=1)
if not self.doc.is_pl_account:
msgprint("Is PL Account field is mandatory", raise_exception=1)
def validate_warehouse_account(self):
if not cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")):
return
if self.doc.account_type == "Warehouse":
old_warehouse = cstr(webnotes.conn.get_value("Account", self.doc.name, "master_name"))
if old_warehouse != cstr(self.doc.master_name):
if old_warehouse:
self.validate_warehouse(old_warehouse)
if self.doc.master_name:
self.validate_warehouse(self.doc.master_name)
else:
webnotes.throw(_("Master Name is mandatory if account type is Warehouse"))
def validate_warehouse(self, warehouse):
if webnotes.conn.get_value("Stock Ledger Entry", {"warehouse": warehouse}):
webnotes.throw(_("Stock transactions exist against warehouse ") + warehouse +
_(" .You can not assign / modify / remove Master Name"))
def validate(self):
self.validate_master_name()
self.validate_parent()
self.validate_duplicate_account()
self.validate_root_details()
self.validate_mandatory()
if not self.doc.parent_account:
self.doc.parent_account = ''
def update_nsm_model(self):
"""update lft, rgt indices for nested set model"""
@@ -198,9 +220,11 @@ class DocType:
return " - ".join(parts)
def get_master_name(doctype, txt, searchfield, start, page_len, filters):
return webnotes.conn.sql("""select name from `tab%s` where %s like %s
conditions = (" and company='%s'"% filters["company"]) if doctype == "Warehouse" else ""
return webnotes.conn.sql("""select name from `tab%s` where %s like %s %s
order by name limit %s, %s""" %
(filters["master_type"], searchfield, "%s", "%s", "%s"),
(filters["master_type"], searchfield, "%s", conditions, "%s", "%s"),
("%%%s%%" % txt, start, page_len), as_list=1)
def get_parent_account(doctype, txt, searchfield, start, page_len, filters):

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-01-30 12:49:46",
"docstatus": 0,
"modified": "2013-07-05 14:23:30",
"modified": "2013-09-16 12:21:10",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -162,7 +162,7 @@
"label": "Account Type",
"oldfieldname": "account_type",
"oldfieldtype": "Select",
"options": "\nFixed Asset Account\nBank or Cash\nExpense Account\nTax\nIncome Account\nChargeable",
"options": "\nFixed Asset Account\nBank or Cash\nExpense Account\nTax\nIncome Account\nChargeable\nWarehouse",
"permlevel": 0,
"search_index": 0
},

View File

@@ -13,5 +13,9 @@ class DocType:
self.doc, self.doclist = d, dl
def on_update(self):
for key in ["auto_accounting_for_stock"]:
webnotes.conn.set_default(key, self.doc.fields.get(key, ''))
webnotes.conn.set_default("auto_accounting_for_stock", self.doc.auto_accounting_for_stock)
if self.doc.auto_accounting_for_stock:
for wh in webnotes.conn.sql("select name from `tabWarehouse`"):
wh_bean = webnotes.bean("Warehouse", wh[0])
wh_bean.save()

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-06-24 15:49:57",
"docstatus": 0,
"modified": "2013-08-28 18:55:43",
"modified": "2013-09-16 14:24:39",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -44,7 +44,7 @@
"doctype": "DocField",
"fieldname": "auto_accounting_for_stock",
"fieldtype": "Check",
"label": "Make Accounting Entry For Every Stock Entry"
"label": "Make Accounting Entry For Every Stock Movement"
},
{
"description": "Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.",

View File

@@ -192,8 +192,6 @@ class DocType(SellingController):
pos = get_pos_settings(self.doc.company)
if pos:
self.doc.conversion_rate = flt(pos.conversion_rate)
if not for_validate:
self.doc.customer = pos.customer
self.set_customer_defaults()

View File

@@ -6,10 +6,12 @@ import unittest, json
from webnotes.utils import flt, cint
from webnotes.model.bean import DocstatusTransitionError, TimestampMismatchError
from accounts.utils import get_stock_and_account_difference
from stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
class TestSalesInvoice(unittest.TestCase):
def make(self):
w = webnotes.bean(copy=test_records[0])
w.doc.is_pos = 0
w.insert()
w.submit()
return w
@@ -93,7 +95,6 @@ class TestSalesInvoice(unittest.TestCase):
si.doclist[1].ref_rate = 1
si.doclist[2].export_rate = 3
si.doclist[2].ref_rate = 3
si.run_method("calculate_taxes_and_totals")
si.insert()
expected_values = {
@@ -259,6 +260,7 @@ class TestSalesInvoice(unittest.TestCase):
def test_payment(self):
w = self.make()
from accounts.doctype.journal_voucher.test_journal_voucher \
import test_records as jv_test_records
@@ -298,8 +300,8 @@ class TestSalesInvoice(unittest.TestCase):
"Batched for Billing")
def test_sales_invoice_gl_entry_without_aii(self):
webnotes.defaults.set_global_default("auto_accounting_for_stock", 0)
self.clear_stock_account_balance()
set_perpetual_inventory(0)
si = webnotes.bean(copy=test_records[1])
si.insert()
si.submit()
@@ -331,10 +333,8 @@ class TestSalesInvoice(unittest.TestCase):
self.assertFalse(gle)
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)
self.clear_stock_account_balance()
set_perpetual_inventory()
self._insert_purchase_receipt()
self._insert_pos_settings()
@@ -359,18 +359,19 @@ class TestSalesInvoice(unittest.TestCase):
["_Test Item", "_Test Warehouse - _TC", -1.0])
# check gl entries
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)
stock_in_hand = webnotes.conn.get_value("Account", {"master_name": "_Test Warehouse - _TC"})
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],
["_Test Account Stock In Hand - _TC", 0.0, 75.0],
[stock_in_hand, 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]
@@ -389,12 +390,13 @@ class TestSalesInvoice(unittest.TestCase):
self.assertFalse(gle)
self.assertFalse(get_stock_and_account_difference(["_Test Account Stock In Hand - _TC"]))
self.assertFalse(get_stock_and_account_difference([stock_in_hand]))
webnotes.defaults.set_global_default("auto_accounting_for_stock", 0)
set_perpetual_inventory(0)
def test_sales_invoice_gl_entry_with_aii_no_item_code(self):
webnotes.defaults.set_global_default("auto_accounting_for_stock", 1)
def test_sales_invoice_gl_entry_with_aii_no_item_code(self):
self.clear_stock_account_balance()
set_perpetual_inventory()
si_copy = webnotes.copy_doclist(test_records[1])
si_copy[1]["item_code"] = None
@@ -417,12 +419,12 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEquals(expected_values[i][0], gle.account)
self.assertEquals(expected_values[i][1], gle.debit)
self.assertEquals(expected_values[i][2], gle.credit)
webnotes.defaults.set_global_default("auto_accounting_for_stock", 0)
def test_sales_invoice_gl_entry_with_aii_non_stock_item(self):
webnotes.defaults.set_global_default("auto_accounting_for_stock", 1)
set_perpetual_inventory(0)
def test_sales_invoice_gl_entry_with_aii_non_stock_item(self):
self.clear_stock_account_balance()
set_perpetual_inventory()
si_copy = webnotes.copy_doclist(test_records[1])
si_copy[1]["item_code"] = "_Test Non Stock Item"
si = webnotes.bean(si_copy)
@@ -445,7 +447,7 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEquals(expected_values[i][1], gle.debit)
self.assertEquals(expected_values[i][2], gle.credit)
webnotes.defaults.set_global_default("auto_accounting_for_stock", 0)
set_perpetual_inventory(0)
def _insert_purchase_receipt(self):
from stock.doctype.purchase_receipt.test_purchase_receipt import test_records \