restructure

This commit is contained in:
Basoff 2026-02-18 14:57:48 +03:00
parent 15c4ee6e41
commit 15376f8cb4
12 changed files with 0 additions and 1089 deletions

View File

@ -1,48 +0,0 @@
-- =============================================================================
-- Добавить колонку roic_norm в contractor_producer_mapping
-- =============================================================================
USE [mag_pbi]
GO
IF NOT EXISTS (
SELECT 1 FROM sys.columns
WHERE object_id = OBJECT_ID(N'[analytics].[contractor_producer_mapping]')
AND name = 'roic_norm'
)
BEGIN
ALTER TABLE [analytics].[contractor_producer_mapping]
ADD [roic_norm] DECIMAL(12,4) NULL;
EXEC sys.sp_addextendedproperty
@name = N'MS_Description',
@value = N'Нормированный ROIC (при торговой надбавке 100%). Рассчитывается по этапам оплаты.',
@level0type = N'SCHEMA', @level0name = N'analytics',
@level1type = N'TABLE', @level1name = N'contractor_producer_mapping',
@level2type = N'COLUMN', @level2name = N'roic_norm';
END
GO
-- Обновить представление v_contractor_producer_mapping
IF OBJECT_ID(N'[analytics].[v_contractor_producer_mapping]', N'V') IS NOT NULL
DROP VIEW [analytics].[v_contractor_producer_mapping];
GO
CREATE VIEW [analytics].[v_contractor_producer_mapping] AS
SELECT
m.id,
m.contractor_1c_id,
c.contractor_id,
c.contractor_name,
m.producer_1c_id,
p.producer_id,
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

View File

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

View File

