feat: cashier/counter reports, service-order & remission flows, Rached migration utils
- Add "Mis cortes de caja" report for cashiers/counters with sales detail. - Cash register history scoped to own cuts for non-admin roles; new /register/<id>/sales endpoint. - Remove dashboard from cashier menu; add Reports to cashier/counter. - Service orders: assign mechanic, budget field, invoice flag, counter/cashier can add items/remissions, convert to remission. - Remission notes module (UI, CSS, courier, counter remissions). - Customer hard-delete and vehicle/customer linkage in workshop. - POS: always show search results, compact payment grid, credit validation, tier pricing (5%/10%), ticket with customer/folio. - Inventory: CSV template with sku_secondary, alias import. - Rached migration scripts and DB migrations. - Version-bump cached JS/CSS query strings. Excludes local Rached session tokens/captures (rached_*.json / rached_*.txt).
This commit is contained in:
@@ -230,6 +230,54 @@ def record_sale(conn, inventory_id, branch_id, quantity, sale_id=None, cost_at_t
|
||||
return op_id
|
||||
|
||||
|
||||
def record_reservation(conn, inventory_id, branch_id, quantity, sale_id=None,
|
||||
cost_at_time=None, remaining_stock=None):
|
||||
"""Reserve stock for a counter remission note (negative quantity).
|
||||
|
||||
The reserved quantity is deducted from available stock until the note is
|
||||
paid or cancelled.
|
||||
"""
|
||||
op_id = record_operation(
|
||||
conn, inventory_id, branch_id, 'REMISSION_RESERVE', -abs(quantity),
|
||||
reference_id=sale_id, reference_type='sale', cost_at_time=cost_at_time,
|
||||
notes='Reserva por nota de remision'
|
||||
)
|
||||
invalidate_stock(inventory_id, branch_id)
|
||||
invalidate_stock(inventory_id, None)
|
||||
|
||||
try:
|
||||
remaining = remaining_stock if remaining_stock is not None else get_stock(conn, inventory_id, branch_id)
|
||||
if remaining <= 0:
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT part_number, name FROM inventory WHERE id = %s", (inventory_id,))
|
||||
inv_row = cur.fetchone()
|
||||
cur.close()
|
||||
if inv_row:
|
||||
from services.push_service import notify_owner
|
||||
notify_owner(
|
||||
conn,
|
||||
'Stock en Cero',
|
||||
f'{inv_row[1] or inv_row[0]} se quedo sin existencias',
|
||||
'/pos'
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return op_id
|
||||
|
||||
|
||||
def release_reservation(conn, inventory_id, branch_id, quantity, sale_id=None, notes=None):
|
||||
"""Release a previous reservation (positive quantity)."""
|
||||
result = record_operation(
|
||||
conn, inventory_id, branch_id, 'REMISSION_RELEASE', abs(quantity),
|
||||
reference_id=sale_id, reference_type='sale',
|
||||
notes=notes or 'Liberacion de reserva de nota de remision'
|
||||
)
|
||||
invalidate_stock(inventory_id, branch_id)
|
||||
invalidate_stock(inventory_id, None)
|
||||
return result
|
||||
|
||||
|
||||
def record_return(conn, inventory_id, branch_id, quantity, sale_id=None, notes=None):
|
||||
"""Record a customer return (positive quantity)."""
|
||||
result = record_operation(
|
||||
|
||||
Reference in New Issue
Block a user