diff --git a/posnext/overrides/pos_invoice.py b/posnext/overrides/pos_invoice.py index b9da847..8b69b5e 100644 --- a/posnext/overrides/pos_invoice.py +++ b/posnext/overrides/pos_invoice.py @@ -2,6 +2,7 @@ from erpnext.accounts.doctype.pos_invoice.pos_invoice import ( get_bin_qty, get_bundle_availability, + get_pos_reserved_qty, ) @@ -10,14 +11,13 @@ def get_stock_availability(item_code: str, warehouse: str) -> tuple: if frappe.db.get_value("Item", item_code, "is_stock_item"): is_stock_item = True bin_qty = get_bin_qty(item_code, warehouse) - # pos_sales_qty = get_pos_reserved_qty(item_code, warehouse) + pos_sales_qty = get_pos_reserved_qty(item_code, warehouse) - return bin_qty, is_stock_item + return bin_qty - pos_sales_qty, is_stock_item else: is_stock_item = True if frappe.db.exists("Product Bundle", {"name": item_code, "disabled": 0}): return get_bundle_availability(item_code, warehouse), is_stock_item else: is_stock_item = False - # Is a service item or non_stock item return 0, is_stock_item diff --git a/posnext/posnext/page/posnext/point_of_sale.py b/posnext/posnext/page/posnext/point_of_sale.py index 825b66c..a5e0079 100644 --- a/posnext/posnext/page/posnext/point_of_sale.py +++ b/posnext/posnext/page/posnext/point_of_sale.py @@ -132,6 +132,7 @@ def get_items( "custom_show_alternative_item_for_pos_search", "custom_show_logical_rack", "custom_skip_stock_transaction_validation", + "selling_price_list", ], as_dict=False, ) @@ -139,10 +140,10 @@ def get_items( if not result: frappe.throw(f"POS Profile {pos_profile} not found") - # Ensure we have exactly 6 values - if not isinstance(result, (tuple, list)) or len(result) != 6: + # Ensure we have exactly 7 values + if not isinstance(result, (tuple, list)) or len(result) != 7: frappe.throw( - f"Invalid POS Profile configuration. Expected 6 fields but got {len(result) if isinstance(result, (tuple, list)) else 'invalid response'}" + f"Invalid POS Profile configuration. Expected 7 fields but got {len(result) if isinstance(result, (tuple, list)) else 'invalid response'}" ) ( @@ -152,6 +153,7 @@ def get_items( custom_show_alternative_item_for_pos_search, custom_show_logical_rack, custom_skip_stock_transaction_validation, + pos_profile_price_list, ) = result result = [] @@ -293,6 +295,23 @@ def get_items( limit=1, ) + if ( + not item_price + and price_list != pos_profile_price_list + and pos_profile_price_list + ): + item_price = frappe.get_all( + "Item Price", + fields=["price_list_rate", "currency", "uom", "batch_no"], + filters={ + "price_list": pos_profile_price_list, + "item_code": item.item_code, + "selling": True, + }, + order_by="creation desc", + limit=1, + ) + if not item_price: result.append(item) diff --git a/posnext/public/js/pos_controller.js b/posnext/public/js/pos_controller.js index a6c9a4c..3d3d239 100644 --- a/posnext/public/js/pos_controller.js +++ b/posnext/public/js/pos_controller.js @@ -391,6 +391,15 @@ posnext.PointOfSale.Controller = class { this.customer_details = details; // will add/remove LP payment method this.payment.render_loyalty_points_payment_mode(); + // refresh item prices using the customer's own price list, bypassing + // doc.selling_price_list which may not be updated yet at this point + if (details && details.default_price_list) { + this.item_selector.filter_items({ + price_list: details.default_price_list, + }); + } else { + this.item_selector.filter_items(); + } }, }, }); diff --git a/posnext/public/js/pos_item_cart.js b/posnext/public/js/pos_item_cart.js index 7d1bc23..53644b1 100644 --- a/posnext/public/js/pos_item_cart.js +++ b/posnext/public/js/pos_item_cart.js @@ -806,6 +806,7 @@ posnext.PointOfSale.ItemCart = class { "mobile_no", "image", "loyalty_program", + "default_price_list", ]) .then(({ message }) => { const { loyalty_program } = message; @@ -1031,6 +1032,20 @@ posnext.PointOfSale.ItemCart = class { } } + refresh_totals_display() { + const frm = this.events.get_frm(); + if (!frm || !frm.doc) return; + const items = frm.doc.items || []; + this.render_net_total(items); + this.render_total_item_qty(items); + let grand_total = cint(frappe.sys_defaults.disable_rounded_total) + ? frm.doc.grand_total + : frm.doc.rounded_total; + if (!items.length && Math.abs(grand_total) != 0.005) grand_total = 0.0; + this.render_grand_total(grand_total); + this.render_taxes(frm.doc.taxes); + } + update_totals_section(frm) { if (!frm) frm = this.events.get_frm(); frm.cscript.calculate_taxes_and_totals(); @@ -1174,6 +1189,7 @@ posnext.PointOfSale.ItemCart = class { this.highlight_checkout_btn(true); this.update_empty_cart_section(no_of_cart_items); + this.refresh_totals_display(); } render_cart_item(item_data, $item_to_update) { diff --git a/posnext/public/js/pos_item_details.js b/posnext/public/js/pos_item_details.js index 433dcd9..477bddf 100644 --- a/posnext/public/js/pos_item_details.js +++ b/posnext/public/js/pos_item_details.js @@ -30,7 +30,7 @@ posnext.PointOfSale.ItemDetails = class { init_child_components() { this.$component.html( `