@ -1,232 +0,0 @@
-- =============================================================================
-- Импорт поставщиков из CSV
-- Пропускает: пустые строки, пустой производитель, "не работаем", двойной (партнёр=производитель)
-- =============================================================================
USE [mag_pbi]
GO
SET NOCOUNT ON;
DECLARE @t TABLE (
partner NVARCHAR(500),
producer NVARCHAR(500),
contractor NVARCHAR(500),
log_val NVARCHAR(50),
sales_val NVARCHAR(50),
n_pct NVARCHAR(50),
n_days NVARCHAR(50),
m_pct NVARCHAR(50),
m_days NVARCHAR(50)
);
INSERT INTO @t (partner, producer, contractor, log_val, sales_val, n_pct, n_days, m_pct, m_days) VALUES
(N'TWIST (Коврига)', N'TWIST', N'ИП Коврига Богдан Владиславович', N'14-21', N'', N'', N'', N'100', N'14-21'),
(N'АО "ПНК "Красная нить"', N'АО "ПНК "Красная нить"', N'ПНК КРАСНАЯ НИТЬ АО', N'7', N'', N'', N'', N'100', N'30'),
(N'АОРА ООО', N'Оллтекс', N'АОРА ООО', N'10', N'', N'', N'', N'100', N'14'),
(N'АПИА', N'АПИА', N'АКВИЛОН ТЕКС ООО', N'5', N'', N'0', N'', N'100', N''),
(N'Астра ООО', N'Астра ООО', N'АСТРА ОООНН5027282471)', N'10', N'30', N'100', N'1', N'0', N'0'),
(N'БАЛТИЙСКИЙ ТЕКСТИЛЬ', N'БАЛТИЙСКИЙ ТЕКСТИЛЬ', N'НЕВА-ТЕКСТИЛЬ ООО', N'10', N'30', N'100', N'1', N'0', N'0'),
(N'ДЕНВИС ООО', N'Денвис ООО', N'ДЕНВИС ООО', N'14', N'', N'', N'', N'100', N'14'),
(N'Дилан-Текс ООО', N'Дилан-Текс', N'ДИЛАН-ТЕКСТИЛЬ ООО', N'3', N'30', N'100', N'', N'0', N'0'),
(N'Зарина Садовод', N'Зарина', N'ИП Ашурова Зарина Мирзоевна', N'7', N'30', N'0', N'', N'100', N'10'),
(N'Зарина Садовод', N'Зарина', N'ИП Забиров Умед Махмадиевич', N'7', N'30', N'0', N'', N'100', N'10'),
(N'Интай (ТЕКСТИЛЬ-ПРИНТ ООО)', N'Интай', N'ТЕКСТИЛЬ-ПРИНТ ООО', N'7', N'', N'0', N'', N'100', N''),
(N'ИП Маркович Олег Вячеславович', N'М-тех', N'ИП Маркович Олег Вячеславович', N'20', N'', N'100', N'', N'', N''),
(N'КАПРИЧЧО ООО', N'КАПРИЧЧО', N'КАПРИЗ ООО', N'7', N'30', N'0', N'', N'100', N'30'),
(N'КВИКЕР ООО (АРИМА)', N'Арима', N'КВИКЕР ООО', N'7', N'30', N'100', N'', N'0', N'0'),
(N'КВИНТА', N'КВИНТА ООО', N'КВИНТА ООО', N'14', N'30', N'50', N'', N'50', N'50'),
(N'КВИНТА', N'КВИНТА ООО', N'ТЕКСИНТЕХ ООО', N'14', N'30', N'50', N'', N'50', N'50'),
(N'КИТАЙ', N'ANHUI PHAETON CO.,LTD.', N'ANHUI PHAETON CO., LTD', N'120', N'180', N'30', N'1', N'70', N'50'),
(N'КИТАЙ', N'ANHUI PHAETON CO.,LTD.', N'ANHUI XINGTAI INTERNATIONAL TRADE CO., LTD', N'120', N'180', N'30', N'1', N'70', N'50'),
(N'КИТАЙ', N'Crafoam', N'CHANGSHA HEAPLAKE ENTERPRISES CO., LTD.', N'120', N'180', N'30', N'1', N'70', N'50'),
(N'КИТАЙ', N'DAVID', N'David YIWU SUPPLY AND MARKETING IMPORT AND EXPORT CO.,LTD', N'120', N'180', N'', N'', N'100', N'90'),
(N'КИТАЙ', N'WENDY', N'FUJIAN FOR BOTH TEXTILE CO.,LTD', N'120', N'180', N'', N'', N'100', N'60'),
(N'КИТАЙ', N'WENDY', N'Fujian Original Textile Co., Ltd', N'120', N'180', N'', N'', N'100', N'60'),
(N'КИТАЙ', N'GREAT ART INDUSTRIAL LTD.', N'GREAT ART INDUSTRIAL LTD.', N'120', N'180', N'30', N'1', N'70', N'60'),
(N'КИТАЙ', N'FEELO', N'AURORA SEWING SOLUTIONS - FZCO / MH / Yisun', N'120', N'180', N'30', N'1', N'70', N'21'),
(N'КИТАЙ', N'FEELO', N'GUANGDONG YILE TOYS CO., LTD.', N'120', N'180', N'30', N'1', N'70', N'21'),
(N'КИТАЙ', N'Evernice', N'GUANGZHOU ARK IMPORT EXPORT CO. LTD', N'120', N'180', N'', N'', N'100', N'60'),
(N'КИТАЙ', N'Evernice', N'Guangzhou Evernice Technology Development Co., Ltd', N'120', N'180', N'', N'', N'100', N'60'),
(N'КИТАЙ', N'ZHEJIANG BEYOND INDUSTRIAL AND TRADING', N'Jessy YIWU SUPPLY AND MARKETING IMPORT AND EXPORT CO.,LTD', N'120', N'180', N'', N'', N'', N''),
(N'КИТАЙ', N'JIANGSU GOLDEN AUTUMN ELASTIC FABRICS CO.,LTD', N'JIANGSU GOLDEN AUTUMN ELASTIC FABRICS CO.,LTD', N'120', N'180', N'30', N'1', N'70', N'60'),
(N'КИТАЙ', N'MH', N'NINGBO MH INDUSTRY CO., LTD.', N'120', N'180', N'50', N'100', N'50', N'160'),
(N'КИТАЙ', N'ZHEJIANG BEYOND INDUSTRIAL AND TRADING', N'NINGBO QUANAO IMP. AND EXP.CO.,LTD', N'120', N'180', N'', N'', N'100', N'120'),
(N'КИТАЙ', N'NINGBO YISUN IMPORT AND EXPORT COMPANY LIMITED', N'NINGBO UNISUN TRADE CO., LTD', N'120', N'180', N'50', N'90', N'50', N'120'),
(N'КИТАЙ', N'XINDEW', N'NINGBO YINZHOU XINDEW TEXTILE CO.,LTD', N'120', N'180', N'30', N'1', N'70', N'60'),
(N'КИТАЙ', N'NINGBO YISUN IMPORT AND EXPORT COMPANY LIMITED', N'SHAAN XI SUCCEED TRADING CO.,LTD', N'120', N'180', N'50', N'90', N'50', N'120'),
(N'КИТАЙ', N'Hebei', N'SHAOXING CITY YEHUA TEXTILE CO.,LTD', N'120', N'180', N'', N'', N'', N''),
(N'КИТАЙ', N'Houwen', N'SHAOXING KEQIAO DISTRICT HOUWEN IMPORT & EXPORT CO., LTD', N'120', N'180', N'30', N'1', N'70', N'60'),
(N'КИТАЙ', N'Mingge', N'SHAOXING KEQIAO MINGGE TEXTILE CO.,LTD', N'120', N'180', N'', N'', N'100', N'60'),
(N'КИТАЙ', N'QX', N'SHAOXING LIUYI TEXTILE IMPORT AND EXPORT CO.,LTD', N'120', N'180', N'', N'', N'', N''),
(N'КИТАЙ', N'Mingge', N'SHAOXING MENGYUE TEXTILE CO., LTD', N'120', N'180', N'', N'', N'100', N'60'),
(N'КИТАЙ', N'Varo', N'SHAOXING VARO TEXTILE CO., LTD', N'120', N'180', N'', N'', N'100', N'80'),
(N'КИТАЙ', N'ZHONGZHE', N'SHAOXING ZHONGZHE TEXTILE IMPORT AND EXPORT CO.,LTD', N'120', N'180', N'50', N'60', N'50', N'80'),
(N'КИТАЙ', N'Joanna', N'SHAOXING ZUHAO TEXTILE CO.,LTD', N'120', N'180', N'', N'', N'100', N'80'),
(N'КИТАЙ', N'SINEM BRODE', N'SINEMBRODE TEKSTIL SANAYI VE TICARET LTD. STI.', N'120', N'180', N'50', N'60', N'50', N'100'),
(N'КИТАЙ', N'RECHSEA', N'TOWARD OCEAN TECHNOLOGY CO., LIMITED', N'120', N'180', N'30', N'1', N'70', N''),
(N'КИТАЙ', N'XINDEW', N'XINDEW GROUP CO LIMITED', N'120', N'180', N'30', N'1', N'70', N'60'),
(N'КИТАЙ', N'Yingfeng Textile', N'Yingfeng Textile (Nanjing) Co., Ltd', N'120', N'180', N'30', N'1', N'70', N'50'),
(N'КИТАЙ', N'Sunshine', N'YIWU JYAO IMPORT AND EXPORT CO.,LTD', N'120', N'180', N'30', N'1', N'70', N'60'),
(N'КИТАЙ', N'ZHEGAO', N'AURORA SEWING SOLUTIONS - FZCO / MH / Yisun', N'120', N'180', N'30', N'1', N'70', N'21'),
(N'КИТАЙ', N'CADA', N'AURORA SEWING SOLUTIONS - FZCO / MH / Yisun', N'120', N'180', N'30', N'1', N'70', N'21'),
(N'КИТАЙ', N'KAVO', N'Shenzhen Sfun Toys Co., Ltd.', N'120', N'180', N'30', N'1', N'70', N'21'),
(N'КИТАЙ', N'Im.master', N'AURORA SEWING SOLUTIONS - FZCO / MH / Yisun', N'120', N'180', N'30', N'1', N'70', N'21'),
(N'КИТАЙ', N'LX', N'AURORA SEWING SOLUTIONS - FZCO / MH / Yisun', N'120', N'180', N'30', N'1', N'70', N'21'),
(N'КИТАЙ', N'LB+', N'AURORA SEWING SOLUTIONS - FZCO / MH / Yisun', N'120', N'180', N'30', N'1', N'70', N'21'),
(N'КИТАЙ', N'CAYI', N'AURORA SEWING SOLUTIONS - FZCO / MH / Yisun', N'120', N'180', N'30', N'1', N'70', N'21'),
(N'КИТАЙ', N'JINGXIN', N'YONGJIA JINGXIN GARMENT ACCESSORIES CO.,LTD', N'120', N'180', N'', N'', N'100', N'21'),
(N'КИТАЙ', N'HP', N'SHISHI HONGPENG METAL WEAR ACCESSORIES CO., LTD.', N'120', N'180', N'30', N'1', N'70', N'21'),
(N'КИТАЙ', N'YANG', N'ZHEJIANG KENKING INDUSTRIAL CO., LTD.', N'120', N'180', N'', N'', N'', N''),
(N'КИТАЙ', N'YANG', N'ZHEJIANG KENKING TEXTILE CO., LTD.', N'120', N'180', N'', N'', N'', N''),
(N'КИТАЙ', N'Larbene', N'ZHEJIANG LARBENE TEXTILE TECHNOLOG Y CO.,LTD', N'120', N'180', N'', N'', N'', N''),
(N'КИТАЙ', N'SHUAINING', N'ZHEJIANG SHUAINING INTERLINING TECHNOLOGY CO., LTD', N'120', N'180', N'', N'', N'100', N'160'),
(N'ЛАВИСТА ТЕКСТИЛЬ ООО', N'ЛАВИСТА ТЕКСТИЛЬ ООО', N'ЛАВИСТА ТЕКСТИЛЬ ООО', N'10', N'30', N'100', N'1', N'0', N'0'),
(N'ЛЕНТА АО (Чебоксары)', N'АО "Лента" (Ч)', N'ЛЕНТА АО (Чебоксары)', N'', N'', N'', N'', N'', N''),
(N'ЛЕРТЕКС ГРУПП ООО', N'ЛЕРТЕКС ГРУПП ООО', N'ЛЕРТЕКС ГРУПП ООО', N'10', N'30', N'100', N'1', N'0', N'0'),
(N'МЕБЕЛЬНАЯ ЛИНИЯ ООО', N'МЕБЕЛЬНАЯ ЛИНИЯ ООО', N'МЕБЕЛЬНАЯ ЛИНИЯ ООО', N'7', N'30', N'100', N'1', N'0', N'0'),
(N'МИР МАНУФАКТУРЫ', N'МИР МАНУФАКТУРЫ', N'РАДУГА ООО/МИР МАНУФАКТУРЫ', N'7', N'30', N'100', N'', N'', N''),
(N'Морозкин Иван Васильевич', N'Морозкин Иван Васильевич', N'ИП Морозкин Иван Васильевич', N'7', N'30', N'0', N'', N'100', N'20'),
(N'Морозкин Иван Васильевич', N'Морозкин Иван Васильевич', N'ИП Морозкина Нина Ивановна', N'7', N'30', N'0', N'', N'100', N'20'),
(N'Московское ПО Металлпластизделие ООО', N'ООО "Московское ПО Металлпластизделие"', N'Московское ПО Металлпластизделие ООО', N'5', N'60', N'', N'', N'100', N'20'),
(N'НЬЮСТАР ООО', N'НЬЮСТАР ООО', N'НЬЮСТАР ООО', N'10', N'60', N'', N'', N'100', N'40'),
(N'ОАО "Лента" Беларусь', N'ОАО "Лента"', N'ОАО "Лента"', N'10', N'', N'', N'', N'100', N'90'),
(N'ОАО ХБК "Шуйские ситцы"', N'ОАО ХБК "Шуйские ситцы"', N'ШУЙСКИЕ СИТЦЫ АО ХБК', N'10', N'30', N'100', N'1', N'', N''),
(N'ОЛДОС', N'АнТекс', N'АНТЕКС ООО', N'3', N'', N'0', N'', N'30', N'30'),
(N'ООО "АРГО ДС"', N'Арго ДС', N'АРГО ДС ООО', N'5', N'', N'', N'', N'', N''),
(N'ООО "ЕВРОПЛАСТИК"', N'ЕВРОПЛАСТИК ПЛЮС ООО', N'ЕВРОПЛАСТИК ПЛЮС ООО', N'14', N'', N'', N'', N'100', N'14'),
(N'ООО "ЕвроСнаб" (Казинников ДВ)', N'ЕВРОСНАБ ООО', N'ЕВРОСНАБ ООО', N'14-21', N'', N'', N'', N'100', N'20'),
(N'ООО "ТриЯна" ДАВА Пласт', N'ДАВА Пласт', N'ДАВА Пласт', N'10', N'30', N'0', N'', N'100', N'10'),
(N'ООО "Ф-ЛЕЙБЛ"', N'ООО "Фуртекс"', N'ООО "ФУРТЕКС" ПРОИЗВОДСТВО ЭТИКЕТОК (Ф-ЛЕЙБЛ)', N'14', N'30', N'', N'', N'100', N'10'),
(N'ООО "ЭЛАСТТЕКС2020"', N'ООО "ЭЛАСТТЕКС2020"', N'ЭЛАСТТЕКС2020', N'14-20', N'', N'30', N'1', N'70', N'14'),
(N'ПИН (Булавки)', N'дистр. ПАО "Мосточлегмаш"', N'БУЛАВКИ ООО', N'5', N'', N'', N'', N'100', N'14'),
(N'ПИН (Булавки)', N'дистр. ПАО "Мосточлегмаш"', N'ПИН ООО 9715499112', N'5', N'', N'', N'', N'100', N'14'),
(N'ПНК ИМ. КИРОВА АО', N'ООО "ПНК им. Кирова"', N'ПНК ИМ. КИРОВА АО', N'7', N'', N'', N'', N'100', N'30'),
(N'ПНК ИМ. КИРОВА АО', N'ООО "ПНК им. Кирова"', N'ПНК ИМ. КИРОВА ООО', N'7', N'', N'', N'', N'100', N'30'),
(N'ПНК ИМ. КИРОВА АО', N'ООО "ПНК им. Кирова"', N'Филиал АО "ПНК ИМ. КИРОВА"', N'7', N'', N'', N'', N'100', N'30'),
(N'ПОЛИМЕРНАЯ ИМПЕРИЯ ООО', N'Мегафторполимер', N'ПОЛИМЕРНАЯ ИМПЕРИЯ ООО', N'20', N'', N'', N'', N'100', N'14'),
(N'ПремиумФорм', N'Антинея', N'ПРЕМИУМФОРМ ООО', N'14-20', N'30', N'100', N'1', N'', N''),
(N'Результат-МСК', N'Следопыт', N'РЕЗУЛЬТАТ-МСК ООО', N'7', N'', N'', N'', N'100', N'30'),
(N'РЭДТЕКС ООО', N'Рэдтекс', N'РЭДТЕКС ООО', N'14-20', N'', N'', N'', N'100', N'30'),
(N'СИДЖЕЙ МОДА ООО', N'СИДЖЕЙ МОДА ООО', N'ЕВРОПА ТЕКС ООО', N'7', N'30', N'0', N'', N'100', N'14'),
(N'СПЕКТР ПРО-АКТИВ ООО', N'СПЕКТР ПРО-АКТИВ ООО', N'СПЕКТР ПРО-АКТИВ ООО', N'7', N'30', N'0', N'', N'100', N'21'),
(N'ТДЛ Текстиль', N'ТДЛ Текстиль', N'ТДЛ ТЕКСТИЛЬ ООО', N'7', N'30', N'0', N'', N'100', N'5'),
(N'ТЕКСТРА ТРЭЙД ООО', N'ООО "Текстра трэйд"', N'ТЕКСТРА РУ ООО', N'3', N'14', N'0', N'', N'14', N'14'),
(N'ТК МегаМаркет', N'ООО "ТК МегаМаркет"', N'МАРКЕТ ПЛЮС ООО', N'3', N'30', N'100', N'', N'0', N'0'),
(N'ТОП ПРИНТ (Азхар Аймаль)', N'Топ принт', N'Азхар Аймаль', N'5', N'20', N'0', N'', N'100', N'14'),
(N'ТОП ПРИНТ (Азхар Аймаль)', N'Топ принт', N'ТОП ПРИНТ ООО', N'5', N'20', N'0', N'', N'100', N'14'),
(N'ТРЕНД ООО ( Колибри)', N'Colibri', N'ТРЕНД ООО', N'30', N'90', N'', N'', N'100', N'120'),
(N'ФЕЛИтеКС Беларусь', N'Фелитекс', N'ФЕЛИтеКС Беларусь', N'14', N'30', N'0', N'', N'30', N'30'),
(N'Фи-текс', N'ООО "Фи-текс"', N'Фи-текс ООО', N'14', N'30', N'0', N'', N'30', N'30'),
(N'ЧУП "Максипресс"', N'ЧУП "Максипресс"', N'НЕЙЛОН ООО', N'25', N'', N'100', N'1', N'', N''),
(N'Экстра Текстиль ООО', N'Экстра Текстиль ООО', N'ЭКСТРА ТЕКСТИЛЬ ООО', N'3', N'15', N'100', N'', N'', N''),
(N'Эскар ООО', N'ЭСКАР ООО', N'ЭСКАР ООО', N'10', N'', N'', N'', N'100', N'14');
-- Фильтрация: пустой производитель, не работаем, партнёр=производитель
;WITH Filtered AS (
SELECT producer, contractor, log_val, sales_val, n_pct, n_days, m_pct, m_days,
ROW_NUMBER() OVER (PARTITION BY LTRIM(RTRIM(producer)), LTRIM(RTRIM(contractor)) ORDER BY (SELECT 1)) AS rn
FROM @t
WHERE LTRIM(RTRIM(producer)) <> N''
AND LOWER(LTRIM(RTRIM(producer))) NOT LIKE N'%не работаем%'
AND LOWER(LTRIM(RTRIM(producer))) NOT LIKE N'%под клиентов%'
AND (LTRIM(RTRIM(partner)) <> LTRIM(RTRIM(producer)) OR LTRIM(RTRIM(partner)) = N'')
)
SELECT producer, contractor, log_val, sales_val, n_pct, n_days, m_pct, m_days
INTO #staging
FROM Filtered
WHERE rn = 1;
DECLARE @log_days INT, @sales_days INT, @n_pct DECIMAL(9,4), @n_days INT, @m_pct DECIMAL(9,4), @m_days INT;
DECLARE @producer NVARCHAR(500), @contractor NVARCHAR(500);
DECLARE @manufacturer_id INT, @contractor_1c_id BINARY(16);
DECLARE @log_val NVARCHAR(50), @sales_val NVARCHAR(50), @n_pct_val NVARCHAR(50), @n_days_val NVARCHAR(50), @m_pct_val NVARCHAR(50), @m_days_val NVARCHAR(50);
DECLARE cur CURSOR LOCAL FAST_FORWARD FOR
SELECT producer, contractor, log_val, sales_val, n_pct, n_days, m_pct, m_days FROM #staging;
OPEN cur;
WHILE 1=1
BEGIN
FETCH cur INTO @producer, @contractor, @log_val, @sales_val, @n_pct_val, @n_days_val, @m_pct_val, @m_days_val;
IF @@FETCH_STATUS <> 0 BREAK;
SET @manufacturer_id = NULL;
SET @contractor_1c_id = NULL;
-- Парсинг чисел: диапазон 14-21 -> среднее, пустое -> NULL
SET @log_days = CASE
WHEN @log_val = N'' OR @log_val IS NULL THEN NULL
WHEN @log_val LIKE N'%-%' AND CHARINDEX(N'-', @log_val) > 1
THEN (TRY_CAST(LEFT(@log_val, CHARINDEX(N'-', @log_val)-1) AS INT) + TRY_CAST(LTRIM(SUBSTRING(@log_val, CHARINDEX(N'-', @log_val)+1, 10)) AS INT))/2
ELSE TRY_CAST(@log_val AS INT) END;
SET @sales_days = CASE
WHEN @sales_val = N'' OR @sales_val IS NULL THEN NULL
WHEN @sales_val LIKE N'%-%' AND CHARINDEX(N'-', @sales_val) > 1
THEN (TRY_CAST(LEFT(@sales_val, CHARINDEX(N'-', @sales_val)-1) AS INT) + TRY_CAST(LTRIM(SUBSTRING(@sales_val, CHARINDEX(N'-', @sales_val)+1, 10)) AS INT))/2
ELSE TRY_CAST(@sales_val AS INT) END;
SET @n_pct = TRY_CAST(@n_pct_val AS DECIMAL(9,4));
SET @n_days = TRY_CAST(@n_days_val AS INT);
SET @m_pct = TRY_CAST(@m_pct_val AS DECIMAL(9,4));
SET @m_days = TRY_CAST(@m_days_val AS INT);
IF @log_days IS NULL SET @log_days = 120;
IF @sales_days IS NULL SET @sales_days = 180;
-- Найти contractor_1c_id в v_contractors (по точному совпадению имени)
SELECT @contractor_1c_id = (SELECT TOP 1 contractor_1c_id
FROM [analytics].[v_contractors]
WHERE LTRIM(RTRIM(contractor_name)) = LTRIM(RTRIM(@contractor)));
IF @contractor_1c_id IS NULL
CONTINUE; -- контрагент не найден в 1С, пропускаем
-- Найти или создать manufacturer (подзапрос — при отсутствии строк переменная станет NULL)
SELECT @manufacturer_id = (SELECT id FROM [analytics].[manufacturers]
WHERE LTRIM(RTRIM(manufacturer)) = LTRIM(RTRIM(@producer)));
IF @manufacturer_id IS NULL
BEGIN
INSERT INTO [analytics].[manufacturers] (manufacturer, days_of_sales, logistics_days, roic_norm)
VALUES (LTRIM(RTRIM(@producer)), @sales_days, @log_days, NULL);
SET @manufacturer_id = SCOPE_IDENTITY();
END
ELSE
BEGIN
UPDATE [analytics].[manufacturers]
SET days_of_sales = @sales_days, logistics_days = @log_days
WHERE id = @manufacturer_id;
END
-- Проверить, нет ли уже связи
IF EXISTS (SELECT 1 FROM [analytics].[manufacturer_counterparty_map]
WHERE manufacturer_id = @manufacturer_id AND contractor_1c_id = @contractor_1c_id)
CONTINUE;
INSERT INTO [analytics].[manufacturer_counterparty_map] (manufacturer_id, contractor_1c_id)
VALUES (@manufacturer_id, @contractor_1c_id);
-- Этапы оплаты
DELETE FROM [analytics].[manufacturer_payment_stage] WHERE manufacturer_id = @manufacturer_id;
IF @n_pct IS NOT NULL AND @n_pct > 0
INSERT INTO [analytics].[manufacturer_payment_stage] (manufacturer_id, name, days, [percent], sort_order)
VALUES (@manufacturer_id, N'Первая оплата', ISNULL(@n_days, 1), @n_pct, 0);
IF @m_pct IS NOT NULL AND @m_pct > 0
INSERT INTO [analytics].[manufacturer_payment_stage] (manufacturer_id, name, days, [percent], sort_order)
VALUES (@manufacturer_id, N'Вторая оплата', ISNULL(@m_days, 60), @m_pct, 1);
IF NOT EXISTS (SELECT 1 FROM [analytics].[manufacturer_payment_stage] WHERE manufacturer_id = @manufacturer_id)
INSERT INTO [analytics].[manufacturer_payment_stage] (manufacturer_id, name, days, [percent], sort_order)
VALUES (@manufacturer_id, N'Предоплата', 14, 100, 0);
END
CLOSE cur;
DEALLOCATE cur;
DROP TABLE #staging;
PRINT 'Импорт завершён.';
GO

