analytics/mag_pbi/scripts/create_contractor_producer_tables.sql
2026-02-18 14:36:38 +03:00

170 lines
8.0 KiB
Transact-SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- =============================================================================
-- Скрипт: сопоставление Контрагент + Производитель с этапами оплаты
-- Схема: analytics
-- Источники: Контрагенты из _Reference168, Производители из _Reference260 (1С MAG_2019)
-- =============================================================================
USE [mag_pbi]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- -----------------------------------------------------------------------------
-- 0. DROP всех сущностей (пересоздание с нуля)
-- -----------------------------------------------------------------------------
IF OBJECT_ID(N'[analytics].[v_contractor_producer_mapping]', N'V') IS NOT NULL
DROP VIEW [analytics].[v_contractor_producer_mapping];
GO
IF OBJECT_ID(N'[analytics].[tr_contractor_producer_mapping_updated]', N'TR') IS NOT NULL
DROP TRIGGER [analytics].[tr_contractor_producer_mapping_updated];
GO
IF OBJECT_ID(N'[analytics].[contractor_producer_payment_stage]', N'U') IS NOT NULL
DROP TABLE [analytics].[contractor_producer_payment_stage];
GO
IF OBJECT_ID(N'[analytics].[contractor_producer_mapping]', N'U') IS NOT NULL
DROP TABLE [analytics].[contractor_producer_mapping];
GO
IF OBJECT_ID(N'[analytics].[v_contractors]', N'V') IS NOT NULL
DROP VIEW [analytics].[v_contractors];
GO
IF OBJECT_ID(N'[analytics].[v_producers]', N'V') IS NOT NULL
DROP VIEW [analytics].[v_producers];
GO
-- -----------------------------------------------------------------------------
-- 1. Представления для списков из 1С
-- -----------------------------------------------------------------------------
-- Контрагенты: [pbi].[ПартнерыКонтрагенты] уже существует (из _Reference168)
-- Для удобства создаём представление analytics.v_contractors с search-friendly полями
CREATE VIEW [analytics].[v_contractors] AS
SELECT
c._IDRRef AS contractor_1c_id, -- бинарный ключ 1С
LOWER(CONCAT(
SUBSTRING(CONVERT(nvarchar(36), c._IDRRef, 2), 25, 8), '-',
SUBSTRING(CONVERT(nvarchar(36), c._IDRRef, 2), 21, 4), '-',
SUBSTRING(CONVERT(nvarchar(36), c._IDRRef, 2), 17, 4), '-',
SUBSTRING(CONVERT(nvarchar(36), c._IDRRef, 2), 1, 4), '-',
SUBSTRING(CONVERT(nvarchar(36), c._IDRRef, 2), 5, 12)
)) AS contractor_id, -- строковый id для API/поиска
c._Description AS contractor_name
FROM [MAG_2019].[dbo].[_Reference168] c
WHERE c._Marked = 0;
GO
-- Производители из справочника 1С _Reference260
CREATE VIEW [analytics].[v_producers] AS
SELECT
pr._IDRRef AS producer_1c_id, -- бинарный ключ 1С
LOWER(CONCAT(
SUBSTRING(CONVERT(nvarchar(36), pr._IDRRef, 2), 25, 8), '-',
SUBSTRING(CONVERT(nvarchar(36), pr._IDRRef, 2), 21, 4), '-',
SUBSTRING(CONVERT(nvarchar(36), pr._IDRRef, 2), 17, 4), '-',
SUBSTRING(CONVERT(nvarchar(36), pr._IDRRef, 2), 1, 4), '-',
SUBSTRING(CONVERT(nvarchar(36), pr._IDRRef, 2), 5, 12)
)) AS producer_id, -- строковый id для API/поиска
pr._Description AS producer_name
FROM [MAG_2019].[dbo].[_Reference260] pr
WHERE pr._Marked = 0;
GO
-- -----------------------------------------------------------------------------
-- 2. Основная таблица: сопоставление Контрагент + Производитель
-- -----------------------------------------------------------------------------
CREATE TABLE [analytics].[contractor_producer_mapping] (
[id] INT IDENTITY(1,1) NOT NULL,
[contractor_1c_id] BINARY(16) NOT NULL, -- бинарный ключ 1С (_Reference168)
[producer_1c_id] BINARY(16) NOT NULL, -- бинарный ключ 1С (_Reference260)
[days_of_sales] INT NOT NULL DEFAULT 180, -- На сколько дней продажи привезли остатков
[logistics_days] INT NOT NULL DEFAULT 120, -- Срок логистики (дней от дня заказа)
[roic_norm] DECIMAL(12,4) NULL, -- Нормированный ROIC (при TN 100%)
[created_at] DATETIME2(0) NOT NULL DEFAULT GETDATE(),
[updated_at] DATETIME2(0) NOT NULL DEFAULT GETDATE(),
CONSTRAINT [PK_contractor_producer_mapping] PRIMARY KEY CLUSTERED ([id] ASC),
CONSTRAINT [UQ_contractor_producer] UNIQUE NONCLUSTERED ([contractor_1c_id], [producer_1c_id])
);
EXEC sys.sp_addextendedproperty
@name = N'MS_Description',
@value = N'Сопоставление Контрагент (1С) + Производитель (1С). Параметры для расчёта нормированного ROIC.',
@level0type = N'SCHEMA', @level0name = N'analytics',
@level1type = N'TABLE', @level1name = N'contractor_producer_mapping';
GO
-- -----------------------------------------------------------------------------
-- 3. Таблица этапов оплаты (неограниченное количество)
-- -----------------------------------------------------------------------------
CREATE TABLE [analytics].[contractor_producer_payment_stage] (
[id] INT IDENTITY(1,1) NOT NULL,
[mapping_id] INT NOT NULL,
[name] NVARCHAR(255) NOT NULL, -- Название этапа (Предоплата, Постоплата и т.д.)
[days] INT NOT NULL, -- Дней от дня заказа до оплаты
[percent] DECIMAL(9,4) NOT NULL, -- Процент от суммы (0..100)
[sort_order] INT NOT NULL DEFAULT 0,
CONSTRAINT [PK_contractor_producer_payment_stage] PRIMARY KEY CLUSTERED ([id] ASC),
CONSTRAINT [FK_payment_stage_mapping] FOREIGN KEY ([mapping_id])
REFERENCES [analytics].[contractor_producer_mapping]([id]) ON DELETE CASCADE
);
CREATE NONCLUSTERED INDEX [IX_payment_stage_mapping_id]
ON [analytics].[contractor_producer_payment_stage]([mapping_id] ASC);
EXEC sys.sp_addextendedproperty
@name = N'MS_Description',
@value = N'Этапы оплаты для пары Контрагент-Производитель. [{days, percent}, ...]. Сумма percent по паре должна = 100.',
@level0type = N'SCHEMA', @level0name = N'analytics',
@level1type = N'TABLE', @level1name = N'contractor_producer_payment_stage';
GO
-- -----------------------------------------------------------------------------
-- 4. Представление для выборки с именами (для UI и API)
-- -----------------------------------------------------------------------------
CREATE VIEW [analytics].[v_contractor_producer_mapping] AS
SELECT
m.id,
m.contractor_1c_id,
c.contractor_id, -- строковый id для API/поиска
c.contractor_name,
m.producer_1c_id,
p.producer_id, -- строковый id для API/поиска
p.producer_name,
m.days_of_sales,
m.logistics_days,
m.roic_norm,
m.created_at,
m.updated_at
FROM [analytics].[contractor_producer_mapping] m
LEFT JOIN [analytics].[v_contractors] c ON c.contractor_1c_id = m.contractor_1c_id
LEFT JOIN [analytics].[v_producers] p ON p.producer_1c_id = m.producer_1c_id;
GO
-- -----------------------------------------------------------------------------
-- 5. Триггер обновления updated_at
-- -----------------------------------------------------------------------------
CREATE TRIGGER [analytics].[tr_contractor_producer_mapping_updated]
ON [analytics].[contractor_producer_mapping]
AFTER UPDATE
AS
UPDATE [analytics].[contractor_producer_mapping]
SET updated_at = GETDATE()
FROM [analytics].[contractor_producer_mapping] t
INNER JOIN inserted i ON t.id = i.id;
GO