From 86f5e2e5641b3e53f2b26a37d9e5194149dece54 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 26 Mar 2013 14:25:25 +0530 Subject: [PATCH] aii: gl entries for serial no --- stock/doctype/item/test_item.py | 19 +++ stock/doctype/serial_no/serial_no.py | 42 +++--- stock/doctype/serial_no/test_serial_no.py | 173 ++++++++++++---------- 3 files changed, 131 insertions(+), 103 deletions(-) diff --git a/stock/doctype/item/test_item.py b/stock/doctype/item/test_item.py index f31f245e81..dbbeecc85b 100644 --- a/stock/doctype/item/test_item.py +++ b/stock/doctype/item/test_item.py @@ -146,4 +146,23 @@ test_records = [ "is_sub_contracted_item": "No", "stock_uom": "_Test UOM" }], + [{ + "doctype": "Item", + "item_code": "_Test Serialized Item", + "item_name": "_Test Serialized Item", + "description": "_Test Serialized Item", + "item_group": "_Test Item Group Desktops", + "is_stock_item": "Yes", + "is_asset_item": "No", + "has_batch_no": "No", + "has_serial_no": "Yes", + "is_purchase_item": "Yes", + "is_sales_item": "Yes", + "is_service_item": "No", + "is_sample_item": "No", + "inspection_required": "No", + "is_pro_applicable": "No", + "is_sub_contracted_item": "No", + "stock_uom": "_Test UOM" + }], ] \ No newline at end of file diff --git a/stock/doctype/serial_no/serial_no.py b/stock/doctype/serial_no/serial_no.py index 00f2de7e40..5b15977635 100644 --- a/stock/doctype/serial_no/serial_no.py +++ b/stock/doctype/serial_no/serial_no.py @@ -19,14 +19,11 @@ import webnotes from webnotes.utils import cint, getdate, nowdate import datetime - -sql = webnotes.conn.sql -msgprint = webnotes.msgprint +from webnotes import msgprint, _ +from controllers.stock_controller import StockController -from utilities.transaction_base import TransactionBase - -class DocType(TransactionBase): +class DocType(StockController): def __init__(self, doc, doclist=[]): self.doc = doc self.doclist = doclist @@ -54,21 +51,14 @@ class DocType(TransactionBase): """ Validate whether serial no is required for this item """ - item = sql("select name, has_serial_no from tabItem where name = '%s'" % self.doc.item_code) + item = webnotes.conn.sql("select name, has_serial_no from tabItem where name = '%s'" % self.doc.item_code) if not item: msgprint("Item is not exists in the system", raise_exception=1) elif item[0][1] == 'No': msgprint("To proceed please select 'Yes' in 'Has Serial No' in Item master: '%s'" % self.doc.item_code, raise_exception=1) - # --------- - # validate - # --------- def validate(self): - # import utilities - # utilities.validate_status(self.doc.status, ["In Store", "Delivered", - # "Not in Use", "Purchase Returned"]) - self.validate_warranty_status() self.validate_amc_status() self.validate_warehouse() @@ -77,10 +67,12 @@ class DocType(TransactionBase): def on_update(self): if self.doc.warehouse and self.doc.status == 'In Store' \ and cint(self.doc.sle_exists) == 0 and \ - not sql("""select name from `tabStock Ledger Entry` where serial_no = %s and - ifnull(is_cancelled, 'No') = 'No'""", self.doc.name): + not webnotes.conn.sql("""select name from `tabStock Ledger Entry` + where serial_no = %s and ifnull(is_cancelled, 'No') = 'No'""", self.doc.name): self.make_stock_ledger_entry(1) webnotes.conn.set(self.doc, 'sle_exists', 1) + + self.make_gl_entries() def make_stock_ledger_entry(self, qty): from webnotes.model.code import get_obj @@ -105,15 +97,13 @@ class DocType(TransactionBase): get_obj('Stock Ledger').update_stock(values) - # --------- - # on trash - # --------- def on_trash(self): if self.doc.status == 'Delivered': msgprint("Cannot trash Serial No : %s as it is already Delivered" % (self.doc.name), raise_exception = 1) elif self.doc.status == 'In Store': webnotes.conn.set(self.doc, 'status', 'Not in Use') self.make_stock_ledger_entry(-1) + self.make_gl_entries(cancel=True) def on_cancel(self): @@ -121,6 +111,7 @@ class DocType(TransactionBase): def on_restore(self): self.make_stock_ledger_entry(1) + self.make_gl_entries() def on_rename(self, new, old): """rename serial_no text fields""" @@ -135,7 +126,16 @@ class DocType(TransactionBase): where name=%s""" % (dt[0], '%s', '%s'), ('\n'.join(serial_nos), item[0])) + def make_gl_entries(self, cancel=False): + if not cint(webnotes.defaults.get_global_default("auto_inventory_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 - \ No newline at end of file + if gl_entries: + make_gl_entries(gl_entries, cancel) \ No newline at end of file diff --git a/stock/doctype/serial_no/test_serial_no.py b/stock/doctype/serial_no/test_serial_no.py index ef20de8f47..fb27aa9329 100644 --- a/stock/doctype/serial_no/test_serial_no.py +++ b/stock/doctype/serial_no/test_serial_no.py @@ -1,93 +1,102 @@ # ERPNext - web based ERP (http://erpnext.com) -# Copyright (C) 2012 Web Notes Technologies Pvt Ltd -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - +# For license information, please see license.txt from __future__ import unicode_literals -import unittest -import webnotes -from webnotes.tests import insert_test_data - -company = webnotes.conn.get_default("company") +import webnotes, unittest class TestSerialNo(unittest.TestCase): - def setUp(self): - webnotes.conn.begin() - self.insert_test_data() - - def tearDown(self): - # print "Message Log:", "\n--\n".join(webnotes.message_log) - # print "Debug Log:", "\n--\n".join(webnotes.debug_log) - webnotes.conn.rollback() + def test_aii_gl_entries_for_serial_no_in_store(self): + webnotes.defaults.set_global_default("auto_inventory_accounting", 1) - def test_serialized_stock_entry(self): - data = [["2012-01-01", "01:00", "10001", 400, 400], - ["2012-01-01", "03:00", "10002", 500, 700], - ["2012-01-01", "04:00", "10003", 700, 700], - ["2012-01-01", "05:00", "10004", 1200, 800], - ["2012-01-01", "05:00", "10005", 800, 800], - ["2012-01-01", "02:00", "10006", 1200, 800], - ["2012-01-01", "06:00", "10007", 1500, 900]] - for d in data: - webnotes.bean([{ - "doctype": "Serial No", - "item_code": "Nebula 8", - "warehouse": "Default Warehouse", - "status": "In Store", - "sle_exists": 0, - "purchase_date": d[0], - "purchase_time": d[1], - "serial_no": d[2], - "purchase_rate": d[3], - "company": company, - }]).insert() + sr = webnotes.bean(copy=test_records[0]) + sr.doc.serial_no = "_Test Serial No 1" + sr.insert() + + stock_in_hand_account = webnotes.conn.get_value("Company", "_Test Company", + "stock_in_hand_account") + against_stock_account = webnotes.conn.get_value("Company", "_Test Company", + "stock_adjustment_account") + + # check stock ledger entries + sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry` + where voucher_type = 'Serial No' and voucher_no = %s""", sr.doc.name, as_dict=1)[0] + self.assertTrue(sle) + self.assertEquals([sle.item_code, sle.warehouse, sle.actual_qty], + ["_Test Serialized Item", "_Test Warehouse", 1.0]) - for d in data: - res = webnotes.conn.sql("""select valuation_rate from `tabStock Ledger Entry` - where posting_date=%s and posting_time=%s and actual_qty=1 and serial_no=%s""", - (d[0], d[1], d[2])) - self.assertEquals(res[0][0], d[4]) + # check gl entries + gl_entries = webnotes.conn.sql("""select account, debit, credit + from `tabGL Entry` where voucher_type='Serial No' and voucher_no=%s + order by account desc""", sr.doc.name, as_dict=1) + self.assertTrue(gl_entries) - print "deleted" - webnotes.delete_doc("Serial No", "10002") + expected_values = [ + [stock_in_hand_account, 1000.0, 0.0], + [against_stock_account, 0.0, 1000.0] + ] - test_data = [["10001", 400, 400], - ["10003", 700, 766.666667], - ["10004", 1200, 875], - ["10005", 800, 860], - ["10006", 1200, 800], - ["10007", 1500, 966.666667]] + for i, gle in enumerate(gl_entries): + self.assertEquals(expected_values[i][0], gle.account) + self.assertEquals(expected_values[i][1], gle.debit) + self.assertEquals(expected_values[i][2], gle.credit) - for d in test_data: - res = webnotes.conn.sql("""select valuation_rate from `tabStock Ledger Entry` - where actual_qty=1 and serial_no=%s""", (d[0],)) - self.assertEquals(res[0][0], d[2]) + sr.load_from_db() + self.assertEquals(sr.doc.sle_exists, 1) + + # save again + sr.save() + gl_entries = webnotes.conn.sql("""select account, debit, credit + from `tabGL Entry` where voucher_type='Serial No' and voucher_no=%s + order by account desc""", sr.doc.name, as_dict=1) + + for i, gle in enumerate(gl_entries): + self.assertEquals(expected_values[i][0], gle.account) + self.assertEquals(expected_values[i][1], gle.debit) + self.assertEquals(expected_values[i][2], gle.credit) + + # trash/cancel + sr.submit() + sr.cancel() + + gl_count = webnotes.conn.sql("""select count(name) from `tabGL Entry` + where voucher_type='Serial No' and voucher_no=%s and ifnull(is_cancelled, 'No') = 'Yes' + order by account asc, name asc""", sr.doc.name) + + self.assertEquals(gl_count[0][0], 4) + + webnotes.defaults.set_global_default("auto_inventory_accounting", 0) + + + def test_aii_gl_entries_for_serial_no_delivered(self): + webnotes.defaults.set_global_default("auto_inventory_accounting", 1) + + sr = webnotes.bean(copy=test_records[0]) + sr.doc.serial_no = "_Test Serial No 2" + sr.doc.status = "Delivered" + sr.insert() + + gl_entries = webnotes.conn.sql("""select account, debit, credit + from `tabGL Entry` where voucher_type='Serial No' and voucher_no=%s + order by account desc""", sr.doc.name, as_dict=1) + self.assertFalse(gl_entries) + + webnotes.defaults.set_global_default("auto_inventory_accounting", 0) - def insert_test_data(self): - # create default warehouse - if not webnotes.conn.exists("Warehouse", "Default Warehouse"): - webnotes.insert({"doctype": "Warehouse", - "warehouse_name": "Default Warehouse", - "warehouse_type": "Stores"}) - - # create UOM: Nos. - if not webnotes.conn.exists("UOM", "Nos"): - webnotes.insert({"doctype": "UOM", "uom_name": "Nos"}) - - # create item groups and items - insert_test_data("Item Group", - sort_fn=lambda ig: (ig[0].get('parent_item_group'), ig[0].get('name'))) - - insert_test_data("Item") \ No newline at end of file + +test_records = [ + [ + { + "company": "_Test Company", + "doctype": "Serial No", + "serial_no": "_Test Serial No", + "status": "In Store", + "item_code": "_Test Serialized Item", + "item_group": "_Test Item Group", + "warehouse": "_Test Warehouse", + "purchase_rate": 1000.0, + "purchase_time": "11:37:39", + "purchase_date": "2013-02-26", + 'fiscal_year': "_Test Fiscal Year 2013" + } + ] +] \ No newline at end of file