655 lines
32 KiB
Transact-SQL
655 lines
32 KiB
Transact-SQL
/*
|
|
FT546 shadow-only read model for SQL Server 2016 RTM (13.0).
|
|
This package creates no Legacy-table triggers and never inserts, updates,
|
|
or deletes Legacy WMS business rows.
|
|
*/
|
|
SET NOCOUNT ON;
|
|
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
|
|
|
|
IF SCHEMA_ID(N'alg') IS NULL EXEC(N'CREATE SCHEMA alg');
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.warehouse_policy', N'U') IS NULL
|
|
CREATE TABLE alg.warehouse_policy (
|
|
warehouse_id varchar(80) NOT NULL PRIMARY KEY,
|
|
target_fill_rate decimal(9,4) NULL,
|
|
fifo_tolerance_hours int NULL,
|
|
updated_at datetime2 NOT NULL CONSTRAINT DF_alg_warehouse_policy_updated_at DEFAULT SYSUTCDATETIME()
|
|
);
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.project_policy', N'U') IS NULL
|
|
CREATE TABLE alg.project_policy (
|
|
project_no varchar(255) NOT NULL PRIMARY KEY,
|
|
is_isolated bit NOT NULL CONSTRAINT DF_alg_project_policy_isolated DEFAULT 0,
|
|
is_common bit NOT NULL CONSTRAINT DF_alg_project_policy_common DEFAULT 0,
|
|
allow_mixed bit NOT NULL CONSTRAINT DF_alg_project_policy_mixed DEFAULT 0,
|
|
updated_at datetime2 NOT NULL CONSTRAINT DF_alg_project_policy_updated_at DEFAULT SYSUTCDATETIME()
|
|
);
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.space_role', N'U') IS NULL
|
|
CREATE TABLE alg.space_role (
|
|
space_id varchar(80) NOT NULL PRIMARY KEY,
|
|
role varchar(40) NOT NULL,
|
|
updated_at datetime2 NOT NULL CONSTRAINT DF_alg_space_role_updated_at DEFAULT SYSUTCDATETIME(),
|
|
CONSTRAINT CK_alg_space_role_role CHECK (role IN ('STORAGE', 'RELOCATION_BUFFER', 'OUTBOUND_BUFFER', 'PROTECTED_CORE'))
|
|
);
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.space_topology', N'U') IS NULL
|
|
CREATE TABLE alg.space_topology (
|
|
warehouse_id varchar(80) NOT NULL,
|
|
space_id varchar(80) NOT NULL CONSTRAINT PK_alg_space_topology PRIMARY KEY,
|
|
lane_code varchar(80) NOT NULL,
|
|
lane_depth int NOT NULL,
|
|
base_zone varchar(20) NOT NULL,
|
|
rebuilt_at datetime2 NOT NULL CONSTRAINT DF_alg_space_topology_rebuilt_at DEFAULT SYSUTCDATETIME(),
|
|
CONSTRAINT CK_alg_space_topology_base_zone CHECK (base_zone IN ('CACHE', 'RESERVE', 'MAIN', 'FLEX'))
|
|
);
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'alg.space_topology') AND name = N'IX_alg_space_topology_warehouse_lane')
|
|
CREATE INDEX IX_alg_space_topology_warehouse_lane ON alg.space_topology(warehouse_id, lane_code);
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.inventory_item_snapshot', N'U') IS NULL
|
|
CREATE TABLE alg.inventory_item_snapshot (
|
|
warehouse_id varchar(80) NOT NULL,
|
|
stock_id varchar(80) NOT NULL,
|
|
space_id varchar(80) NOT NULL,
|
|
tray_code varchar(255) NULL,
|
|
project_no varchar(255) NULL,
|
|
product_no varchar(255) NULL,
|
|
lot_no varchar(80) NULL,
|
|
inbound_time_raw varchar(80) NULL,
|
|
inbound_at datetime2 NULL,
|
|
quantity decimal(38,6) NULL,
|
|
out_quantity decimal(38,6) NULL,
|
|
synchronized_at datetime2 NOT NULL CONSTRAINT DF_alg_inventory_item_snapshot_sync DEFAULT SYSUTCDATETIME(),
|
|
CONSTRAINT PK_alg_inventory_item_snapshot PRIMARY KEY (warehouse_id, stock_id)
|
|
);
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'alg.inventory_item_snapshot') AND name = N'IX_alg_inventory_item_snapshot_space')
|
|
CREATE INDEX IX_alg_inventory_item_snapshot_space ON alg.inventory_item_snapshot(warehouse_id, space_id);
|
|
GO
|
|
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'alg.inventory_item_snapshot') AND name = N'IX_alg_inventory_item_snapshot_tray')
|
|
CREATE INDEX IX_alg_inventory_item_snapshot_tray ON alg.inventory_item_snapshot(warehouse_id, tray_code) INCLUDE (space_id, project_no, product_no);
|
|
GO
|
|
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'alg.inventory_item_snapshot') AND name = N'IX_alg_inventory_item_snapshot_project_product')
|
|
CREATE INDEX IX_alg_inventory_item_snapshot_project_product ON alg.inventory_item_snapshot(warehouse_id, project_no, product_no) INCLUDE (space_id, tray_code, inbound_at);
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.space_inventory_summary', N'U') IS NULL
|
|
CREATE TABLE alg.space_inventory_summary (
|
|
warehouse_id varchar(80) NOT NULL,
|
|
space_id varchar(80) NOT NULL,
|
|
stock_detail_count int NOT NULL,
|
|
stock_tray_count int NOT NULL,
|
|
stock_project_count int NOT NULL,
|
|
stock_product_count int NOT NULL,
|
|
synchronized_at datetime2 NOT NULL CONSTRAINT DF_alg_space_inventory_summary_sync DEFAULT SYSUTCDATETIME(),
|
|
CONSTRAINT PK_alg_space_inventory_summary PRIMARY KEY (warehouse_id, space_id)
|
|
);
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'alg.space_inventory_summary') AND name = N'IX_alg_space_inventory_summary_space')
|
|
CREATE INDEX IX_alg_space_inventory_summary_space ON alg.space_inventory_summary(space_id, warehouse_id);
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.lane_state', N'U') IS NULL
|
|
CREATE TABLE alg.lane_state (
|
|
warehouse_id varchar(80) NOT NULL,
|
|
lane_code varchar(80) NOT NULL,
|
|
space_count int NOT NULL CONSTRAINT DF_alg_lane_state_space_count DEFAULT 0,
|
|
occupied_count int NOT NULL CONSTRAINT DF_alg_lane_state_occupied_count DEFAULT 0,
|
|
available_count int NOT NULL CONSTRAINT DF_alg_lane_state_available_count DEFAULT 0,
|
|
pending_outbound bit NOT NULL CONSTRAINT DF_alg_lane_state_pending_outbound DEFAULT 0,
|
|
has_gap bit NOT NULL CONSTRAINT DF_alg_lane_state_has_gap DEFAULT 0,
|
|
semantic_fingerprint varbinary(32) NULL,
|
|
state_version rowversion NOT NULL,
|
|
rebuilt_at datetime2 NOT NULL CONSTRAINT DF_alg_lane_state_rebuilt_at DEFAULT SYSUTCDATETIME(),
|
|
CONSTRAINT PK_alg_lane_state PRIMARY KEY (warehouse_id, lane_code)
|
|
);
|
|
GO
|
|
|
|
IF COL_LENGTH(N'alg.lane_state', N'semantic_fingerprint') IS NULL
|
|
ALTER TABLE alg.lane_state ADD semantic_fingerprint varbinary(32) NULL;
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.reservation', N'U') IS NULL
|
|
CREATE TABLE alg.reservation (
|
|
reservation_id uniqueidentifier NOT NULL CONSTRAINT PK_alg_reservation PRIMARY KEY,
|
|
warehouse_id varchar(80) NOT NULL,
|
|
lane_code varchar(80) NOT NULL,
|
|
space_id varchar(80) NOT NULL,
|
|
project_no varchar(255) NULL,
|
|
status varchar(20) NOT NULL,
|
|
created_at datetime2 NOT NULL CONSTRAINT DF_alg_reservation_created_at DEFAULT SYSUTCDATETIME(),
|
|
released_at datetime2 NULL,
|
|
CONSTRAINT CK_alg_reservation_status CHECK (status IN ('ACTIVE', 'RELEASED', 'EXPIRED'))
|
|
);
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'alg.reservation') AND name = N'UX_alg_reservation_active_space')
|
|
CREATE UNIQUE INDEX UX_alg_reservation_active_space ON alg.reservation(space_id) WHERE status = 'ACTIVE';
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.deep_workflow_lock', N'U') IS NULL
|
|
CREATE TABLE alg.deep_workflow_lock (
|
|
lock_id uniqueidentifier NOT NULL CONSTRAINT PK_alg_deep_workflow_lock PRIMARY KEY,
|
|
request_id varchar(80) NOT NULL,
|
|
warehouse_id varchar(80) NOT NULL,
|
|
floor_no int NOT NULL,
|
|
status varchar(20) NOT NULL,
|
|
created_at datetime2 NOT NULL CONSTRAINT DF_alg_deep_workflow_lock_created_at DEFAULT SYSUTCDATETIME(),
|
|
released_at datetime2 NULL,
|
|
CONSTRAINT CK_alg_deep_workflow_lock_status CHECK (status IN ('ACTIVE', 'RELEASED'))
|
|
);
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'alg.deep_workflow_lock') AND name = N'UX_alg_deep_workflow_lock_active_floor')
|
|
CREATE UNIQUE INDEX UX_alg_deep_workflow_lock_active_floor
|
|
ON alg.deep_workflow_lock(warehouse_id, floor_no) WHERE status = 'ACTIVE';
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.decision_log', N'U') IS NULL
|
|
CREATE TABLE alg.decision_log (
|
|
decision_id uniqueidentifier NOT NULL CONSTRAINT PK_alg_decision_log PRIMARY KEY,
|
|
warehouse_id varchar(80) NULL,
|
|
decision_type varchar(40) NOT NULL,
|
|
input_version binary(8) NULL,
|
|
result_code varchar(80) NULL,
|
|
reason varchar(2000) NULL,
|
|
created_at datetime2 NOT NULL CONSTRAINT DF_alg_decision_log_created_at DEFAULT SYSUTCDATETIME()
|
|
);
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.usp_rebuild_space_topology', N'P') IS NOT NULL DROP PROCEDURE alg.usp_rebuild_space_topology;
|
|
GO
|
|
EXEC(N'
|
|
CREATE PROCEDURE alg.usp_rebuild_space_topology
|
|
@warehouse_id varchar(80) = NULL
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
;WITH lane_topology AS (
|
|
SELECT warehouse_id, group_coding_no AS lane_code,
|
|
COUNT(*) AS lane_depth,
|
|
MAX(the_column) AS column_no,
|
|
MIN(the_platoon) AS row_no,
|
|
MIN(the_floor) AS floor_no,
|
|
MIN(cargo_space_id) AS stable_id
|
|
FROM dbo.bas_cargo_space
|
|
WHERE NULLIF(LTRIM(RTRIM(group_coding_no)), '''') IS NOT NULL
|
|
AND TRY_CONVERT(int, group_coding) IS NOT NULL
|
|
AND (@warehouse_id IS NULL OR warehouse_id = @warehouse_id)
|
|
GROUP BY warehouse_id, group_coding_no
|
|
), ranked_lanes AS (
|
|
SELECT lane_topology.*,
|
|
CASE WHEN lane_depth = 1 THEN ROW_NUMBER() OVER (
|
|
PARTITION BY warehouse_id
|
|
ORDER BY CASE WHEN lane_depth = 1 THEN 0 ELSE 1 END,
|
|
column_no DESC, row_no ASC, floor_no ASC, stable_id ASC
|
|
) END AS single_depth_rank
|
|
FROM lane_topology
|
|
), source AS (
|
|
SELECT c.warehouse_id, c.cargo_space_id AS space_id, c.group_coding_no AS lane_code,
|
|
ranked_lanes.lane_depth,
|
|
CASE WHEN ranked_lanes.lane_depth = 1 AND ranked_lanes.single_depth_rank <= 80 THEN ''CACHE''
|
|
WHEN ranked_lanes.lane_depth = 1 AND ranked_lanes.single_depth_rank <= 133 THEN ''RESERVE''
|
|
WHEN ranked_lanes.lane_depth = 5 THEN ''MAIN''
|
|
ELSE ''FLEX'' END AS base_zone
|
|
FROM dbo.bas_cargo_space c
|
|
JOIN ranked_lanes ON ranked_lanes.warehouse_id = c.warehouse_id
|
|
AND ranked_lanes.lane_code = c.group_coding_no
|
|
WHERE NULLIF(LTRIM(RTRIM(c.group_coding_no)), '''') IS NOT NULL
|
|
AND TRY_CONVERT(int, c.group_coding) IS NOT NULL
|
|
AND (@warehouse_id IS NULL OR c.warehouse_id = @warehouse_id)
|
|
)
|
|
MERGE alg.space_topology AS target
|
|
USING source ON source.space_id = target.space_id
|
|
WHEN MATCHED AND (target.warehouse_id <> source.warehouse_id OR target.lane_code <> source.lane_code
|
|
OR target.lane_depth <> source.lane_depth OR target.base_zone <> source.base_zone)
|
|
THEN UPDATE SET warehouse_id = source.warehouse_id, lane_code = source.lane_code,
|
|
lane_depth = source.lane_depth, base_zone = source.base_zone,
|
|
rebuilt_at = SYSUTCDATETIME()
|
|
WHEN NOT MATCHED BY TARGET THEN
|
|
INSERT (warehouse_id, space_id, lane_code, lane_depth, base_zone)
|
|
VALUES (source.warehouse_id, source.space_id, source.lane_code, source.lane_depth, source.base_zone)
|
|
WHEN NOT MATCHED BY SOURCE AND (@warehouse_id IS NULL OR target.warehouse_id = @warehouse_id)
|
|
THEN DELETE;
|
|
END;');
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.usp_sync_inventory_snapshot', N'P') IS NOT NULL DROP PROCEDURE alg.usp_sync_inventory_snapshot;
|
|
GO
|
|
EXEC(N'
|
|
CREATE PROCEDURE alg.usp_sync_inventory_snapshot
|
|
@warehouse_id varchar(80) = NULL
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
SET XACT_ABORT ON;
|
|
BEGIN TRANSACTION;
|
|
|
|
DELETE summary
|
|
FROM alg.space_inventory_summary summary
|
|
WHERE @warehouse_id IS NULL OR summary.warehouse_id = @warehouse_id;
|
|
|
|
DELETE item
|
|
FROM alg.inventory_item_snapshot item
|
|
WHERE @warehouse_id IS NULL OR item.warehouse_id = @warehouse_id;
|
|
|
|
INSERT INTO alg.inventory_item_snapshot (
|
|
warehouse_id, stock_id, space_id, tray_code, project_no, product_no, lot_no,
|
|
inbound_time_raw, inbound_at, quantity, out_quantity, synchronized_at)
|
|
SELECT space.warehouse_id, stock.stock_id, stock.cargo_space_id, stock.tray_code,
|
|
stock.spare4, stock.product_id, stock.lot_no, CONVERT(varchar(80), stock.in_date),
|
|
TRY_CONVERT(datetime2, stock.in_date), stock.quantity, stock.out_quantity, SYSUTCDATETIME()
|
|
FROM dbo.bas_stock stock
|
|
JOIN dbo.bas_cargo_space space ON space.cargo_space_id = stock.cargo_space_id
|
|
WHERE @warehouse_id IS NULL OR space.warehouse_id = @warehouse_id;
|
|
|
|
INSERT INTO alg.space_inventory_summary (
|
|
warehouse_id, space_id, stock_detail_count, stock_tray_count,
|
|
stock_project_count, stock_product_count, synchronized_at)
|
|
SELECT item.warehouse_id, item.space_id, COUNT(*),
|
|
COUNT(DISTINCT NULLIF(LTRIM(RTRIM(item.tray_code)), '''')),
|
|
COUNT(DISTINCT NULLIF(LTRIM(RTRIM(item.project_no)), '''')),
|
|
COUNT(DISTINCT NULLIF(LTRIM(RTRIM(item.product_no)), '''')),
|
|
SYSUTCDATETIME()
|
|
FROM alg.inventory_item_snapshot item
|
|
WHERE @warehouse_id IS NULL OR item.warehouse_id = @warehouse_id
|
|
GROUP BY item.warehouse_id, item.space_id;
|
|
|
|
COMMIT TRANSACTION;
|
|
END;');
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.v_inventory_item', N'V') IS NOT NULL DROP VIEW alg.v_inventory_item;
|
|
GO
|
|
EXEC(N'
|
|
CREATE VIEW alg.v_inventory_item AS
|
|
SELECT stock_id, space_id, tray_code, project_no, product_no, lot_no,
|
|
inbound_time_raw, inbound_at, quantity, out_quantity
|
|
FROM alg.inventory_item_snapshot;');
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.v_active_job', N'V') IS NOT NULL DROP VIEW alg.v_active_job;
|
|
GO
|
|
EXEC(N'
|
|
CREATE VIEW alg.v_active_job AS
|
|
WITH tray_candidates AS (
|
|
SELECT j.job_id,
|
|
COUNT(DISTINCT s.space_id) AS space_count,
|
|
MIN(s.space_id) AS cargo_space_id,
|
|
COUNT(DISTINCT NULLIF(LTRIM(RTRIM(s.project_no)), '''')) AS project_count,
|
|
MIN(NULLIF(LTRIM(RTRIM(s.project_no)), '''')) AS project_no,
|
|
COUNT(DISTINCT NULLIF(LTRIM(RTRIM(s.product_no)), '''')) AS product_count,
|
|
MIN(NULLIF(LTRIM(RTRIM(s.product_no)), '''')) AS product_no
|
|
FROM dbo.mydo_job j
|
|
JOIN alg.inventory_item_snapshot s ON s.warehouse_id = j.warehouse_id
|
|
AND s.tray_code = NULLIF(LTRIM(RTRIM(j.tray_code)), '''')
|
|
GROUP BY j.job_id
|
|
), resolved_jobs AS (
|
|
SELECT j.job_id, j.task_no, j.tray_code, j.target_cargo_space_id, j.warehouse_id,
|
|
j.status, j.in_or_out, j.create_time AS create_time_raw,
|
|
COALESCE(source_space.cargo_space_id,
|
|
CASE WHEN tray_candidates.space_count = 1 THEN tray_candidates.cargo_space_id END) AS source_space_id,
|
|
CASE WHEN source_space.cargo_space_id IS NOT NULL THEN ''EXPLICIT''
|
|
WHEN tray_candidates.space_count = 1 THEN ''TRAY''
|
|
WHEN tray_candidates.space_count > 1 THEN ''AMBIGUOUS_TRAY''
|
|
ELSE ''UNRESOLVED'' END AS source_resolution
|
|
FROM dbo.mydo_job j
|
|
LEFT JOIN dbo.bas_cargo_space source_space
|
|
ON source_space.cargo_space_id = NULLIF(LTRIM(RTRIM(j.cargo_space_id)), '''')
|
|
AND source_space.warehouse_id = j.warehouse_id
|
|
LEFT JOIN tray_candidates ON tray_candidates.job_id = j.job_id
|
|
WHERE j.finish_time IS NULL OR LTRIM(RTRIM(j.finish_time)) = ''''
|
|
), source_scope AS (
|
|
SELECT resolved_jobs.job_id,
|
|
COUNT(DISTINCT NULLIF(LTRIM(RTRIM(stock.project_no)), '''')) AS project_count,
|
|
MIN(NULLIF(LTRIM(RTRIM(stock.project_no)), '''')) AS project_no,
|
|
COUNT(DISTINCT NULLIF(LTRIM(RTRIM(stock.product_no)), '''')) AS product_count,
|
|
MIN(NULLIF(LTRIM(RTRIM(stock.product_no)), '''')) AS product_no
|
|
FROM resolved_jobs
|
|
JOIN alg.inventory_item_snapshot stock ON stock.warehouse_id = resolved_jobs.warehouse_id
|
|
AND stock.space_id = resolved_jobs.source_space_id
|
|
GROUP BY resolved_jobs.job_id
|
|
)
|
|
SELECT resolved_jobs.job_id, resolved_jobs.task_no, resolved_jobs.tray_code,
|
|
CASE WHEN resolved_jobs.source_space_id IS NOT NULL
|
|
THEN CASE WHEN source_scope.project_count = 1 THEN source_scope.project_no END
|
|
ELSE CASE WHEN tray_candidates.project_count = 1 THEN tray_candidates.project_no END END AS project_no,
|
|
CASE WHEN resolved_jobs.source_space_id IS NOT NULL
|
|
THEN CASE WHEN source_scope.product_count = 1 THEN source_scope.product_no END
|
|
ELSE CASE WHEN tray_candidates.product_count = 1 THEN tray_candidates.product_no END END AS product_no,
|
|
resolved_jobs.source_space_id, resolved_jobs.target_cargo_space_id, resolved_jobs.warehouse_id,
|
|
resolved_jobs.status, resolved_jobs.in_or_out, resolved_jobs.create_time_raw,
|
|
resolved_space.group_coding_no AS source_lane_code, resolved_jobs.source_resolution
|
|
FROM resolved_jobs
|
|
LEFT JOIN tray_candidates ON tray_candidates.job_id = resolved_jobs.job_id
|
|
LEFT JOIN source_scope ON source_scope.job_id = resolved_jobs.job_id
|
|
LEFT JOIN dbo.bas_cargo_space resolved_space ON resolved_space.cargo_space_id = resolved_jobs.source_space_id;');
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.v_space_state', N'V') IS NOT NULL DROP VIEW alg.v_space_state;
|
|
GO
|
|
EXEC(N'
|
|
CREATE VIEW alg.v_space_state AS
|
|
WITH outbound_lanes AS (
|
|
SELECT DISTINCT warehouse_id, source_lane_code AS lane_code
|
|
FROM alg.v_active_job
|
|
WHERE in_or_out >= 20 AND source_lane_code IS NOT NULL
|
|
), lane_gaps AS (
|
|
SELECT DISTINCT inner_space.warehouse_id, inner_space.group_coding_no AS lane_code
|
|
FROM dbo.bas_cargo_space inner_space
|
|
JOIN dbo.bas_cargo_space outer_space
|
|
ON outer_space.warehouse_id = inner_space.warehouse_id
|
|
AND outer_space.group_coding_no = inner_space.group_coding_no
|
|
AND TRY_CONVERT(int, outer_space.group_coding) > TRY_CONVERT(int, inner_space.group_coding)
|
|
WHERE TRY_CONVERT(int, inner_space.group_coding) IS NOT NULL
|
|
AND TRY_CONVERT(int, outer_space.group_coding) IS NOT NULL
|
|
AND NULLIF(LTRIM(RTRIM(inner_space.tray_code)), '''') IS NULL
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM alg.inventory_item_snapshot inner_stock
|
|
WHERE inner_stock.warehouse_id = inner_space.warehouse_id
|
|
AND inner_stock.space_id = inner_space.cargo_space_id
|
|
)
|
|
AND (
|
|
NULLIF(LTRIM(RTRIM(outer_space.tray_code)), '''') IS NOT NULL
|
|
OR EXISTS (
|
|
SELECT 1 FROM alg.inventory_item_snapshot outer_stock
|
|
WHERE outer_stock.warehouse_id = outer_space.warehouse_id
|
|
AND outer_stock.space_id = outer_space.cargo_space_id
|
|
)
|
|
)
|
|
)
|
|
SELECT c.cargo_space_id AS space_id,
|
|
c.warehouse_id,
|
|
c.group_coding_no AS lane_code,
|
|
c.cargo_area_id AS area_id,
|
|
CASE
|
|
WHEN ISNULL(role.role, ''STORAGE'') IN (''RELOCATION_BUFFER'', ''OUTBOUND_BUFFER'') THEN ''CACHE''
|
|
WHEN ISNULL(role.role, ''STORAGE'') = ''PROTECTED_CORE'' THEN ''RESERVE''
|
|
ELSE topology.base_zone
|
|
END AS zone_code,
|
|
c.roadway_id,
|
|
c.cargo_space_name AS display_name,
|
|
c.the_platoon AS platoon,
|
|
c.the_column AS column_no,
|
|
c.the_floor AS floor_no,
|
|
c.group_coding AS depth_raw,
|
|
TRY_CONVERT(int, c.group_coding) AS depth,
|
|
c.status AS space_status,
|
|
c.locked,
|
|
c.tray_code AS space_tray_code,
|
|
ISNULL(role.role, ''STORAGE'') AS role,
|
|
ISNULL(stock.stock_detail_count, 0) AS stock_detail_count,
|
|
ISNULL(stock.stock_tray_count, 0) AS stock_tray_count,
|
|
ISNULL(stock.stock_project_count, 0) AS stock_project_count,
|
|
ISNULL(stock.stock_product_count, 0) AS stock_product_count,
|
|
CONVERT(bit, CASE WHEN ISNULL(stock.stock_tray_count, 0) > 1 THEN 1 ELSE 0 END) AS tray_conflict,
|
|
CONVERT(bit, CASE WHEN ISNULL(stock.stock_project_count, 0) > 1 THEN 1 ELSE 0 END) AS project_conflict,
|
|
CONVERT(bit, 0) AS product_conflict,
|
|
CONVERT(bit, CASE WHEN outbound_lanes.lane_code IS NULL THEN 0 ELSE 1 END) AS pending_outbound,
|
|
active_reservations.reservation_id,
|
|
CONVERT(bit, CASE WHEN active_reservations.reservation_id IS NULL THEN 0 ELSE 1 END) AS reserved,
|
|
CONVERT(bit, CASE WHEN lane_gaps.lane_code IS NULL THEN 0 ELSE 1 END) AS has_gap,
|
|
CONVERT(bit, CASE
|
|
WHEN c.status IS NULL OR c.status <> ''1'' THEN 0
|
|
WHEN NULLIF(LTRIM(RTRIM(c.locked)), '''') IS NOT NULL AND LTRIM(RTRIM(c.locked)) NOT IN (''0'', ''N'') THEN 0
|
|
WHEN NULLIF(LTRIM(RTRIM(c.tray_code)), '''') IS NOT NULL THEN 0
|
|
WHEN ISNULL(stock.stock_detail_count, 0) <> 0 THEN 0
|
|
WHEN TRY_CONVERT(int, c.group_coding) IS NULL THEN 0
|
|
WHEN ISNULL(role.role, ''STORAGE'') <> ''STORAGE'' THEN 0
|
|
WHEN outbound_lanes.lane_code IS NOT NULL THEN 0
|
|
WHEN active_reservations.reservation_id IS NOT NULL THEN 0
|
|
WHEN lane_gaps.lane_code IS NOT NULL THEN 0
|
|
WHEN EXISTS (
|
|
SELECT 1
|
|
FROM dbo.bas_cargo_space inner_candidate
|
|
LEFT JOIN alg.space_inventory_summary inner_stock
|
|
ON inner_stock.warehouse_id = inner_candidate.warehouse_id
|
|
AND inner_stock.space_id = inner_candidate.cargo_space_id
|
|
WHERE inner_candidate.warehouse_id = c.warehouse_id
|
|
AND inner_candidate.group_coding_no = c.group_coding_no
|
|
AND TRY_CONVERT(int, inner_candidate.group_coding) < TRY_CONVERT(int, c.group_coding)
|
|
AND inner_candidate.status = ''1''
|
|
AND NULLIF(LTRIM(RTRIM(inner_candidate.tray_code)), '''') IS NULL
|
|
AND inner_stock.space_id IS NULL
|
|
) THEN 0
|
|
ELSE 1 END) AS inbound_available
|
|
FROM dbo.bas_cargo_space c
|
|
JOIN alg.space_topology topology ON topology.space_id = c.cargo_space_id
|
|
LEFT JOIN alg.space_inventory_summary stock ON stock.warehouse_id = c.warehouse_id
|
|
AND stock.space_id = c.cargo_space_id
|
|
LEFT JOIN alg.space_role role ON role.space_id = c.cargo_space_id
|
|
LEFT JOIN outbound_lanes ON outbound_lanes.warehouse_id = c.warehouse_id AND outbound_lanes.lane_code = c.group_coding_no
|
|
LEFT JOIN alg.reservation active_reservations ON active_reservations.space_id = c.cargo_space_id AND active_reservations.status = ''ACTIVE''
|
|
LEFT JOIN lane_gaps ON lane_gaps.warehouse_id = c.warehouse_id AND lane_gaps.lane_code = c.group_coding_no;');
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.usp_compute_lane_semantic_fingerprint', N'P') IS NOT NULL DROP PROCEDURE alg.usp_compute_lane_semantic_fingerprint;
|
|
GO
|
|
EXEC(N'
|
|
CREATE PROCEDURE alg.usp_compute_lane_semantic_fingerprint
|
|
@warehouse_id varchar(80),
|
|
@lane_code varchar(80),
|
|
@semantic_fingerprint varbinary(32) OUTPUT,
|
|
@inventory_source varchar(20) = ''LIVE''
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
DECLARE @payload nvarchar(max);
|
|
|
|
CREATE TABLE #fingerprint_inventory (
|
|
stock_id varchar(80) NOT NULL,
|
|
space_id varchar(80) NOT NULL,
|
|
tray_code varchar(255) NULL,
|
|
project_no varchar(255) NULL,
|
|
product_no varchar(255) NULL,
|
|
lot_no varchar(80) NULL,
|
|
inbound_time varchar(80) NULL,
|
|
quantity decimal(38,6) NULL,
|
|
out_quantity decimal(38,6) NULL
|
|
);
|
|
|
|
IF @inventory_source = ''SNAPSHOT''
|
|
BEGIN
|
|
INSERT INTO #fingerprint_inventory (
|
|
stock_id, space_id, tray_code, project_no, product_no, lot_no,
|
|
inbound_time, quantity, out_quantity)
|
|
SELECT stock.stock_id, stock.space_id, stock.tray_code, stock.project_no,
|
|
stock.product_no, stock.lot_no, stock.inbound_time_raw,
|
|
CONVERT(decimal(38,6), stock.quantity), CONVERT(decimal(38,6), stock.out_quantity)
|
|
FROM alg.inventory_item_snapshot stock
|
|
JOIN dbo.bas_cargo_space cargo ON cargo.cargo_space_id = stock.space_id
|
|
AND cargo.warehouse_id = stock.warehouse_id
|
|
WHERE cargo.warehouse_id = @warehouse_id AND cargo.group_coding_no = @lane_code;
|
|
END
|
|
ELSE IF @inventory_source = ''LIVE''
|
|
BEGIN
|
|
INSERT INTO #fingerprint_inventory (
|
|
stock_id, space_id, tray_code, project_no, product_no, lot_no,
|
|
inbound_time, quantity, out_quantity)
|
|
SELECT stock.stock_id, stock.cargo_space_id, stock.tray_code, stock.spare4,
|
|
stock.product_id, stock.lot_no, CONVERT(varchar(80), stock.in_date),
|
|
CONVERT(decimal(38,6), stock.quantity), CONVERT(decimal(38,6), stock.out_quantity)
|
|
FROM dbo.bas_stock stock
|
|
JOIN dbo.bas_cargo_space cargo ON cargo.cargo_space_id = stock.cargo_space_id
|
|
WHERE cargo.warehouse_id = @warehouse_id AND cargo.group_coding_no = @lane_code;
|
|
END
|
|
ELSE
|
|
BEGIN
|
|
THROW 50001, ''Unsupported inventory fingerprint source'', 1;
|
|
END;
|
|
|
|
SELECT @payload = ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT cargo.cargo_space_id AS [@space_id], cargo.status AS [@status],
|
|
cargo.locked AS [@locked], cargo.tray_code AS [@tray_code],
|
|
cargo.group_coding AS [@depth], cargo.the_platoon AS [@platoon],
|
|
cargo.the_column AS [@column], cargo.the_floor AS [@floor],
|
|
topology.lane_depth AS [@lane_depth], topology.base_zone AS [@base_zone],
|
|
ISNULL(role.role, ''STORAGE'') AS [@role]
|
|
FROM dbo.bas_cargo_space cargo
|
|
LEFT JOIN alg.space_topology topology ON topology.space_id = cargo.cargo_space_id
|
|
LEFT JOIN alg.space_role role ON role.space_id = cargo.cargo_space_id
|
|
WHERE cargo.warehouse_id = @warehouse_id AND cargo.group_coding_no = @lane_code
|
|
ORDER BY TRY_CONVERT(int, cargo.group_coding), cargo.cargo_space_id
|
|
FOR XML PATH(''space''), ROOT(''spaces''), TYPE
|
|
)), N'''');
|
|
|
|
SET @payload = @payload + N''|INVENTORY|'' + ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT stock.stock_id AS [@stock_id], stock.space_id AS [@space_id],
|
|
stock.tray_code AS [@tray_code], stock.project_no AS [@project_no],
|
|
stock.product_no AS [@product_no], stock.lot_no AS [@lot_no],
|
|
stock.inbound_time AS [@inbound_time],
|
|
stock.quantity AS [@quantity], stock.out_quantity AS [@out_quantity]
|
|
FROM #fingerprint_inventory stock
|
|
ORDER BY stock.space_id, stock.stock_id
|
|
FOR XML PATH(''item''), ROOT(''inventory''), TYPE
|
|
)), N'''');
|
|
|
|
SET @payload = @payload + N''|ACTIVE_JOBS|'' + ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT job.job_id AS [@job_id], job.task_no AS [@task_no], job.tray_code AS [@tray_code],
|
|
job.source_space_id AS [@source_space_id], job.target_cargo_space_id AS [@target_space_id],
|
|
job.status AS [@status], job.in_or_out AS [@in_or_out],
|
|
job.create_time_raw AS [@create_time]
|
|
FROM alg.v_active_job job
|
|
WHERE job.warehouse_id = @warehouse_id AND job.source_lane_code = @lane_code
|
|
ORDER BY job.job_id
|
|
FOR XML PATH(''job''), ROOT(''jobs''), TYPE
|
|
)), N'''');
|
|
|
|
SET @payload = @payload + N''|PROJECT_POLICY|'' + ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT policy.project_no AS [@project_no], policy.is_isolated AS [@is_isolated],
|
|
policy.is_common AS [@is_common], policy.allow_mixed AS [@allow_mixed]
|
|
FROM alg.project_policy policy
|
|
ORDER BY policy.project_no
|
|
FOR XML PATH(''project''), ROOT(''project_policy''), TYPE
|
|
)), N'''');
|
|
|
|
SET @payload = @payload + N''|WAREHOUSE_POLICY|'' + ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT policy.warehouse_id AS [@warehouse_id], policy.target_fill_rate AS [@target_fill_rate],
|
|
policy.fifo_tolerance_hours AS [@fifo_tolerance_hours]
|
|
FROM alg.warehouse_policy policy
|
|
WHERE policy.warehouse_id = @warehouse_id
|
|
FOR XML PATH(''warehouse''), ROOT(''warehouse_policy''), TYPE
|
|
)), N'''');
|
|
|
|
SET @payload = @payload + N''|RESERVATIONS|'' + ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT reservation.reservation_id AS [@reservation_id], reservation.space_id AS [@space_id],
|
|
reservation.project_no AS [@project_no], reservation.status AS [@status]
|
|
FROM alg.reservation reservation
|
|
WHERE reservation.warehouse_id = @warehouse_id AND reservation.lane_code = @lane_code
|
|
AND reservation.status = ''ACTIVE''
|
|
ORDER BY reservation.space_id, reservation.reservation_id
|
|
FOR XML PATH(''reservation''), ROOT(''reservations''), TYPE
|
|
)), N'''');
|
|
|
|
SET @semantic_fingerprint = HASHBYTES(''SHA2_256'', CONVERT(varbinary(max), @payload));
|
|
END;');
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.usp_rebuild_lane_state', N'P') IS NOT NULL DROP PROCEDURE alg.usp_rebuild_lane_state;
|
|
GO
|
|
EXEC(N'
|
|
CREATE PROCEDURE alg.usp_rebuild_lane_state
|
|
@warehouse_id varchar(80) = NULL,
|
|
@lane_code varchar(80) = NULL
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
SELECT warehouse_id, lane_code,
|
|
COUNT(*) AS space_count,
|
|
SUM(CASE WHEN space_status = ''2'' OR stock_detail_count > 0 THEN 1 ELSE 0 END) AS occupied_count,
|
|
SUM(CASE WHEN inbound_available = 1 THEN 1 ELSE 0 END) AS available_count,
|
|
MAX(CASE WHEN pending_outbound = 1 THEN 1 ELSE 0 END) AS pending_outbound,
|
|
MAX(CASE WHEN has_gap = 1 THEN 1 ELSE 0 END) AS has_gap,
|
|
CAST(NULL AS varbinary(32)) AS semantic_fingerprint
|
|
INTO #source_state
|
|
FROM alg.v_space_state
|
|
WHERE (@warehouse_id IS NULL OR warehouse_id = @warehouse_id)
|
|
AND (@lane_code IS NULL OR lane_code = @lane_code)
|
|
GROUP BY warehouse_id, lane_code;
|
|
|
|
DECLARE @fingerprint_warehouse varchar(80), @fingerprint_lane varchar(80),
|
|
@fingerprint varbinary(32);
|
|
DECLARE fingerprint_cursor CURSOR LOCAL FAST_FORWARD FOR
|
|
SELECT warehouse_id, lane_code FROM #source_state ORDER BY warehouse_id, lane_code;
|
|
OPEN fingerprint_cursor;
|
|
FETCH NEXT FROM fingerprint_cursor INTO @fingerprint_warehouse, @fingerprint_lane;
|
|
WHILE @@FETCH_STATUS = 0
|
|
BEGIN
|
|
EXEC alg.usp_compute_lane_semantic_fingerprint
|
|
@warehouse_id = @fingerprint_warehouse,
|
|
@lane_code = @fingerprint_lane,
|
|
@semantic_fingerprint = @fingerprint OUTPUT,
|
|
@inventory_source = ''SNAPSHOT'';
|
|
UPDATE #source_state SET semantic_fingerprint = @fingerprint
|
|
WHERE warehouse_id = @fingerprint_warehouse AND lane_code = @fingerprint_lane;
|
|
FETCH NEXT FROM fingerprint_cursor INTO @fingerprint_warehouse, @fingerprint_lane;
|
|
END;
|
|
CLOSE fingerprint_cursor;
|
|
DEALLOCATE fingerprint_cursor;
|
|
|
|
MERGE alg.lane_state WITH (HOLDLOCK) AS target
|
|
USING #source_state AS source
|
|
ON target.warehouse_id = source.warehouse_id AND target.lane_code = source.lane_code
|
|
WHEN MATCHED AND (target.space_count <> source.space_count OR
|
|
target.occupied_count <> source.occupied_count OR
|
|
target.available_count <> source.available_count OR
|
|
target.pending_outbound <> source.pending_outbound OR
|
|
target.has_gap <> source.has_gap OR
|
|
target.semantic_fingerprint IS NULL OR
|
|
target.semantic_fingerprint <> source.semantic_fingerprint)
|
|
THEN UPDATE SET space_count = source.space_count,
|
|
occupied_count = source.occupied_count,
|
|
available_count = source.available_count,
|
|
pending_outbound = source.pending_outbound,
|
|
has_gap = source.has_gap,
|
|
semantic_fingerprint = source.semantic_fingerprint,
|
|
rebuilt_at = SYSUTCDATETIME()
|
|
WHEN NOT MATCHED BY TARGET THEN
|
|
INSERT (warehouse_id, lane_code, space_count, occupied_count, available_count,
|
|
pending_outbound, has_gap, semantic_fingerprint)
|
|
VALUES (source.warehouse_id, source.lane_code, source.space_count, source.occupied_count,
|
|
source.available_count, source.pending_outbound, source.has_gap, source.semantic_fingerprint)
|
|
WHEN NOT MATCHED BY SOURCE
|
|
AND (@warehouse_id IS NULL OR target.warehouse_id = @warehouse_id)
|
|
AND (@lane_code IS NULL OR target.lane_code = @lane_code)
|
|
THEN DELETE;
|
|
END;');
|
|
GO
|
|
|
|
IF OBJECT_ID(N'alg.usp_refresh_dirty_lanes', N'P') IS NOT NULL DROP PROCEDURE alg.usp_refresh_dirty_lanes;
|
|
GO
|
|
EXEC(N'
|
|
CREATE PROCEDURE alg.usp_refresh_dirty_lanes
|
|
@warehouse_id varchar(80)
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
IF NULLIF(LTRIM(RTRIM(@warehouse_id)), '''') IS NULL
|
|
THROW 50002, ''warehouse_id is required'', 1;
|
|
|
|
EXEC alg.usp_rebuild_space_topology @warehouse_id = @warehouse_id;
|
|
EXEC alg.usp_sync_inventory_snapshot @warehouse_id = @warehouse_id;
|
|
EXEC alg.usp_rebuild_lane_state @warehouse_id = @warehouse_id;
|
|
END;');
|
|
GO
|
|
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM alg.space_topology)
|
|
AND NOT EXISTS (SELECT 1 FROM alg.inventory_item_snapshot)
|
|
AND NOT EXISTS (SELECT 1 FROM alg.lane_state)
|
|
BEGIN
|
|
EXEC alg.usp_rebuild_space_topology;
|
|
EXEC alg.usp_sync_inventory_snapshot;
|
|
EXEC alg.usp_rebuild_lane_state;
|
|
END;
|
|
GO
|