[perpetual accounting] make gl entries relevant for different transactions
This commit is contained in:
parent
69f350a4d0
commit
43eba26dcf
@ -69,6 +69,7 @@ class DocType:
|
||||
def validate_posting_date(self):
|
||||
from accounts.utils import validate_fiscal_year
|
||||
validate_fiscal_year(self.doc.posting_date, self.doc.fiscal_year, "Posting Date")
|
||||
|
||||
|
||||
def check_credit_limit(self):
|
||||
master_type, master_name = webnotes.conn.get_value("Account",
|
||||
|
@ -33,7 +33,7 @@ class DocType:
|
||||
def validate(self):
|
||||
self.check_for_duplicate()
|
||||
self.validate_expense_account()
|
||||
|
||||
|
||||
def check_for_duplicate(self):
|
||||
res = webnotes.conn.sql("""select name, user from `tabPOS Setting`
|
||||
where ifnull(user, '') = %s and name != %s and company = %s""",
|
||||
@ -47,6 +47,6 @@ class DocType:
|
||||
(res[0][0], self.doc.company), raise_exception=1)
|
||||
|
||||
def validate_expense_account(self):
|
||||
if cint(webnotes.defaults.get_global_default("auto_inventory_accounting")) \
|
||||
if cint(webnotes.defaults.get_global_default("perpetual_accounting")) \
|
||||
and not self.doc.expense_account:
|
||||
msgprint(_("Expense Account is mandatory"), raise_exception=1)
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-05-24 12:15:51",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-08-01 16:50:05",
|
||||
"modified": "2013-08-05 16:51:22",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -163,7 +163,7 @@
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:sys_defaults.auto_inventory_accounting",
|
||||
"depends_on": "eval:sys_defaults.perpetual_accounting",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "expense_account",
|
||||
"fieldtype": "Link",
|
||||
|
@ -235,29 +235,29 @@ class DocType(BuyingController):
|
||||
raise Exception
|
||||
|
||||
def set_against_expense_account(self):
|
||||
auto_inventory_accounting = \
|
||||
cint(webnotes.defaults.get_global_default("auto_inventory_accounting"))
|
||||
perpetual_accounting = cint(webnotes.defaults.get_global_default("perpetual_accounting"))
|
||||
|
||||
if auto_inventory_accounting:
|
||||
if perpetual_accounting:
|
||||
stock_not_billed_account = self.get_company_default("stock_received_but_not_billed")
|
||||
|
||||
against_accounts = []
|
||||
stock_items = self.get_stock_items()
|
||||
for item in self.doclist.get({"parentfield": "entries"}):
|
||||
if auto_inventory_accounting and item.item_code in stock_items:
|
||||
if perpetual_accounting and item.item_code in stock_items:
|
||||
# in case of auto inventory accounting, against expense account is always
|
||||
# Stock Received But Not Billed for a stock item
|
||||
item.expense_head = item.cost_center = None
|
||||
item.expense_head = stock_not_billed_account
|
||||
item.cost_center = None
|
||||
|
||||
if stock_not_billed_account not in against_accounts:
|
||||
against_accounts.append(stock_not_billed_account)
|
||||
|
||||
elif not item.expense_head:
|
||||
msgprint(_("""Expense account is mandatory for item: """) + (item.item_code or item.item_name),
|
||||
raise_exception=1)
|
||||
msgprint(_("Expense account is mandatory for item") + ": " +
|
||||
(item.item_code or item.item_name), raise_exception=1)
|
||||
|
||||
elif item.expense_head not in against_accounts:
|
||||
# if no auto_inventory_accounting or not a stock item
|
||||
# if no perpetual_accounting or not a stock item
|
||||
against_accounts.append(item.expense_head)
|
||||
|
||||
self.doc.against_expense_account = ",".join(against_accounts)
|
||||
@ -340,9 +340,8 @@ class DocType(BuyingController):
|
||||
self.update_prevdoc_status()
|
||||
|
||||
def make_gl_entries(self):
|
||||
from accounts.general_ledger import make_gl_entries
|
||||
auto_inventory_accounting = \
|
||||
cint(webnotes.defaults.get_global_default("auto_inventory_accounting"))
|
||||
perpetual_accounting = \
|
||||
cint(webnotes.defaults.get_global_default("perpetual_accounting"))
|
||||
|
||||
gl_entries = []
|
||||
|
||||
@ -379,18 +378,15 @@ class DocType(BuyingController):
|
||||
valuation_tax += (tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.tax_amount)
|
||||
|
||||
# item gl entries
|
||||
stock_item_and_auto_inventory_accounting = False
|
||||
if auto_inventory_accounting:
|
||||
stock_account = self.get_company_default("stock_received_but_not_billed")
|
||||
|
||||
stock_item_and_perpetual_accounting = False
|
||||
stock_items = self.get_stock_items()
|
||||
for item in self.doclist.get({"parentfield": "entries"}):
|
||||
if auto_inventory_accounting and item.item_code in stock_items:
|
||||
if perpetual_accounting and item.item_code in stock_items:
|
||||
if flt(item.valuation_rate):
|
||||
# if auto inventory accounting enabled and stock item,
|
||||
# then do stock related gl entries
|
||||
# expense will be booked in sales invoice
|
||||
stock_item_and_auto_inventory_accounting = True
|
||||
stock_item_and_perpetual_accounting = True
|
||||
|
||||
valuation_amt = (flt(item.amount, self.precision("amount", item)) +
|
||||
flt(item.item_tax_amount, self.precision("item_tax_amount", item)) +
|
||||
@ -398,7 +394,7 @@ class DocType(BuyingController):
|
||||
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": stock_account,
|
||||
"account": item.expense_head,
|
||||
"against": self.doc.credit_to,
|
||||
"debit": valuation_amt,
|
||||
"remarks": self.doc.remarks or "Accounting Entry for Stock"
|
||||
@ -417,7 +413,7 @@ class DocType(BuyingController):
|
||||
})
|
||||
)
|
||||
|
||||
if stock_item_and_auto_inventory_accounting and valuation_tax:
|
||||
if stock_item_and_perpetual_accounting and valuation_tax:
|
||||
# credit valuation tax amount in "Expenses Included In Valuation"
|
||||
# this will balance out valuation amount included in cost of goods sold
|
||||
gl_entries.append(
|
||||
@ -444,6 +440,7 @@ class DocType(BuyingController):
|
||||
)
|
||||
|
||||
if gl_entries:
|
||||
from accounts.general_ledger import make_gl_entries
|
||||
make_gl_entries(gl_entries, cancel=(self.doc.docstatus == 2))
|
||||
|
||||
def on_cancel(self):
|
||||
|
@ -27,9 +27,9 @@ test_dependencies = ["Item", "Cost Center"]
|
||||
test_ignore = ["Serial No"]
|
||||
|
||||
class TestPurchaseInvoice(unittest.TestCase):
|
||||
def test_gl_entries_without_auto_inventory_accounting(self):
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
|
||||
self.assertTrue(not cint(webnotes.defaults.get_global_default("auto_inventory_accounting")))
|
||||
def test_gl_entries_without_perpetual_accounting(self):
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 0)
|
||||
self.assertTrue(not cint(webnotes.defaults.get_global_default("perpetual_accounting")))
|
||||
|
||||
wrapper = webnotes.bean(copy=test_records[0])
|
||||
wrapper.run_method("calculate_taxes_and_totals")
|
||||
@ -54,9 +54,9 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
for d in gl_entries:
|
||||
self.assertEqual([d.debit, d.credit], expected_gl_entries.get(d.account))
|
||||
|
||||
def test_gl_entries_with_auto_inventory_accounting(self):
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
|
||||
self.assertEqual(cint(webnotes.defaults.get_global_default("auto_inventory_accounting")), 1)
|
||||
def test_gl_entries_with_perpetual_accounting(self):
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 1)
|
||||
self.assertEqual(cint(webnotes.defaults.get_global_default("perpetual_accounting")), 1)
|
||||
|
||||
pi = webnotes.bean(copy=test_records[1])
|
||||
pi.run_method("calculate_taxes_and_totals")
|
||||
@ -81,11 +81,11 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
self.assertEquals(expected_values[i][1], gle.debit)
|
||||
self.assertEquals(expected_values[i][2], gle.credit)
|
||||
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 0)
|
||||
|
||||
def test_gl_entries_with_aia_for_non_stock_items(self):
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
|
||||
self.assertEqual(cint(webnotes.defaults.get_global_default("auto_inventory_accounting")), 1)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 1)
|
||||
self.assertEqual(cint(webnotes.defaults.get_global_default("perpetual_accounting")), 1)
|
||||
|
||||
pi = webnotes.bean(copy=test_records[1])
|
||||
pi.doclist[1].item_code = "_Test Non Stock Item"
|
||||
@ -112,7 +112,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
self.assertEquals(expected_values[i][1], gle.debit)
|
||||
self.assertEquals(expected_values[i][2], gle.credit)
|
||||
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 0)
|
||||
|
||||
def test_purchase_invoice_calculation(self):
|
||||
wrapper = webnotes.bean(copy=test_records[0])
|
||||
|
@ -332,7 +332,7 @@ cur_frm.set_query("income_account", "entries", function(doc) {
|
||||
});
|
||||
|
||||
// expense account
|
||||
if (sys_defaults.auto_inventory_accounting) {
|
||||
if (sys_defaults.perpetual_accounting) {
|
||||
cur_frm.fields_dict['entries'].grid.get_field('expense_account').get_query = function(doc) {
|
||||
return {
|
||||
filters: {
|
||||
|
@ -61,6 +61,8 @@ class DocType(SellingController):
|
||||
self.validate_proj_cust()
|
||||
self.validate_with_previous_doc()
|
||||
self.validate_uom_is_integer("stock_uom", "qty")
|
||||
self.validate_warehouse_with_company([d.warehouse
|
||||
for d in self.doclist.get({"parentfield": "entries"})])
|
||||
|
||||
sales_com_obj = get_obj('Sales Common')
|
||||
sales_com_obj.check_stop_sales_order(self)
|
||||
@ -586,6 +588,10 @@ class DocType(SellingController):
|
||||
make_gl_entries(gl_entries, cancel=(self.doc.docstatus == 2),
|
||||
update_outstanding=update_outstanding, merge_entries=False)
|
||||
|
||||
warehouse_list = list(set([d.warehouse for d in
|
||||
self.doclist.get({"parentfield": "entries"})]))
|
||||
self.sync_stock_account_balance(warehouse_list)
|
||||
|
||||
def make_customer_gl_entry(self, gl_entries):
|
||||
if self.doc.grand_total:
|
||||
gl_entries.append(
|
||||
@ -627,7 +633,7 @@ class DocType(SellingController):
|
||||
)
|
||||
|
||||
# expense account gl entries
|
||||
if cint(webnotes.defaults.get_global_default("auto_inventory_accounting")) \
|
||||
if cint(webnotes.defaults.get_global_default("perpetual_accounting")) \
|
||||
and cint(self.doc.update_stock):
|
||||
|
||||
for item in self.doclist.get({"parentfield": "entries"}):
|
||||
@ -635,7 +641,7 @@ class DocType(SellingController):
|
||||
|
||||
if item.buying_amount:
|
||||
gl_entries += self.get_gl_entries_for_stock(item.expense_account,
|
||||
-1*item.buying_amount, cost_center=item.cost_center)
|
||||
-1*item.buying_amount, item.warehouse, cost_center=item.cost_center)
|
||||
|
||||
def make_pos_gl_entries(self, gl_entries):
|
||||
if cint(self.doc.is_pos) and self.doc.cash_bank_account and self.doc.paid_amount:
|
||||
|
@ -294,7 +294,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
"Batched for Billing")
|
||||
|
||||
def test_sales_invoice_gl_entry_without_aii(self):
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 0)
|
||||
|
||||
si = webnotes.bean(copy=test_records[1])
|
||||
si.insert()
|
||||
@ -329,7 +329,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
|
||||
def atest_pos_gl_entry_with_aii(self):
|
||||
webnotes.conn.sql("delete from `tabStock Ledger Entry`")
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 1)
|
||||
|
||||
old_default_company = webnotes.conn.get_default("company")
|
||||
webnotes.conn.set_default("company", "_Test Company")
|
||||
@ -389,11 +389,11 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
|
||||
self.assertEquals(gl_count[0][0], 16)
|
||||
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 0)
|
||||
webnotes.conn.set_default("company", old_default_company)
|
||||
|
||||
def test_sales_invoice_gl_entry_with_aii_no_item_code(self):
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 1)
|
||||
|
||||
si_copy = webnotes.copy_doclist(test_records[1])
|
||||
si_copy[1]["item_code"] = None
|
||||
@ -417,10 +417,10 @@ 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_inventory_accounting", 0)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 0)
|
||||
|
||||
def test_sales_invoice_gl_entry_with_aii_non_stock_item(self):
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 1)
|
||||
|
||||
si_copy = webnotes.copy_doclist(test_records[1])
|
||||
si_copy[1]["item_code"] = "_Test Non Stock Item"
|
||||
@ -444,7 +444,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_inventory_accounting", 0)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 0)
|
||||
|
||||
def _insert_purchase_receipt(self):
|
||||
from stock.doctype.purchase_receipt.test_purchase_receipt import test_records \
|
||||
|
@ -34,7 +34,7 @@ class AccountsController(TransactionBase):
|
||||
self.set_total_in_words()
|
||||
|
||||
self.validate_for_freezed_account()
|
||||
|
||||
|
||||
def set_missing_values(self, for_validate=False):
|
||||
for fieldname in ["posting_date", "transaction_date"]:
|
||||
if not self.doc.fields.get(fieldname) and self.meta.get_field(fieldname):
|
||||
@ -410,7 +410,6 @@ class AccountsController(TransactionBase):
|
||||
def get_company_default(self, fieldname):
|
||||
from accounts.utils import get_company_default
|
||||
return get_company_default(self.doc.company, fieldname)
|
||||
|
||||
|
||||
def get_stock_items(self):
|
||||
stock_items = []
|
||||
|
@ -33,7 +33,7 @@ erpnext.stock.StockController = wn.ui.form.Controller.extend({
|
||||
},
|
||||
show_general_ledger: function() {
|
||||
var me = this;
|
||||
if(this.frm.doc.docstatus===1 && cint(wn.defaults.get_default("auto_inventory_accounting"))) {
|
||||
if(this.frm.doc.docstatus===1 && cint(wn.defaults.get_default("perpetual_accounting"))) {
|
||||
cur_frm.add_custom_button('Accounting Ledger', function() {
|
||||
wn.route_options = {
|
||||
"voucher_no": me.frm.doc.name,
|
||||
|
@ -72,18 +72,7 @@ cur_frm.fields_dict.receivables_group.get_query = function(doc) {
|
||||
}
|
||||
}
|
||||
|
||||
if (sys_defaults.auto_inventory_accounting) {
|
||||
cur_frm.fields_dict["stock_in_hand_account"].get_query = function(doc) {
|
||||
return {
|
||||
"filters": {
|
||||
"is_pl_account": "No",
|
||||
"debit_or_credit": "Debit",
|
||||
"company": doc.name,
|
||||
'group_or_ledger': "Ledger"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sys_defaults.perpetual_accounting) {
|
||||
cur_frm.fields_dict["stock_adjustment_account"].get_query = function(doc) {
|
||||
return {
|
||||
"filters": {
|
||||
@ -108,10 +97,4 @@ if (sys_defaults.auto_inventory_accounting) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.fields_dict["stock_adjustment_cost_center"].get_query = function(doc) {
|
||||
return {
|
||||
"filters": {"company": doc.name}
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-04-10 08:35:39",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-07-23 11:58:36",
|
||||
"modified": "2013-08-05 17:23:52",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -25,13 +25,20 @@
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
"name": "__common__",
|
||||
"parent": "Company",
|
||||
"parentfield": "permissions",
|
||||
"parenttype": "DocType",
|
||||
"permlevel": 0,
|
||||
"read": 1
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocType",
|
||||
@ -220,19 +227,9 @@
|
||||
{
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "auto_inventory_accounting_settings",
|
||||
"fieldname": "perpetual_accounting_settings",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Auto Inventory Accounting Settings",
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"description": "This account will be used to maintain value of available stock",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "stock_in_hand_account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Stock In Hand Account",
|
||||
"no_copy": 1,
|
||||
"options": "Account",
|
||||
"label": "Perpetual Accounting Settings",
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
@ -244,13 +241,6 @@
|
||||
"options": "Account",
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "col_break23",
|
||||
"fieldtype": "Column Break",
|
||||
"read_only": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "stock_adjustment_account",
|
||||
@ -269,15 +259,6 @@
|
||||
"options": "Account",
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "stock_adjustment_cost_center",
|
||||
"fieldtype": "Link",
|
||||
"label": "Stock Adjustment Cost Center",
|
||||
"no_copy": 1,
|
||||
"options": "Cost Center",
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"description": "For reference only.",
|
||||
"doctype": "DocField",
|
||||
@ -373,17 +354,6 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocPerm",
|
||||
"role": "All"
|
||||
"doctype": "DocPerm"
|
||||
}
|
||||
]
|
@ -119,8 +119,8 @@ class DocType:
|
||||
})
|
||||
global_defaults.save()
|
||||
|
||||
webnotes.conn.set_value("Accounts Settings", None, "auto_inventory_accounting", 1)
|
||||
webnotes.conn.set_default("auto_inventory_accounting", 1)
|
||||
webnotes.conn.set_value("Accounts Settings", None, "perpetual_accounting", 1)
|
||||
webnotes.conn.set_default("perpetual_accounting", 1)
|
||||
|
||||
stock_settings = webnotes.bean("Stock Settings")
|
||||
stock_settings.doc.item_naming_by = "Item Code"
|
||||
|
@ -46,8 +46,8 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend(
|
||||
|
||||
set_print_hide(doc, dt, dn);
|
||||
|
||||
// unhide expense_account and cost_center is auto_inventory_accounting enabled
|
||||
var aii_enabled = cint(sys_defaults.auto_inventory_accounting)
|
||||
// unhide expense_account and cost_center is perpetual_accounting enabled
|
||||
var aii_enabled = cint(sys_defaults.perpetual_accounting)
|
||||
cur_frm.fields_dict[cur_frm.cscript.fname].grid.set_column_disp(["expense_account", "cost_center"], aii_enabled);
|
||||
|
||||
if (this.frm.doc.docstatus===0) {
|
||||
@ -200,7 +200,7 @@ cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
|
||||
}
|
||||
}
|
||||
|
||||
if (sys_defaults.auto_inventory_accounting) {
|
||||
if (sys_defaults.perpetual_accounting) {
|
||||
|
||||
cur_frm.cscript.expense_account = function(doc, cdt, cdn){
|
||||
var d = locals[cdt][cdn];
|
||||
|
@ -107,6 +107,8 @@ class DocType(SellingController):
|
||||
self.validate_for_items()
|
||||
self.validate_warehouse()
|
||||
self.validate_uom_is_integer("stock_uom", "qty")
|
||||
self.validate_warehouse_with_company([d.warehouse
|
||||
for d in self.doclist.get({"parentfield": "delivery_note_details"})])
|
||||
|
||||
sales_com_obj.validate_max_discount(self, 'delivery_note_details')
|
||||
sales_com_obj.check_conversion_rate(self)
|
||||
@ -174,7 +176,7 @@ class DocType(SellingController):
|
||||
if not d['warehouse']:
|
||||
msgprint("Please enter Warehouse for item %s as it is stock item"
|
||||
% d['item_code'], raise_exception=1)
|
||||
|
||||
|
||||
|
||||
def update_current_stock(self):
|
||||
for d in getlist(self.doclist, 'delivery_note_details'):
|
||||
@ -332,32 +334,23 @@ class DocType(SellingController):
|
||||
if not cint(webnotes.defaults.get_global_default("perpetual_accounting")):
|
||||
return
|
||||
|
||||
gl_entries = []
|
||||
warehouse_item_map = {}
|
||||
gl_entries = []
|
||||
warehouse_list = []
|
||||
for item in self.doclist.get({"parentfield": "delivery_note_details"}):
|
||||
self.check_expense_account(item)
|
||||
warehouse_item_map.setdefault(item.warehouse, [])
|
||||
if item.item_code not in warehouse_item_map[item.warehouse]:
|
||||
warehouse_item_map[item.warehouse].append(item.item_code)
|
||||
|
||||
|
||||
|
||||
|
||||
if [item.item_code, item.warehouse] not in item_warehouse:
|
||||
item_warehouse.append([item.item_code, item.warehouse])
|
||||
|
||||
for
|
||||
|
||||
|
||||
|
||||
for wh, cc_dict in expense_account_map.items:
|
||||
for cost_center, warehouse_list in cc_dict.items():
|
||||
if item.buying_amount:
|
||||
gl_entries += self.get_gl_entries_for_stock(item.expense_account,
|
||||
cost_center=item.cost_center, warehouse_list=warehouse_list)
|
||||
-1*item.buying_amount, item.warehouse, cost_center=item.cost_center)
|
||||
if item.warehouse not in warehouse_list:
|
||||
warehouse_list.append(item.warehouse)
|
||||
|
||||
if gl_entries:
|
||||
from accounts.general_ledger import make_gl_entries
|
||||
make_gl_entries(gl_entries, cancel=(self.doc.docstatus == 2))
|
||||
|
||||
self.sync_stock_account_balance(warehouse_list)
|
||||
|
||||
|
||||
def get_invoiced_qty_map(delivery_note):
|
||||
"""returns a map: {dn_detail: invoiced_qty}"""
|
||||
|
@ -50,8 +50,8 @@ class TestDeliveryNote(unittest.TestCase):
|
||||
|
||||
def test_delivery_note_no_gl_entry(self):
|
||||
webnotes.conn.sql("""delete from `tabBin`""")
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
|
||||
self.assertEqual(cint(webnotes.defaults.get_global_default("auto_inventory_accounting")), 0)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 0)
|
||||
self.assertEqual(cint(webnotes.defaults.get_global_default("perpetual_accounting")), 0)
|
||||
|
||||
self._insert_purchase_receipt()
|
||||
|
||||
@ -69,8 +69,8 @@ class TestDeliveryNote(unittest.TestCase):
|
||||
webnotes.conn.sql("""delete from `tabBin`""")
|
||||
webnotes.conn.sql("delete from `tabStock Ledger Entry`")
|
||||
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
|
||||
self.assertEqual(cint(webnotes.defaults.get_global_default("auto_inventory_accounting")), 1)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 1)
|
||||
self.assertEqual(cint(webnotes.defaults.get_global_default("perpetual_accounting")), 1)
|
||||
|
||||
self._insert_purchase_receipt()
|
||||
|
||||
@ -106,7 +106,7 @@ class TestDeliveryNote(unittest.TestCase):
|
||||
bal = get_balance_on(stock_in_hand_account, dn.doc.posting_date)
|
||||
self.assertEquals(bal, prev_bal - 375.0)
|
||||
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 0)
|
||||
|
||||
test_records = [
|
||||
[
|
||||
|
@ -7,7 +7,7 @@ from webnotes.utils import flt
|
||||
|
||||
class TestMaterialRequest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 0)
|
||||
|
||||
def test_make_purchase_order(self):
|
||||
from stock.doctype.material_request.material_request import make_purchase_order
|
||||
|
@ -140,7 +140,10 @@ class DocType(BuyingController):
|
||||
self.validate_inspection()
|
||||
self.validate_uom_is_integer("uom", ["qty", "received_qty"])
|
||||
self.validate_uom_is_integer("stock_uom", "stock_qty")
|
||||
|
||||
self.validate_warehouse_with_company(reduce(lambda x,y: x+y,
|
||||
[[d.warehouse, d.rejected_warehouse] for d in
|
||||
self.doclist.get({"parentfield": "purchase_receipt_details"})]))
|
||||
|
||||
get_obj('Stock Ledger').validate_serial_no(self, 'purchase_receipt_details')
|
||||
self.validate_challan_no()
|
||||
|
||||
@ -319,25 +322,21 @@ class DocType(BuyingController):
|
||||
return
|
||||
|
||||
against_stock_account = self.get_company_default("stock_received_but_not_billed")
|
||||
warehouse_list = [d.warehouse for d in
|
||||
self.doclist.get({"parentfield": "purchase_receipt_details"})]
|
||||
|
||||
gl_entries = self.get_gl_entries_for_stock(against_stock_account, warehouse_list=warehouse_list)
|
||||
gl_entries = []
|
||||
warehouse_list = []
|
||||
for d in self.doclist.get({"parentfield": "purchase_receipt_details"}):
|
||||
if d.valuation_rate:
|
||||
gl_entries += self.get_gl_entries_for_stock(against_stock_account,
|
||||
d.valuation_rate, d.warehouse)
|
||||
|
||||
if d.warehouse not in warehouse_list:
|
||||
warehouse_list.append(d.warehouse)
|
||||
|
||||
if gl_entries:
|
||||
from accounts.general_ledger import make_gl_entries
|
||||
make_gl_entries(gl_entries, cancel=(self.doc.docstatus == 2))
|
||||
|
||||
def get_total_valuation_amount(self):
|
||||
total_valuation_amount = 0.0
|
||||
stock_items = self.get_stock_items()
|
||||
for item in self.doclist.get({"parentfield": "purchase_receipt_details"}):
|
||||
if item.item_code in stock_items:
|
||||
total_valuation_amount += flt(item.valuation_rate) * \
|
||||
flt(item.qty) * flt(item.conversion_factor)
|
||||
|
||||
return total_valuation_amount
|
||||
|
||||
|
||||
self.sync_stock_account_balance(warehouse_list)
|
||||
|
||||
@webnotes.whitelist()
|
||||
def make_purchase_invoice(source_name, target_doclist=None):
|
||||
|
@ -75,6 +75,8 @@ class DocType(StockController):
|
||||
self.make_gl_entries()
|
||||
|
||||
def make_stock_ledger_entry(self, qty):
|
||||
self.validate_warehouse_with_company([self.doc.warehouse])
|
||||
|
||||
sl_entries = [{
|
||||
'item_code' : self.doc.item_code,
|
||||
'warehouse' : self.doc.warehouse,
|
||||
@ -102,7 +104,7 @@ class DocType(StockController):
|
||||
webnotes.conn.set(self.doc, 'status', 'Not in Use')
|
||||
self.make_stock_ledger_entry(-1)
|
||||
|
||||
if cint(webnotes.defaults.get_global_default("auto_inventory_accounting")) \
|
||||
if cint(webnotes.defaults.get_global_default("perpetual_accounting")) \
|
||||
and webnotes.conn.sql("""select name from `tabGL Entry`
|
||||
where voucher_type=%s and voucher_no=%s and ifnull(is_cancelled, 'No')='No'""",
|
||||
(self.doc.doctype, self.doc.name)):
|
||||
@ -133,16 +135,24 @@ class DocType(StockController):
|
||||
('\n'.join(serial_nos), item[0]))
|
||||
|
||||
def make_gl_entries(self, cancel=False):
|
||||
if not cint(webnotes.defaults.get_global_default("auto_inventory_accounting")):
|
||||
if not cint(webnotes.defaults.get_global_default("perpetual_accounting")):
|
||||
return
|
||||
|
||||
from accounts.general_ledger import make_gl_entries
|
||||
against_stock_account = self.get_company_default("stock_adjustment_account")
|
||||
gl_entries = self.get_gl_entries_for_stock(against_stock_account, self.doc.purchase_rate)
|
||||
|
||||
for entry in gl_entries:
|
||||
entry["posting_date"] = self.doc.purchase_date or (self.doc.creation and
|
||||
self.doc.creation.split(' ')[0]) or nowdate()
|
||||
|
||||
if not self.doc.cost_center:
|
||||
msgprint(_("Please enter Cost Center"), raise_exception=1)
|
||||
|
||||
against_stock_account = self.get_company_default("stock_adjustment_account")
|
||||
gl_entries = self.get_gl_entries_for_stock(against_stock_account,
|
||||
self.doc.purchase_rate, self.doc.warehouse, cost_center=self.doc.cost_center)
|
||||
|
||||
posting_date = self.doc.purchase_date or (self.doc.creation and
|
||||
self.doc.creation.split(' ')[0]) or nowdate()
|
||||
|
||||
for entry in gl_entries:
|
||||
entry["posting_date"] = posting_date
|
||||
|
||||
if gl_entries:
|
||||
make_gl_entries(gl_entries, cancel)
|
||||
from accounts.general_ledger import make_gl_entries
|
||||
make_gl_entries(gl_entries, cancel)
|
||||
self.sync_stock_account_balance([self.doc.warehouse], self.doc.cost_center,
|
||||
posting_date)
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-05-16 10:59:15",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-07-22 15:29:43",
|
||||
"modified": "2013-08-05 17:35:10",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -150,6 +150,14 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:sys_defaults.perpetual_accounting",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "cost_center",
|
||||
"fieldtype": "Link",
|
||||
"label": "Cost Center",
|
||||
"options": "Cost Center"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "purchase_details",
|
||||
@ -520,6 +528,13 @@
|
||||
"read_only": 1,
|
||||
"report_hide": 1
|
||||
},
|
||||
{
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
"role": "System Manager",
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
|
@ -7,7 +7,6 @@ import webnotes, unittest
|
||||
class TestSerialNo(unittest.TestCase):
|
||||
def test_aii_gl_entries_for_serial_no_in_store(self):
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 1)
|
||||
|
||||
sr = webnotes.bean(copy=test_records[0])
|
||||
sr.doc.serial_no = "_Test Serial No 1"
|
||||
sr.insert()
|
||||
@ -96,7 +95,8 @@ test_records = [
|
||||
"purchase_rate": 1000.0,
|
||||
"purchase_time": "11:37:39",
|
||||
"purchase_date": "2013-02-26",
|
||||
'fiscal_year': "_Test Fiscal Year 2013"
|
||||
'fiscal_year': "_Test Fiscal Year 2013",
|
||||
"cost_center": "_Test Cost Center - _TC"
|
||||
}
|
||||
]
|
||||
]
|
@ -25,9 +25,9 @@ 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("perpetual_accounting")) && !this.frm.doc.expense_adjustment_account) {
|
||||
if (this.frm.doc.purpose == "Sales Return")
|
||||
account_for = "stock_in_hand_account";
|
||||
account_for = "default_expense_account";
|
||||
else if (this.frm.doc.purpose == "Purchase Return")
|
||||
account_for = "stock_received_but_not_billed";
|
||||
else account_for = "stock_adjustment_account";
|
||||
@ -78,7 +78,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
||||
}
|
||||
};
|
||||
|
||||
if(cint(wn.defaults.get_default("auto_inventory_accounting"))) {
|
||||
if(cint(wn.defaults.get_default("perpetual_accounting"))) {
|
||||
this.frm.add_fetch("company", "stock_adjustment_account", "expense_adjustment_account");
|
||||
|
||||
this.frm.fields_dict["expense_adjustment_account"].get_query = function() {
|
||||
|
@ -51,6 +51,9 @@ class DocType(StockController):
|
||||
self.validate_item()
|
||||
self.validate_uom_is_integer("uom", "qty")
|
||||
self.validate_uom_is_integer("stock_uom", "transfer_qty")
|
||||
self.validate_warehouse_with_company(reduce(lambda x,y: x+y,
|
||||
[[d.s_warehouse, d.t_warehouse] for d in
|
||||
self.doclist.get({"parentfield": "mtn_details"})]))
|
||||
|
||||
self.validate_warehouse(pro_obj)
|
||||
self.validate_production_order(pro_obj)
|
||||
@ -184,32 +187,41 @@ class DocType(StockController):
|
||||
self.doc.total_amount = sum([flt(item.amount) for item in self.doclist.get({"parentfield": "mtn_details"})])
|
||||
|
||||
def make_gl_entries(self):
|
||||
if not cint(webnotes.defaults.get_global_default("auto_inventory_accounting")):
|
||||
if not cint(webnotes.defaults.get_global_default("perpetual_accounting")):
|
||||
return
|
||||
|
||||
if not self.doc.expense_adjustment_account:
|
||||
webnotes.msgprint(_("Please enter Expense/Adjustment Account"), raise_exception=1)
|
||||
|
||||
from accounts.general_ledger import make_gl_entries
|
||||
|
||||
total_valuation_amount = self.get_total_valuation_amount()
|
||||
|
||||
gl_entries = self.get_gl_entries_for_stock(self.doc.expense_adjustment_account,
|
||||
total_valuation_amount)
|
||||
if gl_entries:
|
||||
make_gl_entries(gl_entries, cancel=self.doc.docstatus == 2)
|
||||
|
||||
def get_total_valuation_amount(self):
|
||||
total_valuation_amount = 0
|
||||
gl_entries = []
|
||||
warehouse_list = []
|
||||
against_expense_account = self.doc.expense_adjustment_account
|
||||
for item in self.doclist.get({"parentfield": "mtn_details"}):
|
||||
if item.t_warehouse and not item.s_warehouse:
|
||||
total_valuation_amount += flt(item.incoming_rate, 2) * flt(item.transfer_qty)
|
||||
valuation_amount = flt(item.incoming_rate) * flt(item.transfer_qty)
|
||||
if valuation_amount:
|
||||
if item.t_warehouse and not item.s_warehouse:
|
||||
warehouse = item.t_warehouse
|
||||
elif item.s_warehouse and not item.t_warehouse:
|
||||
warehouse = item.s_warehouse
|
||||
valuation_amount = -1*valuation_amount
|
||||
elif item.s_warehouse and item.t_warehouse:
|
||||
s_account = webnotes.con.get_value("Warehouse", item.s_warehouse, "account")
|
||||
t_account = webnotes.conn.get_value("Warehouse", item.t_warehouse, "account")
|
||||
if s_account != t_account:
|
||||
warehouse = item.s_warehouse
|
||||
against_expense_account = t_account
|
||||
|
||||
if item.s_warehouse and item.s_warehouse not in warehouse_list:
|
||||
warehouse_list.append(item.s_warehouse)
|
||||
if item.t_warehouse and item.t_warehouse not in warehouse_list:
|
||||
warehouse_list.append(item.t_warehouse)
|
||||
|
||||
gl_entries += self.get_gl_entries_for_stock(against_expense_account,
|
||||
valuation_amount, warehouse, self.doc.cost_center)
|
||||
|
||||
if item.s_warehouse and not item.t_warehouse:
|
||||
total_valuation_amount -= flt(item.incoming_rate, 2) * flt(item.transfer_qty)
|
||||
|
||||
return total_valuation_amount
|
||||
if gl_entries:
|
||||
from accounts.general_ledger import make_gl_entries
|
||||
make_gl_entries(gl_entries, cancel=self.doc.docstatus == 2)
|
||||
|
||||
self.sync_stock_account_balance(warehouse_list, self.doc.cost_center)
|
||||
|
||||
def get_stock_and_rate(self):
|
||||
"""get stock and incoming rate on posting date"""
|
||||
for d in getlist(self.doclist, 'mtn_details'):
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-04-09 11:43:55",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-07-05 14:56:06",
|
||||
"modified": "2013-08-05 17:36:25",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -200,7 +200,7 @@
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:sys_defaults.auto_inventory_accounting",
|
||||
"depends_on": "eval:sys_defaults.perpetual_accounting",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "expense_adjustment_account",
|
||||
"fieldtype": "Link",
|
||||
@ -209,6 +209,14 @@
|
||||
"print_hide": 1,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:sys_defaults.perpetual_accounting",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "cost_center",
|
||||
"fieldtype": "Link",
|
||||
"label": "Cost Center",
|
||||
"options": "Cost Center"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "items_section",
|
||||
|
@ -7,7 +7,7 @@ from webnotes.utils import flt
|
||||
|
||||
class TestStockEntry(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 0)
|
||||
if hasattr(self, "old_default_company"):
|
||||
webnotes.conn.set_default("company", self.old_default_company)
|
||||
|
||||
@ -45,7 +45,7 @@ class TestStockEntry(unittest.TestCase):
|
||||
|
||||
def test_material_receipt_gl_entry(self):
|
||||
webnotes.conn.sql("delete from `tabStock Ledger Entry`")
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 1)
|
||||
|
||||
mr = webnotes.bean(copy=test_records[0])
|
||||
mr.insert()
|
||||
@ -80,7 +80,7 @@ class TestStockEntry(unittest.TestCase):
|
||||
|
||||
def test_material_issue_gl_entry(self):
|
||||
self._clear_stock()
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 1)
|
||||
|
||||
mr = webnotes.bean(copy=test_records[0])
|
||||
mr.insert()
|
||||
@ -120,7 +120,7 @@ class TestStockEntry(unittest.TestCase):
|
||||
|
||||
def test_material_transfer_gl_entry(self):
|
||||
self._clear_stock()
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 1)
|
||||
|
||||
mr = webnotes.bean(copy=test_records[0])
|
||||
mr.insert()
|
||||
|
@ -25,7 +25,7 @@ erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({
|
||||
set_default_expense_account: function() {
|
||||
var me = this;
|
||||
|
||||
if (sys_defaults.auto_inventory_accounting && !this.frm.doc.expense_account) {
|
||||
if (sys_defaults.perpetual_accounting && !this.frm.doc.expense_account) {
|
||||
return this.frm.call({
|
||||
method: "accounts.utils.get_company_default",
|
||||
args: {
|
||||
@ -41,7 +41,7 @@ erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({
|
||||
|
||||
setup: function() {
|
||||
var me = this;
|
||||
if (sys_defaults.auto_inventory_accounting) {
|
||||
if (sys_defaults.perpetual_accounting) {
|
||||
this.frm.add_fetch("company", "stock_adjustment_account", "expense_account");
|
||||
|
||||
this.frm.fields_dict["expense_account"].get_query = function() {
|
||||
|
@ -69,8 +69,10 @@ class DocType(StockController):
|
||||
if len(rows) > 100:
|
||||
msgprint(_("""Sorry! We can only allow upto 100 rows for Stock Reconciliation."""),
|
||||
raise_exception=True)
|
||||
|
||||
warehouse_list = []
|
||||
for row_num, row in enumerate(rows):
|
||||
if row[1] not in warehouse_list:
|
||||
warehouse_list.append(row[1])
|
||||
# find duplicates
|
||||
if [row[0], row[1]] in item_warehouse_combinations:
|
||||
self.validation_messages.append(_get_msg(row_num, "Duplicate entry"))
|
||||
@ -102,6 +104,8 @@ class DocType(StockController):
|
||||
|
||||
raise webnotes.ValidationError
|
||||
|
||||
self.validate_warehouse_with_company(warehouse_list)
|
||||
|
||||
def validate_item(self, item_code, row_num):
|
||||
from stock.utils import validate_end_of_life, validate_is_stock_item, \
|
||||
validate_cancelled_item
|
||||
@ -301,26 +305,54 @@ class DocType(StockController):
|
||||
warehouse_list = [d.warehouse for d in self.entries]
|
||||
stock_ledger_entries = self.get_stock_ledger_entries(item_list, warehouse_list)
|
||||
|
||||
self.doc.stock_value_difference = 0.0
|
||||
stock_value_difference = {}
|
||||
for d in self.entries:
|
||||
self.doc.stock_value_difference -= get_buying_amount(d.item_code, d.warehouse,
|
||||
d.actual_qty, self.doc.doctype, self.doc.name, d.voucher_detail_no,
|
||||
stock_ledger_entries)
|
||||
webnotes.conn.set(self.doc, "stock_value_difference", self.doc.stock_value_difference)
|
||||
diff = get_buying_amount(d.item_code, d.warehouse, d.actual_qty, self.doc.doctype,
|
||||
self.doc.name, d.voucher_detail_no, stock_ledger_entries)
|
||||
stock_value_difference.setdefault(d.warehouse, 0.0)
|
||||
stock_value_difference[d.warehouse] += diff
|
||||
|
||||
webnotes.conn.set(self.doc, "stock_value_difference", json.dumps(stock_value_difference))
|
||||
|
||||
def make_gl_entries(self):
|
||||
if not cint(webnotes.defaults.get_global_default("auto_inventory_accounting")):
|
||||
if not cint(webnotes.defaults.get_global_default("perpetual_accounting")):
|
||||
return
|
||||
|
||||
if not self.doc.expense_account:
|
||||
msgprint(_("Please enter Expense Account"), raise_exception=1)
|
||||
else:
|
||||
self.validate_expense_account()
|
||||
|
||||
from accounts.general_ledger import make_gl_entries
|
||||
|
||||
gl_entries = self.get_gl_entries_for_stock(self.doc.expense_account,
|
||||
self.doc.stock_value_difference)
|
||||
if not self.doc.cost_center:
|
||||
msgprint(_("Please enter Cost Center"), raise_exception=1)
|
||||
|
||||
if self.doc.stock_value_difference:
|
||||
stock_value_difference = json.loads(self.doc.stock_value_difference)
|
||||
|
||||
gl_entries = []
|
||||
warehouse_list = []
|
||||
for warehouse, diff in stock_value_difference.items():
|
||||
if diff:
|
||||
gl_entries += self.get_gl_entries_for_stock(self.doc.expense_account, diff,
|
||||
warehouse, self.doc.cost_center)
|
||||
|
||||
if warehouse not in warehouse_list:
|
||||
warehouse_list.append(warehouse)
|
||||
|
||||
if gl_entries:
|
||||
from accounts.general_ledger import make_gl_entries
|
||||
make_gl_entries(gl_entries, cancel=self.doc.docstatus == 2)
|
||||
|
||||
self.sync_stock_account_balance(warehouse_list, self.doc.cost_center)
|
||||
|
||||
def validate_expense_account(self):
|
||||
if not webnotes.conn.sql("select * from `tabStock Ledger Entry`"):
|
||||
if webnotes.conn.get_value("Account", self.doc.expense_account,
|
||||
"is_pl_account") == "Yes":
|
||||
msgprint(_("""Expense Account can not be a PL Account, as this stock \
|
||||
reconciliation is an opening entry. Please select 'Temporary Liability' or \
|
||||
relevant account"""), raise_exception=1)
|
||||
|
||||
|
||||
@webnotes.whitelist()
|
||||
def upload():
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-03-28 10:35:31",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-07-22 15:22:44",
|
||||
"modified": "2013-08-05 17:18:14",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -31,7 +31,6 @@
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
@ -42,7 +41,6 @@
|
||||
"permlevel": 0,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Material Manager",
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
@ -102,13 +100,21 @@
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:sys_defaults.auto_inventory_accounting",
|
||||
"depends_on": "eval:sys_defaults.perpetual_accounting",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "expense_account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Expense Account",
|
||||
"options": "Account"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:sys_defaults.perpetual_accounting",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "cost_center",
|
||||
"fieldtype": "Link",
|
||||
"label": "Cost Center",
|
||||
"options": "Cost Center"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "col1",
|
||||
@ -151,13 +157,19 @@
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "stock_value_difference",
|
||||
"fieldtype": "Currency",
|
||||
"fieldtype": "Long Text",
|
||||
"hidden": 1,
|
||||
"in_list_view": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Stock Value Difference",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocPerm"
|
||||
"amend": 0,
|
||||
"doctype": "DocPerm",
|
||||
"role": "Material Manager"
|
||||
},
|
||||
{
|
||||
"doctype": "DocPerm",
|
||||
"role": "System Manager"
|
||||
}
|
||||
]
|
@ -9,7 +9,7 @@ from accounts.utils import get_fiscal_year
|
||||
|
||||
class TestStockReconciliation(unittest.TestCase):
|
||||
def test_reco_for_fifo(self):
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 0)
|
||||
# [[qty, valuation_rate, posting_date,
|
||||
# posting_time, expected_stock_value, bin_qty, bin_valuation]]
|
||||
input_data = [
|
||||
@ -53,7 +53,7 @@ class TestStockReconciliation(unittest.TestCase):
|
||||
|
||||
|
||||
def test_reco_for_moving_average(self):
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 0)
|
||||
# [[qty, valuation_rate, posting_date,
|
||||
# posting_time, expected_stock_value, bin_qty, bin_valuation]]
|
||||
input_data = [
|
||||
@ -99,7 +99,7 @@ class TestStockReconciliation(unittest.TestCase):
|
||||
self.assertFalse(gl_entries)
|
||||
|
||||
def test_reco_fifo_gl_entries(self):
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 1)
|
||||
|
||||
# [[qty, valuation_rate, posting_date,
|
||||
# posting_time, stock_in_hand_debit]]
|
||||
@ -131,10 +131,10 @@ class TestStockReconciliation(unittest.TestCase):
|
||||
stock_reco.cancel()
|
||||
self.check_gl_entries(stock_reco.doc.name, -d[4], True)
|
||||
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 0)
|
||||
|
||||
def test_reco_moving_average_gl_entries(self):
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 1)
|
||||
|
||||
# [[qty, valuation_rate, posting_date,
|
||||
# posting_time, stock_in_hand_debit]]
|
||||
@ -166,7 +166,7 @@ class TestStockReconciliation(unittest.TestCase):
|
||||
stock_reco.cancel()
|
||||
self.check_gl_entries(stock_reco.doc.name, -d[4], True)
|
||||
|
||||
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
|
||||
webnotes.defaults.set_global_default("perpetual_accounting", 0)
|
||||
|
||||
|
||||
def cleanup_data(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user