mirror of
https://github.com/frappe/erpnext.git
synced 2026-02-16 11:13:32 +00:00
Co-authored-by: Logesh Periyasamy <logeshperiyasamy24@gmail.com> fix: add condition for allow negative stock in pos (#50369)
This commit is contained in:
@@ -189,6 +189,9 @@ class POSInvoice(SalesInvoice):
|
|||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
if not self.customer:
|
||||||
|
frappe.throw(_("Please select Customer first"))
|
||||||
|
|
||||||
if not cint(self.is_pos):
|
if not cint(self.is_pos):
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("POS Invoice should have the field {0} checked.").format(frappe.bold(_("Include Payment")))
|
_("POS Invoice should have the field {0} checked.").format(frappe.bold(_("Include Payment")))
|
||||||
@@ -345,14 +348,14 @@ class POSInvoice(SalesInvoice):
|
|||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
from erpnext.stock.stock_ledger import is_negative_stock_allowed
|
|
||||||
|
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if not d.serial_and_batch_bundle:
|
if not d.serial_and_batch_bundle:
|
||||||
if is_negative_stock_allowed(item_code=d.item_code):
|
available_stock, is_stock_item, is_negative_stock_allowed = get_stock_availability(
|
||||||
return
|
d.item_code, d.warehouse
|
||||||
|
)
|
||||||
|
|
||||||
available_stock, is_stock_item = get_stock_availability(d.item_code, d.warehouse)
|
if is_negative_stock_allowed:
|
||||||
|
continue
|
||||||
|
|
||||||
item_code, warehouse, _qty = (
|
item_code, warehouse, _qty = (
|
||||||
frappe.bold(d.item_code),
|
frappe.bold(d.item_code),
|
||||||
@@ -760,20 +763,22 @@ class POSInvoice(SalesInvoice):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_stock_availability(item_code, warehouse):
|
def get_stock_availability(item_code, warehouse):
|
||||||
|
from erpnext.stock.stock_ledger import is_negative_stock_allowed
|
||||||
|
|
||||||
if frappe.db.get_value("Item", item_code, "is_stock_item"):
|
if frappe.db.get_value("Item", item_code, "is_stock_item"):
|
||||||
is_stock_item = True
|
is_stock_item = True
|
||||||
bin_qty = get_bin_qty(item_code, warehouse)
|
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 - pos_sales_qty, is_stock_item
|
return bin_qty - pos_sales_qty, is_stock_item, is_negative_stock_allowed(item_code=item_code)
|
||||||
else:
|
else:
|
||||||
is_stock_item = True
|
is_stock_item = True
|
||||||
if frappe.db.exists("Product Bundle", {"name": item_code, "disabled": 0}):
|
if frappe.db.exists("Product Bundle", {"name": item_code, "disabled": 0}):
|
||||||
return get_bundle_availability(item_code, warehouse), is_stock_item
|
return get_bundle_availability(item_code, warehouse), is_stock_item, False
|
||||||
else:
|
else:
|
||||||
is_stock_item = False
|
is_stock_item = False
|
||||||
# Is a service item or non_stock item
|
# Is a service item or non_stock item
|
||||||
return 0, is_stock_item
|
return 0, is_stock_item, False
|
||||||
|
|
||||||
|
|
||||||
def get_bundle_availability(bundle_item_code, warehouse):
|
def get_bundle_availability(bundle_item_code, warehouse):
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ def search_by_term(search_term, warehouse, price_list):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
item_stock_qty, is_stock_item = get_stock_availability(item_code, warehouse)
|
item_stock_qty, is_stock_item, is_negative_stock_allowed = get_stock_availability(item_code, warehouse)
|
||||||
item_stock_qty = item_stock_qty // item.get("conversion_factor", 1)
|
item_stock_qty = item_stock_qty // item.get("conversion_factor", 1)
|
||||||
item.update({"actual_qty": item_stock_qty})
|
item.update({"actual_qty": item_stock_qty})
|
||||||
|
|
||||||
@@ -198,7 +198,7 @@ def get_items(start, page_length, price_list, item_group, pos_profile, search_te
|
|||||||
current_date = frappe.utils.today()
|
current_date = frappe.utils.today()
|
||||||
|
|
||||||
for item in items_data:
|
for item in items_data:
|
||||||
item.actual_qty, _ = get_stock_availability(item.item_code, warehouse)
|
item.actual_qty, _, is_negative_stock_allowed = get_stock_availability(item.item_code, warehouse)
|
||||||
|
|
||||||
item_prices = frappe.get_all(
|
item_prices = frappe.get_all(
|
||||||
"Item Price",
|
"Item Price",
|
||||||
|
|||||||
@@ -759,12 +759,16 @@ erpnext.PointOfSale.Controller = class {
|
|||||||
const resp = (await this.get_available_stock(item_row.item_code, warehouse)).message;
|
const resp = (await this.get_available_stock(item_row.item_code, warehouse)).message;
|
||||||
const available_qty = resp[0];
|
const available_qty = resp[0];
|
||||||
const is_stock_item = resp[1];
|
const is_stock_item = resp[1];
|
||||||
|
const is_negative_stock_allowed = resp[2];
|
||||||
|
|
||||||
frappe.dom.unfreeze();
|
frappe.dom.unfreeze();
|
||||||
const bold_uom = item_row.stock_uom.bold();
|
const bold_uom = item_row.stock_uom.bold();
|
||||||
const bold_item_code = item_row.item_code.bold();
|
const bold_item_code = item_row.item_code.bold();
|
||||||
const bold_warehouse = warehouse.bold();
|
const bold_warehouse = warehouse.bold();
|
||||||
const bold_available_qty = available_qty.toString().bold();
|
const bold_available_qty = available_qty.toString().bold();
|
||||||
|
|
||||||
|
if (is_negative_stock_allowed) return;
|
||||||
|
|
||||||
if (!(available_qty > 0)) {
|
if (!(available_qty > 0)) {
|
||||||
if (is_stock_item) {
|
if (is_stock_item) {
|
||||||
frappe.model.clear_doc(item_row.doctype, item_row.name);
|
frappe.model.clear_doc(item_row.doctype, item_row.name);
|
||||||
|
|||||||
Reference in New Issue
Block a user