fix: Dependant sle logic fixes (#24489)

* fix: Dependant sle logic fixes

* fix: negative qty validation

* fix: Travis fixes
This commit is contained in:
Nabin Hait 2021-02-02 22:03:07 +05:30 committed by GitHub
parent 7d64a291b8
commit 7177579051
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 29 additions and 51 deletions

View File

@ -544,7 +544,7 @@ class TestWorkOrder(unittest.TestCase):
expected_qty = {"_Test Item": 2, "_Test Item Home Desktop 100": 4}
for row in ste3.items:
self.assertEquals(row.qty, expected_qty.get(row.item_code))
ste_cancel_list.reverse()
for ste_doc in ste_cancel_list:
ste_doc.cancel()
@ -586,7 +586,7 @@ class TestWorkOrder(unittest.TestCase):
for ste_row in ste2.items:
if itemwise_qty.get(ste_row.item_code) and ste_row.s_warehouse:
self.assertEquals(ste_row.qty, itemwise_qty.get(ste_row.item_code) / 2)
ste_cancel_list.reverse()
for ste_doc in ste_cancel_list:
ste_doc.cancel()

View File

@ -26,7 +26,6 @@ class TestUnitedStates(unittest.TestCase):
make_payment_entry_to_irs_1099_supplier()
filters = frappe._dict({"fiscal_year": "_Test Fiscal Year 2016", "company": "_Test Company 1"})
columns, data = execute_1099_report(filters)
print(columns, data)
expected_row = {'supplier': '_US 1099 Test Supplier',
'supplier_group': 'Services',
'payments': 100.0,

View File

@ -98,8 +98,6 @@ class ItemGroup(NestedSet, WebsiteGenerator):
context.field_filters = filter_engine.get_field_filters()
context.attribute_filters = filter_engine.get_attribute_fitlers()
print(context.field_filters, context.attribute_filters)
context.update({
"parents": get_parent_item_groups(self.parent_item_group),
"title": self.name

View File

@ -16,7 +16,6 @@ class ProductFiltersBuilder:
def get_field_filters(self):
filter_fields = [row.fieldname for row in self.doc.filter_fields]
print('FILTERS', self.doc.filter_fields)
meta = frappe.get_meta('Item')
fields = [df for df in meta.fields if df.fieldname in filter_fields]
@ -53,7 +52,6 @@ class ProductFiltersBuilder:
def get_attribute_fitlers(self):
attributes = [row.attribute for row in self.doc.filter_attributes]
print('ATTRIBUTES', attributes)
attribute_docs = [
frappe.get_doc('Item Attribute', attribute) for attribute in attributes
]

View File

@ -17,7 +17,7 @@ class Bin(Document):
'''Called from erpnext.stock.utils.update_bin'''
self.update_qty(args)
if args.get("actual_qty") or args.get("voucher_type") == "Stock Reconciliation":
from erpnext.stock.stock_ledger import update_entries_after, update_qty_in_future_sle
from erpnext.stock.stock_ledger import update_entries_after, validate_negative_qty_in_future_sle
if not args.get("posting_date"):
args["posting_date"] = nowdate()
@ -37,8 +37,8 @@ class Bin(Document):
"sle_id": args.name
}, allow_negative_stock=allow_negative_stock, via_landed_cost_voucher=via_landed_cost_voucher)
# Update qty_after_transaction in future SLEs of this item and warehouse
update_qty_in_future_sle(args)
# Validate negative qty in future transactions
validate_negative_qty_in_future_sle(args)
def update_qty(self, args):
# update the stock values (for current quantities)

View File

@ -31,7 +31,7 @@ frappe.ui.form.on('Repost Item Valuation', {
}
},
refresh: function(frm) {
if (frm.doc.status == "Failed") {
if (frm.doc.status == "Failed" && frm.doc.docstatus==1) {
frm.add_custom_button(__('Restart'), function () {
frm.trigger("restart_reposting");
}).addClass("btn-primary");

View File

@ -62,7 +62,7 @@ def make_entry(args, allow_negative_stock=False, via_landed_cost_voucher=False):
sle.submit()
return sle
def repost_future_sle(args=None, voucher_type=None, voucher_no=None, allow_negative_stock=False, via_landed_cost_voucher=False):
def repost_future_sle(args=None, voucher_type=None, voucher_no=None, allow_negative_stock=None, via_landed_cost_voucher=False):
if not args and voucher_type and voucher_no:
args = get_args_for_voucher(voucher_type, voucher_no)
@ -181,7 +181,7 @@ class update_entries_after(object):
self.process_sle(sle)
if sle.dependant_sle_voucher_detail_no:
self.get_dependent_entries_to_fix(entries_to_fix, sle)
entries_to_fix = self.get_dependent_entries_to_fix(entries_to_fix, sle)
if self.exceptions:
self.raise_exceptions()
@ -221,13 +221,15 @@ class update_entries_after(object):
excluded_sle=sle.name)
if not dependant_sle:
return
return entries_to_fix
elif dependant_sle.item_code == self.item_code and dependant_sle.warehouse == self.args.warehouse:
return
elif dependant_sle.item_code != self.item_code \
and (dependant_sle.item_code, dependant_sle.warehouse) not in self.new_items:
self.new_items[(dependant_sle.item_code, dependant_sle.warehouse)] = dependant_sle
return
return entries_to_fix
elif dependant_sle.item_code != self.item_code:
if (dependant_sle.item_code, dependant_sle.warehouse) not in self.new_items:
self.new_items[(dependant_sle.item_code, dependant_sle.warehouse)] = dependant_sle
return entries_to_fix
elif dependant_sle.item_code == self.item_code and dependant_sle.warehouse in self.data:
return entries_to_fix
self.initialize_previous_data(dependant_sle)
@ -236,7 +238,7 @@ class update_entries_after(object):
future_sle_for_dependant = list(self.get_sle_after_datetime(args))
entries_to_fix.extend(future_sle_for_dependant)
entries_to_fix = sorted(entries_to_fix, key=lambda k: k['timestamp'])
return sorted(entries_to_fix, key=lambda k: k['timestamp'])
def process_sle(self, sle):
# previous sle data for this warehouse
@ -612,11 +614,11 @@ class update_entries_after(object):
frappe.local.flags.currently_saving):
msg = _("{0} units of {1} needed in {2} to complete this transaction.").format(
abs(deficiency), frappe.get_desk_link('Item', self.item_code),
abs(deficiency), frappe.get_desk_link('Item', exceptions[0]["item_code"]),
frappe.get_desk_link('Warehouse', warehouse))
else:
msg = _("{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction.").format(
abs(deficiency), frappe.get_desk_link('Item', self.item_code),
abs(deficiency), frappe.get_desk_link('Item', exceptions[0]["item_code"]),
frappe.get_desk_link('Warehouse', warehouse),
exceptions[0]["posting_date"], exceptions[0]["posting_time"],
frappe.get_desk_link(exceptions[0]["voucher_type"], exceptions[0]["voucher_no"]))
@ -761,25 +763,6 @@ def get_valuation_rate(item_code, warehouse, voucher_type, voucher_no,
return valuation_rate
def update_qty_in_future_sle(args, allow_negative_stock=None):
frappe.db.sql("""
update `tabStock Ledger Entry`
set qty_after_transaction = qty_after_transaction + {qty}
where
item_code = %(item_code)s
and warehouse = %(warehouse)s
and voucher_no != %(voucher_no)s
and is_cancelled = 0
and (timestamp(posting_date, posting_time) > timestamp(%(posting_date)s, %(posting_time)s)
or (
timestamp(posting_date, posting_time) = timestamp(%(posting_date)s, %(posting_time)s)
and creation > %(creation)s
)
)
""".format(qty=args.actual_qty), args)
validate_negative_qty_in_future_sle(args, allow_negative_stock)
def validate_negative_qty_in_future_sle(args, allow_negative_stock=None):
allow_negative_stock = allow_negative_stock \
or cint(frappe.db.get_single_value("Stock Settings", "allow_negative_stock"))
@ -808,6 +791,7 @@ def get_future_sle_with_negative_qty(args):
and voucher_no != %(voucher_no)s
and timestamp(posting_date, posting_time) >= timestamp(%(posting_date)s, %(posting_time)s)
and is_cancelled = 0
and qty_after_transaction < 0
and qty_after_transaction + {0} < 0
order by timestamp(posting_date, posting_time) asc
limit 1
""", args, as_dict=1)
""".format(args.actual_qty), args, as_dict=1)

View File

@ -147,8 +147,7 @@ class IssueAnalytics(object):
self.entries = frappe.db.get_all('Issue',
fields=[self.field_map.get(self.filters.based_on), 'name', 'opening_date'],
filters=filters,
debug=1
filters=filters
)
def get_common_filters(self):

View File

@ -17,9 +17,12 @@ class TestIssueAnalytics(unittest.TestCase):
current_month_date = getdate()
last_month_date = add_months(current_month_date, -1)
self.current_month = str(months[current_month_date.month - 1]).lower() + '_' + str(current_month_date.year)
self.last_month = str(months[last_month_date.month - 1]).lower() + '_' + str(last_month_date.year)
self.current_month = str(months[current_month_date.month - 1]).lower()
self.last_month = str(months[last_month_date.month - 1]).lower()
if current_month_date.year != last_month_date.year:
self.current_month += '_' + str(current_month_date.year)
self.last_month += '_' + str(last_month_date.year)
def test_issue_analytics(self):
create_service_level_agreements_for_issues()
create_issue_types()

View File

@ -12,7 +12,6 @@ def get_context(context):
search = frappe.form_dict.search
field_filters = frappe.parse_json(frappe.form_dict.field_filters)
attribute_filters = frappe.parse_json(frappe.form_dict.attribute_filters)
print(field_filters, attribute_filters)
start = frappe.parse_json(frappe.form_dict.start)
else:
search = field_filters = attribute_filters = None
@ -30,8 +29,6 @@ def get_context(context):
context.field_filters = filter_engine.get_field_filters()
context.attribute_filters = filter_engine.get_attribute_fitlers()
print(context.field_filters, context.attribute_filters)
context.product_settings = product_settings
context.body_class = "product-page"
context.page_length = product_settings.products_per_page or 20