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