diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index 5a573f9441..e98dfdc2a0 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -565,16 +565,17 @@ class TestSalesInvoice(unittest.TestCase): where against_invoice=%s""", si.doc.name)) def test_recurring_invoice(self): - from webnotes.utils import now_datetime, get_first_day, get_last_day, add_to_date - today = now_datetime().date() - + from webnotes.utils import get_first_day, get_last_day, add_to_date, nowdate, getdate + from accounts.utils import get_fiscal_year + today = nowdate() base_si = webnotes.bean(copy=test_records[0]) base_si.doc.fields.update({ "convert_into_recurring_invoice": 1, "recurring_type": "Monthly", "notification_email_address": "test@example.com, test1@example.com, test2@example.com", - "repeat_on_day_of_month": today.day, + "repeat_on_day_of_month": getdate(today).day, "posting_date": today, + "fiscal_year": get_fiscal_year(today)[0], "invoice_period_from_date": get_first_day(today), "invoice_period_to_date": get_last_day(today) }) diff --git a/accounts/utils.py b/accounts/utils.py index a5fb390e9f..fdd57b35c2 100644 --- a/accounts/utils.py +++ b/accounts/utils.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import webnotes -from webnotes.utils import nowdate, nowtime, cstr, flt, now, getdate, add_months +from webnotes.utils import nowdate, cstr, flt, now, getdate, add_months from webnotes.model.doc import addchild from webnotes import msgprint, _ from webnotes.utils import formatdate @@ -64,7 +64,6 @@ def get_balance_on(account=None, date=None): try: year_start_date = get_fiscal_year(date, verbose=0)[1] except FiscalYearError, e: - from webnotes.utils import getdate if getdate(date) > getdate(nowdate()): # if fiscal year not found and the date is greater than today # get fiscal year for today's date and its corresponding year start date @@ -222,17 +221,26 @@ def get_cost_center_list(doctype, txt, searchfield, start, page_len, filters): tuple(filter_values + ["%%%s%%" % txt, start, page_len])) def remove_against_link_from_jv(ref_type, ref_no, against_field): - webnotes.conn.sql("""update `tabJournal Voucher Detail` set `%s`=null, - modified=%s, modified_by=%s - where `%s`=%s and docstatus < 2""" % (against_field, "%s", "%s", against_field, "%s"), - (now(), webnotes.session.user, ref_no)) + linked_jv = webnotes.conn.sql_list("""select parent from `tabJournal Voucher Detail` + where `%s`=%s and docstatus < 2""" % (against_field, "%s"), (ref_no)) + + if linked_jv: + webnotes.conn.sql("""update `tabJournal Voucher Detail` set `%s`=null, + modified=%s, modified_by=%s + where `%s`=%s and docstatus < 2""" % (against_field, "%s", "%s", against_field, "%s"), + (now(), webnotes.session.user, ref_no)) - webnotes.conn.sql("""update `tabGL Entry` - set against_voucher_type=null, against_voucher=null, - modified=%s, modified_by=%s - where against_voucher_type=%s and against_voucher=%s - and voucher_no != ifnull(against_voucher, '')""", - (now(), webnotes.session.user, ref_type, ref_no)) + webnotes.conn.sql("""update `tabGL Entry` + set against_voucher_type=null, against_voucher=null, + modified=%s, modified_by=%s + where against_voucher_type=%s and against_voucher=%s + and voucher_no != ifnull(against_voucher, '')""", + (now(), webnotes.session.user, ref_type, ref_no)) + + webnotes.msgprint("{msg} {linked_jv}".format(msg = _("""Following linked Journal Vouchers \ + made against this transaction has been unlinked. You can link them again with other \ + transactions via Payment Reconciliation Tool."""), linked_jv="\n".join(linked_jv))) + @webnotes.whitelist() def get_company_default(company, fieldname): @@ -370,4 +378,4 @@ def get_account_for(account_for_doctype, account_for): account_for_field = "account_type" return webnotes.conn.get_value("Account", {account_for_field: account_for_doctype, - "master_name": account_for}) + "master_name": account_for}) \ No newline at end of file diff --git a/buying/doctype/purchase_order/test_purchase_order.py b/buying/doctype/purchase_order/test_purchase_order.py index f6c435c6fb..e1933982c4 100644 --- a/buying/doctype/purchase_order/test_purchase_order.py +++ b/buying/doctype/purchase_order/test_purchase_order.py @@ -22,7 +22,7 @@ class TestPurchaseOrder(unittest.TestCase): pr = make_purchase_receipt(po.doc.name) pr[0]["supplier_warehouse"] = "_Test Warehouse 1 - _TC" - + pr[0]["posting_date"] = "2013-05-12" self.assertEquals(pr[0]["doctype"], "Purchase Receipt") self.assertEquals(len(pr), len(test_records[0])) @@ -52,7 +52,7 @@ class TestPurchaseOrder(unittest.TestCase): self.assertEquals(pr[0]["doctype"], "Purchase Receipt") self.assertEquals(len(pr), len(test_records[0])) - + pr[0]["posting_date"] = "2013-05-12" pr[0].naming_series = "_T-Purchase Receipt-" pr[1].qty = 4.0 pr_bean = webnotes.bean(pr) @@ -66,6 +66,7 @@ class TestPurchaseOrder(unittest.TestCase): pr1 = make_purchase_receipt(po.doc.name) pr1[0].naming_series = "_T-Purchase Receipt-" + pr1[0]["posting_date"] = "2013-05-12" pr1[1].qty = 8 pr1_bean = webnotes.bean(pr1) pr1_bean.insert() @@ -88,7 +89,7 @@ class TestPurchaseOrder(unittest.TestCase): self.assertEquals(pi[0]["doctype"], "Purchase Invoice") self.assertEquals(len(pi), len(test_records[0])) - + pi[0]["posting_date"] = "2013-05-12" pi[0].bill_no = "NA" webnotes.bean(pi).insert() diff --git a/config.json b/config.json index 89c1332005..536e5af1ba 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "app_name": "ERPNext", - "app_version": "3.4.5", + "app_version": "3.4.6", "base_template": "app/portal/templates/base.html", "modules": { "Accounts": { diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index 11480c9ebe..1a399219e4 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -381,24 +381,41 @@ class AccountsController(TransactionBase): }) def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield): + from controllers.status_updater import get_tolerance_for + item_tolerance = {} + global_tolerance = None + for item in self.doclist.get({"parentfield": "entries"}): if item.fields.get(item_ref_dn): already_billed = webnotes.conn.sql("""select sum(%s) from `tab%s` where %s=%s and docstatus=1""" % (based_on, self.tname, item_ref_dn, '%s'), item.fields[item_ref_dn])[0][0] - max_allowed_amt = flt(webnotes.conn.get_value(ref_dt + " Item", - item.fields[item_ref_dn], based_on), self.precision(based_on, item)) - total_billed_amt = flt(flt(already_billed) + flt(item.fields[based_on]), self.precision(based_on, item)) + + ref_amt = flt(webnotes.conn.get_value(ref_dt + " Item", + item.fields[item_ref_dn], based_on), self.precision(based_on, item)) + + tolerance, item_tolerance, global_tolerance = get_tolerance_for(item.item_code, + item_tolerance, global_tolerance) - if max_allowed_amt and total_billed_amt - max_allowed_amt > 0.02: - webnotes.msgprint(_("Row ")+ cstr(item.idx) + ": " + cstr(item.item_code) + - _(" will be over-billed against mentioned ") + cstr(ref_dt) + - _(". Max allowed " + cstr(based_on) + ": " + cstr(max_allowed_amt)), - raise_exception=1) - + max_allowed_amt = flt(ref_amt * (100 + tolerance) / 100) + + if total_billed_amt - max_allowed_amt > 0.01: + reduce_by = total_billed_amt - max_allowed_amt + + webnotes.throw(_("Row #") + cstr(item.idx) + ": " + + _(" Max amount allowed for Item ") + cstr(item.item_code) + + _(" against ") + ref_dt + " " + + cstr(item.fields[ref_dt.lower().replace(" ", "_")]) + _(" is ") + + cstr(max_allowed_amt) + ". \n" + + _("""If you want to increase your overflow tolerance, please increase \ + tolerance % in Global Defaults or Item master. + Or, you must reduce the amount by """) + cstr(reduce_by) + "\n" + + _("""Also, please check if the order item has already been billed \ + in the Sales Order""")) + def get_company_default(self, fieldname): from accounts.utils import get_company_default return get_company_default(self.doc.company, fieldname) diff --git a/controllers/status_updater.py b/controllers/status_updater.py index b2745268f7..a285c4798d 100644 --- a/controllers/status_updater.py +++ b/controllers/status_updater.py @@ -151,7 +151,9 @@ class StatusUpdater(DocListController): """ # check if overflow is within tolerance - tolerance = self.get_tolerance_for(item['item_code']) + tolerance, self.tolerance, self.global_tolerance = get_tolerance_for(item['item_code'], + self.tolerance, self.global_tolerance) + overflow_percent = ((item[args['target_field']] - item[args['target_ref_field']]) / item[args['target_ref_field']]) * 100 @@ -170,23 +172,6 @@ class StatusUpdater(DocListController): Also, please check if the order item has already been billed in the Sales Order""" % item, raise_exception=1) - - def get_tolerance_for(self, item_code): - """ - Returns the tolerance for the item, if not set, returns global tolerance - """ - if self.tolerance.get(item_code): return self.tolerance[item_code] - - tolerance = flt(webnotes.conn.get_value('Item',item_code,'tolerance') or 0) - - if not tolerance: - if self.global_tolerance == None: - self.global_tolerance = flt(webnotes.conn.get_value('Global Defaults', None, - 'tolerance')) - tolerance = self.global_tolerance - - self.tolerance[item_code] = tolerance - return tolerance def update_qty(self, change_modified=True): @@ -245,4 +230,22 @@ class StatusUpdater(DocListController): set %(status_field)s = if(ifnull(%(target_parent_field)s,0)<0.001, 'Not %(keyword)s', if(%(target_parent_field)s>=99.99, 'Fully %(keyword)s', 'Partly %(keyword)s')) - where name='%(name)s'""" % args) \ No newline at end of file + where name='%(name)s'""" % args) + +def get_tolerance_for(item_code, item_tolerance={}, global_tolerance=None): + """ + Returns the tolerance for the item, if not set, returns global tolerance + """ + if item_tolerance.get(item_code): + return item_tolerance[item_code], item_tolerance, global_tolerance + + tolerance = flt(webnotes.conn.get_value('Item',item_code,'tolerance') or 0) + + if not tolerance: + if global_tolerance == None: + global_tolerance = flt(webnotes.conn.get_value('Global Defaults', None, + 'tolerance')) + tolerance = global_tolerance + + item_tolerance[item_code] = tolerance + return tolerance, item_tolerance, global_tolerance \ No newline at end of file diff --git a/manufacturing/doctype/production_order/test_production_order.py b/manufacturing/doctype/production_order/test_production_order.py index 52697292c8..ca28708cc1 100644 --- a/manufacturing/doctype/production_order/test_production_order.py +++ b/manufacturing/doctype/production_order/test_production_order.py @@ -34,6 +34,7 @@ class TestProductionOrder(unittest.TestCase): stock_entry = webnotes.bean(stock_entry) stock_entry.doc.fg_completed_qty = 4 + stock_entry.doc.posting_date = "2013-05-12" stock_entry.run_method("get_items") stock_entry.submit() @@ -50,7 +51,7 @@ class TestProductionOrder(unittest.TestCase): stock_entry = make_stock_entry(pro_order, "Manufacture/Repack") stock_entry = webnotes.bean(stock_entry) - + stock_entry.doc.posting_date = "2013-05-12" stock_entry.doc.fg_completed_qty = 15 stock_entry.run_method("get_items") stock_entry.insert() diff --git a/selling/doctype/quotation/test_quotation.py b/selling/doctype/quotation/test_quotation.py index 8f0e644cb9..327d72f2e0 100644 --- a/selling/doctype/quotation/test_quotation.py +++ b/selling/doctype/quotation/test_quotation.py @@ -28,6 +28,7 @@ class TestQuotation(unittest.TestCase): sales_order[0]["delivery_date"] = "2014-01-01" sales_order[0]["naming_series"] = "_T-Quotation-" + sales_order[0]["transaction_date"] = "2013-05-12" webnotes.bean(sales_order).insert() diff --git a/selling/doctype/sales_order/test_sales_order.py b/selling/doctype/sales_order/test_sales_order.py index 1549b24c89..a6fe8fb5bb 100644 --- a/selling/doctype/sales_order/test_sales_order.py +++ b/selling/doctype/sales_order/test_sales_order.py @@ -53,6 +53,7 @@ class TestSalesOrder(unittest.TestCase): self.assertEquals(len([d for d in si if d["doctype"]=="Sales Invoice Item"]), 1) si = webnotes.bean(si) + si.doc.posting_date = "2013-10-10" si.insert() si.submit() diff --git a/stock/doctype/material_request/test_material_request.py b/stock/doctype/material_request/test_material_request.py index c19bfd3928..81ae27d8c2 100644 --- a/stock/doctype/material_request/test_material_request.py +++ b/stock/doctype/material_request/test_material_request.py @@ -125,6 +125,7 @@ class TestMaterialRequest(unittest.TestCase): from stock.doctype.material_request.material_request import make_purchase_order po_doclist = make_purchase_order(mr.doc.name) po_doclist[0].supplier = "_Test Supplier" + po_doclist[0].transaction_date = "2013-07-07" po_doclist[1].qty = 27.0 po_doclist[2].qty = 1.5 po_doclist[1].schedule_date = "2013-07-09" diff --git a/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt b/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt index 9a641c2ba3..1d9397909d 100755 --- a/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt +++ b/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:10", "docstatus": 0, - "modified": "2013-12-18 10:38:39", + "modified": "2014-01-03 18:28:20", "modified_by": "Administrator", "owner": "Administrator" }, @@ -334,6 +334,16 @@ "report_hide": 0, "reqd": 0 }, + { + "default": ":Company", + "depends_on": "eval:sys_defaults.auto_accounting_for_stock", + "doctype": "DocField", + "fieldname": "cost_center", + "fieldtype": "Link", + "label": "Cost Center", + "options": "Cost Center", + "print_hide": 1 + }, { "doctype": "DocField", "fieldname": "project_name",