Add allow_negative_stock toggle for sales, remissions, quotes, layaways and service orders
This commit is contained in:
@@ -55,6 +55,21 @@ def _validate_zero_price(conn, items):
|
||||
raise ValueError(f"No está permitido vender artículos en $0 ({name})")
|
||||
|
||||
|
||||
def _validate_stock_availability(conn, items, branch_id):
|
||||
"""Raise ValueError if stock is insufficient and the tenant forbids negative stock."""
|
||||
if _tenant_allows_negative_stock(conn):
|
||||
return
|
||||
for item in items:
|
||||
inv_id = item.get('inventory_id')
|
||||
qty = int(item.get('quantity', 1) or 1)
|
||||
if not inv_id:
|
||||
continue
|
||||
available = get_stock(conn, inv_id, branch_id)
|
||||
if available < qty:
|
||||
name = item.get('name') or item.get('part_number') or inv_id
|
||||
raise ValueError(f'Sin stock suficiente para {name}. Disponible: {available}, solicitado: {qty}')
|
||||
|
||||
|
||||
def _enrich_items(cur, items, customer_id=None):
|
||||
"""Look up inventory data for items that lack unit_price/tax_rate.
|
||||
|
||||
@@ -136,22 +151,10 @@ def create_sale():
|
||||
data = request.get_json() or {}
|
||||
conn = get_tenant_conn(g.tenant_id)
|
||||
|
||||
# Verify stock availability per item for the active branch
|
||||
# (skipped for tenants configured to allow negative stock / oversell)
|
||||
branch_id = data.get('branch_id', g.branch_id)
|
||||
if not _tenant_allows_negative_stock(conn):
|
||||
for item in data.get('items', []):
|
||||
inv_id = item.get('inventory_id')
|
||||
qty = int(item.get('quantity', 1))
|
||||
if inv_id:
|
||||
available = get_stock(conn, inv_id, branch_id)
|
||||
if available < qty:
|
||||
conn.close()
|
||||
return jsonify({
|
||||
'error': f'Insufficient stock for item {inv_id}. Available: {available}, requested: {qty}'
|
||||
}), 400
|
||||
|
||||
try:
|
||||
_validate_stock_availability(conn, data.get('items', []), branch_id)
|
||||
_validate_zero_price(conn, data.get('items', []))
|
||||
sale = process_sale(conn, data)
|
||||
conn.commit()
|
||||
@@ -175,19 +178,9 @@ def create_remission():
|
||||
conn = get_tenant_conn(g.tenant_id)
|
||||
|
||||
branch_id = data.get('branch_id', g.branch_id)
|
||||
if not _tenant_allows_negative_stock(conn):
|
||||
for item in data.get('items', []):
|
||||
inv_id = item.get('inventory_id')
|
||||
qty = int(item.get('quantity', 1))
|
||||
if inv_id:
|
||||
available = get_stock(conn, inv_id, branch_id)
|
||||
if available < qty:
|
||||
conn.close()
|
||||
return jsonify({
|
||||
'error': f'Insufficient stock for item {inv_id}. Available: {available}, requested: {qty}'
|
||||
}), 400
|
||||
|
||||
try:
|
||||
_validate_stock_availability(conn, data.get('items', []), branch_id)
|
||||
_validate_zero_price(conn, data.get('items', []))
|
||||
sale = create_remission_note(conn, {
|
||||
'tenant_id': g.tenant_id,
|
||||
@@ -753,6 +746,7 @@ def create_quotation():
|
||||
# Enrich items with inventory data (price, tax, etc.)
|
||||
try:
|
||||
enriched = _enrich_items(cur, items, data.get('customer_id'))
|
||||
_validate_stock_availability(conn, enriched, g.branch_id)
|
||||
_validate_zero_price(conn, enriched)
|
||||
except ValueError as e:
|
||||
cur.close(); conn.close()
|
||||
@@ -1142,6 +1136,7 @@ def update_quotation(quot_id):
|
||||
|
||||
try:
|
||||
enriched = _enrich_items(cur, items, data.get('customer_id'))
|
||||
_validate_stock_availability(conn, enriched, g.branch_id)
|
||||
_validate_zero_price(conn, enriched)
|
||||
except ValueError as e:
|
||||
cur.close(); conn.close()
|
||||
@@ -1629,6 +1624,7 @@ def convert_quotation(quot_id):
|
||||
}
|
||||
|
||||
try:
|
||||
_validate_stock_availability(conn, items, g.branch_id)
|
||||
_validate_zero_price(conn, items)
|
||||
sale = process_sale(conn, sale_data)
|
||||
|
||||
@@ -1788,6 +1784,7 @@ def create_layaway():
|
||||
# Enrich items with inventory data
|
||||
try:
|
||||
enriched = _enrich_items(cur, items, customer_id)
|
||||
_validate_stock_availability(conn, enriched, g.branch_id)
|
||||
_validate_zero_price(conn, enriched)
|
||||
except ValueError as e:
|
||||
cur.close(); conn.close()
|
||||
|
||||
Reference in New Issue
Block a user