View File

@ -1,120 +0,0 @@
-- =============================================================================
-- Миграция: manufacturers + manufacturer_counterparty_map + counterparties
-- → contractor_producer_mapping + contractor_producer_payment_stage
--
-- Источник: analytics.manufacturers, analytics.manufacturer_counterparty_map,
-- analytics.counterparties
-- Назначение: analytics.contractor_producer_mapping,
-- analytics.contractor_producer_payment_stage
--
-- Сопоставление по именам: counterparty → v_contractors (_Reference168),
-- manufacturer → v_producers (_Reference260)
-- =============================================================================
USE [mag_pbi]
GO
SET NOCOUNT ON;
-- 1. Проверка: какие строки будут мигрировать, какие найдутся в 1С
PRINT '=== Сопоставление с v_contractors и v_producers ===';
SELECT
mcm.id AS map_id,
cp.counterparty,
c.contractor_id AS contractor_1c_match,
man.manufacturer,
p.producer_id AS producer_1c_match,
CASE WHEN c.contractor_1c_id IS NULL THEN 'НЕТ' ELSE 'OK' END AS contractor_ok,
CASE WHEN p.producer_1c_id IS NULL THEN 'НЕТ' ELSE 'OK' END AS producer_ok
FROM [analytics].[manufacturer_counterparty_map] mcm
JOIN [analytics].[manufacturers] man ON man.id = mcm.manufacturer_id
JOIN [analytics].[counterparties] cp ON cp.id = mcm.counterparty_id
LEFT JOIN [analytics].[v_contractors] c
ON LTRIM(RTRIM(c.contractor_name)) = LTRIM(RTRIM(cp.counterparty))
LEFT JOIN [analytics].[v_producers] p
ON LTRIM(RTRIM(p.producer_name)) = LTRIM(RTRIM(man.manufacturer))
ORDER BY mcm.id;
-- 2. Вставка в contractor_producer_mapping (только пары, найденные в 1С)
PRINT '';
PRINT '=== Вставка в contractor_producer_mapping ===';
INSERT INTO [analytics].[contractor_producer_mapping]
(contractor_1c_id, producer_1c_id, days_of_sales, logistics_days, roic_norm)
SELECT
c.contractor_1c_id,
p.producer_1c_id,
180,
120,
man.ROI_norm
FROM [analytics].[manufacturer_counterparty_map] mcm
JOIN [analytics].[manufacturers] man ON man.id = mcm.manufacturer_id
JOIN [analytics].[counterparties] cp ON cp.id = mcm.counterparty_id
JOIN [analytics].[v_contractors] c
ON LTRIM(RTRIM(c.contractor_name)) = LTRIM(RTRIM(cp.counterparty))
JOIN [analytics].[v_producers] p
ON LTRIM(RTRIM(p.producer_name)) = LTRIM(RTRIM(man.manufacturer))
WHERE NOT EXISTS (
SELECT 1 FROM [analytics].[contractor_producer_mapping] m2
WHERE m2.contractor_1c_id = c.contractor_1c_id AND m2.producer_1c_id = p.producer_1c_id
);
PRINT 'Вставлено сопоставлений: ' + CAST(@@ROWCOUNT AS NVARCHAR(10));
-- 3. Вставка этапов оплаты для маппингов без этапов
PRINT '';
PRINT '=== Вставка этапов оплаты ===';
DECLARE @mapping_id INT;
DECLARE @n_pct DECIMAL(10,3), @n_d INT, @m_pct DECIMAL(10,3), @m_d INT;
DECLARE cur CURSOR LOCAL FAST_FORWARD FOR
SELECT
m.id,
man.n_percent,
ISNULL(man.n_days, 1),
man.m_percent,
ISNULL(man.m_days, 120)
FROM [analytics].[contractor_producer_mapping] m
JOIN [analytics].[v_contractors] c ON c.contractor_1c_id = m.contractor_1c_id
JOIN [analytics].[v_producers] p ON p.producer_1c_id = m.producer_1c_id
JOIN [analytics].[counterparties] cp ON LTRIM(RTRIM(cp.counterparty)) = LTRIM(RTRIM(c.contractor_name))
JOIN [analytics].[manufacturer_counterparty_map] mcm ON mcm.counterparty_id = cp.id
JOIN [analytics].[manufacturers] man ON man.id = mcm.manufacturer_id
AND LTRIM(RTRIM(man.manufacturer)) = LTRIM(RTRIM(p.producer_name))
WHERE NOT EXISTS (SELECT 1 FROM [analytics].[contractor_producer_payment_stage] s WHERE s.mapping_id = m.id);
OPEN cur;
FETCH NEXT FROM cur INTO @mapping_id, @n_pct, @n_d, @m_pct, @m_d;
WHILE @@FETCH_STATUS = 0
BEGIN
-- Этап 1: Предоплата (n_percent, n_days)
IF @n_pct IS NOT NULL AND @n_pct <> 0
BEGIN
INSERT INTO [analytics].[contractor_producer_payment_stage] (mapping_id, name, days, [percent], sort_order)
VALUES (@mapping_id, N'Предоплата', @n_d,
CASE WHEN @n_pct > 1 THEN @n_pct ELSE @n_pct * 100 END, 0);
END
-- Этап 2: Постоплата (m_percent, m_days)
IF @m_pct IS NOT NULL AND @m_pct <> 0
BEGIN
INSERT INTO [analytics].[contractor_producer_payment_stage] (mapping_id, name, days, [percent], sort_order)
VALUES (@mapping_id, N'Постоплата', @m_d,
CASE WHEN @m_pct > 1 THEN @m_pct ELSE @m_pct * 100 END, 1);
END
-- Если оба NULL — дефолт Предоплата 7-50, Постоплата 120-50
IF (@n_pct IS NULL OR @n_pct = 0) AND (@m_pct IS NULL OR @m_pct = 0)
BEGIN
INSERT INTO [analytics].[contractor_producer_payment_stage] (mapping_id, name, days, [percent], sort_order)
VALUES (@mapping_id, N'Предоплата', 7, 50, 0),
(@mapping_id, N'Постоплата', 120, 50, 1);
END
FETCH NEXT FROM cur INTO @mapping_id, @n_pct, @n_d, @m_pct, @m_d;
END;
CLOSE cur;
DEALLOCATE cur;
PRINT 'Миграция завершена.';
GO

