[fix] update future gl entries for stock
This commit is contained in:
parent
155232e04e
commit
e83069cb32
@ -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,
|
||||||
|
@ -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]
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)
|
@ -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)
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
@ -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",
|
||||||
|
}],
|
||||||
]
|
]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user