[fix] update future gl entries for stock

This commit is contained in:
Nabin Hait 2013-11-14 18:40:08 +05:30
parent 155232e04e
commit e83069cb32
9 changed files with 112 additions and 39 deletions

View File

@ -95,6 +95,7 @@ class DocType(SellingController):
# this sequence because outstanding may get -ve # this sequence because outstanding may get -ve
self.make_gl_entries() self.make_gl_entries()
self.check_credit_limit(self.doc.debit_to)
if not cint(self.doc.is_pos) == 1: if not cint(self.doc.is_pos) == 1:
self.update_against_document_in_jv() self.update_against_document_in_jv()
@ -533,32 +534,39 @@ class DocType(SellingController):
self.make_sl_entries(sl_entries) self.make_sl_entries(sl_entries)
def make_gl_entries(self): def make_gl_entries(self, update_gl_entries_after=True):
from accounts.general_ledger import make_gl_entries, merge_similar_entries gl_entries = self.get_gl_entries()
if gl_entries:
from accounts.general_ledger import make_gl_entries
update_outstanding = cint(self.doc.is_pos) and self.doc.write_off_account \
and 'No' or 'Yes'
make_gl_entries(gl_entries, cancel=(self.doc.docstatus == 2),
update_outstanding=update_outstanding, merge_entries=False)
if update_gl_entries_after and cint(self.doc.update_stock) \
and cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")):
self.update_gl_entries_after()
def get_gl_entries(self, warehouse_account=None):
from accounts.general_ledger import merge_similar_entries
gl_entries = [] gl_entries = []
self.make_customer_gl_entry(gl_entries) self.make_customer_gl_entry(gl_entries)
self.make_tax_gl_entries(gl_entries) self.make_tax_gl_entries(gl_entries)
self.make_item_gl_entries(gl_entries) self.make_item_gl_entries(gl_entries)
# merge gl entries before adding pos entries # merge gl entries before adding pos entries
gl_entries = merge_similar_entries(gl_entries) gl_entries = merge_similar_entries(gl_entries)
self.make_pos_gl_entries(gl_entries) self.make_pos_gl_entries(gl_entries)
update_outstanding = cint(self.doc.is_pos) and self.doc.write_off_account and 'No' or 'Yes' return gl_entries
if gl_entries:
make_gl_entries(gl_entries, cancel=(self.doc.docstatus == 2),
update_outstanding=update_outstanding, merge_entries=False)
if cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")) \
and cint(self.doc.update_stock):
self.update_gl_entries_after()
def make_customer_gl_entry(self, gl_entries): def make_customer_gl_entry(self, gl_entries):
if self.doc.grand_total: if self.doc.grand_total:
gl_entries.append( gl_entries.append(
@ -602,7 +610,7 @@ class DocType(SellingController):
# expense account gl entries # expense account gl entries
if cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")) \ if cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")) \
and cint(self.doc.update_stock): and cint(self.doc.update_stock):
gl_entries += self.get_gl_entries_for_stock() gl_entries += super(DocType, self).get_gl_entries()
def make_pos_gl_entries(self, gl_entries): def make_pos_gl_entries(self, gl_entries):
if cint(self.doc.is_pos) and self.doc.cash_bank_account and self.doc.paid_amount: if cint(self.doc.is_pos) and self.doc.cash_bank_account and self.doc.paid_amount:
@ -866,7 +874,6 @@ def send_notification(new_rv):
def notify_errors(inv, owner): def notify_errors(inv, owner):
import webnotes import webnotes
import website
exception_msg = """ exception_msg = """
Dear User, Dear User,

View File