View File

@ -1,156 +0,0 @@
-- =============================================================================
-- Переход: counterparties → v_contractors (1С)
-- manufacturer_counterparty_map: counterparty_id → contractor_1c_id
-- Контрагенты и производители из 1С (v_contractors, v_producers)
-- =============================================================================
USE [mag_pbi]
GO
SET NOCOUNT ON;
-- Удаляем представления, ссылающиеся на map/counterparties
IF OBJECT_ID(N'[analytics].[v_manufacturer_counterparty_mapping]', N'V') IS NOT NULL
DROP VIEW [analytics].[v_manufacturer_counterparty_mapping];
GO
-- Удалить FK manufacturer_counterparty_map → counterparties (если есть)
DECLARE @fk NVARCHAR(256);
SELECT @fk = name FROM sys.foreign_keys
WHERE parent_object_id = OBJECT_ID(N'[analytics].[manufacturer_counterparty_map]')
AND referenced_object_id = OBJECT_ID(N'[analytics].[counterparties]');
IF @fk IS NOT NULL
EXEC('ALTER TABLE [analytics].[manufacturer_counterparty_map] DROP CONSTRAINT ' + @fk);
GO
-- Очистить таблицу привязки
TRUNCATE TABLE [analytics].[manufacturer_counterparty_map];
PRINT 'manufacturer_counterparty_map: очищена';
GO
-- Заменить counterparty_id на contractor_1c_id
IF EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'[analytics].[manufacturer_counterparty_map]') AND name = 'counterparty_id')
BEGIN
ALTER TABLE [analytics].[manufacturer_counterparty_map] DROP COLUMN [counterparty_id];
PRINT 'Удалена колонка counterparty_id';
END
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'[analytics].[manufacturer_counterparty_map]') AND name = 'contractor_1c_id')
BEGIN
ALTER TABLE [analytics].[manufacturer_counterparty_map] ADD [contractor_1c_id] BINARY(16) NOT NULL;
PRINT 'Добавлена колонка contractor_1c_id';
END
GO
-- Удалить старые уникальные ограничения (на counterparty_id), создать новое
DECLARE @uq NVARCHAR(256);
SELECT @uq = name FROM sys.key_constraints
WHERE parent_object_id = OBJECT_ID(N'[analytics].[manufacturer_counterparty_map]')
AND type = 'UQ' AND name = 'UQ_mcm_counterparty';
IF @uq IS NOT NULL
EXEC('ALTER TABLE [analytics].[manufacturer_counterparty_map] DROP CONSTRAINT ' + @uq);
SELECT @uq = name FROM sys.key_constraints
WHERE parent_object_id = OBJECT_ID(N'[analytics].[manufacturer_counterparty_map]')
AND type = 'UQ' AND name = 'UQ_mcm_pair';
IF @uq IS NOT NULL
EXEC('ALTER TABLE [analytics].[manufacturer_counterparty_map] DROP CONSTRAINT ' + @uq);
-- Один контрагент — один производитель
IF NOT EXISTS (SELECT 1 FROM sys.key_constraints
WHERE parent_object_id = OBJECT_ID(N'[analytics].[manufacturer_counterparty_map]') AND name = 'UQ_mcm_contractor')
ALTER TABLE [analytics].[manufacturer_counterparty_map] ADD CONSTRAINT [UQ_mcm_contractor] UNIQUE ([contractor_1c_id]);
-- Уникальная пара
IF NOT EXISTS (SELECT 1 FROM sys.key_constraints
WHERE parent_object_id = OBJECT_ID(N'[analytics].[manufacturer_counterparty_map]') AND name = 'UQ_mcm_pair')
ALTER TABLE [analytics].[manufacturer_counterparty_map] ADD CONSTRAINT [UQ_mcm_pair] UNIQUE ([manufacturer_id], [contractor_1c_id]);
GO
-- Удалить таблицу counterparties
IF OBJECT_ID(N'[analytics].[counterparties]', N'U') IS NOT NULL
BEGIN
DROP TABLE [analytics].[counterparties];
PRINT 'Удалена таблица analytics.counterparties';
END
GO
-- Создать v_contractors, v_producers если не существуют
IF OBJECT_ID(N'[analytics].[v_contractors]', N'V') IS NULL
BEGIN
EXEC('
CREATE VIEW [analytics].[v_contractors] AS
SELECT
c._IDRRef AS contractor_1c_id,
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,
c._Description AS contractor_name
FROM [MAG_2019].[dbo].[_Reference168] c
WHERE c._Marked = 0');
PRINT 'Создано представление v_contractors';
END
IF OBJECT_ID(N'[analytics].[v_producers]', N'V') IS NULL
BEGIN
EXEC('
CREATE VIEW [analytics].[v_producers] AS
SELECT
pr._IDRRef AS producer_1c_id,
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,
pr._Description AS producer_name
FROM [MAG_2019].[dbo].[_Reference260] pr
WHERE pr._Marked = 0');
PRINT 'Создано представление v_producers';
END
GO
-- Представление для API: map + manufacturer + contractor/producer (из 1С)
CREATE VIEW [analytics].[v_manufacturer_counterparty_mapping] AS
SELECT
mcm.id,
mcm.manufacturer_id,
p.producer_id,
man.manufacturer AS manufacturer_name,
mcm.contractor_1c_id,
c.contractor_id,
c.contractor_name AS contractor_name,
man.days_of_sales,
man.logistics_days,
man.roic_norm
FROM [analytics].[manufacturer_counterparty_map] mcm
LEFT JOIN [analytics].[manufacturers] man ON man.id = mcm.manufacturer_id
LEFT JOIN [analytics].[v_contractors] c ON c.contractor_1c_id = mcm.contractor_1c_id
LEFT JOIN [analytics].[v_producers] p ON LTRIM(RTRIM(p.producer_name)) = LTRIM(RTRIM(man.manufacturer));
GO
-- Исправить [analytics].[get_orders_list]: counterparties удалена, map по contractor_1c_id,
-- manufacturers без ROI_norm/n_percent/n_days/m_percent/m_days — использовать v_manufacturers_roi_compat
IF OBJECT_ID(N'[analytics].[get_orders_list]', N'V') IS NOT NULL
BEGIN
DECLARE @def NVARCHAR(MAX);
SELECT @def = OBJECT_DEFINITION(OBJECT_ID(N'[analytics].[get_orders_list]'));
IF @def LIKE N'%counterparties%'
BEGIN
SET @def = REPLACE(@def, N'LEFT JOIN [analytics].[counterparties] cp ON cp.[counterparty] = r._Description', N'');
SET @def = REPLACE(@def, N'map.[counterparty_id] = cp.id', N'map.[contractor_1c_id] = r._IDRRef');
-- manufacturers без старых полей — join на v_manufacturers_roi_compat (ROI_norm, n_percent, n_days, m_percent, m_days)
IF @def LIKE N'%ROI_norm%' AND OBJECT_ID(N'[analytics].[v_manufacturers_roi_compat]', N'V') IS NOT NULL
SET @def = REPLACE(@def, N'[analytics].[manufacturers] man', N'[analytics].[v_manufacturers_roi_compat] man');
DROP VIEW [analytics].[get_orders_list];
EXEC sp_executesql @def;
PRINT 'Обновлено представление analytics.get_orders_list';
END
END
GO
PRINT 'Готово: manufacturer_counterparty_map с contractor_1c_id, counterparties удалена';
GO

View File

@ -1,252 +0,0 @@
-- =============================================================================
-- Миграция: логистика, дни продаж и этапы оплаты — на manufacturers
-- manufacturer_counterparty_map — только связь manufacturer_id + contractor_1c_id (из 1С)
--
-- ВАЖНО: Перед запуском выполнить migrate_map_to_contractor_1c.sql
-- (удаление counterparties, переход на contractor_1c_id)
--
-- ИСТОЧНИК: contractor_producer_mapping, contractor_producer_payment_stage
-- (сопоставление по v_contractors, v_producers → counterparties, manufacturers)
--
-- 1. manufacturers: добавить days_of_sales, logistics_days, roic_norm
-- 2. manufacturer_payment_stage: новая таблица, FK на manufacturers
-- 3. Миграция из contractor_producer_* в manufacturers, map, manufacturer_payment_stage
-- 4. manufacturer_counterparty_map: убрать days_of_sales, logistics_days, roic_norm (если есть)
-- 5. Удалить contractor_producer_*, manufacturer_counterparty_payment_stage
-- =============================================================================
USE [mag_pbi]
GO
SET NOCOUNT ON;
-- =============================================================================
-- 1. manufacturers: добавить days_of_sales, logistics_days, roic_norm
-- =============================================================================
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'[analytics].[manufacturers]') AND name = 'days_of_sales')
ALTER TABLE [analytics].[manufacturers] ADD [days_of_sales] INT NOT NULL DEFAULT 180;
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'[analytics].[manufacturers]') AND name = 'logistics_days')
ALTER TABLE [analytics].[manufacturers] ADD [logistics_days] INT NOT NULL DEFAULT 120;
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'[analytics].[manufacturers]') AND name = 'roic_norm')
ALTER TABLE [analytics].[manufacturers] ADD [roic_norm] DECIMAL(12,4) NULL;
-- Миграция из manufacturers.ROI_norm (если ещё не удалена, roic_norm уже добавлена)
IF EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'[analytics].[manufacturers]') AND name = 'ROI_norm')
AND EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'[analytics].[manufacturers]') AND name = 'roic_norm')
BEGIN
UPDATE [analytics].[manufacturers] SET [roic_norm] = [ROI_norm] WHERE [roic_norm] IS NULL AND [ROI_norm] IS NOT NULL;
END
-- Удалить старые поля manufacturers (n_percent, n_days, m_percent, m_days, ROI_norm)
IF EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'[analytics].[manufacturers]') AND name = 'ROI_norm')
ALTER TABLE [analytics].[manufacturers] DROP COLUMN [ROI_norm];
IF EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'[analytics].[manufacturers]') AND name = 'n_percent')
ALTER TABLE [analytics].[manufacturers] DROP COLUMN [n_percent];
IF EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'[analytics].[manufacturers]') AND name = 'n_days')
ALTER TABLE [analytics].[manufacturers] DROP COLUMN [n_days];
IF EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'[analytics].[manufacturers]') AND name = 'm_percent')
ALTER TABLE [analytics].[manufacturers] DROP COLUMN [m_percent];
IF EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'[analytics].[manufacturers]') AND name = 'm_days')
ALTER TABLE [analytics].[manufacturers] DROP COLUMN [m_days];
PRINT 'manufacturers: добавлены days_of_sales, logistics_days, roic_norm';
GO
-- =============================================================================
-- 2. manufacturer_payment_stage — этапы оплаты, привязаны к manufacturers
-- =============================================================================
IF OBJECT_ID(N'[analytics].[manufacturer_payment_stage]', N'U') IS NULL
BEGIN
CREATE TABLE [analytics].[manufacturer_payment_stage] (
[id] INT IDENTITY(1,1) NOT NULL,
[manufacturer_id] INT NOT NULL,
[name] NVARCHAR(255) NOT NULL,
[days] INT NOT NULL,
[percent] DECIMAL(9,4) NOT NULL,
[sort_order] INT NOT NULL DEFAULT 0,
CONSTRAINT [PK_manufacturer_payment_stage] PRIMARY KEY CLUSTERED ([id]),
CONSTRAINT [FK_manufacturer_payment_stage] FOREIGN KEY ([manufacturer_id])
REFERENCES [analytics].[manufacturers]([id]) ON DELETE CASCADE
);
CREATE NONCLUSTERED INDEX [IX_manufacturer_payment_stage_manufacturer_id]
ON [analytics].[manufacturer_payment_stage]([manufacturer_id]);
PRINT 'Создана таблица manufacturer_payment_stage';
END
GO
-- =============================================================================
-- Миграция из contractor_producer_mapping и contractor_producer_payment_stage
-- (требует v_contractors, v_producers; manufacturer_counterparty_map с contractor_1c_id)
-- =============================================================================
IF OBJECT_ID(N'[analytics].[contractor_producer_mapping]', N'U') IS NOT NULL
AND OBJECT_ID(N'[analytics].[contractor_producer_payment_stage]', N'U') IS NOT NULL
AND OBJECT_ID(N'[analytics].[v_contractors]', N'V') IS NOT NULL
AND OBJECT_ID(N'[analytics].[v_producers]', N'V') IS NOT NULL
AND EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'[analytics].[manufacturer_counterparty_map]') AND name = 'contractor_1c_id')
BEGIN
-- 3a. Добавить недостающие manufacturers (по именам из 1С)
INSERT INTO [analytics].[manufacturers] (manufacturer, days_of_sales, logistics_days, roic_norm)
SELECT t.producer_name, t.days_of_sales, t.logistics_days, t.roic_norm
FROM (
SELECT LTRIM(RTRIM(p.producer_name)) AS producer_name, m.days_of_sales, m.logistics_days, m.roic_norm,
ROW_NUMBER() OVER (PARTITION BY LTRIM(RTRIM(p.producer_name)) ORDER BY m.id) AS rn
FROM [analytics].[contractor_producer_mapping] m
JOIN [analytics].[v_producers] p ON p.producer_1c_id = m.producer_1c_id
) t
WHERE t.rn = 1
AND NOT EXISTS (SELECT 1 FROM [analytics].[manufacturers] man WHERE LTRIM(RTRIM(man.manufacturer)) = t.producer_name);
-- 3b. Обновить manufacturers (days, logistics, roic) из contractor_producer_mapping
UPDATE man
SET man.days_of_sales = src.days_of_sales,
man.logistics_days = src.logistics_days,
man.roic_norm = COALESCE(man.roic_norm, src.roic_norm)
FROM [analytics].[manufacturers] man
JOIN (
SELECT p.producer_name, m.days_of_sales, m.logistics_days, m.roic_norm,
ROW_NUMBER() OVER (PARTITION BY LTRIM(RTRIM(p.producer_name)) ORDER BY m.id) AS rn
FROM [analytics].[contractor_producer_mapping] m
JOIN [analytics].[v_producers] p ON p.producer_1c_id = m.producer_1c_id
) src ON LTRIM(RTRIM(man.manufacturer)) = LTRIM(RTRIM(src.producer_name)) AND src.rn = 1;
-- 3c. Вставить связи в manufacturer_counterparty_map (contractor_1c_id из 1С)
INSERT INTO [analytics].[manufacturer_counterparty_map] (manufacturer_id, contractor_1c_id)
SELECT man.id, m.contractor_1c_id
FROM [analytics].[contractor_producer_mapping] m
JOIN [analytics].[v_producers] p ON p.producer_1c_id = m.producer_1c_id
JOIN [analytics].[manufacturers] man ON LTRIM(RTRIM(man.manufacturer)) = LTRIM(RTRIM(p.producer_name))
WHERE NOT EXISTS (
SELECT 1 FROM [analytics].[manufacturer_counterparty_map] mcm
WHERE mcm.manufacturer_id = man.id AND mcm.contractor_1c_id = m.contractor_1c_id
);
PRINT 'Миграция из contractor_producer_mapping: вставлено связей ' + CAST(@@ROWCOUNT AS NVARCHAR(10));
-- 3d. Миграция этапов в manufacturer_payment_stage (по одному набору на производителя — из первого mapping)
INSERT INTO [analytics].[manufacturer_payment_stage] (manufacturer_id, name, [days], [percent], sort_order)
SELECT man.id, s.name, s.[days], s.[percent], s.sort_order
FROM [analytics].[contractor_producer_payment_stage] s
JOIN [analytics].[contractor_producer_mapping] m ON m.id = s.mapping_id
JOIN [analytics].[v_producers] p ON p.producer_1c_id = m.producer_1c_id
JOIN [analytics].[manufacturers] man ON LTRIM(RTRIM(man.manufacturer)) = LTRIM(RTRIM(p.producer_name))
WHERE m.id = (
SELECT MIN(m2.id) FROM [analytics].[contractor_producer_mapping] m2
JOIN [analytics].[v_producers] p2 ON p2.producer_1c_id = m2.producer_1c_id
WHERE LTRIM(RTRIM(p2.producer_name)) = LTRIM(RTRIM(p.producer_name))
)
AND man.id NOT IN (SELECT manufacturer_id FROM [analytics].[manufacturer_payment_stage]);
PRINT 'Миграция из contractor_producer_payment_stage: вставлено этапов ' + CAST(@@ROWCOUNT AS NVARCHAR(10));
END
GO
-- Fallback: миграция из manufacturer_counterparty_payment_stage (если contractor_producer уже удалён)
IF OBJECT_ID(N'[analytics].[manufacturer_counterparty_payment_stage]', N'U') IS NOT NULL
BEGIN
INSERT INTO [analytics].[manufacturer_payment_stage] (manufacturer_id, name, [days], [percent], sort_order)
SELECT mcm.manufacturer_id, s.name, s.[days], s.[percent], s.sort_order
FROM [analytics].[manufacturer_counterparty_payment_stage] s
JOIN [analytics].[manufacturer_counterparty_map] mcm ON mcm.id = s.map_id
WHERE mcm.id = (SELECT MIN(m2.id) FROM [analytics].[manufacturer_counterparty_map] m2 WHERE m2.manufacturer_id = mcm.manufacturer_id)
AND mcm.manufacturer_id NOT IN (SELECT manufacturer_id FROM [analytics].[manufacturer_payment_stage]);
PRINT 'Миграция из manufacturer_counterparty_payment_stage: ' + CAST(@@ROWCOUNT AS NVARCHAR(10));
END
GO
-- Дефолтные этапы для manufacturers без этапов (из старых n_/m_ полей, если остались — уже удалены)
-- Берём manufacturers без этапов и добавляем Предоплата+Постоплата
INSERT INTO [analytics].[manufacturer_payment_stage] (manufacturer_id, name, [days], [percent], sort_order)
SELECT man.id, N'Предоплата', 7, 50, 0
FROM [analytics].[manufacturers] man
WHERE NOT EXISTS (SELECT 1 FROM [analytics].[manufacturer_payment_stage] s WHERE s.manufacturer_id = man.id);
INSERT INTO [analytics].[manufacturer_payment_stage] (manufacturer_id, name, [days], [percent], sort_order)
SELECT man.id, N'Постоплата', 120, 50, 1
FROM [analytics].[manufacturers] man
WHERE (SELECT COUNT(*) FROM [analytics].[manufacturer_payment_stage] s WHERE s.manufacturer_id = man.id) = 1;
PRINT 'Созданы дефолтные этапы оплаты';
GO
-- =============================================================================
-- 3. manufacturer_counterparty_map: убрать days_of_sales, logistics_days, roic_norm
-- =============================================================================
IF EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'[analytics].[manufacturer_counterparty_map]') AND name = 'days_of_sales')
ALTER TABLE [analytics].[manufacturer_counterparty_map] DROP COLUMN [days_of_sales];
IF EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'[analytics].[manufacturer_counterparty_map]') AND name = 'logistics_days')
ALTER TABLE [analytics].[manufacturer_counterparty_map] DROP COLUMN [logistics_days];
IF EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'[analytics].[manufacturer_counterparty_map]') AND name = 'roic_norm')
ALTER TABLE [analytics].[manufacturer_counterparty_map] DROP COLUMN [roic_norm];
PRINT 'manufacturer_counterparty_map: оставлены только manufacturer_id, counterparty_id';
GO
-- =============================================================================
-- 4. Удалить manufacturer_counterparty_payment_stage и contractor_producer_*
-- =============================================================================
IF OBJECT_ID(N'[analytics].[manufacturer_counterparty_payment_stage]', N'U') IS NOT NULL
DROP TABLE [analytics].[manufacturer_counterparty_payment_stage];
IF OBJECT_ID(N'[analytics].[v_contractor_producer_mapping]', N'V') IS NOT NULL
DROP VIEW [analytics].[v_contractor_producer_mapping];
IF OBJECT_ID(N'[analytics].[contractor_producer_payment_stage]', N'U') IS NOT NULL
DROP TABLE [analytics].[contractor_producer_payment_stage];
IF OBJECT_ID(N'[analytics].[contractor_producer_mapping]', N'U') IS NOT NULL
DROP TABLE [analytics].[contractor_producer_mapping];
PRINT 'Удалены manufacturer_counterparty_payment_stage и contractor_producer_*';
GO
-- =============================================================================
-- 5. Представление для API (map + manufacturer + counterparty, roic из manufacturers)
-- =============================================================================
IF OBJECT_ID(N'[analytics].[v_manufacturer_counterparty_mapping]', N'V') IS NOT NULL
DROP VIEW [analytics].[v_manufacturer_counterparty_mapping];
GO
CREATE VIEW [analytics].[v_manufacturer_counterparty_mapping] AS
SELECT
mcm.id,
mcm.manufacturer_id,
p.producer_id,
man.manufacturer AS manufacturer_name,
mcm.contractor_1c_id,
c.contractor_id,
c.contractor_name AS contractor_name,
man.days_of_sales,
man.logistics_days,
man.roic_norm
FROM [analytics].[manufacturer_counterparty_map] mcm
LEFT JOIN [analytics].[manufacturers] man ON man.id = mcm.manufacturer_id
LEFT JOIN [analytics].[v_contractors] c ON c.contractor_1c_id = mcm.contractor_1c_id
LEFT JOIN [analytics].[v_producers] p ON LTRIM(RTRIM(p.producer_name)) = LTRIM(RTRIM(man.manufacturer));
GO
PRINT 'Создано представление v_manufacturer_counterparty_mapping';
GO
-- =============================================================================
-- 6. View для обратной совместимости процедур (manufacturer + roic + n_/m_)
-- =============================================================================
IF OBJECT_ID(N'[analytics].[v_manufacturers_roi_compat]', N'V') IS NOT NULL
DROP VIEW [analytics].[v_manufacturers_roi_compat];
GO
CREATE VIEW [analytics].[v_manufacturers_roi_compat] AS
SELECT
man.id,
man.manufacturer,
man.roic_norm AS ROI_norm,
n_stage.[percent] / 100.0 AS n_percent,
n_stage.[days] AS n_days,
m_stage.[percent] / 100.0 AS m_percent,
m_stage.[days] AS m_days
FROM [analytics].[manufacturers] man
LEFT JOIN (
SELECT manufacturer_id, [percent], [days],
ROW_NUMBER() OVER (PARTITION BY manufacturer_id ORDER BY sort_order, [days]) AS rn
FROM [analytics].[manufacturer_payment_stage]
) n_stage ON n_stage.manufacturer_id = man.id AND n_stage.rn = 1
LEFT JOIN (
SELECT manufacturer_id, [percent], [days],
ROW_NUMBER() OVER (PARTITION BY manufacturer_id ORDER BY sort_order, [days]) AS rn
FROM [analytics].[manufacturer_payment_stage]
) m_stage ON m_stage.manufacturer_id = man.id AND m_stage.rn = 2;
GO

