- Add DB migration v4.4_workshop.sql (sale_id, service_catalog, reserved_quantity, SO_RESERVE/SO_RELEASE operation types). - Extend service_order_engine with inventory reservation, release, convert-to-sale, mechanic assignment, and service catalog CRUD. - Extend service_order_bp with /reserve, /convert-to-sale, /assign-mechanic, and /service-catalog endpoints. - Create workshop Kanban UI: workshop.html, workshop.js, workshop.css. - Add /pos/workshop route and sidebar navigation (sidebar.js + inline templates). - Add 11 unit tests with mocked cursors. - Update FASES_IMPLEMENTADAS.md with FASE 9 documentation. Tests: 92 passing (61 console + 20 Facturapi + 11 workshop).
67 lines
4.2 KiB
PL/PgSQL
67 lines
4.2 KiB
PL/PgSQL
-- v4.4 Workshop Lite
|
|
-- Extends service orders with inventory reservation, sale linking and a labor catalog.
|
|
|
|
-- ═════════════════════════════════════════════════════════════════════════════
|
|
-- 1. SERVICE_ORDERS: link to the sale generated from the order
|
|
-- ═════════════════════════════════════════════════════════════════════════════
|
|
ALTER TABLE service_orders
|
|
ADD COLUMN IF NOT EXISTS sale_id INTEGER REFERENCES sales(id);
|
|
|
|
COMMENT ON COLUMN service_orders.sale_id IS 'Sale/invoice generated from this service order';
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_service_orders_sale_id ON service_orders(sale_id);
|
|
|
|
-- ═════════════════════════════════════════════════════════════════════════════
|
|
-- 2. SERVICE_CATALOG: reusable labor/work concepts for mechanics
|
|
-- ═════════════════════════════════════════════════════════════════════════════
|
|
CREATE TABLE IF NOT EXISTS service_catalog (
|
|
id SERIAL PRIMARY KEY,
|
|
tenant_id INTEGER NOT NULL,
|
|
name VARCHAR(200) NOT NULL,
|
|
description TEXT,
|
|
suggested_hours NUMERIC(6,2) DEFAULT 0,
|
|
suggested_rate NUMERIC(12,2) DEFAULT 0,
|
|
is_active BOOLEAN DEFAULT true,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_service_catalog_tenant ON service_catalog(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_service_catalog_active ON service_catalog(is_active);
|
|
|
|
COMMENT ON TABLE service_catalog IS 'Reusable labor concepts for workshop service orders';
|
|
|
|
-- Trigger to auto-update updated_at on service_catalog
|
|
CREATE OR REPLACE FUNCTION update_service_catalog_updated_at()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
DROP TRIGGER IF EXISTS trg_service_catalog_updated_at ON service_catalog;
|
|
CREATE TRIGGER trg_service_catalog_updated_at
|
|
BEFORE UPDATE ON service_catalog
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_service_catalog_updated_at();
|
|
|
|
-- ═════════════════════════════════════════════════════════════════════════════
|
|
-- 3. SERVICE_ORDER_ITEMS: track reserved quantity separately
|
|
-- ═════════════════════════════════════════════════════════════════════════════
|
|
ALTER TABLE service_order_items
|
|
ADD COLUMN IF NOT EXISTS reserved_quantity NUMERIC(10,2) DEFAULT 0;
|
|
|
|
COMMENT ON COLUMN service_order_items.reserved_quantity IS 'Quantity currently reserved from inventory';
|
|
|
|
-- ═════════════════════════════════════════════════════════════════════════════
|
|
-- 4. INVENTORY_OPERATIONS: new operation types for service orders
|
|
-- ═════════════════════════════════════════════════════════════════════════════
|
|
-- operation_type is VARCHAR(20) without a constraint, so no ALTER is needed.
|
|
-- New types used by the workshop module:
|
|
-- SO_RESERVE : negative quantity, reserves stock when item is added to SO
|
|
-- SO_RELEASE : positive quantity, releases a previous reservation
|
|
-- SO_CONSUME : negative quantity, final deduction when SO is converted to sale
|
|
COMMENT ON COLUMN inventory_operations.operation_type IS
|
|
'SALE, PURCHASE, RETURN, ADJUST, TRANSFER, INITIAL, QUOTE_RESERVE, QUOTE_RELEASE, SO_RESERVE, SO_RELEASE, SO_CONSUME';
|