1328 lines
68 KiB
Transact-SQL
1328 lines
68 KiB
Transact-SQL
/*
|
|
FT546 shadow-only read model for SQL Server 2016 RTM (13.0).
|
|
This package writes only alg.* and never changes Legacy WMS business rows.
|
|
A clean install creates an INITIALIZING state for warehouse 01. The v3
|
|
worker owns the first refresh and publication.
|
|
*/
|
|
SET NOCOUNT ON;
|
|
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
|
|
|
|
IF SCHEMA_ID(N'alg') IS NOT NULL
|
|
THROW 51000, 'FT546 shadow install refused: alg schema already exists', 1;
|
|
|
|
CREATE SCHEMA alg;
|
|
GO
|
|
|
|
CREATE TABLE alg.shadow_package_manifest (
|
|
package_id varchar(80) NOT NULL CONSTRAINT PK_alg_shadow_package_manifest PRIMARY KEY,
|
|
package_version varchar(40) NOT NULL,
|
|
installed_at datetime2 NOT NULL CONSTRAINT DF_alg_shadow_package_manifest_installed_at DEFAULT SYSUTCDATETIME()
|
|
);
|
|
|
|
INSERT INTO alg.shadow_package_manifest (package_id, package_version)
|
|
VALUES ('FT546WMS_SHADOW_ONLY', '2026-09-03-3');
|
|
GO
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
CREATE TABLE alg.space_topology (
|
|
warehouse_id varchar(80) NOT NULL,
|
|
space_id varchar(80) NOT NULL,
|
|
lane_code varchar(80) NOT NULL,
|
|
lane_depth int NOT NULL,
|
|
base_zone varchar(20) NOT NULL,
|
|
snapshot_generation bigint NOT NULL,
|
|
rebuilt_at datetime2 NOT NULL CONSTRAINT DF_alg_space_topology_rebuilt_at DEFAULT SYSUTCDATETIME(),
|
|
CONSTRAINT PK_alg_space_topology PRIMARY KEY (warehouse_id, space_id),
|
|
CONSTRAINT CK_alg_space_topology_base_zone CHECK (base_zone IN ('CACHE', 'RESERVE', 'MAIN', 'FLEX'))
|
|
);
|
|
GO
|
|
|
|
CREATE INDEX IX_alg_space_topology_warehouse_lane ON alg.space_topology(warehouse_id, lane_code);
|
|
GO
|
|
|
|
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,
|
|
snapshot_generation bigint NOT 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
|
|
|
|
CREATE INDEX IX_alg_inventory_item_snapshot_space
|
|
ON alg.inventory_item_snapshot(warehouse_id, space_id);
|
|
GO
|
|
|
|
CREATE INDEX IX_alg_inventory_item_snapshot_tray
|
|
ON alg.inventory_item_snapshot(warehouse_id, tray_code)
|
|
INCLUDE (space_id, project_no, product_no, snapshot_generation);
|
|
GO
|
|
|
|
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, snapshot_generation);
|
|
GO
|
|
|
|
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,
|
|
snapshot_generation bigint 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
|
|
|
|
CREATE INDEX IX_alg_space_inventory_summary_space
|
|
ON alg.space_inventory_summary(space_id, warehouse_id);
|
|
GO
|
|
|
|
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,
|
|
snapshot_generation bigint NOT 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
|
|
|
|
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
|
|
|
|
CREATE UNIQUE INDEX UX_alg_reservation_active_space
|
|
ON alg.reservation(space_id) WHERE status = 'ACTIVE';
|
|
GO
|
|
|
|
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
|
|
|
|
CREATE UNIQUE INDEX UX_alg_deep_workflow_lock_active_floor
|
|
ON alg.deep_workflow_lock(warehouse_id, floor_no) WHERE status = 'ACTIVE';
|
|
GO
|
|
|
|
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 nvarchar(4000) NULL,
|
|
created_at datetime2 NOT NULL CONSTRAINT DF_alg_decision_log_created_at DEFAULT SYSUTCDATETIME()
|
|
);
|
|
GO
|
|
|
|
CREATE TABLE alg.shadow_snapshot_state (
|
|
warehouse_id varchar(80) NOT NULL PRIMARY KEY,
|
|
snapshot_generation bigint NOT NULL,
|
|
snapshot_status varchar(20) NOT NULL,
|
|
synchronized_at datetime2 NULL,
|
|
source_signature varbinary(32) NULL,
|
|
source_row_count bigint NULL,
|
|
instance_id varchar(80) NULL,
|
|
last_error varchar(1000) NULL,
|
|
CONSTRAINT CK_alg_shadow_snapshot_state_status CHECK (snapshot_status IN ('INITIALIZING', 'REFRESHING', 'PUBLISHED', 'FAILED'))
|
|
);
|
|
GO
|
|
|
|
INSERT INTO alg.shadow_snapshot_state (warehouse_id, snapshot_generation, snapshot_status)
|
|
VALUES ('01', 0, 'INITIALIZING');
|
|
GO
|
|
|
|
CREATE TABLE alg.cargo_space_snapshot (
|
|
warehouse_id varchar(80) NOT NULL,
|
|
space_id varchar(80) NOT NULL,
|
|
lane_code varchar(80) NULL,
|
|
cargo_area_id varchar(80) NULL,
|
|
roadway_id varchar(80) NULL,
|
|
display_name varchar(255) NULL,
|
|
platoon int NULL,
|
|
column_no int NULL,
|
|
floor_no int NULL,
|
|
depth_raw varchar(80) NULL,
|
|
space_status varchar(20) NULL,
|
|
locked varchar(20) NULL,
|
|
tray_code varchar(255) NULL,
|
|
snapshot_generation bigint NOT NULL,
|
|
synchronized_at datetime2 NOT NULL,
|
|
CONSTRAINT PK_alg_cargo_space_snapshot PRIMARY KEY (warehouse_id, space_id)
|
|
);
|
|
GO
|
|
|
|
CREATE TABLE alg.active_job_snapshot (
|
|
warehouse_id varchar(80) NOT NULL,
|
|
job_id varchar(80) NOT NULL,
|
|
task_no varchar(80) NULL,
|
|
tray_code varchar(255) NULL,
|
|
source_space_id varchar(80) NULL,
|
|
target_space_id varchar(80) NULL,
|
|
status varchar(20) NULL,
|
|
in_or_out varchar(20) NULL,
|
|
create_time_raw varchar(80) NULL,
|
|
snapshot_generation bigint NOT NULL,
|
|
synchronized_at datetime2 NOT NULL,
|
|
CONSTRAINT PK_alg_active_job_snapshot PRIMARY KEY (warehouse_id, job_id)
|
|
);
|
|
GO
|
|
|
|
CREATE TABLE alg.shadow_inbound_request_snapshot (
|
|
warehouse_id varchar(80) NOT NULL,
|
|
task_no varchar(80) NOT NULL,
|
|
tray_no varchar(255) NOT NULL,
|
|
request_id varchar(80) NULL,
|
|
raw_warehouse_id varchar(80) NULL,
|
|
project_no varchar(255) NULL,
|
|
product_id varchar(255) NULL,
|
|
lot_no varchar(80) NULL,
|
|
snapshot_generation bigint NOT NULL,
|
|
synchronized_at datetime2 NOT NULL,
|
|
CONSTRAINT PK_alg_shadow_inbound_request_snapshot PRIMARY KEY (warehouse_id, task_no, tray_no)
|
|
);
|
|
GO
|
|
|
|
CREATE TABLE alg.shadow_outbound_request_snapshot (
|
|
warehouse_id varchar(80) NOT NULL,
|
|
stockout_detail_id varchar(80) NOT NULL,
|
|
raw_warehouse_id varchar(80) NULL,
|
|
project_no varchar(255) NULL,
|
|
product_id varchar(255) NULL,
|
|
requested_quantity decimal(38,6) NULL,
|
|
snapshot_generation bigint NOT NULL,
|
|
synchronized_at datetime2 NOT NULL,
|
|
CONSTRAINT PK_alg_shadow_outbound_request_snapshot PRIMARY KEY (warehouse_id, stockout_detail_id)
|
|
);
|
|
GO
|
|
|
|
CREATE TABLE alg.shadow_runtime_metric (
|
|
warehouse_id varchar(80) NOT NULL,
|
|
metric_name varchar(80) NOT NULL,
|
|
bucket_upper_micros bigint NOT NULL,
|
|
metric_count bigint NOT NULL CONSTRAINT DF_alg_shadow_runtime_metric_count DEFAULT 0,
|
|
metric_total_micros bigint NOT NULL CONSTRAINT DF_alg_shadow_runtime_metric_total DEFAULT 0,
|
|
metric_max_micros bigint NOT NULL CONSTRAINT DF_alg_shadow_runtime_metric_max DEFAULT 0,
|
|
flushed_at datetime2 NULL,
|
|
CONSTRAINT PK_alg_shadow_runtime_metric PRIMARY KEY (warehouse_id, metric_name, bucket_upper_micros)
|
|
);
|
|
GO
|
|
|
|
CREATE TABLE alg.shadow_instance_heartbeat (
|
|
warehouse_id varchar(80) NOT NULL PRIMARY KEY,
|
|
instance_id varchar(80) NOT NULL,
|
|
claimed_at datetime2 NOT NULL,
|
|
last_seen_at datetime2 NOT NULL
|
|
);
|
|
GO
|
|
|
|
CREATE PROCEDURE alg.usp_rebuild_space_topology
|
|
@warehouse_id varchar(80) = NULL,
|
|
@snapshot_generation bigint = NULL
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
IF NULLIF(LTRIM(RTRIM(@warehouse_id)), '') IS NULL
|
|
THROW 51019, 'warehouse_id is required', 1;
|
|
DECLARE @generation bigint;
|
|
|
|
SET @generation = @snapshot_generation;
|
|
IF @generation IS NULL
|
|
SELECT @generation = state.snapshot_generation
|
|
FROM alg.shadow_snapshot_state state
|
|
WHERE state.warehouse_id = @warehouse_id
|
|
AND state.snapshot_status = 'PUBLISHED';
|
|
|
|
IF @generation IS NULL
|
|
THROW 51020, 'FT546 shadow topology rebuild requires a snapshot generation', 1;
|
|
|
|
;WITH lane_topology AS (
|
|
SELECT cargo.warehouse_id, cargo.lane_code,
|
|
COUNT(*) AS lane_depth,
|
|
MAX(cargo.column_no) AS column_no,
|
|
MIN(cargo.platoon) AS row_no,
|
|
MIN(cargo.floor_no) AS floor_no,
|
|
MIN(cargo.space_id) AS stable_id
|
|
FROM alg.cargo_space_snapshot cargo
|
|
WHERE cargo.snapshot_generation = @generation
|
|
AND NULLIF(LTRIM(RTRIM(cargo.lane_code)), '') IS NOT NULL
|
|
AND TRY_CONVERT(int, cargo.depth_raw) IS NOT NULL
|
|
AND (@warehouse_id IS NULL OR cargo.warehouse_id = @warehouse_id)
|
|
GROUP BY cargo.warehouse_id, cargo.lane_code
|
|
), ranked_lanes AS (
|
|
SELECT lane_topology.*,
|
|
CASE WHEN lane_depth = 1 THEN ROW_NUMBER() OVER (
|
|
PARTITION BY warehouse_id
|
|
ORDER BY column_no DESC, row_no ASC, floor_no ASC, stable_id ASC
|
|
) END AS single_depth_rank
|
|
FROM lane_topology
|
|
), source_rows AS (
|
|
SELECT cargo.warehouse_id, cargo.space_id, cargo.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 alg.cargo_space_snapshot cargo
|
|
JOIN ranked_lanes ON ranked_lanes.warehouse_id = cargo.warehouse_id
|
|
AND ranked_lanes.lane_code = cargo.lane_code
|
|
WHERE cargo.snapshot_generation = @generation
|
|
AND NULLIF(LTRIM(RTRIM(cargo.lane_code)), '') IS NOT NULL
|
|
AND TRY_CONVERT(int, cargo.depth_raw) IS NOT NULL
|
|
AND (@warehouse_id IS NULL OR cargo.warehouse_id = @warehouse_id)
|
|
)
|
|
MERGE alg.space_topology WITH (HOLDLOCK) AS target
|
|
USING source_rows AS source
|
|
ON target.warehouse_id = source.warehouse_id AND target.space_id = source.space_id
|
|
WHEN MATCHED AND (target.lane_code <> source.lane_code OR target.lane_depth <> source.lane_depth
|
|
OR target.base_zone <> source.base_zone OR target.snapshot_generation <> @generation)
|
|
THEN UPDATE SET lane_code = source.lane_code, lane_depth = source.lane_depth,
|
|
base_zone = source.base_zone, snapshot_generation = @generation,
|
|
rebuilt_at = SYSUTCDATETIME()
|
|
WHEN NOT MATCHED BY TARGET THEN
|
|
INSERT (warehouse_id, space_id, lane_code, lane_depth, base_zone, snapshot_generation)
|
|
VALUES (source.warehouse_id, source.space_id, source.lane_code, source.lane_depth,
|
|
source.base_zone, @generation)
|
|
WHEN NOT MATCHED BY SOURCE AND (@warehouse_id IS NULL OR target.warehouse_id = @warehouse_id)
|
|
THEN DELETE;
|
|
END;
|
|
GO
|
|
|
|
CREATE PROCEDURE alg.usp_sync_inventory_snapshot
|
|
@warehouse_id varchar(80) = NULL,
|
|
@snapshot_generation bigint = NULL
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
IF NULLIF(LTRIM(RTRIM(@warehouse_id)), '') IS NULL
|
|
THROW 51019, 'warehouse_id is required', 1;
|
|
DECLARE @generation bigint;
|
|
|
|
SET @generation = @snapshot_generation;
|
|
IF @generation IS NULL
|
|
SELECT @generation = state.snapshot_generation
|
|
FROM alg.shadow_snapshot_state state
|
|
WHERE state.warehouse_id = @warehouse_id
|
|
AND state.snapshot_status = 'PUBLISHED';
|
|
|
|
IF @generation IS NULL
|
|
THROW 51021, 'FT546 shadow inventory summary requires a snapshot generation', 1;
|
|
|
|
DELETE summary
|
|
FROM alg.space_inventory_summary summary
|
|
WHERE (@warehouse_id IS NULL OR summary.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, snapshot_generation, 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)), '')),
|
|
@generation, SYSUTCDATETIME()
|
|
FROM alg.inventory_item_snapshot item
|
|
WHERE item.snapshot_generation = @generation
|
|
AND (@warehouse_id IS NULL OR item.warehouse_id = @warehouse_id)
|
|
GROUP BY item.warehouse_id, item.space_id;
|
|
END;
|
|
GO
|
|
|
|
CREATE VIEW alg.v_inventory_item
|
|
AS
|
|
-- generation contract: WHERE snapshot_generation = published_snapshot.snapshot_generation
|
|
SELECT item.warehouse_id, item.stock_id, item.space_id, item.tray_code,
|
|
item.project_no, item.product_no, item.lot_no, item.inbound_time_raw,
|
|
item.inbound_at, item.quantity, item.out_quantity, item.snapshot_generation
|
|
FROM alg.inventory_item_snapshot item
|
|
JOIN alg.shadow_snapshot_state published_snapshot
|
|
ON published_snapshot.warehouse_id = item.warehouse_id
|
|
AND published_snapshot.snapshot_status = 'PUBLISHED'
|
|
AND item.snapshot_generation = published_snapshot.snapshot_generation;
|
|
GO
|
|
|
|
CREATE VIEW alg.v_active_job
|
|
AS
|
|
WITH published_jobs AS (
|
|
SELECT job.warehouse_id, job.job_id, job.task_no, job.tray_code,
|
|
job.source_space_id, job.target_space_id, job.status, job.in_or_out,
|
|
job.create_time_raw, job.snapshot_generation
|
|
FROM alg.active_job_snapshot job
|
|
JOIN alg.shadow_snapshot_state published_snapshot
|
|
ON published_snapshot.warehouse_id = job.warehouse_id
|
|
AND published_snapshot.snapshot_status = 'PUBLISHED'
|
|
AND job.snapshot_generation = published_snapshot.snapshot_generation
|
|
), tray_candidates AS (
|
|
SELECT job.warehouse_id, job.job_id, job.snapshot_generation,
|
|
COUNT(DISTINCT stock.space_id) AS space_count,
|
|
MIN(stock.space_id) AS cargo_space_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 published_jobs job
|
|
JOIN alg.inventory_item_snapshot stock
|
|
ON stock.warehouse_id = job.warehouse_id
|
|
AND stock.snapshot_generation = job.snapshot_generation
|
|
AND stock.tray_code = NULLIF(LTRIM(RTRIM(job.tray_code)), '')
|
|
GROUP BY job.warehouse_id, job.job_id, job.snapshot_generation
|
|
), resolved_jobs AS (
|
|
SELECT job.job_id, job.task_no, job.tray_code, job.target_space_id,
|
|
job.warehouse_id, job.status, job.in_or_out, job.create_time_raw,
|
|
job.snapshot_generation,
|
|
COALESCE(NULLIF(LTRIM(RTRIM(job.source_space_id)), ''),
|
|
CASE WHEN tray_candidates.space_count = 1 THEN tray_candidates.cargo_space_id END) AS source_space_id,
|
|
CASE WHEN NULLIF(LTRIM(RTRIM(job.source_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 published_jobs job
|
|
LEFT JOIN tray_candidates
|
|
ON tray_candidates.warehouse_id = job.warehouse_id
|
|
AND tray_candidates.job_id = job.job_id
|
|
AND tray_candidates.snapshot_generation = job.snapshot_generation
|
|
WHERE job.snapshot_generation IS NOT NULL
|
|
), source_scope AS (
|
|
SELECT resolved.warehouse_id, resolved.job_id, resolved.snapshot_generation,
|
|
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 resolved
|
|
JOIN alg.inventory_item_snapshot stock
|
|
ON stock.warehouse_id = resolved.warehouse_id
|
|
AND stock.snapshot_generation = resolved.snapshot_generation
|
|
AND stock.space_id = resolved.source_space_id
|
|
GROUP BY resolved.warehouse_id, resolved.job_id, resolved.snapshot_generation
|
|
)
|
|
SELECT resolved.job_id, resolved.task_no, resolved.tray_code,
|
|
CASE WHEN resolved.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.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.source_space_id, resolved.target_space_id AS target_cargo_space_id,
|
|
resolved.warehouse_id, resolved.status, resolved.in_or_out,
|
|
resolved.create_time_raw, source_cargo.lane_code AS source_lane_code,
|
|
resolved.source_resolution, resolved.snapshot_generation
|
|
FROM resolved_jobs resolved
|
|
LEFT JOIN tray_candidates
|
|
ON tray_candidates.warehouse_id = resolved.warehouse_id
|
|
AND tray_candidates.job_id = resolved.job_id
|
|
AND tray_candidates.snapshot_generation = resolved.snapshot_generation
|
|
LEFT JOIN source_scope
|
|
ON source_scope.warehouse_id = resolved.warehouse_id
|
|
AND source_scope.job_id = resolved.job_id
|
|
AND source_scope.snapshot_generation = resolved.snapshot_generation
|
|
LEFT JOIN alg.cargo_space_snapshot source_cargo
|
|
ON source_cargo.warehouse_id = resolved.warehouse_id
|
|
AND source_cargo.space_id = resolved.source_space_id
|
|
AND source_cargo.snapshot_generation = resolved.snapshot_generation;
|
|
GO
|
|
|
|
CREATE VIEW alg.v_space_state
|
|
AS
|
|
WITH published_snapshot AS (
|
|
SELECT state.warehouse_id, state.snapshot_generation
|
|
FROM alg.shadow_snapshot_state state
|
|
WHERE state.snapshot_status = 'PUBLISHED'
|
|
), outbound_lanes AS (
|
|
SELECT DISTINCT job.warehouse_id, job.source_lane_code AS lane_code,
|
|
job.snapshot_generation
|
|
FROM alg.v_active_job job
|
|
WHERE TRY_CONVERT(int, job.in_or_out) >= 20
|
|
AND job.source_lane_code IS NOT NULL
|
|
), lane_gaps AS (
|
|
SELECT DISTINCT inner_space.warehouse_id, inner_space.lane_code,
|
|
inner_space.snapshot_generation
|
|
FROM alg.cargo_space_snapshot inner_space
|
|
JOIN alg.cargo_space_snapshot outer_space
|
|
ON outer_space.warehouse_id = inner_space.warehouse_id
|
|
AND outer_space.lane_code = inner_space.lane_code
|
|
AND outer_space.snapshot_generation = inner_space.snapshot_generation
|
|
AND TRY_CONVERT(int, outer_space.depth_raw) > TRY_CONVERT(int, inner_space.depth_raw)
|
|
JOIN published_snapshot published
|
|
ON published.warehouse_id = inner_space.warehouse_id
|
|
AND published.snapshot_generation = inner_space.snapshot_generation
|
|
LEFT JOIN alg.space_inventory_summary inner_stock
|
|
ON inner_stock.warehouse_id = inner_space.warehouse_id
|
|
AND inner_stock.space_id = inner_space.space_id
|
|
AND inner_stock.snapshot_generation = inner_space.snapshot_generation
|
|
LEFT JOIN alg.space_inventory_summary outer_stock
|
|
ON outer_stock.warehouse_id = outer_space.warehouse_id
|
|
AND outer_stock.space_id = outer_space.space_id
|
|
AND outer_stock.snapshot_generation = outer_space.snapshot_generation
|
|
WHERE TRY_CONVERT(int, inner_space.depth_raw) IS NOT NULL
|
|
AND TRY_CONVERT(int, outer_space.depth_raw) IS NOT NULL
|
|
AND NULLIF(LTRIM(RTRIM(inner_space.tray_code)), '') IS NULL
|
|
AND inner_stock.space_id IS NULL
|
|
AND (NULLIF(LTRIM(RTRIM(outer_space.tray_code)), '') IS NOT NULL
|
|
OR outer_stock.space_id IS NOT NULL)
|
|
)
|
|
SELECT cargo.space_id, cargo.warehouse_id, cargo.lane_code,
|
|
cargo.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,
|
|
cargo.roadway_id, cargo.display_name, cargo.platoon, cargo.column_no,
|
|
cargo.floor_no, cargo.depth_raw,
|
|
TRY_CONVERT(int, cargo.depth_raw) AS depth, cargo.space_status,
|
|
cargo.locked, cargo.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 cargo.space_status IS NULL OR cargo.space_status <> '1' THEN 0
|
|
WHEN NULLIF(LTRIM(RTRIM(cargo.locked)), '') IS NOT NULL
|
|
AND LTRIM(RTRIM(cargo.locked)) NOT IN ('0', 'N') THEN 0
|
|
WHEN NULLIF(LTRIM(RTRIM(cargo.tray_code)), '') IS NOT NULL THEN 0
|
|
WHEN ISNULL(stock.stock_detail_count, 0) <> 0 THEN 0
|
|
WHEN TRY_CONVERT(int, cargo.depth_raw) 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 EXISTS (
|
|
SELECT 1
|
|
FROM alg.cargo_space_snapshot inner_candidate
|
|
LEFT JOIN alg.space_inventory_summary inner_candidate_stock
|
|
ON inner_candidate_stock.warehouse_id = inner_candidate.warehouse_id
|
|
AND inner_candidate_stock.space_id = inner_candidate.space_id
|
|
AND inner_candidate_stock.snapshot_generation = inner_candidate.snapshot_generation
|
|
WHERE inner_candidate.warehouse_id = cargo.warehouse_id
|
|
AND inner_candidate.lane_code = cargo.lane_code
|
|
AND inner_candidate.snapshot_generation = cargo.snapshot_generation
|
|
AND TRY_CONVERT(int, inner_candidate.depth_raw) < TRY_CONVERT(int, cargo.depth_raw)
|
|
AND inner_candidate.space_status = '1'
|
|
AND NULLIF(LTRIM(RTRIM(inner_candidate.tray_code)), '') IS NULL
|
|
AND inner_candidate_stock.space_id IS NULL
|
|
) THEN 0
|
|
ELSE 1 END) AS inbound_available,
|
|
cargo.snapshot_generation
|
|
FROM alg.cargo_space_snapshot cargo
|
|
JOIN published_snapshot published
|
|
ON published.warehouse_id = cargo.warehouse_id
|
|
AND published.snapshot_generation = cargo.snapshot_generation
|
|
JOIN alg.space_topology topology
|
|
ON topology.warehouse_id = cargo.warehouse_id
|
|
AND topology.space_id = cargo.space_id
|
|
AND topology.snapshot_generation = cargo.snapshot_generation
|
|
LEFT JOIN alg.space_inventory_summary stock
|
|
ON stock.warehouse_id = cargo.warehouse_id
|
|
AND stock.space_id = cargo.space_id
|
|
AND stock.snapshot_generation = cargo.snapshot_generation
|
|
LEFT JOIN alg.space_role role ON role.space_id = cargo.space_id
|
|
LEFT JOIN outbound_lanes
|
|
ON outbound_lanes.warehouse_id = cargo.warehouse_id
|
|
AND outbound_lanes.lane_code = cargo.lane_code
|
|
AND outbound_lanes.snapshot_generation = cargo.snapshot_generation
|
|
LEFT JOIN alg.reservation active_reservations
|
|
ON active_reservations.space_id = cargo.space_id
|
|
AND active_reservations.status = 'ACTIVE'
|
|
LEFT JOIN lane_gaps
|
|
ON lane_gaps.warehouse_id = cargo.warehouse_id
|
|
AND lane_gaps.lane_code = cargo.lane_code
|
|
AND lane_gaps.snapshot_generation = cargo.snapshot_generation;
|
|
GO
|
|
|
|
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) = 'SNAPSHOT',
|
|
@snapshot_generation bigint = NULL
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
DECLARE @generation bigint, @payload nvarchar(max);
|
|
|
|
IF @inventory_source <> 'SNAPSHOT'
|
|
THROW 51022, 'FT546 shadow fingerprint source must be SNAPSHOT', 1;
|
|
|
|
SELECT @generation = COALESCE(@snapshot_generation, state.snapshot_generation)
|
|
FROM alg.shadow_snapshot_state state
|
|
WHERE state.warehouse_id = @warehouse_id
|
|
AND state.snapshot_status = 'PUBLISHED';
|
|
|
|
IF @generation IS NULL
|
|
THROW 51023, 'FT546 shadow fingerprint requires a snapshot generation', 1;
|
|
|
|
SELECT @payload = ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT cargo.space_id AS [@space_id], cargo.space_status AS [@status],
|
|
cargo.locked AS [@locked], cargo.tray_code AS [@tray_code],
|
|
cargo.depth_raw AS [@depth], cargo.platoon AS [@platoon],
|
|
cargo.column_no AS [@column], cargo.floor_no AS [@floor],
|
|
topology.lane_depth AS [@lane_depth], topology.base_zone AS [@base_zone],
|
|
ISNULL(role.role, 'STORAGE') AS [@role]
|
|
FROM alg.cargo_space_snapshot cargo
|
|
LEFT JOIN alg.space_topology topology
|
|
ON topology.warehouse_id = cargo.warehouse_id
|
|
AND topology.space_id = cargo.space_id
|
|
AND topology.snapshot_generation = @generation
|
|
LEFT JOIN alg.space_role role ON role.space_id = cargo.space_id
|
|
WHERE cargo.warehouse_id = @warehouse_id
|
|
AND cargo.lane_code = @lane_code
|
|
AND cargo.snapshot_generation = @generation
|
|
ORDER BY TRY_CONVERT(int, cargo.depth_raw), cargo.space_id
|
|
FOR XML PATH('space'), ROOT('spaces'), TYPE
|
|
)), '');
|
|
|
|
SET @payload = @payload + '|INVENTORY|' + ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT item.stock_id AS [@stock_id], item.space_id AS [@space_id],
|
|
item.tray_code AS [@tray_code], item.project_no AS [@project_no],
|
|
item.product_no AS [@product_no], item.lot_no AS [@lot_no],
|
|
item.inbound_time_raw AS [@inbound_time], item.quantity AS [@quantity],
|
|
item.out_quantity AS [@out_quantity]
|
|
FROM alg.inventory_item_snapshot item
|
|
WHERE item.warehouse_id = @warehouse_id
|
|
AND item.snapshot_generation = @generation
|
|
AND EXISTS (SELECT 1 FROM alg.cargo_space_snapshot cargo
|
|
WHERE cargo.warehouse_id = item.warehouse_id
|
|
AND cargo.space_id = item.space_id
|
|
AND cargo.lane_code = @lane_code
|
|
AND cargo.snapshot_generation = @generation)
|
|
ORDER BY item.space_id, item.stock_id
|
|
FOR XML PATH('item'), ROOT('inventory'), TYPE
|
|
)), '');
|
|
|
|
SET @payload = @payload + '|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_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.active_job_snapshot job
|
|
JOIN alg.cargo_space_snapshot source_cargo
|
|
ON source_cargo.warehouse_id = job.warehouse_id
|
|
AND source_cargo.space_id = job.source_space_id
|
|
AND source_cargo.snapshot_generation = job.snapshot_generation
|
|
WHERE job.warehouse_id = @warehouse_id
|
|
AND source_cargo.lane_code = @lane_code
|
|
AND job.snapshot_generation = @generation
|
|
ORDER BY job.job_id
|
|
FOR XML PATH('job'), ROOT('jobs'), TYPE
|
|
)), '');
|
|
|
|
SET @payload = @payload + '|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
|
|
)), '');
|
|
|
|
SET @payload = @payload + '|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
|
|
)), '');
|
|
|
|
SET @payload = @payload + '|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
|
|
)), '');
|
|
|
|
SET @semantic_fingerprint = HASHBYTES('SHA2_256', CONVERT(varbinary(max), @payload));
|
|
END;
|
|
GO
|
|
|
|
CREATE PROCEDURE alg.usp_rebuild_lane_state
|
|
@warehouse_id varchar(80) = NULL,
|
|
@lane_code varchar(80) = NULL,
|
|
@snapshot_generation bigint = NULL
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
IF NULLIF(LTRIM(RTRIM(@warehouse_id)), '') IS NULL
|
|
THROW 51019, 'warehouse_id is required', 1;
|
|
DECLARE @generation bigint;
|
|
|
|
SET @generation = @snapshot_generation;
|
|
IF @generation IS NULL
|
|
SELECT @generation = state.snapshot_generation
|
|
FROM alg.shadow_snapshot_state state
|
|
WHERE state.warehouse_id = @warehouse_id
|
|
AND state.snapshot_status = 'PUBLISHED';
|
|
|
|
IF @generation IS NULL
|
|
THROW 51024, 'FT546 shadow lane rebuild requires a snapshot generation', 1;
|
|
|
|
;WITH outbound_lanes AS (
|
|
SELECT DISTINCT job.warehouse_id, cargo.lane_code
|
|
FROM alg.active_job_snapshot job
|
|
JOIN alg.cargo_space_snapshot cargo
|
|
ON cargo.warehouse_id = job.warehouse_id
|
|
AND cargo.space_id = job.source_space_id
|
|
AND cargo.snapshot_generation = @generation
|
|
WHERE job.snapshot_generation = @generation
|
|
AND TRY_CONVERT(int, job.in_or_out) >= 20
|
|
AND cargo.lane_code IS NOT NULL
|
|
), lane_gaps AS (
|
|
SELECT DISTINCT inner_space.warehouse_id, inner_space.lane_code
|
|
FROM alg.cargo_space_snapshot inner_space
|
|
JOIN alg.cargo_space_snapshot outer_space
|
|
ON outer_space.warehouse_id = inner_space.warehouse_id
|
|
AND outer_space.lane_code = inner_space.lane_code
|
|
AND outer_space.snapshot_generation = @generation
|
|
AND TRY_CONVERT(int, outer_space.depth_raw) > TRY_CONVERT(int, inner_space.depth_raw)
|
|
LEFT JOIN alg.space_inventory_summary inner_stock
|
|
ON inner_stock.warehouse_id = inner_space.warehouse_id
|
|
AND inner_stock.space_id = inner_space.space_id
|
|
AND inner_stock.snapshot_generation = @generation
|
|
LEFT JOIN alg.space_inventory_summary outer_stock
|
|
ON outer_stock.warehouse_id = outer_space.warehouse_id
|
|
AND outer_stock.space_id = outer_space.space_id
|
|
AND outer_stock.snapshot_generation = @generation
|
|
WHERE inner_space.snapshot_generation = @generation
|
|
AND NULLIF(LTRIM(RTRIM(inner_space.tray_code)), '') IS NULL
|
|
AND inner_stock.space_id IS NULL
|
|
AND (NULLIF(LTRIM(RTRIM(outer_space.tray_code)), '') IS NOT NULL
|
|
OR outer_stock.space_id IS NOT NULL)
|
|
)
|
|
SELECT cargo.warehouse_id, cargo.lane_code,
|
|
COUNT(*) AS space_count,
|
|
SUM(CASE WHEN cargo.space_status = '2' OR ISNULL(stock.stock_detail_count, 0) > 0 THEN 1 ELSE 0 END) AS occupied_count,
|
|
SUM(CASE WHEN cargo.space_status = '1'
|
|
AND (NULLIF(LTRIM(RTRIM(cargo.locked)), '') IS NULL OR LTRIM(RTRIM(cargo.locked)) IN ('0', 'N'))
|
|
AND NULLIF(LTRIM(RTRIM(cargo.tray_code)), '') IS NULL
|
|
AND ISNULL(stock.stock_detail_count, 0) = 0
|
|
AND ISNULL(role.role, 'STORAGE') = 'STORAGE'
|
|
AND outbound_lanes.lane_code IS NULL
|
|
AND reservation.reservation_id IS NULL
|
|
AND lane_gaps.lane_code IS NULL
|
|
THEN 1 ELSE 0 END) AS available_count,
|
|
CONVERT(bit, CASE WHEN outbound_lanes.lane_code IS NULL THEN 0 ELSE 1 END) AS pending_outbound,
|
|
CONVERT(bit, CASE WHEN lane_gaps.lane_code IS NULL THEN 0 ELSE 1 END) AS has_gap,
|
|
CAST(NULL AS varbinary(32)) AS semantic_fingerprint
|
|
INTO #source_state
|
|
FROM alg.cargo_space_snapshot cargo
|
|
LEFT JOIN alg.space_inventory_summary stock
|
|
ON stock.warehouse_id = cargo.warehouse_id
|
|
AND stock.space_id = cargo.space_id
|
|
AND stock.snapshot_generation = @generation
|
|
LEFT JOIN alg.space_role role ON role.space_id = cargo.space_id
|
|
LEFT JOIN outbound_lanes
|
|
ON outbound_lanes.warehouse_id = cargo.warehouse_id
|
|
AND outbound_lanes.lane_code = cargo.lane_code
|
|
LEFT JOIN alg.reservation reservation
|
|
ON reservation.space_id = cargo.space_id
|
|
AND reservation.status = 'ACTIVE'
|
|
LEFT JOIN lane_gaps
|
|
ON lane_gaps.warehouse_id = cargo.warehouse_id
|
|
AND lane_gaps.lane_code = cargo.lane_code
|
|
WHERE cargo.snapshot_generation = @generation
|
|
AND (@warehouse_id IS NULL OR cargo.warehouse_id = @warehouse_id)
|
|
AND (@lane_code IS NULL OR cargo.lane_code = @lane_code)
|
|
GROUP BY cargo.warehouse_id, cargo.lane_code,
|
|
outbound_lanes.lane_code, lane_gaps.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',
|
|
@snapshot_generation = @generation;
|
|
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.snapshot_generation <> @generation 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,
|
|
snapshot_generation = @generation,
|
|
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, snapshot_generation)
|
|
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, @generation)
|
|
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
|
|
|
|
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 51002, 'warehouse_id is required', 1;
|
|
|
|
DECLARE @generation bigint;
|
|
SELECT @generation = snapshot_generation
|
|
FROM alg.shadow_snapshot_state
|
|
WHERE warehouse_id = @warehouse_id AND snapshot_status = 'PUBLISHED';
|
|
|
|
IF @generation IS NULL
|
|
THROW 51003, 'published snapshot is required', 1;
|
|
|
|
EXEC alg.usp_rebuild_space_topology @warehouse_id = @warehouse_id,
|
|
@snapshot_generation = @generation;
|
|
EXEC alg.usp_sync_inventory_snapshot @warehouse_id = @warehouse_id,
|
|
@snapshot_generation = @generation;
|
|
EXEC alg.usp_rebuild_lane_state @warehouse_id = @warehouse_id,
|
|
@snapshot_generation = @generation;
|
|
END;
|
|
GO
|
|
|
|
CREATE PROCEDURE alg.usp_claim_shadow_instance
|
|
@warehouse_id varchar(80),
|
|
@instance_id varchar(80),
|
|
@claimed bit OUTPUT
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
SET XACT_ABORT ON;
|
|
SET @claimed = 0;
|
|
|
|
IF NULLIF(LTRIM(RTRIM(@warehouse_id)), '') IS NULL
|
|
THROW 51004, 'warehouse_id is required', 1;
|
|
IF NULLIF(LTRIM(RTRIM(@instance_id)), '') IS NULL
|
|
THROW 51005, 'instance_id is required', 1;
|
|
|
|
DECLARE @now datetime2 = SYSUTCDATETIME(), @current_instance varchar(80),
|
|
@last_seen_at datetime2;
|
|
|
|
BEGIN TRY
|
|
BEGIN TRANSACTION;
|
|
SELECT @current_instance = heartbeat.instance_id, @last_seen_at = heartbeat.last_seen_at
|
|
FROM alg.shadow_instance_heartbeat heartbeat WITH (UPDLOCK, HOLDLOCK)
|
|
WHERE heartbeat.warehouse_id = @warehouse_id;
|
|
|
|
IF @current_instance IS NULL
|
|
BEGIN
|
|
INSERT INTO alg.shadow_instance_heartbeat (warehouse_id, instance_id, claimed_at, last_seen_at)
|
|
VALUES (@warehouse_id, @instance_id, @now, @now);
|
|
SET @claimed = 1;
|
|
END
|
|
ELSE IF @current_instance = @instance_id
|
|
BEGIN
|
|
UPDATE alg.shadow_instance_heartbeat
|
|
SET last_seen_at = @now
|
|
WHERE warehouse_id = @warehouse_id;
|
|
SET @claimed = 1;
|
|
END
|
|
ELSE IF @last_seen_at < DATEADD(second, -120, @now)
|
|
BEGIN
|
|
UPDATE alg.shadow_instance_heartbeat
|
|
SET instance_id = @instance_id, claimed_at = @now, last_seen_at = @now
|
|
WHERE warehouse_id = @warehouse_id;
|
|
SET @claimed = 1;
|
|
END;
|
|
|
|
COMMIT TRANSACTION;
|
|
END TRY
|
|
BEGIN CATCH
|
|
IF @@TRANCOUNT > 0
|
|
ROLLBACK TRANSACTION;
|
|
THROW;
|
|
END CATCH;
|
|
SELECT @claimed AS claimed;
|
|
END;
|
|
GO
|
|
|
|
CREATE PROCEDURE alg.usp_refresh_shadow_snapshot
|
|
@warehouse_id varchar(80),
|
|
@snapshot_generation bigint,
|
|
@instance_id varchar(80)
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
SET XACT_ABORT ON;
|
|
|
|
IF NULLIF(LTRIM(RTRIM(@warehouse_id)), '') IS NULL
|
|
THROW 51006, 'warehouse_id is required', 1;
|
|
IF NULLIF(LTRIM(RTRIM(@instance_id)), '') IS NULL
|
|
THROW 51007, 'instance_id is required', 1;
|
|
IF @snapshot_generation <= 0
|
|
THROW 51008, 'snapshot_generation must be positive', 1;
|
|
|
|
DECLARE @pre_source_count bigint, @post_source_count bigint,
|
|
@pre_source_signature varbinary(32), @post_source_signature varbinary(32),
|
|
@source_payload nvarchar(max), @synchronized_at datetime2,
|
|
@numeric_warehouse_id decimal(38,0),
|
|
@current_generation bigint;
|
|
|
|
IF LTRIM(RTRIM(@warehouse_id)) NOT LIKE '%[^0-9]%'
|
|
SET @numeric_warehouse_id = TRY_CONVERT(decimal(38,0), LTRIM(RTRIM(@warehouse_id)));
|
|
|
|
BEGIN TRY
|
|
BEGIN TRANSACTION;
|
|
|
|
SELECT @current_generation = state.snapshot_generation
|
|
FROM alg.shadow_snapshot_state state WITH (UPDLOCK, HOLDLOCK)
|
|
WHERE state.warehouse_id = @warehouse_id;
|
|
|
|
IF @current_generation IS NOT NULL AND @snapshot_generation <= @current_generation
|
|
THROW 51009, 'snapshot_generation must advance the published generation', 1;
|
|
|
|
SELECT @pre_source_count =
|
|
(SELECT COUNT_BIG(*) FROM dbo.bas_cargo_space cargo WITH (NOLOCK) WHERE cargo.warehouse_id = @warehouse_id)
|
|
+ (SELECT COUNT_BIG(*) FROM dbo.bas_stock stock WITH (NOLOCK)
|
|
JOIN dbo.bas_cargo_space cargo WITH (NOLOCK) ON cargo.cargo_space_id = stock.cargo_space_id
|
|
WHERE cargo.warehouse_id = @warehouse_id)
|
|
+ (SELECT COUNT_BIG(*) FROM dbo.mydo_job job WITH (NOLOCK) WHERE job.warehouse_id = @warehouse_id)
|
|
+ (SELECT COUNT_BIG(*) FROM dbo.mydo_job_detail detail WITH (NOLOCK)
|
|
JOIN dbo.mydo_job job WITH (NOLOCK) ON job.job_id = detail.job_id
|
|
WHERE job.warehouse_id = @warehouse_id)
|
|
+ (SELECT COUNT_BIG(*) FROM dbo.in_stockin_detail inbound WITH (NOLOCK)
|
|
JOIN dbo.mydo_job_detail detail WITH (NOLOCK) ON detail.stockin_detail_id = inbound.stockin_detail_id
|
|
JOIN dbo.mydo_job job WITH (NOLOCK) ON job.job_id = detail.job_id
|
|
JOIN dbo.in_stockin stockin WITH (NOLOCK) ON stockin.stockin_id = inbound.stockin_id
|
|
WHERE (job.finish_time IS NULL OR LTRIM(RTRIM(job.finish_time)) = '')
|
|
AND (LTRIM(RTRIM(stockin.warehouse_id)) = LTRIM(RTRIM(@warehouse_id))
|
|
OR (@numeric_warehouse_id IS NOT NULL
|
|
AND LTRIM(RTRIM(stockin.warehouse_id)) NOT LIKE '%[^0-9]%'
|
|
AND TRY_CONVERT(decimal(38,0), LTRIM(RTRIM(stockin.warehouse_id))) = @numeric_warehouse_id)))
|
|
+ (SELECT COUNT_BIG(*) FROM dbo.out_stockout_detail outbound WITH (NOLOCK)
|
|
JOIN dbo.out_stockout stockout WITH (NOLOCK) ON stockout.stockout_id = outbound.stockout_id
|
|
WHERE ISNULL(outbound.quantity, 0) > ISNULL(outbound.allot_quantity, 0)
|
|
AND (LTRIM(RTRIM(stockout.warehouse_id)) = LTRIM(RTRIM(@warehouse_id))
|
|
OR (@numeric_warehouse_id IS NOT NULL
|
|
AND LTRIM(RTRIM(stockout.warehouse_id)) NOT LIKE '%[^0-9]%'
|
|
AND TRY_CONVERT(decimal(38,0), LTRIM(RTRIM(stockout.warehouse_id))) = @numeric_warehouse_id)));
|
|
|
|
SELECT @source_payload = ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT cargo.cargo_space_id AS [@space_id], cargo.warehouse_id AS [@warehouse_id],
|
|
cargo.group_coding_no AS [@lane_code], cargo.cargo_area_id AS [@cargo_area_id],
|
|
cargo.roadway_id AS [@roadway_id], cargo.cargo_space_name AS [@display_name],
|
|
cargo.the_platoon AS [@platoon], cargo.the_column AS [@column_no],
|
|
cargo.the_floor AS [@floor_no], cargo.group_coding AS [@depth_raw],
|
|
cargo.status AS [@space_status], cargo.locked AS [@locked], cargo.tray_code AS [@tray_code]
|
|
FROM dbo.bas_cargo_space cargo WITH (NOLOCK)
|
|
WHERE cargo.warehouse_id = @warehouse_id
|
|
ORDER BY cargo.cargo_space_id
|
|
FOR XML PATH('cargo'), ROOT('cargo_spaces'), TYPE
|
|
)), '');
|
|
|
|
SET @source_payload = @source_payload + '|STOCK|' + ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT stock.stock_id AS [@stock_id], stock.cargo_space_id AS [@space_id],
|
|
stock.warehouse_id AS [@warehouse_id], stock.tray_code AS [@tray_code],
|
|
stock.spare4 AS [@project_no], stock.product_id AS [@product_no],
|
|
stock.lot_no AS [@lot_no], stock.in_date AS [@in_date],
|
|
stock.quantity AS [@quantity], stock.out_quantity AS [@out_quantity]
|
|
FROM dbo.bas_stock stock WITH (NOLOCK)
|
|
JOIN dbo.bas_cargo_space cargo WITH (NOLOCK) ON cargo.cargo_space_id = stock.cargo_space_id
|
|
WHERE cargo.warehouse_id = @warehouse_id
|
|
ORDER BY stock.stock_id
|
|
FOR XML PATH('stock'), ROOT('stocks'), TYPE
|
|
)), '');
|
|
|
|
SET @source_payload = @source_payload + '|JOB|' + ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT job.job_id AS [@job_id], job.status AS [@status], job.task_no AS [@task_no],
|
|
job.tray_code AS [@tray_code], job.cargo_space_id AS [@source_space_id],
|
|
job.target_cargo_space_id AS [@target_space_id], job.in_or_out AS [@in_or_out],
|
|
job.create_time AS [@create_time], job.finish_time AS [@finish_time],
|
|
job.warehouse_id AS [@warehouse_id]
|
|
FROM dbo.mydo_job job WITH (NOLOCK)
|
|
WHERE job.warehouse_id = @warehouse_id
|
|
ORDER BY job.job_id
|
|
FOR XML PATH('job'), ROOT('jobs'), TYPE
|
|
)), '');
|
|
|
|
SET @source_payload = @source_payload + '|JOB_DETAIL|' + ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT detail.job_detail_id AS [@job_detail_id], detail.job_id AS [@job_id],
|
|
detail.stock_id AS [@stock_id], detail.lot_no AS [@lot_no],
|
|
detail.in_date AS [@in_date], detail.in_or_out_id AS [@request_id],
|
|
detail.in_or_out_d_id AS [@request_detail_id], detail.product_id AS [@product_id],
|
|
detail.stock_status AS [@stock_status], detail.in_quantity AS [@in_quantity],
|
|
detail.stock_quantity AS [@stock_quantity], detail.out_quantity AS [@out_quantity],
|
|
detail.pick_quantity AS [@pick_quantity], detail.stockin_detail_id AS [@stockin_detail_id]
|
|
FROM dbo.mydo_job_detail detail WITH (NOLOCK)
|
|
JOIN dbo.mydo_job job WITH (NOLOCK) ON job.job_id = detail.job_id
|
|
WHERE job.warehouse_id = @warehouse_id
|
|
ORDER BY detail.job_detail_id
|
|
FOR XML PATH('job_detail'), ROOT('job_details'), TYPE
|
|
)), '');
|
|
|
|
SET @source_payload = @source_payload + '|INBOUND|' + ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT inbound.stockin_detail_id AS [@stockin_detail_id], inbound.stockin_guid AS [@stockin_guid],
|
|
inbound.stockin_id AS [@stockin_id], inbound.lot_no AS [@lot_no],
|
|
inbound.product_id AS [@product_id], inbound.quantity AS [@quantity],
|
|
inbound.assign_num AS [@assign_num], inbound.spare4 AS [@project_no],
|
|
job.warehouse_id AS [@warehouse_id], stockin.warehouse_id AS [@source_warehouse_id],
|
|
job.task_no AS [@task_no],
|
|
job.tray_code AS [@tray_code], detail.job_id AS [@job_id],
|
|
detail.in_or_out_id AS [@request_id]
|
|
FROM dbo.in_stockin_detail inbound WITH (NOLOCK)
|
|
JOIN dbo.mydo_job_detail detail WITH (NOLOCK) ON detail.stockin_detail_id = inbound.stockin_detail_id
|
|
JOIN dbo.mydo_job job WITH (NOLOCK) ON job.job_id = detail.job_id
|
|
JOIN dbo.in_stockin stockin WITH (NOLOCK) ON stockin.stockin_id = inbound.stockin_id
|
|
WHERE (job.finish_time IS NULL OR LTRIM(RTRIM(job.finish_time)) = '')
|
|
AND (LTRIM(RTRIM(stockin.warehouse_id)) = LTRIM(RTRIM(@warehouse_id))
|
|
OR (@numeric_warehouse_id IS NOT NULL
|
|
AND LTRIM(RTRIM(stockin.warehouse_id)) NOT LIKE '%[^0-9]%'
|
|
AND TRY_CONVERT(decimal(38,0), LTRIM(RTRIM(stockin.warehouse_id))) = @numeric_warehouse_id))
|
|
ORDER BY inbound.stockin_detail_id
|
|
FOR XML PATH('inbound'), ROOT('inbound_requests'), TYPE
|
|
)), '');
|
|
|
|
SET @source_payload = @source_payload + '|OUTBOUND|' + ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT outbound.stockout_detail_id AS [@stockout_detail_id], outbound.warehouse_id AS [@warehouse_id],
|
|
stockout.warehouse_id AS [@source_warehouse_id],
|
|
warehouse.project_no AS [@project_no],
|
|
outbound.product_id AS [@product_id], outbound.lot_no AS [@lot_no],
|
|
outbound.quantity AS [@quantity], outbound.assign_num AS [@assign_num],
|
|
outbound.allot_quantity AS [@allot_quantity]
|
|
FROM dbo.out_stockout_detail outbound WITH (NOLOCK)
|
|
JOIN dbo.out_stockout stockout WITH (NOLOCK) ON stockout.stockout_id = outbound.stockout_id
|
|
LEFT JOIN dbo.bas_warehouse warehouse WITH (NOLOCK)
|
|
ON warehouse.warehouse_id = @warehouse_id
|
|
WHERE ISNULL(outbound.quantity, 0) > ISNULL(outbound.allot_quantity, 0)
|
|
AND (LTRIM(RTRIM(stockout.warehouse_id)) = LTRIM(RTRIM(@warehouse_id))
|
|
OR (@numeric_warehouse_id IS NOT NULL
|
|
AND LTRIM(RTRIM(stockout.warehouse_id)) NOT LIKE '%[^0-9]%'
|
|
AND TRY_CONVERT(decimal(38,0), LTRIM(RTRIM(stockout.warehouse_id))) = @numeric_warehouse_id))
|
|
ORDER BY outbound.stockout_detail_id
|
|
FOR XML PATH('outbound'), ROOT('outbound_requests'), TYPE
|
|
)), '');
|
|
|
|
SET @pre_source_signature = HASHBYTES('SHA2_256', CONVERT(varbinary(max), @source_payload));
|
|
|
|
DELETE FROM alg.cargo_space_snapshot WHERE warehouse_id = @warehouse_id;
|
|
DELETE FROM alg.inventory_item_snapshot WHERE warehouse_id = @warehouse_id;
|
|
DELETE FROM alg.active_job_snapshot WHERE warehouse_id = @warehouse_id;
|
|
DELETE FROM alg.shadow_inbound_request_snapshot WHERE warehouse_id = @warehouse_id;
|
|
DELETE FROM alg.shadow_outbound_request_snapshot WHERE warehouse_id = @warehouse_id;
|
|
DELETE FROM alg.space_topology WHERE warehouse_id = @warehouse_id;
|
|
DELETE FROM alg.space_inventory_summary WHERE warehouse_id = @warehouse_id;
|
|
DELETE FROM alg.lane_state WHERE warehouse_id = @warehouse_id;
|
|
|
|
SET @synchronized_at = SYSUTCDATETIME();
|
|
|
|
INSERT INTO alg.cargo_space_snapshot (
|
|
warehouse_id, space_id, lane_code, cargo_area_id, roadway_id, display_name,
|
|
platoon, column_no, floor_no, depth_raw, space_status, locked, tray_code,
|
|
snapshot_generation, synchronized_at)
|
|
SELECT cargo.warehouse_id, cargo.cargo_space_id, cargo.group_coding_no,
|
|
cargo.cargo_area_id, cargo.roadway_id, cargo.cargo_space_name,
|
|
cargo.the_platoon, cargo.the_column, cargo.the_floor, cargo.group_coding,
|
|
cargo.status, cargo.locked, cargo.tray_code,
|
|
@snapshot_generation, @synchronized_at
|
|
FROM dbo.bas_cargo_space cargo WITH (NOLOCK)
|
|
WHERE cargo.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, snapshot_generation, synchronized_at)
|
|
SELECT cargo.warehouse_id, stock.stock_id, stock.cargo_space_id, stock.tray_code,
|
|
stock.spare4, stock.product_id, stock.lot_no, stock.in_date,
|
|
TRY_CONVERT(datetime2, stock.in_date), stock.quantity, stock.out_quantity,
|
|
@snapshot_generation, @synchronized_at
|
|
FROM dbo.bas_stock stock WITH (NOLOCK)
|
|
JOIN dbo.bas_cargo_space cargo WITH (NOLOCK) ON cargo.cargo_space_id = stock.cargo_space_id
|
|
WHERE cargo.warehouse_id = @warehouse_id;
|
|
|
|
INSERT INTO alg.active_job_snapshot (
|
|
warehouse_id, job_id, task_no, tray_code, source_space_id, target_space_id,
|
|
status, in_or_out, create_time_raw, snapshot_generation, synchronized_at)
|
|
SELECT job.warehouse_id, job.job_id, job.task_no, job.tray_code,
|
|
NULLIF(LTRIM(RTRIM(job.cargo_space_id)), ''),
|
|
NULLIF(LTRIM(RTRIM(job.target_cargo_space_id)), ''), job.status,
|
|
job.in_or_out, job.create_time, @snapshot_generation, @synchronized_at
|
|
FROM dbo.mydo_job job WITH (NOLOCK)
|
|
WHERE job.warehouse_id = @warehouse_id
|
|
AND (job.finish_time IS NULL OR LTRIM(RTRIM(job.finish_time)) = '');
|
|
|
|
;WITH inbound_source AS (
|
|
SELECT @warehouse_id AS warehouse_id, job.task_no, job.tray_code,
|
|
detail.in_or_out_id AS request_id, job.warehouse_id AS raw_warehouse_id,
|
|
inbound.spare4 AS project_no, inbound.product_id, inbound.lot_no,
|
|
ROW_NUMBER() OVER (
|
|
PARTITION BY job.task_no, job.tray_code
|
|
ORDER BY inbound.stockin_detail_id, detail.job_detail_id) AS source_rank
|
|
FROM dbo.in_stockin_detail inbound WITH (NOLOCK)
|
|
JOIN dbo.mydo_job_detail detail WITH (NOLOCK)
|
|
ON detail.stockin_detail_id = inbound.stockin_detail_id
|
|
JOIN dbo.mydo_job job WITH (NOLOCK) ON job.job_id = detail.job_id
|
|
JOIN dbo.in_stockin stockin WITH (NOLOCK) ON stockin.stockin_id = inbound.stockin_id
|
|
WHERE (job.finish_time IS NULL OR LTRIM(RTRIM(job.finish_time)) = '')
|
|
AND (LTRIM(RTRIM(stockin.warehouse_id)) = LTRIM(RTRIM(@warehouse_id))
|
|
OR (@numeric_warehouse_id IS NOT NULL
|
|
AND LTRIM(RTRIM(stockin.warehouse_id)) NOT LIKE '%[^0-9]%'
|
|
AND TRY_CONVERT(decimal(38,0), LTRIM(RTRIM(stockin.warehouse_id))) = @numeric_warehouse_id))
|
|
)
|
|
INSERT INTO alg.shadow_inbound_request_snapshot (
|
|
warehouse_id, task_no, tray_no, request_id, raw_warehouse_id,
|
|
project_no, product_id, lot_no, snapshot_generation, synchronized_at)
|
|
SELECT @warehouse_id, ISNULL(task_no, ''), ISNULL(tray_code, ''), request_id,
|
|
raw_warehouse_id, project_no, product_id, lot_no,
|
|
@snapshot_generation, @synchronized_at
|
|
FROM inbound_source
|
|
WHERE source_rank = 1;
|
|
|
|
INSERT INTO alg.shadow_outbound_request_snapshot (
|
|
warehouse_id, stockout_detail_id, raw_warehouse_id, project_no, product_id,
|
|
requested_quantity, snapshot_generation, synchronized_at)
|
|
SELECT @warehouse_id, outbound.stockout_detail_id, outbound.warehouse_id,
|
|
NULLIF(LTRIM(RTRIM(warehouse.project_no)), ''), outbound.product_id,
|
|
CONVERT(decimal(38,6), outbound.quantity),
|
|
@snapshot_generation, @synchronized_at
|
|
FROM dbo.out_stockout_detail outbound WITH (NOLOCK)
|
|
JOIN dbo.out_stockout stockout WITH (NOLOCK) ON stockout.stockout_id = outbound.stockout_id
|
|
LEFT JOIN dbo.bas_warehouse warehouse WITH (NOLOCK)
|
|
ON warehouse.warehouse_id = @warehouse_id
|
|
WHERE ISNULL(outbound.quantity, 0) > ISNULL(outbound.allot_quantity, 0)
|
|
AND (LTRIM(RTRIM(stockout.warehouse_id)) = LTRIM(RTRIM(@warehouse_id))
|
|
OR (@numeric_warehouse_id IS NOT NULL
|
|
AND LTRIM(RTRIM(stockout.warehouse_id)) NOT LIKE '%[^0-9]%'
|
|
AND TRY_CONVERT(decimal(38,0), LTRIM(RTRIM(stockout.warehouse_id))) = @numeric_warehouse_id));
|
|
|
|
EXEC alg.usp_rebuild_space_topology @warehouse_id = @warehouse_id,
|
|
@snapshot_generation = @snapshot_generation;
|
|
EXEC alg.usp_sync_inventory_snapshot @warehouse_id = @warehouse_id,
|
|
@snapshot_generation = @snapshot_generation;
|
|
EXEC alg.usp_rebuild_lane_state @warehouse_id = @warehouse_id,
|
|
@snapshot_generation = @snapshot_generation;
|
|
|
|
SELECT @post_source_count =
|
|
(SELECT COUNT_BIG(*) FROM dbo.bas_cargo_space cargo WITH (NOLOCK) WHERE cargo.warehouse_id = @warehouse_id)
|
|
+ (SELECT COUNT_BIG(*) FROM dbo.bas_stock stock WITH (NOLOCK)
|
|
JOIN dbo.bas_cargo_space cargo WITH (NOLOCK) ON cargo.cargo_space_id = stock.cargo_space_id
|
|
WHERE cargo.warehouse_id = @warehouse_id)
|
|
+ (SELECT COUNT_BIG(*) FROM dbo.mydo_job job WITH (NOLOCK) WHERE job.warehouse_id = @warehouse_id)
|
|
+ (SELECT COUNT_BIG(*) FROM dbo.mydo_job_detail detail WITH (NOLOCK)
|
|
JOIN dbo.mydo_job job WITH (NOLOCK) ON job.job_id = detail.job_id
|
|
WHERE job.warehouse_id = @warehouse_id)
|
|
+ (SELECT COUNT_BIG(*) FROM dbo.in_stockin_detail inbound WITH (NOLOCK)
|
|
JOIN dbo.mydo_job_detail detail WITH (NOLOCK) ON detail.stockin_detail_id = inbound.stockin_detail_id
|
|
JOIN dbo.mydo_job job WITH (NOLOCK) ON job.job_id = detail.job_id
|
|
JOIN dbo.in_stockin stockin WITH (NOLOCK) ON stockin.stockin_id = inbound.stockin_id
|
|
WHERE (job.finish_time IS NULL OR LTRIM(RTRIM(job.finish_time)) = '')
|
|
AND (LTRIM(RTRIM(stockin.warehouse_id)) = LTRIM(RTRIM(@warehouse_id))
|
|
OR (@numeric_warehouse_id IS NOT NULL
|
|
AND LTRIM(RTRIM(stockin.warehouse_id)) NOT LIKE '%[^0-9]%'
|
|
AND TRY_CONVERT(decimal(38,0), LTRIM(RTRIM(stockin.warehouse_id))) = @numeric_warehouse_id)))
|
|
+ (SELECT COUNT_BIG(*) FROM dbo.out_stockout_detail outbound WITH (NOLOCK)
|
|
JOIN dbo.out_stockout stockout WITH (NOLOCK) ON stockout.stockout_id = outbound.stockout_id
|
|
WHERE ISNULL(outbound.quantity, 0) > ISNULL(outbound.allot_quantity, 0)
|
|
AND (LTRIM(RTRIM(stockout.warehouse_id)) = LTRIM(RTRIM(@warehouse_id))
|
|
OR (@numeric_warehouse_id IS NOT NULL
|
|
AND LTRIM(RTRIM(stockout.warehouse_id)) NOT LIKE '%[^0-9]%'
|
|
AND TRY_CONVERT(decimal(38,0), LTRIM(RTRIM(stockout.warehouse_id))) = @numeric_warehouse_id)));
|
|
|
|
SELECT @source_payload = ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT cargo.cargo_space_id AS [@space_id], cargo.warehouse_id AS [@warehouse_id],
|
|
cargo.group_coding_no AS [@lane_code], cargo.cargo_area_id AS [@cargo_area_id],
|
|
cargo.roadway_id AS [@roadway_id], cargo.cargo_space_name AS [@display_name],
|
|
cargo.the_platoon AS [@platoon], cargo.the_column AS [@column_no],
|
|
cargo.the_floor AS [@floor_no], cargo.group_coding AS [@depth_raw],
|
|
cargo.status AS [@space_status], cargo.locked AS [@locked], cargo.tray_code AS [@tray_code]
|
|
FROM dbo.bas_cargo_space cargo WITH (NOLOCK)
|
|
WHERE cargo.warehouse_id = @warehouse_id
|
|
ORDER BY cargo.cargo_space_id
|
|
FOR XML PATH('cargo'), ROOT('cargo_spaces'), TYPE
|
|
)), '');
|
|
SET @source_payload = @source_payload + '|STOCK|' + ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT stock.stock_id AS [@stock_id], stock.cargo_space_id AS [@space_id],
|
|
stock.warehouse_id AS [@warehouse_id], stock.tray_code AS [@tray_code],
|
|
stock.spare4 AS [@project_no], stock.product_id AS [@product_no],
|
|
stock.lot_no AS [@lot_no], stock.in_date AS [@in_date],
|
|
stock.quantity AS [@quantity], stock.out_quantity AS [@out_quantity]
|
|
FROM dbo.bas_stock stock WITH (NOLOCK)
|
|
JOIN dbo.bas_cargo_space cargo WITH (NOLOCK) ON cargo.cargo_space_id = stock.cargo_space_id
|
|
WHERE cargo.warehouse_id = @warehouse_id
|
|
ORDER BY stock.stock_id
|
|
FOR XML PATH('stock'), ROOT('stocks'), TYPE
|
|
)), '');
|
|
SET @source_payload = @source_payload + '|JOB|' + ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT job.job_id AS [@job_id], job.status AS [@status], job.task_no AS [@task_no],
|
|
job.tray_code AS [@tray_code], job.cargo_space_id AS [@source_space_id],
|
|
job.target_cargo_space_id AS [@target_space_id], job.in_or_out AS [@in_or_out],
|
|
job.create_time AS [@create_time], job.finish_time AS [@finish_time],
|
|
job.warehouse_id AS [@warehouse_id]
|
|
FROM dbo.mydo_job job WITH (NOLOCK)
|
|
WHERE job.warehouse_id = @warehouse_id
|
|
ORDER BY job.job_id
|
|
FOR XML PATH('job'), ROOT('jobs'), TYPE
|
|
)), '');
|
|
SET @source_payload = @source_payload + '|JOB_DETAIL|' + ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT detail.job_detail_id AS [@job_detail_id], detail.job_id AS [@job_id],
|
|
detail.stock_id AS [@stock_id], detail.lot_no AS [@lot_no],
|
|
detail.in_date AS [@in_date], detail.in_or_out_id AS [@request_id],
|
|
detail.in_or_out_d_id AS [@request_detail_id], detail.product_id AS [@product_id],
|
|
detail.stock_status AS [@stock_status], detail.in_quantity AS [@in_quantity],
|
|
detail.stock_quantity AS [@stock_quantity], detail.out_quantity AS [@out_quantity],
|
|
detail.pick_quantity AS [@pick_quantity], detail.stockin_detail_id AS [@stockin_detail_id]
|
|
FROM dbo.mydo_job_detail detail WITH (NOLOCK)
|
|
JOIN dbo.mydo_job job WITH (NOLOCK) ON job.job_id = detail.job_id
|
|
WHERE job.warehouse_id = @warehouse_id
|
|
ORDER BY detail.job_detail_id
|
|
FOR XML PATH('job_detail'), ROOT('job_details'), TYPE
|
|
)), '');
|
|
SET @source_payload = @source_payload + '|INBOUND|' + ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT inbound.stockin_detail_id AS [@stockin_detail_id], inbound.stockin_guid AS [@stockin_guid],
|
|
inbound.stockin_id AS [@stockin_id], inbound.lot_no AS [@lot_no],
|
|
inbound.product_id AS [@product_id], inbound.quantity AS [@quantity],
|
|
inbound.assign_num AS [@assign_num], inbound.spare4 AS [@project_no],
|
|
job.warehouse_id AS [@warehouse_id], stockin.warehouse_id AS [@source_warehouse_id],
|
|
job.task_no AS [@task_no],
|
|
job.tray_code AS [@tray_code], detail.job_id AS [@job_id],
|
|
detail.in_or_out_id AS [@request_id]
|
|
FROM dbo.in_stockin_detail inbound WITH (NOLOCK)
|
|
JOIN dbo.mydo_job_detail detail WITH (NOLOCK) ON detail.stockin_detail_id = inbound.stockin_detail_id
|
|
JOIN dbo.mydo_job job WITH (NOLOCK) ON job.job_id = detail.job_id
|
|
JOIN dbo.in_stockin stockin WITH (NOLOCK) ON stockin.stockin_id = inbound.stockin_id
|
|
WHERE (job.finish_time IS NULL OR LTRIM(RTRIM(job.finish_time)) = '')
|
|
AND (LTRIM(RTRIM(stockin.warehouse_id)) = LTRIM(RTRIM(@warehouse_id))
|
|
OR (@numeric_warehouse_id IS NOT NULL
|
|
AND LTRIM(RTRIM(stockin.warehouse_id)) NOT LIKE '%[^0-9]%'
|
|
AND TRY_CONVERT(decimal(38,0), LTRIM(RTRIM(stockin.warehouse_id))) = @numeric_warehouse_id))
|
|
ORDER BY inbound.stockin_detail_id
|
|
FOR XML PATH('inbound'), ROOT('inbound_requests'), TYPE
|
|
)), '');
|
|
SET @source_payload = @source_payload + '|OUTBOUND|' + ISNULL(CONVERT(nvarchar(max), (
|
|
SELECT outbound.stockout_detail_id AS [@stockout_detail_id], outbound.warehouse_id AS [@warehouse_id],
|
|
stockout.warehouse_id AS [@source_warehouse_id],
|
|
warehouse.project_no AS [@project_no],
|
|
outbound.product_id AS [@product_id], outbound.lot_no AS [@lot_no],
|
|
outbound.quantity AS [@quantity], outbound.assign_num AS [@assign_num],
|
|
outbound.allot_quantity AS [@allot_quantity]
|
|
FROM dbo.out_stockout_detail outbound WITH (NOLOCK)
|
|
JOIN dbo.out_stockout stockout WITH (NOLOCK) ON stockout.stockout_id = outbound.stockout_id
|
|
LEFT JOIN dbo.bas_warehouse warehouse WITH (NOLOCK)
|
|
ON warehouse.warehouse_id = @warehouse_id
|
|
WHERE ISNULL(outbound.quantity, 0) > ISNULL(outbound.allot_quantity, 0)
|
|
AND (LTRIM(RTRIM(stockout.warehouse_id)) = LTRIM(RTRIM(@warehouse_id))
|
|
OR (@numeric_warehouse_id IS NOT NULL
|
|
AND LTRIM(RTRIM(stockout.warehouse_id)) NOT LIKE '%[^0-9]%'
|
|
AND TRY_CONVERT(decimal(38,0), LTRIM(RTRIM(stockout.warehouse_id))) = @numeric_warehouse_id))
|
|
ORDER BY outbound.stockout_detail_id
|
|
FOR XML PATH('outbound'), ROOT('outbound_requests'), TYPE
|
|
)), '');
|
|
SET @post_source_signature = HASHBYTES('SHA2_256', CONVERT(varbinary(max), @source_payload));
|
|
|
|
IF @pre_source_count <> @post_source_count
|
|
OR @pre_source_signature <> @post_source_signature
|
|
THROW 51025, 'FT546 shadow refresh refused: source changed during refresh', 1;
|
|
|
|
MERGE alg.shadow_snapshot_state WITH (HOLDLOCK) AS target
|
|
USING (SELECT @warehouse_id AS warehouse_id) AS source
|
|
ON source.warehouse_id = target.warehouse_id
|
|
WHEN MATCHED THEN UPDATE SET
|
|
snapshot_generation = @snapshot_generation,
|
|
snapshot_status = 'PUBLISHED',
|
|
synchronized_at = SYSUTCDATETIME(),
|
|
source_signature = @post_source_signature,
|
|
source_row_count = @post_source_count,
|
|
instance_id = @instance_id,
|
|
last_error = NULL
|
|
WHEN NOT MATCHED THEN INSERT (
|
|
warehouse_id, snapshot_generation, snapshot_status, synchronized_at,
|
|
source_signature, source_row_count, instance_id, last_error)
|
|
VALUES (
|
|
@warehouse_id, @snapshot_generation, 'PUBLISHED', SYSUTCDATETIME(),
|
|
@post_source_signature, @post_source_count, @instance_id, NULL);
|
|
|
|
COMMIT TRANSACTION;
|
|
END TRY
|
|
BEGIN CATCH
|
|
IF @@TRANCOUNT > 0
|
|
ROLLBACK TRANSACTION;
|
|
THROW;
|
|
END CATCH;
|
|
END;
|
|
GO
|