fix: Check for backdated validation only for transaction company (#23639)
* fix: Check SLE only for transaction company * fix: Add tests * fix: Move backdated entry validation from transaction base to stock ledger entry * chore: Add tests Co-authored-by: Nabin Hait <nabinhait@gmail.com>
This commit is contained in:
parent
e0cb6c3b9d
commit
8859b71956
@ -6,7 +6,7 @@ import unittest
|
||||
import json
|
||||
import frappe, erpnext
|
||||
import frappe.defaults
|
||||
from frappe.utils import cint, flt, cstr, today, random_string
|
||||
from frappe.utils import cint, flt, cstr, today, random_string, add_days
|
||||
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice
|
||||
from erpnext.stock.doctype.item.test_item import create_item
|
||||
from erpnext import set_perpetual_inventory
|
||||
@ -665,6 +665,59 @@ class TestPurchaseReceipt(unittest.TestCase):
|
||||
warehouse.account = ''
|
||||
warehouse.save()
|
||||
|
||||
def test_backdated_purchase_receipt(self):
|
||||
# make purchase receipt for default company
|
||||
make_purchase_receipt(company="_Test Company 4", warehouse="Stores - _TC4")
|
||||
|
||||
# try to make another backdated PR
|
||||
posting_date = add_days(today(), -1)
|
||||
pr = make_purchase_receipt(company="_Test Company 4", warehouse="Stores - _TC4",
|
||||
do_not_submit=True)
|
||||
|
||||
pr.set_posting_time = 1
|
||||
pr.posting_date = posting_date
|
||||
pr.save()
|
||||
|
||||
self.assertRaises(frappe.ValidationError, pr.submit)
|
||||
|
||||
# make purchase receipt for other company backdated
|
||||
pr = make_purchase_receipt(company="_Test Company 5", warehouse="Stores - _TC5",
|
||||
do_not_submit=True)
|
||||
|
||||
pr.set_posting_time = 1
|
||||
pr.posting_date = posting_date
|
||||
pr.submit()
|
||||
|
||||
# Allowed to submit for other company's PR
|
||||
self.assertEqual(pr.docstatus, 1)
|
||||
|
||||
def test_backdated_purchase_receipt_for_same_company_different_warehouse(self):
|
||||
# make purchase receipt for default company
|
||||
make_purchase_receipt(company="_Test Company 4", warehouse="Stores - _TC4")
|
||||
|
||||
# try to make another backdated PR
|
||||
posting_date = add_days(today(), -1)
|
||||
pr = make_purchase_receipt(company="_Test Company 4", warehouse="Stores - _TC4",
|
||||
do_not_submit=True)
|
||||
|
||||
pr.set_posting_time = 1
|
||||
pr.posting_date = posting_date
|
||||
pr.save()
|
||||
|
||||
self.assertRaises(frappe.ValidationError, pr.submit)
|
||||
|
||||
# make purchase receipt for other company backdated
|
||||
pr = make_purchase_receipt(company="_Test Company 4", warehouse="Finished Goods - _TC4",
|
||||
do_not_submit=True)
|
||||
|
||||
pr.set_posting_time = 1
|
||||
pr.posting_date = posting_date
|
||||
pr.submit()
|
||||
|
||||
# Allowed to submit for other company's PR
|
||||
self.assertEqual(pr.docstatus, 1)
|
||||
|
||||
|
||||
def get_sl_entries(voucher_type, voucher_no):
|
||||
return frappe.db.sql(""" select actual_qty, warehouse, stock_value_difference
|
||||
from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s
|
||||
|
@ -5,7 +5,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt, getdate, add_days, formatdate
|
||||
from frappe.utils import flt, getdate, add_days, formatdate, get_datetime, date_diff
|
||||
from frappe.model.document import Document
|
||||
from datetime import date
|
||||
from erpnext.controllers.item_variant import ItemTemplateCannotHaveStock
|
||||
@ -33,6 +33,8 @@ class StockLedgerEntry(Document):
|
||||
self.scrub_posting_time()
|
||||
self.validate_and_set_fiscal_year()
|
||||
self.block_transactions_against_group_warehouse()
|
||||
self.validate_with_last_transaction_posting_time()
|
||||
self.validate_future_posting()
|
||||
|
||||
def on_submit(self):
|
||||
self.check_stock_frozen_date()
|
||||
@ -139,6 +141,30 @@ class StockLedgerEntry(Document):
|
||||
from erpnext.stock.utils import is_group_warehouse
|
||||
is_group_warehouse(self.warehouse)
|
||||
|
||||
def validate_with_last_transaction_posting_time(self):
|
||||
last_transaction_time = frappe.db.sql("""
|
||||
select MAX(timestamp(posting_date, posting_time)) as posting_time
|
||||
from `tabStock Ledger Entry`
|
||||
where docstatus = 1 and item_code = %s
|
||||
and warehouse = %s""", (self.item_code, self.warehouse))[0][0]
|
||||
|
||||
cur_doc_posting_datetime = "%s %s" % (self.posting_date, self.get("posting_time") or "00:00:00")
|
||||
|
||||
if last_transaction_time and get_datetime(cur_doc_posting_datetime) < get_datetime(last_transaction_time):
|
||||
msg = _("Last Stock Transaction for item {0} under warehouse {1} was on {2}.").format(frappe.bold(self.item_code),
|
||||
frappe.bold(self.warehouse), frappe.bold(last_transaction_time))
|
||||
|
||||
msg += "<br><br>" + _("Stock Transactions for Item {0} under warehouse {1} cannot be posted before this time.").format(
|
||||
frappe.bold(self.item_code), frappe.bold(self.warehouse))
|
||||
|
||||
msg += "<br><br>" + _("Please remove this item and try to submit again or update the posting time.")
|
||||
frappe.throw(msg, title=_("Backdated Stock Entry"))
|
||||
|
||||
def validate_future_posting(self):
|
||||
if date_diff(self.posting_date, getdate()) > 0:
|
||||
msg = _("Posting future stock transactions are not allowed due to Immutable Ledger")
|
||||
frappe.throw(msg, title=_("Future Posting Not Allowed"))
|
||||
|
||||
def on_doctype_update():
|
||||
if not frappe.db.has_index('tabStock Ledger Entry', 'posting_sort_index'):
|
||||
frappe.db.commit()
|
||||
|
@ -29,28 +29,6 @@ class TransactionBase(StatusUpdater):
|
||||
except ValueError:
|
||||
frappe.throw(_('Invalid Posting Time'))
|
||||
|
||||
self.validate_future_posting()
|
||||
self.validate_with_last_transaction_posting_time()
|
||||
|
||||
def is_stock_transaction(self):
|
||||
if self.doctype not in ["Sales Invoice", "Purchase Invoice", "Stock Entry", "Stock Reconciliation",
|
||||
"Delivery Note", "Purchase Receipt", "Fees"]:
|
||||
return False
|
||||
|
||||
if self.doctype in ["Sales Invoice", "Purchase Invoice"]:
|
||||
if not (self.get("update_stock") or self.get("is_pos")):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def validate_future_posting(self):
|
||||
if not self.is_stock_transaction():
|
||||
return
|
||||
|
||||
if getattr(self, 'set_posting_time', None) and date_diff(self.posting_date, nowdate()) > 0:
|
||||
msg = _("Posting future transactions are not allowed due to Immutable Ledger")
|
||||
frappe.throw(msg, title=_("Future Posting Not Allowed"))
|
||||
|
||||
def add_calendar_event(self, opts, force=False):
|
||||
if cstr(self.contact_by) != cstr(self._prev.contact_by) or \
|
||||
cstr(self.contact_date) != cstr(self._prev.contact_date) or force or \
|
||||
@ -180,25 +158,6 @@ class TransactionBase(StatusUpdater):
|
||||
|
||||
return ret
|
||||
|
||||
def validate_with_last_transaction_posting_time(self):
|
||||
|
||||
if not self.is_stock_transaction():
|
||||
return
|
||||
|
||||
for item in self.get('items'):
|
||||
last_transaction_time = frappe.db.sql("""
|
||||
select MAX(timestamp(posting_date, posting_time)) as posting_time
|
||||
from `tabStock Ledger Entry`
|
||||
where docstatus = 1 and item_code = %s """, (item.item_code))[0][0]
|
||||
|
||||
cur_doc_posting_datetime = "%s %s" % (self.posting_date, self.get("posting_time") or "00:00:00")
|
||||
|
||||
if last_transaction_time and get_datetime(cur_doc_posting_datetime) < get_datetime(last_transaction_time):
|
||||
msg = _("Last Stock Transaction for item {0} was on {1}.").format(frappe.bold(item.item_code), frappe.bold(last_transaction_time))
|
||||
msg += "<br><br>" + _("Stock Transactions for Item {0} cannot be posted before this time.").format(frappe.bold(item.item_code))
|
||||
msg += "<br><br>" + _("Please remove this item and try to submit again or update the posting time.")
|
||||
frappe.throw(msg, title=_("Backdated Stock Entry"))
|
||||
|
||||
def delete_events(ref_type, ref_name):
|
||||
events = frappe.db.sql_list(""" SELECT
|
||||
distinct `tabEvent`.name
|
||||
|
Loading…
x
Reference in New Issue
Block a user