View File

@ -1,50 +0,0 @@
-- =============================================================================
-- Пересчёт roic_norm по методике (возврат денег по ходу продаж)
-- Таблицы: manufacturers, manufacturer_payment_stage
-- Алгоритм: avgReturnDay = logistics_days + days_of_sales/2
-- frozenDays = avgReturnDay - effectiveDeferralDays
-- roic_norm = 12 / (frozenDays/30) * 100
-- =============================================================================
USE [mag_pbi]
GO
;WITH stage_agg AS (
SELECT
manufacturer_id,
SUM([percent] / 100.0 * [days]) AS effective_deferral_days,
SUM([percent] / 100.0) AS total_percent
FROM [analytics].[manufacturer_payment_stage]
GROUP BY manufacturer_id
),
calc AS (
SELECT
man.id,
man.days_of_sales,
man.logistics_days,
COALESCE(s.effective_deferral_days, 0) AS effective_deferral_days,
COALESCE(s.total_percent, 0) AS total_percent,
(man.logistics_days + man.days_of_sales / 2.0) AS avg_return_day
FROM [analytics].[manufacturers] man
LEFT JOIN stage_agg s ON s.manufacturer_id = man.id
),
roic_calc AS (
SELECT
id,
CASE
WHEN total_percent <= 0 THEN NULL
WHEN (avg_return_day - effective_deferral_days) <= 0 THEN NULL
ELSE ROUND(12.0 / ((avg_return_day - effective_deferral_days) / 30.0) * 100.0, 2)
END AS new_roic
FROM calc
)
UPDATE man
SET man.roic_norm = r.new_roic
FROM [analytics].[manufacturers] man
JOIN roic_calc r ON r.id = man.id;
SELECT
COUNT(*) AS total,
COUNT(roic_norm) AS with_roic,
COUNT(*) - COUNT(roic_norm) AS without_roic
FROM [analytics].[manufacturers];

