170 lines
8.0 KiB
Transact-SQL
170 lines
8.0 KiB
Transact-SQL
-- =============================================================================
|
||
-- Скрипт: сопоставление Контрагент + Производитель с этапами оплаты
|
||
-- Схема: 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
|