[fix] [minor] Repost future gl entries and testcases

This commit is contained in:
Nabin Hait 2013-08-28 18:53:11 +05:30
parent 92b0e777e8
commit 2e296fa46f
12 changed files with 238 additions and 174 deletions

View File

@ -557,8 +557,10 @@ class DocType(SellingController):
if gl_entries: if gl_entries:
make_gl_entries(gl_entries, cancel=(self.doc.docstatus == 2), make_gl_entries(gl_entries, cancel=(self.doc.docstatus == 2),
update_outstanding=update_outstanding, merge_entries=False) update_outstanding=update_outstanding, merge_entries=False)
self.update_gl_entries_after() if cint(webnotes.defaults.get_global_default("perpetual_accounting")) \
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:

View File

@ -9,11 +9,12 @@ from accounts.utils import validate_expense_against_budget
def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True,
update_outstanding='Yes'): update_outstanding='Yes'):
if not cancel: if gl_map:
gl_map = process_gl_map(gl_map, merge_entries) if not cancel:
save_entries(gl_map, adv_adj, update_outstanding) gl_map = process_gl_map(gl_map, merge_entries)
else: save_entries(gl_map, adv_adj, update_outstanding)
delete_gl_entries(gl_map, adv_adj, update_outstanding) else:
delete_gl_entries(gl_map, adv_adj=adv_adj, update_outstanding=update_outstanding)
def process_gl_map(gl_map, merge_entries=True): def process_gl_map(gl_map, merge_entries=True):
if merge_entries: if merge_entries:
@ -21,12 +22,13 @@ def process_gl_map(gl_map, merge_entries=True):
for entry in gl_map: for entry in gl_map:
# round off upto 2 decimal # round off upto 2 decimal
entry["debit"] = flt(entry["debit"], 2) entry.debit = flt(entry.debit, 2)
entry["credit"] = flt(entry["credit"], 2) entry.credit = flt(entry.credit, 2)
# toggle debit, credit if negative entry # toggle debit, credit if negative entry
if flt(entry["debit"]) < 0 or flt(entry["credit"]) < 0: if flt(entry.debit) < 0 or flt(entry.credit) < 0:
entry["debit"], entry["credit"] = abs(flt(entry["credit"])), abs(flt(entry["debit"])) entry.debit, entry.credit = abs(flt(entry.credit)), abs(flt(entry.debit))
return gl_map return gl_map
def merge_similar_entries(gl_map): def merge_similar_entries(gl_map):
@ -36,18 +38,18 @@ def merge_similar_entries(gl_map):
# to that entry # to that entry
same_head = check_if_in_list(entry, merged_gl_map) same_head = check_if_in_list(entry, merged_gl_map)
if same_head: if same_head:
same_head['debit'] = flt(same_head['debit']) + flt(entry['debit']) same_head.debit = flt(same_head.debit) + flt(entry.debit)
same_head['credit'] = flt(same_head['credit']) + flt(entry['credit']) same_head.credit = flt(same_head.credit) + flt(entry.credit)
else: else:
merged_gl_map.append(entry) merged_gl_map.append(entry)
# filter zero debit and credit entries # filter zero debit and credit entries
merged_gl_map = filter(lambda x: flt(x["debit"])!=0 or flt(x["credit"])!=0, merged_gl_map) merged_gl_map = filter(lambda x: flt(x.debit)!=0 or flt(x.credit)!=0, merged_gl_map)
return merged_gl_map return merged_gl_map
def check_if_in_list(gle, gl_mqp): def check_if_in_list(gle, gl_mqp):
for e in gl_mqp: for e in gl_mqp:
if e['account'] == gle['account'] and \ if e.account == gle.account and \
cstr(e.get('against_voucher'))==cstr(gle.get('against_voucher')) \ cstr(e.get('against_voucher'))==cstr(gle.get('against_voucher')) \
and cstr(e.get('against_voucher_type')) == \ and cstr(e.get('against_voucher_type')) == \
cstr(gle.get('against_voucher_type')) \ cstr(gle.get('against_voucher_type')) \
@ -62,8 +64,8 @@ def save_entries(gl_map, adv_adj, update_outstanding):
validate_expense_against_budget(entry) validate_expense_against_budget(entry)
# update total debit / credit # update total debit / credit
total_debit += flt(entry["debit"]) total_debit += flt(entry.debit)
total_credit += flt(entry["credit"]) total_credit += flt(entry.credit)
validate_total_debit_credit(total_debit, total_credit) validate_total_debit_credit(total_debit, total_credit)
@ -80,14 +82,20 @@ def validate_total_debit_credit(total_debit, total_credit):
webnotes.throw(webnotes._("Debit and Credit not equal for this voucher: Diff (Debit) is ") + webnotes.throw(webnotes._("Debit and Credit not equal for this voucher: Diff (Debit) is ") +
cstr(total_debit - total_credit)) cstr(total_debit - total_credit))
def delete_gl_entries(gl_entries=None, adv_adj=False, update_outstanding="Yes"): def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
adv_adj=False, update_outstanding="Yes"):
from accounts.doctype.gl_entry.gl_entry import check_negative_balance, \ from accounts.doctype.gl_entry.gl_entry import check_negative_balance, \
check_freezing_date, update_outstanding_amt, validate_freezed_account check_freezing_date, update_outstanding_amt, validate_freezed_account
if not gl_entries:
gl_entries = webnotes.conn.sql("""select * from `tabGL Entry`
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no), as_dict=True)
if gl_entries: if gl_entries:
check_freezing_date(gl_entries[0]["posting_date"], adv_adj) check_freezing_date(gl_entries[0]["posting_date"], adv_adj)
webnotes.conn.sql("""delete from `tabGL Entry` where voucher_type=%s and voucher_no=%s""", webnotes.conn.sql("""delete from `tabGL Entry` where voucher_type=%s and voucher_no=%s""",
(gl_entries[0]["voucher_type"], gl_entries[0]["voucher_no"])) (voucher_type or gl_entries[0]["voucher_type"], voucher_no or gl_entries[0]["voucher_no"]))
for entry in gl_entries: for entry in gl_entries:
validate_freezed_account(entry["account"], adv_adj) validate_freezed_account(entry["account"], adv_adj)

View File

@ -360,7 +360,6 @@ def get_stock_and_account_difference(account_list=None, posting_date=None):
for account, warehouse_list in account_warehouse_map.items(): for account, warehouse_list in account_warehouse_map.items():
account_balance = get_balance_on(account, posting_date) account_balance = get_balance_on(account, posting_date)
stock_value = get_stock_balance_on(warehouse_list, posting_date) stock_value = get_stock_balance_on(warehouse_list, posting_date)
if abs(flt(stock_value) - flt(account_balance)) > 0.005: if abs(flt(stock_value) - flt(account_balance)) > 0.005:
difference.setdefault(account, flt(stock_value) - flt(account_balance)) difference.setdefault(account, flt(stock_value) - flt(account_balance))

View File

@ -332,7 +332,7 @@ class AccountsController(TransactionBase):
def get_gl_dict(self, args): def get_gl_dict(self, args):
"""this method populates the common properties of a gl entry record""" """this method populates the common properties of a gl entry record"""
gl_dict = { gl_dict = webnotes._dict({
'company': self.doc.company, 'company': self.doc.company,
'posting_date': self.doc.posting_date, 'posting_date': self.doc.posting_date,
'voucher_type': self.doc.doctype, 'voucher_type': self.doc.doctype,
@ -343,7 +343,7 @@ class AccountsController(TransactionBase):
'debit': 0, 'debit': 0,
'credit': 0, 'credit': 0,
'is_opening': self.doc.fields.get("is_opening") or "No", 'is_opening': self.doc.fields.get("is_opening") or "No",
} })
gl_dict.update(args) gl_dict.update(args)
return gl_dict return gl_dict

View File

@ -8,130 +8,130 @@ from webnotes import msgprint, _
import webnotes.defaults import webnotes.defaults
from controllers.accounts_controller import AccountsController from controllers.accounts_controller import AccountsController
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):
if not cint(webnotes.defaults.get_global_default("perpetual_accounting")): if not cint(webnotes.defaults.get_global_default("perpetual_accounting")):
return return
from accounts.general_ledger import make_gl_entries, delete_gl_entries if self.doc.docstatus==1:
gl_entries = self.get_gl_entries_for_stock() gl_entries = self.get_gl_entries_for_stock()
if gl_entries and self.doc.docstatus==1:
make_gl_entries(gl_entries) make_gl_entries(gl_entries)
elif self.doc.docstatus==2: else:
webnotes.conn.sql("""delete from `tabGL Entry` where voucher_type=%s delete_gl_entries(voucher_type=self.doc.doctype, voucher_no=self.doc.name)
and voucher_no=%s""", (self.doc.doctype, self.doc.name))
self.update_gl_entries_after() self.update_gl_entries_after()
def get_gl_entries_for_stock(self, default_expense_account=None, default_cost_center=None):
def get_gl_entries_for_stock(self, item_acc_map=None, expense_account=None, cost_center=None):
from accounts.general_ledger import process_gl_map from accounts.general_ledger import process_gl_map
warehouse_account = self.get_warehouse_account()
stock_ledger = self.get_stock_ledger_details()
voucher_details = self.get_voucher_details(stock_ledger, default_expense_account,
default_cost_center)
gl_list = []
for detail in voucher_details:
sle_list = stock_ledger.get(detail.name)
if sle_list:
for sle in sle_list:
if warehouse_account.get(sle.warehouse):
# from warehouse account
gl_list.append(self.get_gl_dict({
"account": warehouse_account[sle.warehouse],
"against": detail.expense_account,
"cost_center": detail.cost_center,
"remarks": self.doc.remarks or "Accounting Entry for Stock",
"debit": sle.stock_value_difference
}))
if not (expense_account or cost_center or item_acc_map): # to target warehouse / expense account
item_acc_map = {} gl_list.append(self.get_gl_dict({
for item in self.doclist.get({"parentfield": self.fname}): "account": detail.expense_account,
self.check_expense_account(item) "against": warehouse_account[sle.warehouse],
item_acc_map.setdefault(item.name, [item.expense_account, item.cost_center]) "cost_center": detail.cost_center,
gl_entries = []
stock_value_diff = self.get_stock_value_diff_from_sle(item_acc_map, expense_account,
cost_center)
for stock_in_hand_account, against_stock_account_dict in stock_value_diff.items():
for against_stock_account, cost_center_dict in against_stock_account_dict.items():
for cost_center, value_diff in cost_center_dict.items():
gl_entries += [
# stock in hand account
self.get_gl_dict({
"account": stock_in_hand_account,
"against": against_stock_account,
"debit": value_diff,
"remarks": self.doc.remarks or "Accounting Entry for Stock", "remarks": self.doc.remarks or "Accounting Entry for Stock",
}), "credit": sle.stock_value_difference
}))
# account against stock in hand
self.get_gl_dict({
"account": against_stock_account,
"against": stock_in_hand_account,
"credit": value_diff,
"cost_center": cost_center != "No Cost Center" and cost_center or None,
"remarks": self.doc.remarks or "Accounting Entry for Stock",
}),
]
gl_entries = process_gl_map(gl_entries)
return gl_entries
return process_gl_map(gl_list)
def get_stock_value_diff_from_sle(self, item_acc_map, expense_account, cost_center): def get_voucher_details(self, stock_ledger, default_expense_account, default_cost_center):
wh_acc_map = self.get_warehouse_account_map() if not default_expense_account:
stock_value_diff = {} details = self.doclist.get({"parentfield": self.fname})
for d in details:
self.check_expense_account(d)
else:
details = [webnotes._dict({
"name":d,
"expense_account": default_expense_account,
"cost_center": default_cost_center
}) for d in stock_ledger.keys()]
return details
def get_stock_ledger_details(self):
stock_ledger = {}
for sle in webnotes.conn.sql("""select warehouse, stock_value_difference, voucher_detail_no for sle in webnotes.conn.sql("""select warehouse, stock_value_difference, voucher_detail_no
from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s""", from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s""",
(self.doc.doctype, self.doc.name), as_dict=True): (self.doc.doctype, self.doc.name), as_dict=True):
account = wh_acc_map[sle.warehouse] stock_ledger.setdefault(sle.voucher_detail_no, []).append(sle)
against_account = expense_account or item_acc_map[sle.voucher_detail_no][0] return stock_ledger
cost_center = cost_center or item_acc_map[sle.voucher_detail_no][1] or \
"No Cost Center"
stock_value_diff.setdefault(account, {}).setdefault(against_account, {})\
.setdefault(cost_center, 0)
stock_value_diff[account][against_account][cost_center] += \
flt(sle.stock_value_difference)
return stock_value_diff
def get_warehouse_account_map(self): def get_warehouse_account(self):
wh_acc_map = {} warehouse_account = dict(webnotes.conn.sql("""select name, account from `tabWarehouse`
warehouse_with_no_account = [] where ifnull(account, '') != ''"""))
for d in webnotes.conn.sql("""select name, account from `tabWarehouse`""", as_dict=True):
if not d.account: warehouse_with_no_account.append(d.name)
wh_acc_map.setdefault(d.name, d.account)
if warehouse_with_no_account:
webnotes.throw(_("Please mention Perpetual Account in warehouse master for \
following warehouses") + ": " + '\n'.join(warehouse_with_no_account))
return wh_acc_map return warehouse_account
def update_gl_entries_after(self): def update_gl_entries_after(self):
from accounts.utils import get_stock_and_account_difference
future_stock_vouchers = self.get_future_stock_vouchers() future_stock_vouchers = self.get_future_stock_vouchers()
gle = self.get_voucherwise_gl_entries(future_stock_vouchers) gle = self.get_voucherwise_gl_entries(future_stock_vouchers)
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_bean = webnotes.bean(voucher_type, voucher_no) voucher_obj = webnotes.get_obj(voucher_type, voucher_no)
expected_gle = voucher_bean.run_method("get_gl_entries_for_stock") expected_gle = voucher_obj.get_gl_entries_for_stock()
if expected_gle: if expected_gle:
matched = True
if existing_gle: if existing_gle:
matched = True
for entry in expected_gle: for entry in expected_gle:
entry_amount = existing_gle.get(entry.account, {}).get(entry.cost_center \ for e in existing_gle:
or "No Cost Center", [0, 0]) if entry.account==e.account \
and entry.against_account==e.against_account\
if [entry.debit, entry.credit] != entry_amount: and entry.cost_center==e.cost_center:
matched = False if entry.debit != e.debit or entry.credit != e.credit:
break matched = False
break
if not matched:
# make updated entry
webnotes.conn.sql("""delete from `tabGL Entry`
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
voucher_bean.run_method("make_gl_entries")
else: else:
# make adjustment entry on that date matched = False
self.make_adjustment_entry(expected_gle, voucher_bean)
if not matched:
self.delete_gl_entries(voucher_type, voucher_no)
make_gl_entries(expected_gle)
else:
self.delete_gl_entries(voucher_type, voucher_no)
# else:
# # make adjustment entry on that date
# self.make_adjustment_entry(expected_gle, voucher_obj)
def get_future_stock_vouchers(self): def get_future_stock_vouchers(self):
future_stock_vouchers = [] future_stock_vouchers = []
for d in webnotes.conn.sql("""select distinct voucher_type, voucher_no item_codes = webnotes.conn.sql_list("""select distinct item_code
from `tabStock Ledger Entry` from `tabStock Ledger Entry`
where timestamp(posting_date, posting_time) >= timestamp(%s, %s) where voucher_type=%s and voucher_no=%s""", (self.doc.doctype, self.doc.name))
order by timestamp(posting_date, posting_time) asc, name asc""",
for d in webnotes.conn.sql("""select distinct sle.voucher_type, sle.voucher_no
from `tabStock Ledger Entry` sle
where timestamp(sle.posting_date, sle.posting_time) >= timestamp(%s, %s)
order by timestamp(sle.posting_date, sle.posting_time) asc, name asc""",
(self.doc.posting_date, self.doc.posting_time), as_dict=True): (self.doc.posting_date, self.doc.posting_time), as_dict=True):
future_stock_vouchers.append([d.voucher_type, d.voucher_no]) future_stock_vouchers.append([d.voucher_type, d.voucher_no])
return future_stock_vouchers return future_stock_vouchers
def get_voucherwise_gl_entries(self, future_stock_vouchers): def get_voucherwise_gl_entries(self, future_stock_vouchers):
@ -141,13 +141,15 @@ class StockController(AccountsController):
where posting_date >= %s and voucher_no in (%s)""" % where posting_date >= %s and voucher_no in (%s)""" %
('%s', ', '.join(['%s']*len(future_stock_vouchers))), ('%s', ', '.join(['%s']*len(future_stock_vouchers))),
tuple([self.doc.posting_date] + [d[1] for d in future_stock_vouchers]), as_dict=1): tuple([self.doc.posting_date] + [d[1] for d in future_stock_vouchers]), as_dict=1):
gl_entries.setdefault((d.voucher_type, d.voucher_no), {})\ gl_entries.setdefault((d.voucher_type, d.voucher_no), []).append(d)
.setdefault(d.account, {})\
.setdefault(d.cost_center, [d.debit, d.credit])
return gl_entries return gl_entries
def delete_gl_entries(self, voucher_type, voucher_no):
webnotes.conn.sql("""delete from `tabGL Entry`
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
def make_adjustment_entry(self, expected_gle, voucher_bean): def make_adjustment_entry(self, expected_gle, voucher_obj):
from accounts.utils import get_stock_and_account_difference from accounts.utils import get_stock_and_account_difference
account_list = [d.account for d in expected_gle] account_list = [d.account for d in expected_gle]
acc_diff = get_stock_and_account_difference(account_list, expected_gle[0].posting_date) acc_diff = get_stock_and_account_difference(account_list, expected_gle[0].posting_date)
@ -160,7 +162,7 @@ class StockController(AccountsController):
if diff: if diff:
gl_entries.append([ gl_entries.append([
# stock in hand account # stock in hand account
voucher_bean.get_gl_dict({ voucher_obj.get_gl_dict({
"account": account, "account": account,
"against": stock_adjustment_account, "against": stock_adjustment_account,
"debit": diff, "debit": diff,
@ -168,7 +170,7 @@ class StockController(AccountsController):
}), }),
# account against stock in hand # account against stock in hand
voucher_bean.get_gl_dict({ voucher_obj.get_gl_dict({
"account": stock_adjustment_account, "account": stock_adjustment_account,
"against": account, "against": account,
"credit": diff, "credit": diff,

View File

@ -123,7 +123,6 @@ class DocType(SellingController):
} }
}) })
def validate_proj_cust(self): def validate_proj_cust(self):
"""check for does customer belong to same project as entered..""" """check for does customer belong to same project as entered.."""
if self.doc.project_name and self.doc.customer: if self.doc.project_name and self.doc.customer:

View File

@ -7,13 +7,13 @@ import unittest
import webnotes import webnotes
import webnotes.defaults import webnotes.defaults
from webnotes.utils import cint from webnotes.utils import cint
from accounts.utils import get_stock_and_account_difference from stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries, test_records as pr_test_records
class TestDeliveryNote(unittest.TestCase): class TestDeliveryNote(unittest.TestCase):
def _insert_purchase_receipt(self): def _insert_purchase_receipt(self, item_code=None):
from stock.doctype.purchase_receipt.test_purchase_receipt import test_records as pr_test_records
pr = webnotes.bean(copy=pr_test_records[0]) pr = webnotes.bean(copy=pr_test_records[0])
pr.run_method("calculate_taxes_and_totals") if item_code:
pr.doclist[1].item_code = item_code
pr.insert() pr.insert()
pr.submit() pr.submit()
@ -61,13 +61,14 @@ class TestDeliveryNote(unittest.TestCase):
from `tabGL Entry` where voucher_type='Delivery Note' and voucher_no=%s from `tabGL Entry` where voucher_type='Delivery Note' and voucher_no=%s
order by account desc""", dn.doc.name, as_dict=1) order by account desc""", dn.doc.name, as_dict=1)
self.assertTrue(not gl_entries) self.assertFalse(get_gl_entries("Delivery Note", dn.doc.name))
def test_delivery_note_gl_entry(self): def test_delivery_note_gl_entry(self):
self.clear_stock_account_balance() self.clear_stock_account_balance()
webnotes.defaults.set_global_default("perpetual_accounting", 1) webnotes.defaults.set_global_default("perpetual_accounting", 1)
self.assertEqual(cint(webnotes.defaults.get_global_default("perpetual_accounting")), 1) self.assertEqual(cint(webnotes.defaults.get_global_default("perpetual_accounting")), 1)
webnotes.conn.set_value("Item", "_Test Item", "valuation_method", "FIFO")
self._insert_purchase_receipt() self._insert_purchase_receipt()
@ -84,25 +85,78 @@ class TestDeliveryNote(unittest.TestCase):
dn.insert() dn.insert()
dn.submit() dn.submit()
gl_entries = get_gl_entries("Delivery Note", dn.doc.name)
gl_entries = webnotes.conn.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Delivery Note' and voucher_no=%s
order by account asc""", dn.doc.name, as_dict=1)
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
expected_values = {
expected_values = sorted([ stock_in_hand_account: [0.0, 375.0],
[stock_in_hand_account, 0.0, 375.0], "Cost of Goods Sold - _TC": [375.0, 0.0]
["Cost of Goods Sold - _TC", 375.0, 0.0] }
])
for i, gle in enumerate(gl_entries): for i, gle in enumerate(gl_entries):
self.assertEquals(expected_values[i][0], gle.account) self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account))
self.assertEquals(expected_values[i][1], gle.debit)
self.assertEquals(expected_values[i][2], gle.credit)
# check stock in hand balance # check stock in hand balance
bal = get_balance_on(stock_in_hand_account, dn.doc.posting_date) bal = get_balance_on(stock_in_hand_account, dn.doc.posting_date)
self.assertEquals(bal, prev_bal - 375.0) self.assertEquals(bal, prev_bal - 375.0)
self.assertFalse(get_stock_and_account_difference([dn.doclist[1].warehouse]))
# back dated purchase receipt
pr = webnotes.bean(copy=pr_test_records[0])
pr.doc.posting_date = "2013-01-01"
pr.doclist[1].import_rate = 100
pr.doclist[1].amount = 100
pr.insert()
pr.submit()
gl_entries = get_gl_entries("Delivery Note", dn.doc.name)
self.assertTrue(gl_entries)
expected_values = {
stock_in_hand_account: [0.0, 666.65],
"Cost of Goods Sold - _TC": [666.65, 0.0]
}
for i, gle in enumerate(gl_entries):
self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account))
dn.cancel()
self.assertFalse(get_gl_entries("Delivery Note", dn.doc.name))
webnotes.defaults.set_global_default("perpetual_accounting", 0)
def test_delivery_note_gl_entry_packing_item(self):
self.clear_stock_account_balance()
webnotes.defaults.set_global_default("perpetual_accounting", 1)
self._insert_purchase_receipt()
self._insert_purchase_receipt("_Test Item Home Desktop 100")
dn = webnotes.bean(copy=test_records[0])
dn.doclist[1].item_code = "_Test Sales BOM Item"
dn.doclist[1].qty = 1
stock_in_hand_account = webnotes.conn.get_value("Warehouse", dn.doclist[1].warehouse,
"account")
from accounts.utils import get_balance_on
prev_bal = get_balance_on(stock_in_hand_account, dn.doc.posting_date)
dn.insert()
dn.submit()
gl_entries = get_gl_entries("Delivery Note", dn.doc.name)
self.assertTrue(gl_entries)
expected_values = {
stock_in_hand_account: [0.0, 525],
"Cost of Goods Sold - _TC": [525.0, 0.0]
}
for i, gle in enumerate(gl_entries):
self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account))
# check stock in hand balance
bal = get_balance_on(stock_in_hand_account, dn.doc.posting_date)
self.assertEquals(bal, prev_bal - 525.0)
dn.cancel()
self.assertFalse(get_gl_entries("Delivery Note", dn.doc.name))
webnotes.defaults.set_global_default("perpetual_accounting", 0) webnotes.defaults.set_global_default("perpetual_accounting", 0)
@ -163,6 +217,8 @@ class TestDeliveryNote(unittest.TestCase):
webnotes.conn.sql("delete from `tabStock Ledger Entry`") webnotes.conn.sql("delete from `tabStock Ledger Entry`")
webnotes.conn.sql("delete from `tabGL Entry`") webnotes.conn.sql("delete from `tabGL Entry`")
test_dependencies = ["Sales BOM"]
test_records = [ test_records = [
[ [
{ {
@ -196,8 +252,10 @@ test_records = [
"export_rate": 100.0, "export_rate": 100.0,
"amount": 500.0, "amount": 500.0,
"warehouse": "_Test Warehouse - _TC", "warehouse": "_Test Warehouse - _TC",
"stock_uom": "_Test UOM" "stock_uom": "_Test UOM",
"expense_account": "Cost of Goods Sold - _TC",
"cost_center": "Main - _TC"
} }
] ]
] ]

View File

@ -302,11 +302,8 @@ class DocType(BuyingController):
def get_gl_entries_for_stock(self): def get_gl_entries_for_stock(self):
against_stock_account = self.get_company_default("stock_received_but_not_billed") against_stock_account = self.get_company_default("stock_received_but_not_billed")
item_acc_map = {}
for item in self.doclist.get({"parentfield": "purchase_receipt_details"}): gl_entries = super(DocType, self).get_gl_entries_for_stock(against_stock_account, None)
item_acc_map.setdefault(item.name, [against_stock_account, None])
gl_entries = super(DocType, self).get_gl_entries_for_stock(item_acc_map)
return gl_entries return gl_entries

View File

@ -50,11 +50,7 @@ class TestPurchaseReceipt(unittest.TestCase):
"warehouse": "_Test Warehouse - _TC"}, "stock_value") "warehouse": "_Test Warehouse - _TC"}, "stock_value")
self.assertEqual(bin_stock_value, 375) self.assertEqual(bin_stock_value, 375)
gl_entries = webnotes.conn.sql("""select account, debit, credit self.assertFalse(get_gl_entries("Purchase Receipt", pr.doc.name))
from `tabGL Entry` where voucher_type='Purchase Receipt' and voucher_no=%s
order by account desc""", pr.doc.name, as_dict=1)
self.assertTrue(not gl_entries)
def test_purchase_receipt_gl_entry(self): def test_purchase_receipt_gl_entry(self):
webnotes.defaults.set_global_default("perpetual_accounting", 1) webnotes.defaults.set_global_default("perpetual_accounting", 1)
@ -66,14 +62,12 @@ class TestPurchaseReceipt(unittest.TestCase):
pr.insert() pr.insert()
pr.submit() pr.submit()
gl_entries = webnotes.conn.sql("""select account, debit, credit gl_entries = get_gl_entries("Purchase Receipt", pr.doc.name)
from `tabGL Entry` where voucher_type='Purchase Receipt' and voucher_no=%s
order by account desc""", pr.doc.name, as_dict=1)
self.assertTrue(gl_entries) self.assertTrue(gl_entries)
stock_in_hand_account = webnotes.conn.get_value("Warehouse", pr.doclist[1].warehouse, stock_in_hand_account = webnotes.conn.get_value("Warehouse", pr.doclist[1].warehouse,
"account") "account")
fixed_asset_account = webnotes.conn.get_value("Warehouse", pr.doclist[2].warehouse, fixed_asset_account = webnotes.conn.get_value("Warehouse", pr.doclist[2].warehouse,
"account") "account")
@ -87,9 +81,9 @@ class TestPurchaseReceipt(unittest.TestCase):
self.assertEquals(expected_values[gle.account][0], gle.debit) self.assertEquals(expected_values[gle.account][0], gle.debit)
self.assertEquals(expected_values[gle.account][1], gle.credit) self.assertEquals(expected_values[gle.account][1], gle.credit)
self.assertFalse(get_stock_and_account_difference([pr.doclist[1].warehouse, pr.cancel()
pr.doclist[2].warehouse])) self.assertFalse(get_gl_entries("Purchase Receipt", pr.doc.name))
webnotes.defaults.set_global_default("perpetual_accounting", 0) webnotes.defaults.set_global_default("perpetual_accounting", 0)
def _clear_stock_account_balance(self): def _clear_stock_account_balance(self):
@ -126,6 +120,11 @@ class TestPurchaseReceipt(unittest.TestCase):
self.assertEqual(webnotes.conn.get_value("Serial No", pr.doclist[1].serial_no, self.assertEqual(webnotes.conn.get_value("Serial No", pr.doclist[1].serial_no,
"status"), "Not Available") "status"), "Not Available")
def get_gl_entries(voucher_type, voucher_no):
return webnotes.conn.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type=%s and voucher_no=%s
order by account desc""", (voucher_type, voucher_no), as_dict=1)

View File

@ -320,7 +320,7 @@ class DocType(StockController):
sl_entries.append(self.get_sl_entries(d, { sl_entries.append(self.get_sl_entries(d, {
"warehouse": cstr(d.s_warehouse), "warehouse": cstr(d.s_warehouse),
"actual_qty": -flt(d.transfer_qty), "actual_qty": -flt(d.transfer_qty),
"incoming_rate": flt(d.incoming_rate) "incoming_rate": 0
})) }))
if cstr(d.t_warehouse): if cstr(d.t_warehouse):

View File

@ -298,8 +298,8 @@ class DocType(StockController):
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)
super(DocType, self).get_gl_entries_for_stock(expense_account=self.doc.expense_account, return super(DocType, self).get_gl_entries_for_stock(self.doc.expense_account,
cost_center=self.doc.cost_center) self.doc.cost_center)
def validate_expense_account(self): def validate_expense_account(self):

View File

@ -12,7 +12,7 @@ from accounts.utils import get_fiscal_year, get_stock_and_account_difference, ge
class TestStockReconciliation(unittest.TestCase): class TestStockReconciliation(unittest.TestCase):
def atest_reco_for_fifo(self): def test_reco_for_fifo(self):
webnotes.defaults.set_global_default("perpetual_accounting", 0) webnotes.defaults.set_global_default("perpetual_accounting", 0)
# [[qty, valuation_rate, posting_date, # [[qty, valuation_rate, posting_date,
# posting_time, expected_stock_value, bin_qty, bin_valuation]] # posting_time, expected_stock_value, bin_qty, bin_valuation]]
@ -90,7 +90,6 @@ class TestStockReconciliation(unittest.TestCase):
self.assertEqual(res and flt(res[0][0], 4) or 0, d[4]) self.assertEqual(res and flt(res[0][0], 4) or 0, d[4])
# bin qty and stock value # bin qty and stock value
print "bin"
bin = webnotes.conn.sql("""select actual_qty, stock_value from `tabBin` bin = webnotes.conn.sql("""select actual_qty, stock_value from `tabBin`
where item_code = '_Test Item' and warehouse = '_Test Warehouse - _TC'""") where item_code = '_Test Item' and warehouse = '_Test Warehouse - _TC'""")
@ -103,7 +102,7 @@ class TestStockReconciliation(unittest.TestCase):
stock_reco.doc.name) stock_reco.doc.name)
self.assertFalse(gl_entries) self.assertFalse(gl_entries)
def atest_reco_fifo_gl_entries(self): def test_reco_fifo_gl_entries(self):
webnotes.defaults.set_global_default("perpetual_accounting", 1) webnotes.defaults.set_global_default("perpetual_accounting", 1)
# [[qty, valuation_rate, posting_date, posting_time, stock_in_hand_debit]] # [[qty, valuation_rate, posting_date, posting_time, stock_in_hand_debit]]
@ -120,23 +119,23 @@ class TestStockReconciliation(unittest.TestCase):
[50, 1000, "2013-01-01", "12:00"], [50, 1000, "2013-01-01", "12:00"],
[5, 1000, "2013-01-01", "12:00"], [5, 1000, "2013-01-01", "12:00"],
[1, 1000, "2012-12-01", "00:00"], [1, 1000, "2012-12-01", "00:00"],
] ]
for d in input_data: for d in input_data:
# print d[0], d[1], d[2], d[3]
self.cleanup_data() self.cleanup_data()
self.insert_existing_sle("FIFO") self.insert_existing_sle("FIFO")
self.assertFalse(get_stock_and_account_difference(["_Test Account Stock In Hand - _TC"]))
stock_reco = self.submit_stock_reconciliation(d[0], d[1], d[2], d[3]) stock_reco = self.submit_stock_reconciliation(d[0], d[1], d[2], d[3])
self.assertFalse(get_stock_and_account_difference(["_Test Warehouse - _TC"]))
# cancel
stock_reco.cancel()
self.assertFalse(get_stock_and_account_difference(["_Test Warehouse - _TC"]))
webnotes.defaults.set_global_default("perpetual_accounting", 0)
def atest_reco_moving_average_gl_entries(self): self.assertFalse(get_stock_and_account_difference(["_Test Account Stock In Hand - _TC"]))
stock_reco.cancel()
self.assertFalse(get_stock_and_account_difference(["_Test Account Stock In Hand - _TC"]))
webnotes.defaults.set_global_default("perpetual_accounting", 0)
def test_reco_moving_average_gl_entries(self):
webnotes.defaults.set_global_default("perpetual_accounting", 1) webnotes.defaults.set_global_default("perpetual_accounting", 1)
# [[qty, valuation_rate, posting_date, # [[qty, valuation_rate, posting_date,
@ -259,6 +258,7 @@ class TestStockReconciliation(unittest.TestCase):
pr3.insert() pr3.insert()
pr3.submit() pr3.submit()
pr4 = webnotes.bean(copy=stock_entry) pr4 = webnotes.bean(copy=stock_entry)
pr4.doc.posting_date = "2013-01-05" pr4.doc.posting_date = "2013-01-05"
pr4.doc.fiscal_year = "_Test Fiscal Year 2013" pr4.doc.fiscal_year = "_Test Fiscal Year 2013"