View File

@ -1,62 +0,0 @@
-- =============================================================================
-- Процедура пересчёта roic_norm для manufacturers
-- Параметры: @manufacturer_id INT = NULL — id строки в manufacturers; если NULL, пересчёт для всех
-- Формула: avgReturnDay = logistics_days + days_of_sales/2
-- frozenDays = avgReturnDay - effectiveDeferralDays (из этапов оплаты)
-- roic_norm = 12 / (frozenDays/30) * 100
-- =============================================================================
USE [mag_pbi]
GO
IF OBJECT_ID(N'[analytics].[sp_recalc_roic]', N'P') IS NOT NULL
DROP PROCEDURE [analytics].[sp_recalc_roic];
GO
CREATE PROCEDURE [analytics].[sp_recalc_roic]
@manufacturer_id INT = NULL
AS
SET NOCOUNT ON;
;WITH stage_agg AS (
SELECT
manufacturer_id,
SUM([percent] / 100.0 * [days]) AS effective_deferral_days,
SUM([percent] / 100.0) AS total_percent
FROM [analytics].[manufacturer_payment_stage]
WHERE @manufacturer_id IS NULL OR manufacturer_id = @manufacturer_id
GROUP BY manufacturer_id
),
calc AS (
SELECT
man.id,
man.days_of_sales,
man.logistics_days,
COALESCE(s.effective_deferral_days, 0) AS effective_deferral_days,
COALESCE(s.total_percent, 0) AS total_percent,
(ISNULL(man.logistics_days, 120) + ISNULL(man.days_of_sales, 180) / 2.0) AS avg_return_day
FROM [analytics].[manufacturers] man
LEFT JOIN stage_agg s ON s.manufacturer_id = man.id
WHERE @manufacturer_id IS NULL OR man.id = @manufacturer_id
),
roic_calc AS (
SELECT
id,
CASE
WHEN total_percent <= 0 THEN NULL
WHEN (avg_return_day - effective_deferral_days) <= 0 THEN NULL
ELSE ROUND(12.0 / ((avg_return_day - effective_deferral_days) / 30.0) * 100.0, 2)
END AS new_roic
FROM calc
)
UPDATE man
SET man.roic_norm = r.new_roic
FROM [analytics].[manufacturers] man
JOIN roic_calc r ON r.id = man.id;
SELECT @@ROWCOUNT AS updated_count;
GO
-- Примеры вызова:
-- EXEC [analytics].[sp_recalc_roic]; -- пересчёт для всех
-- EXEC [analytics].[sp_recalc_roic] @manufacturer_id = 5; -- только для id=5

Binary file not shown.

Binary file not shown.