Запросы, используемые в расчетах прогнозов
check_semaphore_ready
Используется в батче ‘Отправить SMS при отсутствии семафора’. В строках возвращает те сообщения, которые система отправляет на соответствующие номера в SMS.
all_stores
Используется в модуле classes/loaders/storeDim. Загружает список магазинов в память, чтобы каждый раз не запрашивать его из базы. Периодически перезагржается модулем loaders/masterData, в зависимости от параметра options.loader.reloadMasterDataHours
, который по умолчанию равен 4-м часам. Также загружает привязки магазинов к регионам, к кодам погоды, и ценовым линиям (если используются в запросе prices_by_sku_store
)
select s.STORE_ID NUM, s.STORE_NAME NAME, s.REGION_ID REGION, w.WEATHER_CODE WEATHER, WHS from STORES s left join STORE_WEATHER w on s.STORE_ID=w.STORE_ID where s.STORE_ID in (select distinct store_id from sku_range where end_date is null or end_date > dateadd(d, -90, getdate())) order by s.REGION_ID, s.STORE_ID
STORE_WEATHER
это маппинг магазина и кода региона для получения данных погоды
должно быть из значений, определенных в опции - weather - locations
new_stores
Используется в модуле classes/loaders/storeDim для того, чтобы загружать новые магазины. Также как и запрос all_stores, периодически перезагружается в память.
select n.NEW_STORE_ID, n.OLD_STORE_ID, n.COEFFICIENT from RPM_NEW_STORES n where now() between n.START_DATE and n.END_DATE and n.IS_ACTIVE = 1
all_regions
Используется в модуле classes/loaders/storeDim для того, чтобы загружать список регионов. Также как и запрос all_stores, периодически перезагружается в память.
select '0' NUM, 'All' NAME, null WEATHER union all select r.REGION_ID NUM, r.REGION_NAME NAME, w.WEATHER_CODE WEATHER from REGIONS r left join REGION_WEATHER w on r.REGION_ID=w.REGION_ID
all_groups
Используется в модуле classes/loaders/ProductDim для того чтобы загружать полный справочник товарных групп. Периодически перезагружается в память модулем loaders/masterData, в зависимости от параметра options.loader.reloadMasterDataHours
, который по умолчанию равен 4-м часам.
SELECT GROUP_ID as GRP, GROUP_NAME as NAME FROM GROUPS WHERE GROUP_ID in ( SELECT distinct GROUP_ID FROM PRODUCTS P WHERE (P.SKU_ID in (select distinct SKU_ID from SKU_RANGE where end_date >= dateadd(d, -365, getdate()) or end_date is null) or (select min(start_date) from PRICES PR where PR.sku_id=P.sku_id) >= dateadd(d, -90, getdate()) ) ) order by GROUP_ID
sku_group
Используется в модуле classes/loaders/ProductDim для того чтобы загружать полный справочник товаров, обычно, либо ограниченный наличием ассортиментной матрицы, либо если новый товар, определяя его по наличию первой цены в последние 30 дней. Также периодически перезагружается в память модулем loaders/masterData, в зависимости от параметра options.loader.reloadMasterDataHours
, который по умолчанию равен 4-м часам.
Вместе со справочником товаров, загружает в память их закупочные цены и % НДС (для модуля Цены, формы Оптимизация цен), коэф-ты страхового запаса на позиции и привязки позиций к товарным группам
select SKU_ID SKU, GROUP_ID GRP, case when ITEM_CODE is null then ARTICLE_NAME else '(' + cast(ITEM_CODE as varchar) + ') ' + ARTICLE_NAME end NAME, (SELECT SS FROM SS_ADJUSTMENTS SSA WHERE SSA.SKU_ID = p.SKU_ID) SS_COEF, LAST_PURCHASE_PRICE LAST_PP, VAT_PERCENT VAT, 1 LINE from PRODUCTS p where SKU_ID [sku_list] and GROUP_ID [group_list] and (P.SKU_ID in (select distinct SKU_ID from SKU_RANGE where end_date >= dateadd(d, -182, getdate()) or end_date is null) or (select min(start_date) from PRICES PR where PR.sku_id=P.sku_id) >= dateadd(d, -30, getdate()) ) order by GROUP_ID, SKU_ID
all_suppliers
Используется в модуле classes/loaders/supplierDim для того, чтобы загружать полный справочник поставщиком. Также периодически перезагружается в память модулем loaders/masterData, в зависимости от параметра options.loader.reloadMasterDataHours
, который по умолчанию равен 4-м часам.
select SUPPLIER_ID NUM, SUPPLIER_NAME NAME from SUPPLIERS order by SUPPLIER_NAME
all_lines
Используется в модуле classes/loaders/supplierDim для того, чтобы загружать полный справочник товарный линий, которые используются в модуле Цены (форма “Оптимизация цен”, “Политики”, “Динамика ценовых индексов”. Также периодически перезагружается в память модулем loaders/masterData, в зависимости от параметра options.loader.reloadMasterDataHours
, который по умолчанию равен 4-м часам.
select 1 ID, 'All lines' NAME;
sku_store_ss_coef
Используется в модуле classes/loaders/skuStoreSSCoef для того, чтобы загружать коэффициенты страхового запаса в разрезе SKU-магазин, которые имеют приоритет над коэф-тами страхового запаса в разрезе SKU или магазина.
select SKU_ID SKU, STORE_ID STORE, SS_COEF from SKU_STORE_SS_COEF
sales_sum_stores_sum_groups
Загружает суммарные продажи по группам и магазинам для анализа на сводном уровне. Используется в модуле classes/loaders/Sales, в том случае, если и для группы и для магазина в форме Анализ проставляется значение “sum”. Исторически, этот функционал не нашел широкого применения и имеет статус “экспериментальный”.
select WEEK, sum(STOCK_ITEM_COUNT) CNT, sum(STOCK_VOLUME) STOCK, sum(TRX_VOLUME) TRX_VOL, sum(SALES_VOLUME) SALES, {price_disc_sum} from SALES_GROUP where WEEK between :start_week and :end_week and ((sales_volume > 0) or (stock_volume > 0)) group by WEEK где {price_disc_sum} case when sum(SALES_VOLUME)=0 then null else round(sum(SALES_VALUE)/sum(SALES_VOLUME), 2) end PRICE, case when sum(SALES_VOLUME)=0 then 0 else round(sum(DISCOUNT_VALUE)/sum(SALES_VOLUME), 2) end DISC
sales_by_stores_sum_groups
Загружает суммарные продажи по группам для анализа на сводном уровне, но в разрезе магазинов. Используется в модуле classes/loaders/Sales, в том случае, если только для группы (не для магазинов) в форме Анализ проставляется значение “sum”. Исторически, этот функционал не нашел широкого применения и имеет статус “экспериментальный”.
select STORE_ID STORE, WEEK, sum(STOCK_ITEM_COUNT) CNT, sum(STOCK_VOLUME) STOCK, sum(TRX_VOLUME) TRX_VOL, sum(SALES_VOLUME) SALES, {price_disc_sum} from SALES_GROUP where STORE_ID [store_list] and WEEK between :start_week and :end_week and ((sales_volume > 0) or (stock_volume > 0)) group by STORE_ID, WEEK где {price_disc_sum} case when sum(SALES_VOLUME)=0 then null else round(sum(SALES_VALUE)/sum(SALES_VOLUME), 2) end PRICE, case when sum(SALES_VOLUME)=0 then 0 else round(sum(DISCOUNT_VALUE)/sum(SALES_VOLUME), 2) end DISC
sales_by_group_sum_stores
Загружает суммарные продажи по магазинам для анализа на сводном уровне, но в разрезе групп. Используется в модуле classes/loaders/Sales, в том случае, если только для магазинов (не для групп) в форме Анализ проставляется значение “sum”, а для SKU - значение “skip”. Исторически, этот функционал не нашел широкого применения и имеет статус “экспериментальный”.
select STORE_ID STORE, WEEK, sum(STOCK_ITEM_COUNT) CNT, sum(STOCK_VOLUME) STOCK, sum(TRX_VOLUME) TRX_VOL, sum(SALES_VOLUME) SALES, {price_disc_sum} from SALES_GROUP where STORE_ID [store_list] and WEEK between :start_week and :end_week and ((sales_volume > 0) or (stock_volume > 0)) group by STORE_ID, WEEK где {price_disc_sum} case when sum(SALES_VOLUME)=0 then null else round(sum(SALES_VALUE)/sum(SALES_VOLUME), 2) end PRICE, case when sum(SALES_VOLUME)=0 then 0 else round(sum(DISCOUNT_VALUE)/sum(SALES_VOLUME), 2) end DISC
sales_by_sku_sum_stores
Загружает суммарные продажи по магазинам для анализа на сводном уровне, но в разрезе SKU. Используется в модуле classes/loaders/Sales, в том случае, если только для магазинов (не для групп и не для SKU) в форме Анализ проставляется значение “sum”. Исторически, этот функционал не нашел широкого применения и имеет статус “экспериментальный”.
select WEEK, sum(STOCK_ITEM_COUNT) CNT, sum(STOCK_VOLUME) STOCK, sum(TRX_VOLUME) TRX_VOL, sum(SALES_VOLUME) SALES, {price_disc_sum} from SALES_GROUP where GROUP_ID = :group and WEEK between :start_week and :end_week and ((sales_volume > 0) or (stock_volume > 0)) group by GROUP_ID, WEEK где {price_disc_sum} case when sum(SALES_VOLUME)=0 then null else round(sum(SALES_VALUE)/sum(SALES_VOLUME), 2) end PRICE, case when sum(SALES_VOLUME)=0 then 0 else round(sum(DISCOUNT_VALUE)/sum(SALES_VOLUME), 2) end DISC
sales_by_group_store
Загружает продажи в разрезе группа-магазин-неделя. Используется в модуле classes/loaders/Sales, если пользователь запрашивает прогнозы в разрезе SKU-магазин, либо группа-магазин, либо если запускается батч “Расчет прогнозов” (batches/fcst_batch). Указывается отдельно для каждого клиента, чтобы можно было исключать определенные недели или другие данные. При изменении этого запроса необходимо очищать и перезагружать файловый кэш.
SELECT STORE_ID STORE, WEEK, STOCK_ITEM_COUNT CNT, STOCK_VOLUME STOCK, SALES_VOLUME SALES, {price_disc} FROM SALES_GROUP WHERE STORE_ID [store_list] AND GROUP_ID = :group AND WEEK between :start_week and :end_week AND ((sales_volume > 0) or (stock_volume > 0)) где {price_disc} case when SALES_VOLUME=0 then null else round(SALES_VALUE/SALES_VOLUME, 2) end PRICE, case when SALES_VOLUME=0 then 0 else round(DISCOUNT_VALUE/SALES_VOLUME, 2) end DISC
sales_by_sku_store
Загружает продажи в разрезе SKU-магазин-неделя. Используется в модуле classes/loaders/Sales, если пользователь запрашивает прогнозы в разрезе SKU-магазин, либо если запускается батч “Расчет прогнозов” (batches/fcst_batch). Указывается отдельно для каждого клиента, чтобы можно было исключать определенные недели или другие данные. При изменении этого запроса необходимо очищать и перезагружать файловый кэш.
SELECT SKU_ID SKU, STORE_ID STORE, WEEK, STOCK_VOLUME STOCK, SALES_VOLUME SALES, {price_disc} FROM SALES_SKU WHERE STORE_ID [store_list] AND SKU_ID [sku_list] AND ((sales_volume > 0) or (stock_volume > 0)) AND WEEK between :start_week and :end_week где {price_disc} case when SALES_VOLUME=0 then null else round(SALES_VALUE/SALES_VOLUME, 2) end PRICE, case when SALES_VOLUME=0 then 0 else round(DISCOUNT_VALUE/SALES_VOLUME, 2) end DISC
ranges_by_sku_store
Загружает ассортиментные матрицы для расчета прогнозов. Используется если пользователь запрашивает расчет прогнозов в разрезе SKU-магазин, либо если запускается батч “Расчет прогнозов” (batches/fcst_batch).
select r.sku_id SKU, r.store_id STORE, case when ns.start_date > r.start_date then convert(varchar, ns.start_date, 21) else convert(varchar, r.start_date, 21) end STARTD, case when (max(r.end_date) is null and s.CLOSE_DATE is null) then '2050-01-01' when (max(r.end_date) is null and s.CLOSE_DATE is not null) then convert(varchar, s.CLOSE_DATE, 21) when (max(r.end_date) is not null and s.CLOSE_DATE is not null and max(r.end_date) > s.CLOSE_DATE) then convert(varchar, s.CLOSE_DATE, 21) else convert(varchar, max(r.end_date), 21) end as ENDD from sku_range r join stores s on s.STORE_ID = r.STORE_ID and coalesce(s.WHS,0) = 0 left join rpm_new_stores ns on ns.new_store_id = r.store_id where (r.end_date is null or r.end_date >= ':end_date') and r.STORE_ID [store_list] and r.SKU_ID [sku_list] group by r.sku_id, r.store_id, r.start_date, ns.START_DATE, s.CLOSE_DATE
presentation_by_sku_store
Загружает презентационный запас для того, чтобы эти данные подтягивались в форму “Анализ” или для расчета прогнозов. Используется если пользователь запрашивает расчет прогнозов в разрезе SKU-магазин, либо если запускается батч “Расчет прогнозов (batches/fcst_batch).
select r.sku_id SKU, r.store_id STORE, sum(r.presentation_1+presentation_2) P, dbo.iso_week(r.start_date) STARTW, case when max(r.end_date) is null then '205001' else dbo.iso_week(max(r.end_date)) end ENDW from presentation_stock_history r, STORES s where (r.end_date is null or r.end_date >= ':end_date') and r.store_id = s.store_id and r.STORE_ID [store_list] and r.SKU_ID [sku_list] and r.PRESENTATION_1 > 0 group by r.sku_id, r.store_id, s.close_date, r.start_date
master_fcst_by_sku_store
Загружает мастер-прогнозы и подвязанные к ним магазины. Используется если пользователь запрашивает расчет прогнозов в разрезе SKU-магазин, либо если запускается батч “Расчет прогнозов (batches/fcst_batch). Движок использует эти данные, чтобы пропорционально повышать или понижать прогнозы в разрезе магазинов.
select SKU_ID SKU, WEEK, FCST, FIX, STUFF( (SELECT ',' + cast(s.store_id as varchar) FROM master_fcst_stores s WHERE s.sku_id=m.sku_id and m.week=s.week and m.revision=s.revision and m.all_stores=0 FOR XML PATH ('')), 1, 1, '') STORES from master_fcst m where revision=0 and deleted is null and sku_id [sku_list] and week between :start_week and :end_week
future_group_store_prices
Загружает прогнозные будущие цены в разрезе группа-магазин, которые используются при расчете прогнозов, если в прогнозах включена каннибализация (предикторы grp_price
или grp_price_r
в файле options.json5)
select f.WEEK, f.STORE_ID as STORE, sum(f.A_PRICE*f.FORECAST)/sum(f.FORECAST) PRICE, count(*) CNT from FCST_SKU f with (nolock) join PRODUCTS p on f.SKU_ID=p.SKU_ID where f.ID=(select max(ID) from FCST with (nolock) where loaded is not null) and f.STORE_ID [store_list] and p.GROUP_ID = :group and f.FORECAST > 0 and f.WEEK > :end_week and f.WEEK <= :max_week group by f.WEEK, f.STORE_ID
prices_by_sku_store
Загружает прошлые и будущие цены из таблицы PRICES, которые могут быть либо в разрезе SKU-магазин, либо SKU-ценовая линия. Определяющим для выбора системой уровня либо SKU-магазин, либо SKU-ценовая линия, является наличие в результах поля STORE или PRL. Используется если пользователь запрашивает расчет прогнозов в разрезе SKU-магазин, либо если запускается батч “Расчет прогнозов (batches/fcst_batch).
select SKU_ID SKU, STORE_ID STORE, PRICE ,convert(varchar(10), START_DATE, 120) STARTD ,convert(varchar(10), END_DATE, 120) ENDD from PRICES where SKU_ID [sku_list] and STORE_ID [store_list] and (END_DATE is null or END_DATE > convert(varchar(8), CONVERT(DATETIME, ':start_date', 126), 112))
comp_prices_by_sku
Загружает цены конкурентов, чтобы отображать их в форме Анализ, либо использовать в прогнозах. Используется если пользователь запрашивает расчет прогнозов в разрезе SKU-магазин, либо если запускается батч “Расчет прогнозов (batches/fcst_batch).
select COMPETITOR COMP, SKU_ID SKU, SDATE, case when ABSENT=1 or (error_msg is not null and isnull(PROMO_VALUE, VALUE) is null) then -1 else isnull(PROMO_VALUE, VALUE) end PRICE from PRICE_MONITORING_DATA where SKU_ID [sku_list] and COMPETITOR [comp_list] and (ABSENT=1 or PROMO_VALUE is not null or VALUE is not null) and SDATE >= :start_date
sales_day_by_sku_store
Загружает последние продажи в разрезе SKU-магазин-день, для того, чтобы движок обрабатывал предиктор adj_day (Дневная корректировка), корректирующий прогноз на ближайшие недели на основании последних продаж. Используется если пользователь запрашивает расчет прогнозов в разрезе SKU-магазин, либо если запускается батч “Расчет прогнозов” (batches/fcst_batch).
select s.SKU_ID SKU, s.STORE_ID STORE, to_char(s.SDATE, 'YYYYMMDD') D, s.SALES_VOLUME SALES, s.SALES_VALUE/nullif(s.SALES_VOLUME, 0) PRICE, s.STOCK_VOLUME STOCK, s.TRX_VOLUME TRX_VOL from sales_sku_day s where s.sku_id [sku_list] and s.store_id [store_list] and s.sdate between to_date(':start_date', 'YYYY-MM-DD') and to_date(':end_date', 'YYYY-MM-DD')
sales_day_share_by_sku_store
Загружает доли продаж по дням недели в разрезе SKU-магазин, для того, чтобы движок обрабатывал предиктор adj_day (Дневная корректировка), корректирующий прогноз на ближайшие недели на основании последних продаж. Используется если пользователь запрашивает расчет прогнозов в разрезе SKU-магазин, либо если запускается батч “Расчет прогнозов” (batches/fcst_batch).
select SKU_ID SKU, STORE_ID STORE, MONDAY_SHARE MON, TUESDAY_SHARE TUE, WEDNESDAY_SHARE WED, THURSDAY_SHARE THU, FRIDAY_SHARE FRI, SATURDAY_SHARE SAT, SUNDAY_SHARE SUN from sales_sku_share where sku_id [sku_list] and store_id [store_list] and MONDAY_SHARE between 0.07 and 0.25 and TUESDAY_SHARE between 0.07 and 0.25 and WEDNESDAY_SHARE between 0.07 and 0.25 and THURSDAY_SHARE between 0.07 and 0.25 and FRIDAY_SHARE between 0.07 and 0.25 and SATURDAY_SHARE between 0.07 and 0.25 and SUNDAY_SHARE between 0.07 and 0.25
sales_day_share_by_group_store
Загружает доли продаж по дням недели в разрезе группа-магазин, для того, чтобы движок обрабатывал предиктор adj_day (Дневная корректировка), корректирующий прогноз на ближайшие недели на основании последних продаж, в случае, если доли продаж по дням в разрезе группа-магазин, вытягиваемые запросом sales_day_share_by_sku_store
, не найдены. Используется если пользователь запрашивает расчет прогнозов в разрезе SKU-магазин, либо если запускается батч “Расчет прогнозов (batches/fcst_batch).
select STORE_ID STORE, MONDAY_SHARE MON, TUESDAY_SHARE TUE, WEDNESDAY_SHARE WED, THURSDAY_SHARE THU, FRIDAY_SHARE FRI, SATURDAY_SHARE SAT, SUNDAY_SHARE SUN from sales_group_share where group_id=:group and store_id [store_list] and MONDAY_SHARE between 0.07 and 0.25 and TUESDAY_SHARE between 0.07 and 0.25 and WEDNESDAY_SHARE between 0.07 and 0.25 and THURSDAY_SHARE between 0.07 and 0.25 and FRIDAY_SHARE between 0.07 and 0.25 and SATURDAY_SHARE between 0.07 and 0.25 and SUNDAY_SHARE between 0.07 and 0.25
select_max_sales_week
Используется для определения последней недели продаж, за которую имеются данные. Движок строит прогноз в прошлом до этой недели, а прогноз в будущем - только начиная с текущей недели.
select max(week) WEEK from SALES_GROUP
after_forecasting_batch_query
Набор запросов, выполняемый после завершения батча “Расчет прогнозов”. В нем, в частности, применяются значения корректировок прогнозов из таблицы FCST_ADJUSTMENTS
и проставляется дата в поле LOADED таблицы FCST.
Форма Новые SKU/группы
На страницах сайта new_sku_load и new_group_load не используется, так как не используется в routes\api.js, Т.е. все что приходит в формы страниц сайта идет через http запросы, которые описаны в routes\api.js
new_sku_load и new_group_load используются в расчетах прогнозов
new_sku_load
Извлекает список пар новый SKU/аналог и соотношение RATIO, также извлекается ID группы.
В качестве фильтров может использоваться: список новых SKU, список групп, список поставщиков и завершающая неделя.
NEW_SKU_ID - новый товар, его аналогом является OLD_SKU_ID
который относится к товарной группе GROUP_ID, поставляемый поставщиком из списка supplier_list
RATIO (диапазон значений от 0,01 до 9,99) определяет насколько сильно влияет OLD_SKU_ID на NEW_SKU_ID в расчетах, а WEEK определяет, когда это влияние закончится.
Причем между SKU и группами, есть одно отличие. Новой группе можно назначить только один аналог, а SKU можно назначить несколько.
select p.GROUP_ID GRP, n.NEW_SKU_ID NEW_ID, n.OLD_SKU_ID OLD_ID, n.RATIO from new_sku n, products p where n.new_sku_id=p.sku_id and n.NEW_SKU_ID [sku_list] and p.GROUP_ID [group_list] and p.SUPPLIER_ID [supplier_list] and n.IS_ACTIVE = 1 and n.WEEK > :end_week
new_group_load
Извлекает список пар новый GROUP/аналог и соотношение RATIO.
В качестве фильтров может использоваться список новых GROUP и завершающая неделя.
select n.NEW_GROUP_ID NEW_ID, n.OLD_GROUP_ID OLD_ID, n.RATIO from new_groups n where n.IS_ACTIVE = 1 and n.NEW_GROUP_ID [group_list] and n.WEEK > :end_week
sku_for_group
Извлекает список SKU_ID и наименований для заданного GROUP_ID.
Возвращает результат по запросу /api/new_items/sku_for_group на странице new_items.
Данные предназначены для заполнения выпадающих списков выбора нового SKU и аналогов.
SELECT SKU_ID SKU, GROUP_ID GRP, case when ITEM_CODE is null then ARTICLE_NAME else '(' + cast(ITEM_CODE as varchar) + ') ' + ARTICLE_NAME end NAME FROM PRODUCTS WHERE GROUP_ID = :group_id order by GROUP_ID, SKU_ID
all_new_items
Возвращает результат запроса /api/new_items/list для заполнения основной таблицы new_items. Извлекает новый SKU, наименование, ID группы, завершающую неделю и также списки аналогов и соотношений RATIO с разделителем ";". В качестве фильтра может использоваться строка поиска, как для наименования, так и одного SKU_ID.
remove_new_item
Удаляет связь заданного нового SKU с аналогами, установкой признака IS_ACTIVE в 0.
Вызывается со страницы new_items запросом /api/new_items/remove с newsku в качестве параметра.
add_new_item
Добавляет связь нового SKU с аналогом и соотношением RATIO, либо добавив новую запись в таблицу NEW_SKU, либо обновив существующую.
Вызывается со страницы new_items запросами /api/new_items/add , /api/new_items/edit и /api/new_items/create_from_file, соответственно при добавлении, редактировании и импорте из CSV.
В SQL запрос передается один новый SKU, аналог, соотношение RATIO и завершающая неделя, http запросы массив из таких записей.
all_new_groups
Возвращает результат запроса /api/new_groups/list для заполнения основной таблицы new_groups. Извлекает ID новой группы, ID аналога, соотношение RATIO и завершающую неделю. Наименования групп заполняются в браузере из словарей.
remove_new_group
Удаляет связь заданной новой группы с аналогом, установкой признака IS_ACTIVE в 0.
Вызывается со страницы new_groups запросом /api/new_groups/remove с newgroup в качестве параметра
add_new_group
Добавляет связь новой группы с аналогом и соотношением RATIO, либо добавив новую запись в таблицу new_groups, либо обновив существующую.
Вызывается со страницы new_groups запросами /api/new_groups/create.
В SQL запрос передается ID новой группы, ID аналога, соотношение RATIO и завершающая неделя, а http запрос массив из таких записей.
Форма Мастер-прогноз
master_fcst_table
master_fcst_check_fcst
master_fcst_add_fcst
master_fcst_stores_set_revision
master_fcst_delete_fcst
Форма Доп. загрузка (экспериментальная)
add_fcst_main_table
add_fcst_sku_stores
add_fcst_sku_check
add_fcst_add_record
add_fcst_add_record_stores
add_fcst_edit_record
add_fcst_delete_record
Регулировка страхового запаса
Для чего и как используется регулировка страхового запаса описано тут.
Следующие 7 запросов относятся к странице http://localhost:3000/ss_adjust "Регулировка Страхового Запаса"
Коэффициент страхового запаса можно устанавливать на уровнях:
SKU-Вся сеть - установленный коэффициент применяется для всех магазинов в сети - таблица SS_ADJUSTMENTS;
Магазин - коэффициент применяется для всех позиций в выбранном магазине - таблица STORE_SS_COEF;
SKU-Магазин - коэффициент применяется для конкретной пары sku-магазин - таблица SKU_STORE_SS_COEF.
Таблицы имеют похожую структуру: набор ID к которым привязывается коэффициент страхового запаса для последующего автозаказа, сам коэффициент SS_COEF numeric(9,1) и пара UPDATED_BY/UPDATED с ID менеджера и временем изменения.
Фронтовой функционал собран в:
public\javascripts\ss_adjust\main.js
public\javascripts\ss_adjust\templates.js
Серверная часть в:
classes\controllers\ssAdjust.js
Практически все запросы по модификации таблиц SS_ADJUSTMENTS/STORE_SS_COEF/SKU_STORE_SS_COEF через http запросы из api.js выведены в public\javascripts\ss_adjust\main.js
То что открывается, например по http://localhost:3000/ss_adjust , это index.html собранный из .jade шаблонов и набор .js скриптов. Для удобства, основная часть собрана в main.js.
Эти скрипты выполняются в браузере на клиентской стороне и обеспечивают визуальную составляющую, а максимум что могут, так отправлять http запросы и разбирать ответ на них. У нас все http запросы собраны в routes\api.js и тут можно найти, что из backend обработки соответствует какому запросу.
А вот содержимое api.js уже выполняется на стороне сервера и уже здесь есть доступ к базе данных.
И как раз тут видно, что все запросы /api/ss_adjust/.../ обращаются к classes\controllers\ssAdjust.js Внутри ssAdjust.js можно найти обращение к базе и используемые SQL запросы.
Фронтовой функционал собран в:
public\javascripts\ss_adjust\main.js
public\javascripts\ss_adjust\templates.js
Серверная часть в:
classes\controllers\ssAdjust.jsss_adjustments_table_get_skus
Основной запрос наполнения таблицы таба "SKUs" ss_adjust. Назначен на /api/ss_adjust/get_skus_by_group.
Фильтр список групп. Поиск по SKU осуществляется в браузере.
SELECT P.GROUP_ID, P.SKU_ID, 'DEFAULT USER' MANAGER, SUBSTRING(CONVERT(VARCHAR, SSA.UPDATED, 120), 1, 16) UPDATED, SSA.SS as SKU_SS FROM PRODUCTS as P LEFT JOIN SS_ADJUSTMENTS as SSA ON P.SKU_ID = SSA.SKU_ID WHERE P.GROUP_ID [group_id] ORDER BY UPDATED DESC;
ss_adjustments_table_get_stores
Основной запрос наполнения таблицы таба "Магазины" ss_adjust. Назначен на /api/ss_adjust/data.
Фильтров нет. Поиск по названию или ID магазина осуществляется в браузере.
SELECT S.STORE_ID, S.STORE_NAME, 'DEFAULT USER' STORE_MANAGER, SUBSTRING(CONVERT(VARCHAR, SSA.UPDATED, 120), 1, 16) STORE_UPDATED, SSA.SS_COEF as STORE_SS FROM STORES as S LEFT JOIN STORE_SS_COEF as SSA ON S.STORE_ID = SSA.STORE_ID ORDER BY STORE_UPDATED DESC;
ss_adjustments_table_get_sku-stores
Основной запрос наполнения таблицы таба "SKUs/Магазины" ss_adjust. Назначен на /api/ss_adjust/data.
Фильтров нет. Поиск по названию или ID магазина или SKU осуществляется в браузере.
Выпадающие списки для SKU/STORE - это форма добавления новой записи в таблицу.
SELECT SSA.SKU_ID as SS_SKU_ID, P.ARTICLE_NAME as SS_SKU_NAME, SSA.STORE_ID as SS_STORE_ID, S.STORE_NAME as SS_STORE_NAME, 'DEFAULT USER' SS_MANAGER, SUBSTRING(CONVERT(VARCHAR, SSA.UPDATED, 120), 1, 16) SS_UPDATED, SSA.SS_COEF FROM SKU_STORE_SS_COEF AS SSA INNER JOIN PRODUCTS as P ON P.SKU_ID = SSA.SKU_ID INNER JOIN STORES as S ON S.STORE_ID = SSA.STORE_ID ORDER BY SS_UPDATED DESC;
ss_adjustments_sku_coef_update
Запрос сохранения данных в SS_ADJUSTMENTS. Привязан к /api/ss_adjust/update-sku-coef и /api/ss_adjust/import_skus_to_table и /api/ss_adjust/bulk-update'.
Используется как при редактировании данных из формы, так и при импорте из csv.
MERGE INTO SS_ADJUSTMENTS dest USING (SELECT :sku SKU_ID) src ON(dest.SKU_ID = src.SKU_ID) WHEN MATCHED THEN UPDATE SET UPDATED = GETDATE(), UPDATED_BY = :user, SS = :ss WHEN NOT MATCHED THEN INSERT(SKU_ID, UPDATED_BY, SS, UPDATED) VALUES(src.SKU_ID, :user, :ss, GETDATE());
ss_adjustments_store_coef_update
Запрос сохранения данных в STORE_SS_COEF. Привязан к /api/ss_adjust/update-store-coef и /api/ss_adjust/import_stores_to_table и /api/ss_adjust/bulk-update'.
Используется как при редактировании данных из формы, так и при импорте из csv.
MERGE INTO STORE_SS_COEF dest USING (SELECT :store STORE_ID) src ON (dest.STORE_ID = src.STORE_ID) WHEN MATCHED THEN UPDATE SET UPDATED = GETDATE(), UPDATED_BY = :user, SS_COEF = :ss WHEN NOT MATCHED THEN INSERT(STORE_ID, SS_COEF, UPDATED_BY, UPDATED) VALUES(src.STORE_ID, :ss, :user, GETDATE());
ss_adjustments_skustore_coef_update
Запрос сохранения данных в SKU_STORE_SS_COEF. Привязан к /api/ss_adjust/update-skustore-coef и /api/ss_adjust/import_skustores_to_table и /api/ss_adjust/bulk-update'.
Используется как при редактировании данных из формы, так и при импорте из csv.
MERGE INTO SKU_STORE_SS_COEF dest USING (SELECT :sku SKU_ID, :store STORE_ID) src ON (dest.SKU_ID = src.SKU_ID AND dest.STORE_ID = src.STORE_ID) WHEN MATCHED THEN UPDATE SET UPDATED = GETDATE(), UPDATED_BY = :user, SS_COEF = :ss WHEN NOT MATCHED THEN INSERT(SKU_ID, STORE_ID, SS_COEF, UPDATED_BY, UPDATED) VALUES(src.SKU_ID, src.STORE_ID, :ss, :user, GETDATE());
ss_adjustments_skustore_create
Запрос добавления данных в SKU_STORE_SS_COEF. Привязан к /api/ss_adjust/create-new-skustore.
Используется для добавления новой пары SKU/STORE в таблицу с пустым SS_COEF.
MERGE INTO SKU_STORE_SS_COEF dest USING (SELECT :sku SKU_ID, :store STORE_ID) src ON (dest.SKU_ID = src.SKU_ID AND dest.STORE_ID = src.STORE_ID) --WHEN MATCHED THEN UPDATE SET UPDATED = GETDATE(), UPDATED_BY = :user WHEN NOT MATCHED THEN INSERT(SKU_ID, STORE_ID, UPDATED_BY, UPDATED) VALUES(src.SKU_ID, src.STORE_ID, :user, GETDATE());
Форма Корректировка прогноза
ss_adjustments_table_get_skus
ss_adjustments_table_get_stores
ss_adjustments_table_get_sku-stores
ss_adjustments_sku_coef_update
ss_adjustments_store_coef_update
ss_adjustments_skustore_coef_update
ss_adjustments_skustore_create
manual_forecast_table_data
manual_forecast_create
manual_forecast_delete
manual_forecast_update
manual_forecast_sales_sku_day
manual_forecast_sales_sku_day_group
fcst_adjustments_promo
fcst_adjustments_promo_stores_by_id
fcst_adjustments_promo_skus_by_id
Форма Просмотр прогнозов
fcst_view_sku_by_all_regions
fcst_view_sku_by_region
fcst_view_sku_by_store
fcst_view_group_by_region
fcst_view_group_by_store
fcst_view_sku_by_sum_stores
fcst_view_stock_sku_by_all_regions
fcst_view_stock_sku_by_store
fcst_view_stock_group_by_region
fcst_view_stock_group_by_store
fcst_view_stock_sku_by_region
fcst_view_assort_sku_by_all_regions
fcst_view_assort_sku_by_region
fcst_view_assort_sku_by_store
fcst_view_managers
Запросы Промо
Формы Промо
promo_group_headers
promo_by_sku_store
item_structure
store_structure
promo_update_item_prices
promo_approve
promo_user
promo_headers
promo_headers_calendar
select_promo_id
create_promo
import_internal_promo_header
promo_delete
delete_promo_skus
delete_promo_stores
promo_items
promo_items_detailed
promo_stores
promo_details
promo_update_dates
promo_update_params
promo_unapprove
promo_update_fmt_stores
promo_revisions
promo_add_revision
promo_delete_revision
promo_update_revision
promo_update_revision_sku
promo_update_sku_parameters
promo_update_sku_parameters_with_sales_price
promo_up_revision
promo_up_revision_header
promo_shift_revisions
promo_shift_revisions
promo_update_sku_benefit_with_sales_price
promo_update_sku_benefit_with_communications
promo_update_sku_benefit_with_sales_price_with_communications
promo_get_sku_duplicates
promo_item_names
promo_revision_details
promo_make_copy
promo_get_sku_comparables
promo_get_promo_revision_comparables
promo_get_skus_by_item_code
promo_excel_download
Промо-процессор
promo_update_group_ratio
promo_max_end_week
promo_update_group_ratio
fcst_promo_items
fcst_promo_avg_sales
fcst_promo_avg_sales_group
fcst_promo_stores
promo_delete_sku
promo_delete_sku
fcst_promo_details
fcst_promo_comparable_sku_delete
fcst_promo_items_update
fcst_promo_result_clean
fcst_promo_result_header_update
fcst_update_promo_group_uplift
fcst_promo_result_update
promo_calc_batch_headers
promo_batch_headers
promo_batch_stores
promo_batch_avg_sales_sku
promo_batch_avg_sales_group
promo_batch_merge_sku_sales
update_group_avg_promo_uplift
update_sku_avg_promo_uplift
Запросы, используемые при расчете заказов в модуле Пополнение
rpm_get_all_cross_dock_if_any
Данный запрос используется для того, чтобы определить список кросс-док диаграмм магазинов, которые нужно пересчитывать, если батч запущен по кросс-док диаграммам склада. Это необходимо для того, чтобы пересчитывать заказы магазинов сначала, перед тем, как пересчитывать КД-заказы склад-поставщик
rpm_get_store_picking_diagrams_by_contract_and_whs_id
Данные запрос используется, чтобы выбрать все диаграммы склад-поставщик и поставщик-склад для каждого конкретного склада, в том случае, если в параметрах указана хоть одна диаграмма, относящаяся к этому складу. Это необходимо потому, что заказ поставщик-склад зависит от заказов склад-магазин, а заказы склад-магазин зависят от заказов склад-поставщик (в части корректировки доставки по наличию остатка), а позиции в разных диаграммах/контрактах могут пересекаться. Отследить как именно они пересекаются - трудоемко, поэтому пересчет заказов по складу возможен только общий.
rpm_get_stores_for_orders
Данные запрос выбирает все пары магазин-склад либо, склад-склад, либо склад-поставщик из имеющихся диаграмм, для того чтобы выстроить очередность пересчета магазинов и складов. Очередность магазинов (которые не являются в тоже время и складами), выстраивается просто по возрастанию номеров, так как она не имеет логического значения. Очередность пересчета складов выстраивается по принципу: сначала промежуточные склады, потом склады, которые которые заказывают у поставщиков. Если цепочка промежуточных складов имеет несколько звеньев, то сначала пересчитываются более поздние звеня цепи, потом более ранние. Очередность так выстраивается потому, что заказы более поздних звеньев цепи являются прогнозом отгрузок при расчете заказов более ранних звеньев цепи.
rpm_get_diagrams_by_store
Данные запрос отрабатывает отдельно по каждому магазину или складу, в соответствии с очередностью их расчета. Он вытягивает те номера и параметры диаграмм, которые влияют на расчет заказов, кроме самого графика (вместо него подтягиваются календари запросом rpm_only_calendars_by_store).
rpm_only_calendars_by_store
Данные запрос отрабатывает отдельно по каждому магазину или складу, в соответствии с очередностью их расчета. Он вытягивает все календари, в привязке к диаграммам, а также даты заказа, доставки и следующей доставки, необходимые для расчета заказов.
rpm_get_skus_by_store
Данные запрос вытягивает номера SKU в привязке к событиям календаря, а также значения пользовательских изменений заказа, тип заказа, и пользователя который его изменил, если на момент расчета заказ по этому событию-SKU имеется. Это необходимо, чтобы сохранить пользовательские изменения при пересчете, а также отличить системные изменения заказа от пользовательских. Отрабатывает отдельно по каждому магазину или складу.
rpm_get_forecasts_by_store
Данный запрос выполняется отдельно для каждого магазина или склада и вытягивает прогнозы ( разрезе недель), страховой запас и промо-составляющую в прогнозе по всем пересчитываемым SKU.
rpm_get_master_products_forecasts_by_store
Данный запрос выполняется отдельно для каждого магазина или склада и вытягивает прогнозы (в разрезе недель), страховой запас и промо-составляющую в прогнозе по всем пересчитываемым SKU, которые являются готовым продуктом или полуфабрикатом в одной из рецептур и у них стоит галочка “производство” в параметрах позиций на этом конкретном магазине или складе.
rpm_get_sku_range_for_master_products
Данный запрос выполняется отдельно для каждого магазина или склада, и вытягивает ассортиментные матрицы в привязке к датам для каждого SKU, которое является готовым продуктом или полуфабрикатом в одной из рецептур.
rpm_get_if_bom_by_store
Данный запрос выполняется отдельно для каждого магазина или склада, и вытягивает все рецептуры для всех мастер-продуктов или полуфабрикатов, у которых в параметрах позиций стоит галочка “производство” на этом конкретном магазине или складе.
rpm_get_master_products_stock_presentation
Данный запрос выполняется отдельно для каждого магазина или склада, и вытягивает значения презентационного запаса для мастер-продуктов в рецептурах, у которых стоит галочка “производство”
rpm_get_presentation_stock_by_store
Данный запрос выполняется отдельно для каждого магазина или склада, и вытягивает значения презентации для всех пересчитываемых SKU.
rpm_get_add_presentation_stock_by_store
Данный запрос выполняется отдельно для каждого магазина или склада, и вытягивает значения дополнительной выкладки для всех пересчитываемых SKU.
rpm_get_latest_stock_by_store
Данный запрос вытягивает значения остатка, за минусом кол-ва, зарезервированного для заказов pick-to-zero, для каждого магазина или склада, а также дату этого остатка.
rpm_get_latest_stock_for_whs_stock_estimation
Данный запрос выполняется перед началом расчетов магазинов, и вытягивает остатки складов, которые затем используются для расчета прогнозного остатка склада по датам, чтобы выполнять корректировку доставки заказов магазинов и оценивать прогнозный остаток магазинов по датам, увеличивая будущие заказы магазинов там, где остаток склада будет вымываться.
rpm_get_latest_stock_date
Данный запрос вытягивает самую последнюю дату остатков из таблицы LATEST_STOCK. Заказы считаются на N вперед от этой даты. От этой же даты рассчитываются прогнозные остатки склада. Дата корректируется на +1 день, исходя из предположения, что остатки загружаются на вчера на вечер, а система считает их как сегодня на утро (параметр options.replenishment.adjustStockDate
)
rpm_get_tender_items
Запрос вытягивает активные тендерные позиции из таблицы RPM_TENDER_ITEMS
. Эти данные используются для того, чтобы проставлять на заказах признак “Тендер”.
rpm_get_sku_range_by_store
Запрос вытягивает активные позиции в ассортиментной матрице в разрезе дат. Выполняется по каждому магазину отдельно. Далее, эти данные используются, чтобы не заказывать позиции, которые не активные в АМ.
rpm_get_master_sku_range_by_store
Запрос вытягивает готовую продукцию, которая активна в ассортиментной матрице в разрезе дат, и производится в этом магазине.. Выполняется по каждому магазину отдельно. Далее, эти данные используются, чтобы не заказывать ингредиенты для готовой продукции, которая не активна в АМ.
rpm_get_sku_parameters
Данный запрос выполняется для каждого магазина отдельно, и вытягивает параметры позиций, по которым рассчитывается заказ: цена закупки, галочка “утро”, признак “pick-to-zero” для склада, с которого заказывается позиция, признак “whs-pick-to-zero” для транзитного склада, для которого рассчитывается заказ, срок годности для расчета прогноза списания (SHELF_DAYS
), срок годности, умноженный на коэффициент для обрезания заказов (SHELF_DAYS_FOR_LIMIT
), максимальная вместимость, вес, гарантированный заказ, кратность, минимальный заказ, признак “лимит срока годности”, дополнительные циклы заказа, дополнительные дни в прогнозе Д1Д2, фактор округления кратности, лимит списаний.
По умолчанию, для ограничения заказов по сроку годности, используется следующая формула:round(coalesce(cast(ssc.SHELF_LIFE_PERC as numeric)/100, 0.8)
* (p.SHELF_DAYS - case when p.SHELF_DAYS >= 14 then 2 when p.SHELF_DAYS >= 3 then 1 else 0 end), 1) SHELF_DAYS_FOR_LIMIT
При необходимости ее поменять, необходимо кастомизировать этот запрос для заказчика.
rpm_get_add_load_by_store
Вытягивает даты дополнительной загрузки для SKU по каждому магазину отдельно.
rpm_get_sales_holiday_uplift
Вытягивает повышающие коэффициенты для праздничных дней в разрезе групп, для каждого магазина отдельно.
rpm_get_sales_sku_share
Вытягивает коэффициенты дней недели для каждого SKU. В случае, если для SKU не были посчитаны КДН, они берутся этим запросом с группы. Выполняется по каждому магазину отдельно.
rpm_get_master_products_sales_sku_share
Вытягивает коэффициенты дней недели для каждого мастер-продукта из рецептур (IF_BOM_V
). В случае, если для SKU не были посчитаны КДН, они берутся этим запросом с группы. Выполняется по каждому магазину отдельно.
rpm_get_elasticity_formulas
Вытягивает формулы ценовой эластичности, чтобы корректировать прогноз по дням в случае изменения цены в середине недели. Выполняется для каждого магазина отдельно.
rpm_get_elasticity_formulas_for_master_products
Вытягивает формулы ценовой эластичности для мастер-продуктов из рецептур (IF_BOM_V
), чтобы корректировать прогноз по дням в случае изменения цены в середине недели. Выполняется для каждого магазина отдельно.
rpm_get_prices_for_store
Вытягивает текущие и будущие цены в разрезе дат для всех SKU, по которым считается заказ. Выполняется для каждого магазина отдельно.
rpm_get_prices_for_store_master_products
Вытягивает текущие и будущие цены в разрезе дат для мастер-продуктов из рецептур (IF_BOM_V
). Выполняется для каждого магазина отдельно.
rpm_get_all_promo_and_stores
Вытягивает информацию о заголовках промо: номер промо, дата начала, дата завершения, название промо, % скидки по умолчанию, перечень магазинов в которых проводится промо.
rpm_get_all_promo_skus
Вытягивает информацию об SKU, которые участвуют в промо: номер промо, номер SKU, % скидки, цена продажи без скидки, повышающие коэф-ты промо (с учетом скидки и без).
rpm_get_store_orders_by_delivery_date_period
Вытягивает подтвержденные заказы магазинов, по которым нет прихода (oh.RECEIVED_DATE is null and ol.RECEIVED_QTY is null
), а также ручные заказы из таблицы MANUAL_ORDERS
. Используется для формирования товаров в пути в заказах. Выполняется по каждому магазину отдельно.
rpm_get_whs_orders_by_delivery_date_period_for_picking
Вытягивает подтвержденные заказы складов, по которым нет прихода (oh.RECEIVED_DATE is null and ol.RECEIVED_QTY is null
), а также ручные заказы из таблицы MANUAL_ORDERS
. Используется для расчета прогнозного остатка склада по датам.
rpm_delete_orders
Удаляет неподтвержденные заказы по каждому магазину отдельно, для диаграмм, которые участвуют в расчете. Это делается для того, чтобы вместо старых заказов, вставить новые, пересчитанные заказы.
rpm_insert_order_header
Запрос добавляет один новый заказ в таблицу RPM_ORDER_HEADER
. Если при вставке пачки заказов через bulk insert возникла ошибка, то используется этот запрос, чтобы вставить в таблицу заказы по одному, для того, чтобы проблема в одном заказе не влияла на другие заказы в пачке.
rpm_insert_order_line
Запрос добавляет одну новую строку заказа в таблицу RPM_ORDER_LINE
. Если при вставке пачки заказов через bulk insert возникла ошибка, то используется этот запрос, чтобы вставить в таблицу заказы по одному, для того, чтобы проблема в одном заказе не влияла на другие заказы в пачке.
rpm_get_previous_deliveries_for_writeoffs_calc
Вытягивает предыдущие заказы, по которым были доставки и оприходовано количество больше нуля, для расчета прогноза списаний товара. Выполняется по каждому магазину отдельно.
rpm_confirmed_deliveries_for_write_off_calc
Вытягивает предыдущие заказы, по которым доставка будет сегодня или будущей датой, для расчета прогноза списаний товара. Выполняется по каждому магазину отдельно.
rpm_get_confirmed_pick_zero_deliveries
Вытягивает подтвержденные заказы склад-поставщик pick-to-zero. Эти данные затем используются для того, чтобы выравнивать количество в заказах магазинов с количеством в заказе склада.
rpm_check_whs_working_day
Вытягивает рабочие дни склада на основании активных событий в календарях. Используется для того, чтобы при адаптации графика заказов магазинов по схеме pick-to-zero, заказы не попадали на нерабочие дни.
rpm_get_whs_pick_zero_calendars
rpm_get_whs_pick_zero_stock
rpm_get_store_pick_zero_orders
rpm_create_skus_by_diagrams_table
rpm_delete_skus_by_diagrams_table
rpm_delete_tmp_table_by_store
rpm_truncate_tmp_table_by_store
rpm_fill_tmp_table_with_skus_by_diagram
rpm_select_tmp_table_diagrams
rpm_clear_store_adjusted_delivery_today_order_delivery
rpm_get_existing_cross_dock_orders
rpm_delete_existing_cross_dock_orders
rpm_get_orders_by_stores_for_cross_dock
rpm_update_line_order_volume
rpm_add_whs_order_id_to_header
rpm_get_cross_dock_calendars
rpm_get_forecasts_for_picking
rpm_get_forecasts_for_picking_by_store
rpm_get_master_products_forecasts_picking_by_store
rpm_get_closest_picking_calendars
rpm_get_store_orders_with_insufficient_stock
rpm_get_pick_to_zero_with_insufficient_order
rpm_save_picking_forecast_orders
rpm_delete_assigned_lots
rpm_get_picking_orders_for_lots_assignment
rpm_get_picking_lots_for_assignment
rpm_get_adjusted_picking_orders_to_recalculate
rpm_get_cross_orders_to_adjust_sku_delivery
rpm_clear_adjusted_delivery
rpm_set_adjusted_delivery_by_order_id
rpm_get_todays_whs_deliveries
rpm_confirm_orders_after_orders_batch
rpm_max_calendar_id
rpm_delete_calendars
rpm_delete_unlinked_headers_and_lines
Запросы, используемые при работе с функционалом модуля Пополнение
rpm_check_orders_batch_running
Форма Диаграммы
rpm_diagrams
rpm_suppliers
rpm_warehouses
rpm_contracts_by_supplier
rpm_get_contract_by_diagram
rpm_check_remaining_stores_for_cross_dock
rpm_skus_by_supplier
rpm_get_diagram
rpm_get_groups_for_diagram
rpm_delete_rpm_diagram_groups_by_diagram
rpm_get_diagram_by_id
rpm_get_diagram_mins_for_store
rpm_get_diagram_and_related_crdock
rpm_check_cross_dock_stores_confirmation
rpm_check_cross_dock_whs_confirmation
rpm_max_diagram_id
rpm_update_diagram
rpm_get_all_diagrams
rpm_stores_by_contract
rpm_check_if_diagram_orders_confirmed
rpm_full_delete_diagram_calendars_orders
rpm_full_delete_diagram_calendars_orders_cross_dock_stores
rpm_get_cross_dock_whs_diagram
rpm_delete_rpm_diagram_items_by_diagram
rpm_check_contract_for_supplier
rpm_check_stores_for_contract
rpm_check_skus_for_contract_and_stores
rpm_get_whs_cross_dock_diagram_by_child_id
rpm_current_diagrams_by_contract_and_store
rpm_check_is_future_diagram_exists
rpm_check_if_confirmed_orders_exist
rpm_close_existing_diagrams
rpm_check_if_store_can_be_added_to_cross_dock
rpm_check_if_store_is_attached_to_crdock_pack
rpm_check_if_store_is_attached_to_another_crdock_pack
rpm_get_diagrams_to_copy_params
rpm_get_diagram_items_by_id
rpm_update_diagram_end_date
rpm_delete_calendar_by_diagram_id_and_end_date
rpm_check_if_today_confirmed_order
rpm_update_start_store_crdock_diagrams
rpm_update_interval_store_crdock_diagrams
rpm_get_delivery_days_of_crdock_pack
rpm_update_schedule_store_crdock_diagrams
rpm_delete_skus_store_cr_dock_diagrams
rpm_update_all_skus_store_cross_dock_diagrams
rpm_get_cr_dock_store_diagram_ids
Форма Календари
Место Календарей в системе MySales
Диаграмма описывает общие правила по которым будут создаваться заказы и поставки (приходы) от поставщика на магазины, или от поставщика на склады, и со складов на магазины. В диаграмме указывается диапазон дат когда такие правила будут действовать.
Другими словами диаграма описывает:
График заказов (дни или периоды)
График поставок (дни или периоды)
Время когда Майселс автоматически подтвердит и сохранит заказ в системе и если указан email, то отправит заказ по електронной почте
Привязка вышеуказанеых настроек к контракту поставщику магазину или складу
Подробнее про диаграммы тут.
На основании диаграмм создаются Календари на события.
События бывают двух видов: Заказ и Поставка.
По каким либо причинам поставка может отмениться, и если это известно заранее, ее следует деактивировать в календаре. При пересчете заказов Система учтет что из плана выпала поставка и пересчитает Заказы и Поставки с учетом таких “каникул“ поставщика. Если по какой либо причине не было деактивировано событие в календаре, а поставка не произошла, то это необходимо отобразить в приходах нулевым количеством или если это не будет сделано, то система по остаткам скорректируется и при очередном пересчете скорректирует заказы.
Календари создаются в таких случаях:
при сохранении диаграммы календари сразу создаются под эту диаграмму на срок действия диаграммы или на некоторое количество дней вперед (это настройка файла опций - config/options_databasename.json5 replenishment: {calendarDays: 80 // how many days ahead the calendar is calculated} )
можно пересчитать (пересоздать) календари, из таблицы с диаграммами на сайте - localhost:3000/diagrams (или со странице с календарями - localhost:3000/calendars, как указано на картинках ниже. Перед пересчетом заказов, пересчитываются календари на основании которых создаются эти заказы. Пересчитываются заказы по выбранной диаграмме, и только те, у которых дата больше текущей. Если нужно пересчитать календари и заказы по одной диаграмме, то это можно сделать из меню строки слева. Если пересчитать несколько диаграмм, то слева в чекбоксах отметить необходимые для пересчета диаграммы, а потом справа в меню выбрать пересчет отмеченых диграмм. При пересчете заказов (календарей) по выбранной диаграмме, так же пересчитываются и календари и заказы по всем связанным диаграммам
если ко времени запуска батча есть недосчитанные календари, они досчитываются
ручное добавление календаря ( с привязкой к диаграмме и без привязки к диаграмме )
В момент создания диаграммы, автоматически создаются календари. Потом если в диаграмме меняется расписание, буквально сразу, то не подвержденные календари удаляются, и создаются новые.
При сохранении скорректированной диаграммы, по которой уже созданы календари и прошло время (сформировались заказы и были подтверждены), удаляються только те календари которые по дате позже чем календари с подтвержденными заказами, т.е. подтвержденные календари не удаляются, а удаляются те, которые по хронологии идут позже и не имеют подтвержденных заказов.
Календарь можно пересчитать по отдельно взятой диаграмме. Если этого не сделать он будет пересчитан ночью батчем.
Пересчитать календари можно со страницы календарей или со страницы диаграмм.
“Пересчитать календари“ не стоит понимать дословно. Сами по себе календари не пересчитываются они создаются Диаграммой и по сути являются расписанием событий для этой диграммы. События - Заказ или Поставка.
”Пересчитать календари” это значит пересчитать Заказы и Поставки которые будет происходит согласно этим календарям. Система это осуществляет по расписанию, как правило ночью, путем запуска Батча - скрипта, который выполняет расчеты.
Форма Календари
http://localhost:3000/calendar
Основная таблица этой формы RPM_CALENDAR
ID - уникальный идентификатор Календаря, его номер
DIAGRAM_ID - номер Диаграммы, на основании которой был создан Календарь
ORDER_DATE - дата Заказа который создается по этому календарю
DELIVERY_DATE - дата Поставки которая создается по этому календарю
NEXT_DELIVERY_DATE - дата Следующей Поставки которая создается по этому календарю
MORNING - утром или не утром произойдет Поставка запланированная на DELIVERY_DATE
IS_ACTIVE - активен ли данный календарь. Если значение 1, тогда система будет создавать Заказы и Поставки по этому календарю. Если значение 0 - не будет
DELETED_DATE - дата изменения поля IS_ACTIVE
DELETED_BY - кем было изменено поле IS_ACTIVE. Если -1, то изменение внесла либо система, либо разработчик
DELETED_REASON - причина изменения поля IS_ACTIVE
TYPE - тип календаря. d - созданный по диаграмме (автоматически при сохранении или редактировании диаграммы,
с - созданный вручную, custom (дополнительный),
m - созданный вручную, manual (ручной)
Строки из RPM_CALENDAR не удаляются, при “выключении“ Календаря, а IS_ACTIVE становится равным 0
Физическое удаление строк из таблицы RPM_CALENDAR происходит при пересчет расписания или при удаление диаграммы.
По одной диаграмме может быть создано несколько календарей с одной и той же датой, но с разным значением TYPE (В коде JS это обычно calendarTYPE)
Однако на одну дату может быть только один календарь с определенным типом.
Когда в расписании Диаграммы на одной неделе создается более 1 события, учитывается, чтобы дата поставки раннего календаря не была больше или равна дате поставки позднего.
Например: понедельник - 4, вторник - 2
На сайте на странице календарей ( http://localhost:3000/calendar ) можно наблюдать, что одна строка из таблицы RPM_CALENDAR будет отображаться двумя строками Заказ и Поставка
В дальнейшем по календарям формируются Заказы и Поставки.
Запросы FrontEnd
Фронтовой функционал собран в:
public\javascripts\rpm_calendars\main.js
public\javascripts\rpm_calendars\templates.js
public\javascripts\rpm_calendars\calendar_validators.js
public\javascripts\rpm_calendars\addStoreAndDiagramModal.js
public\javascripts\rpm_calendars\createCustomCalendarForm.js
Серверная часть в:
classes\controllers\rpm\calendar.js
rpm_max_order_id
В http запрос не выведен. Предназначен для служебных целей определения следующего ID заказа авто-инкрементом.
Используется в addManualEvent назначенном на /api/rpm/add_manual_event , для создания пользовательского события формирования заказа. Сами записи календарей создает и удаляет система в фоновой обработке (батч). Пользователь может только активировать и деактивировать запись в календаре.
select max(i.ID) as ID from ( select max(ID) as ID from RPM_ORDER_HEADER union all select max(ID) as ID from RPM_ORDER_LINE union all select max(ID) as ID from RPM_ORDER_HEADER_HIST union all select max(ID) as ID from RPM_ORDER_LINE_HIST ) i
rpm_select_events
Основной запрос страницы calendar. Предназначен для извлечения данных отображаемых таблицей. Назначен на /api/rpm/get_events.
Фильтры:
diagramID - массив ID диаграмм, через запятую,
diagramName - строка для поиска диаграммы по имени,
date - интервал дат разделенный "--", для определения ORDER_DATE или DELIVERY_DATE в зависимости от ключа,
supplier - для определения поставщика по связи с RPM_DIAGRAM.SUPPLIER_ID,
contract - для определения договора, по связи через RPM_DIAGRAM.SPECIFICATION_ID и CONTRACTS.CONTRACT_ID, есть условие как на CONTRACT_ID, так и на CONTRACT_NAME,
store - для определения магазина, по связи через RPM_DIAGRAM.STORE_ID,
eventType - для задания ключа поиска дат ('all','delivery','order'),
calendarType - для определения типа события,
manager - для определения пользователя, последним изменившего запись в RPM_DIAGRAM.
select c.ID CALENDAR_ID, d.ID DIAGRAM_ID, d.NAME DIAGRAM_NAME, convert(varchar, c.ORDER_DATE, 21) as ORDER_DATE, convert(varchar, d.START_DATE, 21) as DIAGRAM_START, convert(varchar, d.END_DATE, 21) as DIAGRAM_END, d.UPDATED_BY as MANAGER_ID, mn.NAME as MANAGER_NAME, s.SUPPLIER_NAME, c.IS_ACTIVE, c.DELETED_DATE, c.DELETED_BY, c.DELETED_REASON, c.TYPE as CALENDAR_TYPE, d.WHS_ID, d.WAREHOUSE_TYPE, st.STORE_NAME as WHS_STORE_NAME, st.STORE_CODE, d.STORE_ID, st1.STORE_NAME, d.SUPPLIER_ID, ct.CONTRACT_ID, ct.CONTRACT_NAME, convert(varchar, c.DELIVERY_DATE, 21) as DELIVERY_DATE, convert(varchar, c.NEXT_DELIVERY_DATE, 21) as NEXT_DELIVERY_DATE, case when d.ALL_SKUS = '0' then (select count(*) from RPM_DIAGRAM_ITEMS i where i.DIAGRAM_ID = d.ID) else (select count(*) from PRODUCTS p where p.SUPPLIER_ID = d.SUPPLIER_ID) end CNT_SKUS, c.EVENT_TYPE TYPE from (select *, 'order' EVENT_TYPE from RPM_CALENDAR rc where :need_order = 1 and ORDER_DATE BETWEEN ':startDate' AND ':endDate' and (':calendar_type' = '0' or rc.TYPE = ':calendar_type') union all select *, 'delivery' EVENT_TYPE from RPM_CALENDAR rc1 where :need_delivery = 1 and DELIVERY_DATE BETWEEN ':startDate' AND ':endDate' and (':calendar_type' = '0' or rc1.TYPE = ':calendar_type') ) c inner join RPM_DIAGRAM d on d.ID = c.DIAGRAM_ID inner join CONTRACTS ct on ct.CONTRACT_ID = d.SPECIFICATION_ID and d.ID [diagram_id] and d.NAME like ':diagram_name' and d.SUPPLIER_ID [supplier] and ( d.UPDATED_BY = :manager_id or :manager_id is null ) and d.STORE_ID [store] and (d.SPECIFICATION_ID like ':contract' or upper(ct.CONTRACT_NAME) like ':contract') left join SUPPLIERS s on s.SUPPLIER_ID = d.SUPPLIER_ID left join STORES st on st.STORE_ID = d.WHS_ID left join STORES st1 on st1.STORE_ID = d.STORE_ID left join MANAGER mn on mn.ID = d.UPDATED_BY
get_diagram_managers
Назначен на /api/rpm/get_diagram_managers. Используется для наполнения выпадающего списка выбора менеджеров, для фильтра основной таблицы.
select m.ID as MANAGER_ID, m.NAME as MANAGER from MANAGER m where exists (select 1 from RPM_DIAGRAM rd where rd.UPDATED_BY = m.ID) order by m.NAME
rpm_get_event_details
Назначен на /api/rpm/get_diagram_managers. Используется для извлечения записи события по calendar_id, для наполнения модального окна редактирования события календаря.
select oh.STORE_ID, s.STORE_NAME, ol.SKU_ID, p.ARTICLE_NAME as SKU_NAME, ol.RECEIVED_QTY, ol.ADJUSTED_DELIVERY, coalesce(ol.CUSTOM_ORDER_VOLUME, ol.ORDER_VOLUME) as VOLUME, p.ITEM_CODE from (select * from RPM_CALENDAR where ID = :calendar_id) c inner join RPM_ORDER_HEADER oh on oh.CALENDAR_ID = c.ID inner join RPM_ORDER_LINE ol on ol.ID = oh.ID inner join STORES s on s.STORE_ID = oh.STORE_ID inner join PRODUCTS p on p.SKU_ID = ol.SKU_ID
rpm_get_details_for_manual_event
Назначен на /api/rpm/get_skus_for_manual_event. Используется в модальном окне создания пользовательского события формирования заказа.
rpm_get_diagram_schedule
Назначен на /api/rpm/get_diagram_schedule. Используется для извлечения графика по диаграмме, который отображается в модальном окне.
select ID, convert(varchar, ORDER_DATE, 121) as ORDER_DATE, convert(varchar, DELIVERY_DATE, 121) as DELIVERY_DATE, IS_ACTIVE, DELETED_REASON from RPM_CALENDAR where DIAGRAM_ID = :diagram_id and (ORDER_DATE >= ':start_date' or DELIVERY_DATE >= ':start_date') order by ORDER_DATE
rpm_cancel_calendar_event
Назначен на /api/rpm/cancel_event. Используется для отмены события в календаре, при снятии галки "Актив." или массово над отмеченными записями из меню "Отменить события".
rpm_make_calendar_event_active_again
Назначен на /api/rpm/make_event_active_again. Используется для активирования ранее отмененных событий в календаре.
rpm_get_suppliers_from_diagrams
Назначен на /api/rpm/get_custom_params. Вызывается при открытии модального окна добавления события. Извлекает список поставщиков для активных диаграмм. Наполняет выпадающий список поставщиков в модальном окне.
select distinct s.SUPPLIER_ID ID, s.SUPPLIER_NAME NAME from RPM_DIAGRAM d inner join SUPPLIERS s on d.SUPPLIER_ID = s.SUPPLIER_ID where coalesce(d.WAREHOUSE_TYPE, 'any') <> 'c' and d.START_DATE <= cast(getdate() as date) and (d.END_DATE >= cast(getdate() as date) or d.END_DATE is null)
rpm_get_diagrams_by_supplier
Назначен на /api/rpm/get_custom_params и /api/rpm/get_custom_params_by_supplier. Второе используется в public\javascripts\rpm_calendars\createCustomCalendarForm.js Извлекает список диаграмм для заданного поставщика.
select distinct d.ID, d.NAME from RPM_DIAGRAM d where d.SUPPLIER_ID = :supplier_id and coalesce(d.WAREHOUSE_TYPE, 'any') <> 'c' and d.START_DATE <= cast(getdate() as date) and (d.END_DATE >= cast(getdate() as date) or d.END_DATE is null) order by d.ID
rpm_get_diagrams_by_contract
Назначен на /api/rpm/get_custom_params_by_contract. Используется в public\javascripts\rpm_calendars\createCustomCalendarForm.js Извлекает список диаграмм для заданного договора.
select d.ID as DIAGRAM_ID, d.NAME as DIAGRAM_NAME, d.STORE_ID, s.STORE_NAME from RPM_DIAGRAM d left join STORES s on s.STORE_ID = d.STORE_ID where d.SPECIFICATION_ID = :contract_id and coalesce(d.WAREHOUSE_TYPE, 'any') <> 'c' and d.START_DATE <= ':calendar_date' and (d.END_DATE >= ':calendar_date' or d.END_DATE is null) order by d.ID
rpm_check_todays_calendar
Используется в addCustomEvent выведенном в /api/rpm/add_custom_event. Проверяет существование календаря на заданную дату.
select ID from RPM_CALENDAR where ORDER_DATE = ':order_date' and DIAGRAM_ID = :diagram_id and TYPE != 'm'
rpm_get_max_calendar_dates
Используется в addCustomEvent выведенном в /api/rpm/add_custom_event. Определяет предельные даты заказа и доставки для заданной диаграммы.
select convert(varchar, max(ORDER_DATE), 121) as MAX_ORDER_DATE, convert(varchar, max(DELIVERY_DATE), 121) as MAX_DELIVERY_DATE from RPM_CALENDAR where DIAGRAM_ID = :diagram_id
rpm_create_custom_event
Используется в addCustomEvent выведенном в /api/rpm/add_custom_event. Добавляет в RPM_CALENDAR запись о новом событии.
insert into RPM_CALENDAR (ID, DIAGRAM_ID, ORDER_DATE, DELIVERY_DATE, IS_ACTIVE, TYPE, NEXT_DELIVERY_DATE) values (:id, :diagram_id, ':order_date', ':delivery_date', ':active', ':type', (select min(r.DELIVERY_DATE) from (select * from RPM_CALENDAR) r where r.DIAGRAM_ID = :diagram_id and r.DELIVERY_DATE > ':delivery_date' and r.IS_ACTIVE = '1' and r.TYPE != 'm') ); update c set NEXT_DELIVERY_DATE = (select min(DELIVERY_DATE) from RPM_CALENDAR where DELIVERY_DATE > c.DELIVERY_DATE and DIAGRAM_ID = c.DIAGRAM_ID and TYPE != 'm' and IS_ACTIVE = '1') from RPM_CALENDAR c where (ORDER_DATE >= (select max(ORDER_DATE) from RPM_CALENDAR where DIAGRAM_ID = :diagram_id and ORDER_DATE < ':order_date' and ORDER_DATE >= cast(getdate() as date) and TYPE != 'm' and IS_ACTIVE = '1' and not exists(select 1 from RPM_ORDER_HEADER where CALENDAR_ID = c.ID and IS_CONFIRMED = '1')) or ORDER_DATE > ':order_date') and DELIVERY_DATE != (select max(DELIVERY_DATE) from RPM_CALENDAR where DIAGRAM_ID = :diagram_id and TYPE != 'm') and DIAGRAM_ID = :diagram_id and TYPE != 'm' and IS_ACTIVE = '1' and not exists(select 1 from RPM_ORDER_HEADER where CALENDAR_ID = c.ID and IS_CONFIRMED = '1');
rpm_calendar_get_additional_data
Используется в assignTotalsToManualOrder и далее в addManualEvent выведенном в /api/rpm/add_manual_event. Извлекает список SKU/цен и объемов для заданных магазина и договора.
select ssc.SKU_ID, ssc.PURCHASE_PRICE, p.WEIGHT from PRODUCTS p left join SKU_STORE_CONTRACT_V ssc on ssc.SKU_ID = p.SKU_ID and ssc.STORE_ID = :store_id and ssc.CONTRACT_ID = :contract_id where p.SKU_ID [sku_id]
rpm_get_calendar_by_id
Используется в addManualEvent выведенном в /api/rpm/add_manual_event. Извлекает дату следующей доставки, договор, поставщика и склад по заданному ID события в календаре.
select convert(varchar, c.NEXT_DELIVERY_DATE, 21) as NEXT_DELIVERY_DATE, d.SPECIFICATION_ID, d.SUPPLIER_ID, d.WHS_ID from RPM_CALENDAR c inner join RPM_DIAGRAM d on d.ID = c.DIAGRAM_ID where c.ID = :calendar_id
rpm_max_calendar_id
Используется в addCustomEvent выведенном в /api/rpm/add_custom_event. Предназначен для служебных целей определения следующего ID события в календаре авто-инкрементом.
select max(ID) as ID from ( select max(ID) as ID from RPM_CALENDAR union all select max(ID) as ID from RPM_CALENDAR_HIST ) a
rpm_delete_calendars
Используется в classes\controllers\rpm\dbServices.js в deleteCalendars. Далее в classes\engine\rpm_units.js есть вызов calendarDbService.deleteCalendars в deletePickZeroCalendarsAndOrders, что вызывается в calcStoreOrders из batches\rpm_create_orders.js, т.е. используется только в фоновой обработке.
delete c from RPM_DIAGRAM d inner join RPM_CALENDAR c on c.DIAGRAM_ID = d.ID where d.ID [diagram_id] and d.STORE_ID [store_id] and c.ORDER_DATE >= cast(getdate() as date) and c.TYPE '[type]' and not exists ( select 1 from RPM_ORDER_HEADER with (nolock) where CALENDAR_ID = c.ID and IS_CONFIRMED = '1' )
Сейчас (ноябрь 2022) в calendar не используется.rpm_adjust_delivery_by_sku
Назначен на /api/rpm/adjust_delivery_by_sku. Используется в orders, сейчас в calendar не используется.
rpm_get_cross_dock_store_orders_id
Используется в adjustDeliveryBySku назначенном /api/rpm/adjust_delivery_by_sku из classes\controllers\rpm\orders.js , перед вызовом rpm_adjust_delivery_by_sku.
Используется в orders, сейчас в calendar не используется.
rpm_order_stock_change_reasons
Назначен на /api/rpm/get_order_stock_change_reasons. Используется в public\javascripts\rpm_orders\main.js в calendar не используется.
rpm_change_order_stock
Назначен на /api/rpm/edit_order_stock и /api/rpm/edit_order_stock_and_volume. Используется в public\javascripts\rpm_orders\customStockInput.js и далее в public\javascripts\rpm_orders\main.js в calendar не используется.
rpm_set_cross_dock_optimization_if_any
Используется в classes\controllers\rpm\orders.js в setOrderVolume, что выведено в /api/rpm/edit_order_volume. Используется в public\javascripts\rpm_orders\main.js в calendar не используется.
rpm_change_order_volume
Используется в classes\controllers\rpm\orders.js в setOrderVolume, что выведено в /api/rpm/edit_order_volume. Используется в public\javascripts\rpm_orders\main.js в calendar не используется.
rpm_max_order_id
rpm_select_events
get_diagram_managers
rpm_get_event_details
rpm_adjust_delivery_by_sku
rpm_get_cross_dock_store_orders_id
rpm_get_details_for_manual_event
rpm_get_diagram_schedule
rpm_cancel_calendar_event
rpm_make_calendar_event_active_again
rpm_order_stock_change_reasons
rpm_change_order_stock
rpm_set_cross_dock_optimization_if_any
rpm_change_order_volume
rpm_get_suppliers_from_diagrams
rpm_get_diagrams_by_supplier
rpm_get_diagrams_by_contract
rpm_check_todays_calendar
rpm_get_max_calendar_dates
rpm_create_custom_event
rpm_calendar_get_additional_data
rpm_get_calendar_by_id
rpm_max_calendar_id
rpm_delete_calendars
Форма Новые магазины
rpm_get_new_stores
rpm_check_new_store
rpm_add_new_store
rpm_get_new_store
rpm_edit_new_store
rpm_delete_old_store
rpm_delete_new_store
Форма Спецификации (экспериментальная)
Вместо нее используется просто загружаемая таблица IF_BOM
rpm_get_products
rpm_edit_product_notes
rpm_edit_component_quantity
rpm_get_max_product_id
rpm_get_last_product_version
rpm_add_product
rpm_add_product_version
rpm_add_product_component
rpm_set_main_product
rpm_delete_product
rpm_delete_product_version
Форма Тендерные позиции
rpm_get_sku_tenders
rpm_get_supplier_emails
rpm_get_allowed_contracts
rpm_get_sku_suitable_contracts
rpm_set_order_contract
rpm_erase_sku_tender
rpm_delete_sku_tender
Форма Заказы
rpm_get_managers
rpm_select_orders_to_autoconfirm
rpm_change_order_confirm
rpm_get_order_by_id
rpm_get_cross_dock_orders_by_id
rpm_get_cross_dock_breakdown_by_organization
rpm_set_order_header_email_date
rpm_get_order_headers
rpm_orders
rpm_order_rows_excel_export
rpm_order_headers_excel_export
rpm_get_info_by_order_ids
rpm_get_orders_for_recalculation
rpm_get_full_header
rpm_get_order_tracking
rpm_get_full_order_line
rpm_update_order_line_custom_order
rpm_update_order_line_received
rpm_bulk_update_order_line_received
rpm_update_order_head_received
rpm_update_order_header_opt
rpm_update_order_line
rpm_bulk_update_order_head_received
rpm_cancel_order_line
rpm_update_adjusted_del_date
rpm_check_whs_cross_dock_and_stores_orders_equality
rpm_check_cross_dock_order_equality_by_sku
rpm_confirm_cross_dock_store_orders
rpm_record_email_error
rpm_get_manager_by_id
rpm_cancel_order_confirmation
rpm_check_orders_before_send
rpm_get_sub_product_hierarchy
rpm_get_sub_product_hierarchy_picking
rpm_get_just_diagram_by_id
rpm_bulk_confirm_orders
rpm_get_main_record_diagram_by_id
rpm_get_whs_picking_fcst_details
rpm_reset_order_received_date
rpm_check_if_any_crdock_store_order_confirmed
rpm_bulk_cancel_orders
rpm_reset_order_cancelation
rpm_get_lines_for_adjust_custom_order
rpm_update_single_order_line_by_sku_and_id
rpm_get_main_header_record_by_id
rpm_update_order_totals
rpm_update_order_headers_by_id
Форма Параметры позиций
http://localhost:3000/sku_store_params
Основная таблица этой формы RPM_SKU_STORE_PARAMS
public\javascripts\rpm_sku_store_params\main.js
Фронтовой функционал собран в:
public\javascripts\rpm_sku_store_params\main.js
public\javascripts\rpm_sku_store_params\templates.js
Серверная часть в:
classes\controllers\rpm\skuStoreParams.js
rpm_get_sku_store_params_rows
Основной запрос страницы sku_store_params. Предназначен для извлечения данных отображаемых таблицей. Назначен на /api/rpm/sku_store_params_get_rows.
Фильтры SKU (сравнивается как с SKU_ID, так и на подстроку в PRODUCTS.ARTICLE_NAME или PRODUCTS.ITEM_CODE), магазин, договор, поставщик, менеджер и признаки sku-range и is-new.
rpm_get_sku_store_params_by_key
Предназначен для извлечения из RPM_SKU_STORE_PARAMS признака PICK_TO_ZERO по заданным SKU и магазину.
Используется в classes\controllers\rpm\dbServices.js и далее в getPickingFcstDetails из classes\controllers\rpm\orders.js, что выведено в /api/rpm/get_picking_fcst_details , а сам запрос вызывается из orders.
rpm_get_sku_store_params_by_pairs
Предназначен для извлечения из RPM_SKU_STORE_PARAMS минимального заказа, кратности и признака sku-range по заданным SKU и магазину.
Используется в checkSkuStoreParamsByPairs из classes\controllers\rpm\push\index.js , что выведено в /api/rpm/push_check_sku_store_params_by_pairs, а сам запрос вызывается из rpm_push.
rpm_sku_store_params_get_init_data
Предназначен для извлечения списка менеджеров, наполняющего выпадающий список фильтра. Используется в getInitialData из classes\controllers\rpm\skuStoreParams.js и выведен в /api/rpm/sku_params_get_initial_data.
rpm_sku_store_params_get_contracts
Предназначен для извлечения списка договоров, наполняющего выпадающий список фильтра. Используется в getInitialData из classes\controllers\rpm\skuStoreParams.js и выведен в /api/rpm/sku_params_get_initial_data.
rpm_sku_store_params_update_is_order
Предназначен для обновления поля IS_ORDER таблицы RPM_SKU_STORE_PARAMS для заданных SKU и магазина. Сейчас не используется.
rpm_sku_store_params_update_is_production
Предназначен для обновления поля IS_PRODUCTION таблицы RPM_SKU_STORE_PARAMS для заданных SKU и магазина. Сейчас не используется.
rpm_sku_store_params_update_is_shelf_limit
Предназначен для обновления поля IS_SHELF_LIMIT таблицы RPM_SKU_STORE_PARAMS для заданных SKU и магазина. Сейчас не используется.
rpm_get_check_order
По заданному набору SKU и магазинов из вью SKU_STORE_CONTRACT_V извлекает договора, поставщиков и различные признаки для проверки возможности заказа.
Используется в checkPossibilityToOrder из classes\controllers\rpm\skuStoreParams.js и выведен в /api/rpm/sku_store_params/check_order_possibility.
Это ключевой запрос модального окна "Проверка возможности заказа".
select st.STORE_ID,st.STORE_NAME, p.SKU_ID, case when p.ITEM_CODE is null then p.ARTICLE_NAME else concat('(', cast(p.ITEM_CODE as varchar), ') ', p.ARTICLE_NAME) end as ARTICLE_NAME, (case when exists( select 1 from SKU_RANGE where STORE_ID = st.STORE_ID and SKU_ID = p.SKU_ID and START_DATE <= cast(getdate() as date) and (END_DATE >= cast(getdate() as date) or END_DATE is null) ) then 1 else 0 end) as IS_AM, ssc.CONTRACT_ID, ssc.PACKAGE_CONTENT, ssc.IS_ORDER, c.CONTRACT_NAME, s.SUPPLIER_ID, s.SUPPLIER_NAME from STORES st join PRODUCTS p on p.SKU_ID [skus] or p.ITEM_CODE '[item_codes]' left join SKU_STORE_CONTRACT_V ssc on ssc.SKU_ID = p.SKU_ID and ssc.STORE_ID = st.STORE_ID left join CONTRACTS c on c.CONTRACT_ID = ssc.CONTRACT_ID left join SUPPLIERS s on c.SUPPLIER_ID = s.SUPPLIER_ID where st.STORE_ID [stores]
rpm_get_diagram_and_cal_by_skus
По заданному набору SKU и магазинов извлекает диаграммы для проверки возможности заказа.
Используется в checkPossibilityToOrder из classes\controllers\rpm\skuStoreParams.js и выведен в /api/rpm/sku_store_params/check_order_possibility.
Это ключевой запрос модального окна "Проверка возможности заказа".
rpm_check_sku_store_pairs_existence
Проверяет существование SKU и магазинов в таблице RPM_SKU_STORE_PARAMS. Используется в filterNonExistentPairs и далее importFromFile из classes\controllers\rpm\skuStoreParams.js
назначенном в /api/rpm/sku_store_params/import_items. Используется при импорте из csv.
rpm_update_item_params_record
Предназначен для обновления полей таблицы RPM_SKU_STORE_PARAMS для заданных SKU и магазина. Используется в updateParamsBySkuIdStoreId из classes\controllers\rpm\dbServices.js и далее в importFromFile, updateRecordIntoDb и bulkUpdateRecordsIntoDb выведенных соответственно в /api/rpm/sku_store_params/import_items , /api/rpm/sku_store_params/update_record и /api/rpm/sku_store_params/bulk_update_record.
rpm_sku_store_params_import
Предназначен для вставки записи в таблицу RPM_SKU_STORE_PARAMS. Используется в updateParamsBySkuIdStoreId из classes\controllers\rpm\dbServices.js и далее в importFromFile, updateRecordIntoDb и bulkUpdateRecordsIntoDb выведенных соответственно в /api/rpm/sku_store_params/import_items , /api/rpm/sku_store_params/update_record и /api/rpm/sku_store_params/bulk_update_record.
Форма Дополнительная загрузка
rpm_get_promo_for_add_load
rpm_get_promo_stores
rpm_get_promo_skus
rpm_create_add_load
rpm_get_max_add_load_id
rpm_add_load_get_rows
rpm_delete_add_load
rpm_get_load_id_details
rpm_check_add_load_intersections
Форму Пуш распределение
rpm_push_get_stores
rpm_push_get_skus
rpm_push_get_sku_by_items
rpm_push_get_sku_by_eans
rpm_push_get_contract_by_stores_skus
rpm_push_get_store_sku_pairs
rpm_push_get_existing_diagrams
rpm_get_suppliers_by_contract
rpm_push_get_existing_diagrams_broad_params
rpm_push_get_forecasts_for_calc_distribution
rpm_push_get_max_push_id
rpm_create_push
rpm_get_closest_next_delivery_days_by_diagrams
rpm_get_managers_by_sku_store
rpm_get_purchase_prices_by_sku_store
rpm_get_all_push
rpm_push_get_whs_cross_dock_params
rpm_push_find_closest_delieveries
Форма Дополнительные места
http://localhost:3000/rpm_add_presentation
Эта функциональность завязана на две таблицы:
RPM_ADD_PRESENTATION - заголовки дополнительных мест
RPM_ADD_PRESENTATION_ITEMS - распределения дополнительных мест
rpm_add_presentation_get_table_rows
Основной запрос страницы rpm_add_presentation. Предназначен для извлечения данных отображаемых таблицей. Назначен на /api/rpm/add_presentation_get_rows.
Фильтры дата, название и SKU (сравнивается как с SKU_ID, так и на подстроку в PRODUCTS.ARTICLE_NAME).
SELECT AP.ID, AP.NAME, (select count(*) from RPM_ADD_PRESENTATION_ITEMS where ID = AP.ID) as QTY_RECORDS, AP.ALL_STORES, convert(varchar, AP.START_DATE, 21) as START_DATE, convert(varchar, AP.END_DATE, 21) as END_DATE, convert(varchar, AP.UPDATE_DATE, 21) as UPDATE_DATE, AP.UPDATED_BY, MANAGER.NAME AS MANAGER, AP.PROMO_ID, PH.NAME as PROMO_NAME FROM RPM_ADD_PRESENTATION as AP LEFT JOIN PROMO_HEADER AS PH on AP.PROMO_ID = PH.ID LEFT JOIN MANAGER on MANAGER.ID = AP.UPDATED_BY WHERE AP.END_DATE >= ':date' AND AP.NAME like ':name' AND AP.IS_ACTIVE = 1 and exists (select ID from RPM_ADD_PRESENTATION_ITEMS as API left join PRODUCTS on PRODUCTS.SKU_ID = API.SKU_ID where AP.ID = API.ID and (API.SKU_ID like ':sku' or PRODUCTS.ARTICLE_NAME like ':sku'));
rpm_add_presentation_get_promo
Назначен на /api/rpm/add_presentation_get_promo. Используется для наполнения выпадающего списка выбора "Промо" в модальном окне заведения новых дополнительных мест.
В качестве фильтра текущая дата (выбирается в левом верхнем углу страницы), должна быть меньше либо равна дате завершения "Промо"
SELECT ID, NAME, convert(varchar, PH.START_DATE, 121) as START_DATE, convert(varchar, PH.END_DATE, 121) as END_DATE FROM PROMO_HEADER PH WHERE END_DATE >= ':start_date'
rpm_add_presentation_get_promo_stores
Назначен на /api/rpm/add_presentation_get_promo_stores. Используется для наполнения выпадающего списка выбора магазинов, в модальном окне заведения новых дополнительных мест, с учетом выбранного "Промо". Фильтр, выбранный ID Промо.
select STORE_ID as ID, (select STORE_NAME from STORES where STORES.STORE_ID = ps.STORE_ID) as NAME from PROMO_STORES as ps where ID = :promo_id
rpm_add_presentation_get_promo_skus
Назначен на /api/rpm/add_presentation_get_promo_skus. Используется для наполнения выпадающего списка выбора SKU, в модальном окне заведения новых дополнительных мест, с учетом выбранного "Промо". Фильтр, выбранный ID Промо.
SELECT SKU_ID as ID, (SELECT ARTICLE_NAME FROM PRODUCTS WHERE PRODUCTS.SKU_ID = ps.SKU_ID) as NAME from PROMO_SKU as ps where ID = :promo_id
rpm_add_presentation_get_sku_store_pairs
Назначен на /api/rpm/add_presentation_get_sku_store_pairs. Предназначен для извлечения объемов дополнительных мест по заданным массивам SKU и магазинов.
SELECT P.SKU_ID, case when P.ITEM_CODE is null then P.ARTICLE_NAME else '(' + cast(P.ITEM_CODE as varchar) + ') ' + P.ARTICLE_NAME end as ARTICLE_NAME, S.STORE_ID, S.STORE_NAME, (select API.QUANTITY from RPM_ADD_PRESENTATION_ITEMS as API where P.SKU_ID = API.SKU_ID and S.STORE_ID = API.STORE_ID and API.ID = ':max_id') as QTY FROM PRODUCTS as P CROSS JOIN STORES as S WHERE P.SKU_ID [skus] and S.STORE_ID [stores]
rpm_add_presentation_max_id
В http запрос не выведен. Предназначен для служебных целей определения следующего ID дополнительных мест авто-инкрементом.
SELECT MAX(ID) AS MAXID from RPM_ADD_PRESENTATION
rpm_add_presentation_create
Назначен на /api/rpm/add_presentation_create. Предназначен для сохранения заголовка дополнительных мест.
DELETE FROM RPM_ADD_PRESENTATION_ITEMS WHERE ID = :max_id; MERGE INTO RPM_ADD_PRESENTATION dest USING (SELECT :max_id as ID) src ON (dest.ID = src.ID) WHEN MATCHED THEN UPDATE SET NAME = ':name', START_DATE = ':startDate', END_DATE = ':endDate', PROMO_ID = :selectedPromo, UPDATE_DATE = getdate(), UPDATED_BY = :user, ALL_STORES = :isAllStores WHEN NOT MATCHED THEN INSERT(ID, NAME, START_DATE, END_DATE, PROMO_ID, UPDATE_DATE, UPDATED_BY, ALL_STORES, IS_ACTIVE) VALUES(:max_id, ':name', ':startDate', ':endDate', :selectedPromo, getdate(), :user, :isAllStores, 1);
rpm_add_presentation_delete
Назначен на /api/rpm/add_presentation_delete. Предназначен для удаления дополнительных мест, установкой признака IS_ACTIVE в 0.
UPDATE RPM_ADD_PRESENTATION set IS_ACTIVE = 0, UPDATED_BY = :user, UPDATE_DATE = getdate() where ID = :id
rpm_add_presentation_get_by_id
Назначен на /api/rpm/add_presentation_load_by_id. Предназначен для извлечения заголовка дополнительных мест и списков ID SKU и магазинов, разделенных запятыми.
Используется в модальном окне редактирования.
SELECT AP.ID, AP.NAME, AP.ALL_STORES, convert(varchar, AP.START_DATE, 21) as START_DATE, convert(varchar, AP.END_DATE, 21) as END_DATE, stuff( (select ',' + convert(varchar, SKU_ID) from RPM_ADD_PRESENTATION_ITEMS AS API where API.ID = :id for xml path('')), 1, 1, '') as SKUS, stuff( (select ',' + convert(varchar, STORE_ID) from RPM_ADD_PRESENTATION_ITEMS AS API where API.ID = :id for xml path('')), 1, 1, '') as STORES, AP.UPDATED_BY, AP.PROMO_ID FROM RPM_ADD_PRESENTATION as AP WHERE AP.IS_ACTIVE = 1 AND AP.ID = :id
add_presentation_check_sku_promo
Назначен на /api/rpm/add_presentation_check_sku_list. Используется для доопределения SKU_ID по заданным EAN или ITEM_CODE при импорте из csv.
Также используется в rpm_push при импорте.
SELECT distinct PS.ID FROM PROMO_STORES PS JOIN PROMO_SKU_APPROVED PSA ON PSA.ID=PS.ID JOIN PROMO_HEADER PH ON PH.ID=PS.ID AND (:store_id = -1 OR PS.STORE_ID = :store_id) AND (:sku_id = -1 OR PSA.SKU_ID = :sku_id) AND (:promo_id = -1 OR PS.ID = :promo_id) AND (:promo_id > -1 OR PH.START_DATE BETWEEN ':startDate' AND ':endDate' OR PH.END_DATE BETWEEN ':startDate' AND ':endDate' OR ':startDate' BETWEEN PH.START_DATE AND PH.END_DATE OR ':endDate' BETWEEN PH.START_DATE AND PH.END_DATE)
rpm_add_presentation_check_unique_store_sku_dates
Назначен на /api/rpm/check_unique_store_sku_dates_for_presentation.
Выполняет проверку выбранных списков SKU/магазинов на пересечение с другими дополнительными местами.
Заводить пересекающиеся дополнительные места функционал позволяет, но отмечает предупреждение розовым цветом.
SELECT AP.NAME, RAPI.ID,RAPI.SKU_ID,RAPI.STORE_ID, convert(varchar, AP.START_DATE, 21) as START_DATE, convert(varchar, AP.END_DATE, 21) as END_DATE FROM RPM_ADD_PRESENTATION AS AP JOIN RPM_ADD_PRESENTATION_ITEMS RAPI ON RAPI.ID=AP.ID WHERE AP.IS_ACTIVE=1 AND AP.ID <> :id AND RAPI.SKU_ID = :sku_id AND RAPI.STORE_ID [store_list] AND (AP.START_DATE BETWEEN ':startDate' AND ':endDate' OR AP.END_DATE BETWEEN ':startDate' AND ':endDate' OR ':startDate' BETWEEN AP.START_DATE AND AP.END_DATE OR ':endDate' BETWEEN AP.START_DATE AND AP.END_DATE)
Форма Перемещения
get_stores_with_overstock
get_skus_with_overstock_by_store
get_stores_for_sku_transfer
get_store_to_store_skus
get_store_to_supplier_skus
get_store_transfers
get_store_transfer_lines
get_max_store_transfers_id
update_store_transfer_record
update_store_transfer_line
delete_store_transfer_record
delete_store_transfer_line
get_sku_nearest_promo_in_store
Батчи
Батч расчета заказов
Батч расчета заказов - config/[customer]/sql_[customer]_batches.ini
Индивидуален для каждого клиента
Предварительные операции с таблицами перед началом расчета заказов
[rpm_pre_calc_orders_batch
]
Выполняет предварительные операции с таблицами перед началом расчета заказов, а именно:
- синхронизирует цены в products.last_purchase_price
и sku_store_contract.last_purchase_price
,
где last_purchase_price
- последняя актуальная цена товарной позиции
- обновляет в RPM_SKU_STORE_PARAMS
записи на основе SKU_STORE_CONTRACT
где SKU_STORE_CONTRACT
- таблица, которая заполняется клиентом, откуда берутся привязки SKU к актуальным контрактам. RPM_SKU_STORE_PARAMS
- это внутренняя таблица для расчетов автозаказа
- выставляет round_factor
= 0,5 для записей, где он не указан явно, в таблице RPM_SKU_STORE_PARAMS
- в таблице RPM_SKU_STORE_PARAMS
выставляет поле is_order
на основе sku_range_current
, rpm_presentation
, SKU_WHS_DISABLED_ORDERS
и др.
поле is_order
определяет можно ли по паре SKU-STORE делать заказ. Значение 1 - можно, 0 - нельзя.
- обновляет manual_orders
на основе manual_order_close
, manual_order_receivings
. manual_orders
таблица ручных заказов, которая обновляется на основании закрытых, уже не актуальных ручных заказов manual_order_close
и таблицы приходов по ручным заказам manual_order_receivings
. Когда по заказу есть приход, заказ становится не актуальным. Так же заказ может становится не актуальным по дате close_date
. Поле order_number
во всех эти таблицах является связующим полем.
- автоматически закрывает manual_orders
, если дата заказа устарела и где релевантно учитывает RPM_TRANSFERS
(внутренее перемещение между магазинами). По состоянию на ноябрь 2022 таблица RPM_TRANSFERS
практически никем не используется.
- обновляет received_qty
в rpm_order_line
на основе RPM_RECEIVINGS
и где релевантно RPM_TRANSFERS
где rpm_order_line
- таблица со строками автозаказов (табличная часть заказа, в вебинтерфейсе “строки“), а RPM_RECEIVINGS
таблица приходов которые формируются согласно заказам.
- может автоматически выставлять в 0 received_qty
в rpm_order_line
для устаревших заказов.
- может автоматически закрывать устаревшие заказы
Т.к. расчет заказов у каждого ретейлера осуществляется по индивидуальному алгоритму, то и выставление 0 в received_qty
может происходить при разных условиях. Например одни считают, что если на магазин пришла только часть заказа, то надо закрывать весь заказ, обозначая отсутствующие позиции нулями. А вот другие считают, что заказ может ехать частями, и должен закрываться только когда доедут все позиции или он устареет, не сбрасывая в 0 полученное количество.
- закрывает заказ (поле received_date
в rpm_order_header
) на основе RPM_RECEIVINGS
и rpm_order_close
где RPM_ORDER_ADJUSTMENTS
делают ручные корректировки автоматически сгенерированых заказов, а RPM_RECEIVINGS
-
- обновляет количество товара в заказе adjusted_delivery
на основе RPM_ORDER_ADJUSTMENTS
- обновляет дату поставки adjusted_delivery_date
на основе rpm_order_delay
- может иметь специальные условия для заказов на склад