@ -3,7 +3,7 @@
import webnotes import webnotes
import unittest, json import unittest, json
from webnotes.utils import flt, cint from webnotes.utils import flt
from webnotes.model.bean import DocstatusTransitionError, TimestampMismatchError from webnotes.model.bean import DocstatusTransitionError, TimestampMismatchError
from accounts.utils import get_stock_and_account_difference from accounts.utils import get_stock_and_account_difference
from stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory from stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
@ -364,6 +364,7 @@ class TestSalesInvoice(unittest.TestCase):
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
order by account asc, debit asc""", si.doc.name, as_dict=1) order by account asc, debit asc""", si.doc.name, as_dict=1)
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
# print gl_entries
stock_in_hand = webnotes.conn.get_value("Account", {"master_name": "_Test Warehouse - _TC"}) stock_in_hand = webnotes.conn.get_value("Account", {"master_name": "_Test Warehouse - _TC"})
@ -382,9 +383,6 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEquals(expected_gl_entries[i][1], gle.debit) self.assertEquals(expected_gl_entries[i][1], gle.debit)
self.assertEquals(expected_gl_entries[i][2], gle.credit) self.assertEquals(expected_gl_entries[i][2], gle.credit)
# cancel
si.cancel() si.cancel()
gle = webnotes.conn.sql("""select * from `tabGL Entry` gle = webnotes.conn.sql("""select * from `tabGL Entry`
where voucher_type='Sales Invoice' and voucher_no=%s""", si.doc.name) where voucher_type='Sales Invoice' and voucher_no=%s""", si.doc.name)
@ -395,6 +393,62 @@ class TestSalesInvoice(unittest.TestCase):
set_perpetual_inventory(0) set_perpetual_inventory(0)
def test_si_gl_entry_with_aii_and_update_stock_with_warehouse_but_no_account(self):
self.clear_stock_account_balance()
set_perpetual_inventory()
webnotes.delete_doc("Account", "_Test Warehouse No Account - _TC")
# insert purchase receipt
from stock.doctype.purchase_receipt.test_purchase_receipt import test_records \
as pr_test_records
pr = webnotes.bean(copy=pr_test_records[0])
pr.doc.naming_series = "_T-Purchase Receipt-"
pr.doclist[1].warehouse = "_Test Warehouse No Account - _TC"
pr.run_method("calculate_taxes_and_totals")
pr.insert()
pr.submit()
si_doclist = webnotes.copy_doclist(test_records[1])
si_doclist[0]["update_stock"] = 1
si_doclist[0]["posting_time"] = "12:05"
si_doclist[1]["warehouse"] = "_Test Warehouse No Account - _TC"
si = webnotes.bean(copy=si_doclist)
si.insert()
si.submit()
# check stock ledger entries
sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry`
where voucher_type = 'Sales Invoice' and voucher_no = %s""",
si.doc.name, as_dict=1)[0]
self.assertTrue(sle)
self.assertEquals([sle.item_code, sle.warehouse, sle.actual_qty],
["_Test Item", "_Test Warehouse No Account - _TC", -1.0])
# 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)
expected_gl_entries = sorted([
[si.doc.debit_to, 630.0, 0.0],
[si_doclist[1]["income_account"], 0.0, 500.0],
[si_doclist[2]["account_head"], 0.0, 80.0],
[si_doclist[3]["account_head"], 0.0, 50.0],
])
for i, gle in enumerate(gl_entries):
self.assertEquals(expected_gl_entries[i][0], gle.account)
self.assertEquals(expected_gl_entries[i][1], gle.debit)
self.assertEquals(expected_gl_entries[i][2], gle.credit)
si.cancel()
gle = webnotes.conn.sql("""select * from `tabGL Entry`
where voucher_type='Sales Invoice' and voucher_no=%s""", si.doc.name)
self.assertFalse(gle)
set_perpetual_inventory(0)
def test_sales_invoice_gl_entry_with_aii_no_item_code(self): def test_sales_invoice_gl_entry_with_aii_no_item_code(self):
self.clear_stock_account_balance() self.clear_stock_account_balance()
set_perpetual_inventory() set_perpetual_inventory()
@ -599,7 +653,7 @@ class TestSalesInvoice(unittest.TestCase):
self._test_recurring_invoice(si7, True) self._test_recurring_invoice(si7, True)
def _test_recurring_invoice(self, base_si, first_and_last_day): def _test_recurring_invoice(self, base_si, first_and_last_day):
from webnotes.utils import add_months, get_last_day, getdate from webnotes.utils import add_months, get_last_day
from accounts.doctype.sales_invoice.sales_invoice import manage_recurring_invoices from accounts.doctype.sales_invoice.sales_invoice import manage_recurring_invoices
no_of_months = ({"Monthly": 1, "Quarterly": 3, "Yearly": 12})[base_si.doc.recurring_type] no_of_months = ({"Monthly": 1, "Quarterly": 3, "Yearly": 12})[base_si.doc.recurring_type]

View File

@ -3,9 +3,8 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import webnotes import webnotes
from webnotes.utils import flt, cstr, now from webnotes.utils import flt, cstr
from webnotes.model.doc import Document from webnotes import _
from webnotes import msgprint, _
from accounts.utils import validate_expense_against_budget from accounts.utils import validate_expense_against_budget

View File

@ -5,6 +5,7 @@ from __future__ import unicode_literals
import webnotes import webnotes
from webnotes import _, msgprint from webnotes import _, msgprint
from webnotes.utils import flt, cint, today, cstr from webnotes.utils import flt, cint, today, cstr
from webnotes.model.code import get_obj
from setup.utils import get_company_currency from setup.utils import get_company_currency
from accounts.utils import get_fiscal_year, validate_fiscal_year from accounts.utils import get_fiscal_year, validate_fiscal_year
from utilities.transaction_base import TransactionBase, validate_conversion_rate from utilities.transaction_base import TransactionBase, validate_conversion_rate
@ -422,3 +423,12 @@ 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
def check_credit_limit(self, account):
total_outstanding = webnotes.conn.sql("""
select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
from `tabGL Entry` where account = %s""", account)
total_outstanding = flt(total_outstanding[0][0]) if total_outstanding else 0
if total_outstanding:
get_obj('Account', account).check_credit_limit(total_outstanding)

View File

@ -11,7 +11,7 @@ from controllers.accounts_controller import AccountsController
from accounts.general_ledger import make_gl_entries, delete_gl_entries from accounts.general_ledger import make_gl_entries, delete_gl_entries
class StockController(AccountsController): class StockController(AccountsController):
def make_gl_entries(self): def make_gl_entries(self, update_gl_entries_after=True):
if self.doc.docstatus == 2: if self.doc.docstatus == 2:
delete_gl_entries(voucher_type=self.doc.doctype, voucher_no=self.doc.name) delete_gl_entries(voucher_type=self.doc.doctype, voucher_no=self.doc.name)
@ -19,12 +19,13 @@ class StockController(AccountsController):
warehouse_account = self.get_warehouse_account() warehouse_account = self.get_warehouse_account()
if self.doc.docstatus==1: if self.doc.docstatus==1:
gl_entries = self.get_gl_entries_for_stock(warehouse_account) gl_entries = self.get_gl_entries(warehouse_account)
make_gl_entries(gl_entries) make_gl_entries(gl_entries)
self.update_gl_entries_after(warehouse_account) if update_gl_entries_after:
self.update_gl_entries_after(warehouse_account)
def get_gl_entries_for_stock(self, warehouse_account=None, default_expense_account=None, def get_gl_entries(self, warehouse_account=None, default_expense_account=None,
default_cost_center=None): default_cost_center=None):
from accounts.general_ledger import process_gl_map from accounts.general_ledger import process_gl_map
if not warehouse_account: if not warehouse_account:
@ -99,12 +100,10 @@ class StockController(AccountsController):
gle = self.get_voucherwise_gl_entries(future_stock_vouchers) gle = self.get_voucherwise_gl_entries(future_stock_vouchers)
if not warehouse_account: if not warehouse_account:
warehouse_account = self.get_warehouse_account() warehouse_account = self.get_warehouse_account()
for voucher_type, voucher_no in future_stock_vouchers: for voucher_type, voucher_no in future_stock_vouchers:
existing_gle = gle.get((voucher_type, voucher_no), []) existing_gle = gle.get((voucher_type, voucher_no), [])
voucher_obj = webnotes.get_obj(voucher_type, voucher_no) voucher_obj = webnotes.get_obj(voucher_type, voucher_no)
expected_gle = voucher_obj.get_gl_entries_for_stock(warehouse_account) expected_gle = voucher_obj.get_gl_entries(warehouse_account)
if expected_gle: if expected_gle:
matched = True matched = True
if existing_gle: if existing_gle:
@ -121,7 +120,7 @@ class StockController(AccountsController):
if not matched: if not matched:
self.delete_gl_entries(voucher_type, voucher_no) self.delete_gl_entries(voucher_type, voucher_no)
make_gl_entries(expected_gle) voucher_obj.make_gl_entries(update_gl_entries_after=False)
else: else:
self.delete_gl_entries(voucher_type, voucher_no) self.delete_gl_entries(voucher_type, voucher_no)

View File

@ -294,11 +294,10 @@ class DocType(BuyingController):
def get_rate(self,arg): def get_rate(self,arg):
return get_obj('Purchase Common').get_rate(arg,self) return get_obj('Purchase Common').get_rate(arg,self)
def get_gl_entries_for_stock(self, warehouse_account=None): def get_gl_entries(self, warehouse_account=None):
against_stock_account = self.get_company_default("stock_received_but_not_billed") against_stock_account = self.get_company_default("stock_received_but_not_billed")
gl_entries = super(DocType, self).get_gl_entries_for_stock(warehouse_account, gl_entries = super(DocType, self).get_gl_entries(warehouse_account, against_stock_account)
against_stock_account)
return gl_entries return gl_entries

View File

@ -478,7 +478,7 @@ class DocType(StockController):
self.doc.from_warehouse = "" self.doc.from_warehouse = ""
item = webnotes.conn.sql("""select name, item_name, description, item = webnotes.conn.sql("""select name, item_name, description,
uom, purchase_account, cost_center from `tabItem` stock_uom, purchase_account, cost_center from `tabItem`
where name=(select item from tabBOM where name=%s)""", where name=(select item from tabBOM where name=%s)""",
self.doc.bom_no, as_dict=1) self.doc.bom_no, as_dict=1)
self.add_to_stock_entry_detail({ self.add_to_stock_entry_detail({
@ -486,7 +486,7 @@ class DocType(StockController):
"qty": self.doc.fg_completed_qty, "qty": self.doc.fg_completed_qty,
"item_name": item[0].item_name, "item_name": item[0].item_name,
"description": item[0]["description"], "description": item[0]["description"],
"stock_uom": item[0]["uom"], "stock_uom": item[0]["stock_uom"],
"from_warehouse": "", "from_warehouse": "",
"expense_account": item[0].purchase_account, "expense_account": item[0].purchase_account,
"cost_center": item[0].cost_center, "cost_center": item[0].cost_center,

View File

@ -275,11 +275,11 @@ class DocType(StockController):
"posting_time": self.doc.posting_time "posting_time": self.doc.posting_time
}) })
def get_gl_entries_for_stock(self, warehouse_account=None): def get_gl_entries(self, warehouse_account=None):
if not self.doc.cost_center: if not self.doc.cost_center:
msgprint(_("Please enter Cost Center"), raise_exception=1) msgprint(_("Please enter Cost Center"), raise_exception=1)
return super(DocType, self).get_gl_entries_for_stock(warehouse_account, return super(DocType, self).get_gl_entries(warehouse_account,
self.doc.expense_account, self.doc.cost_center) self.doc.expense_account, self.doc.cost_center)

View File

@ -23,5 +23,10 @@ test_records = [
"doctype": "Warehouse User", "doctype": "Warehouse User",
"parentfield": "warehouse_users", "parentfield": "warehouse_users",
"user": "test2@example.com" "user": "test2@example.com"
}] }],
[{
"doctype": "Warehouse",
"warehouse_name": "_Test Warehouse No Account",
"company": "_Test Company",
}],
] ]