diff --git a/internal/lkgateway/depoevents.go b/internal/lkgateway/depoevents.go index 4c5f780..7c65e51 100644 --- a/internal/lkgateway/depoevents.go +++ b/internal/lkgateway/depoevents.go @@ -754,6 +754,32 @@ EXEC dbo.sp_add_jobschedule @job_name = N'%[1]s', @name = N'%[1]s', @enabled = 1 EXEC dbo.sp_add_jobserver @job_name = N'%[1]s';`, depoJobName, f.DepoDB(), depoJobProcName(f), depoJobEvery(f)) } +// depoJobAgentAdminScript — тот же набор для администратора SQL (вариант «создаёт администратор по +// скрипту»): с пояснениями и защитой от повторного запуска (джоба уже есть — ничего не делает). +// depoJobAgentScript остаётся построчным: его выполняет сам bj в варианте «джобу создаёт bj». +func depoJobAgentAdminScript(f FancyMSSQLSettings) string { + return fmt.Sprintf(`-- Bridge&Join: джоба SQL Server Agent «%[1]s» — обработка таблиц обмена M2M в базе %[2]s. +-- Каждые %[4]d с вызывает процедуру %[3]s: записи bj превращаются в документы и операции учёта DEPO. +-- Выполнить в SSMS или sqlcmd под логином с правами sysadmin (или SQLAgentOperatorRole в msdb). +-- Служба SQL Server Agent должна быть запущена. Скрипт можно запускать повторно: если джоба уже есть, он её не трогает. + +USE msdb; +GO + +IF NOT EXISTS (SELECT 1 FROM msdb.dbo.sysjobs WHERE name = N'%[1]s') +BEGIN + EXEC dbo.sp_add_job @job_name = N'%[1]s', @enabled = 1, @description = N'bj2depo: обработка трансферных таблиц M2M (bj)'; + EXEC dbo.sp_add_jobstep @job_name = N'%[1]s', @step_name = N'%[1]s', @subsystem = N'TSQL', @database_name = N'%[2]s', @command = N'exec %[3]s;'; + EXEC dbo.sp_add_jobschedule @job_name = N'%[1]s', @name = N'%[1]s', @enabled = 1, @freq_type = 4, @freq_interval = 1, @freq_subday_type = 2, @freq_subday_interval = %[4]d, @active_start_time = 0; + EXEC dbo.sp_add_jobserver @job_name = N'%[1]s'; + PRINT N'Джоба %[1]s создана.'; +END +ELSE + PRINT N'Джоба %[1]s уже есть — не изменялась.'; +GO +`, depoJobName, f.DepoDB(), depoJobProcName(f), depoJobEvery(f)) +} + // depoJobGrantScript — права для варианта «внутри bj». func depoJobGrantScript(f FancyMSSQLSettings) string { return fmt.Sprintf("USE %s;\nGRANT EXECUTE ON %s TO %s;", f.DepoDB(), depoJobProcName(f), f.User) @@ -872,11 +898,12 @@ func depoJobCreateAgent(ctx context.Context, rc *RuntimeConfig, adminUser, admin // DepoJobView — данные карточки «Где запускается обработка». type DepoJobView struct { Name, Proc, GrantScript, AgentRights, AgentScript string + AdminScript string // для администратора: с пояснениями и защитой от повтора Every int } func depoJobView(f FancyMSSQLSettings) DepoJobView { - return DepoJobView{Name: depoJobName, Proc: depoJobProcName(f), Every: depoJobEvery(f), GrantScript: depoJobGrantScript(f), AgentRights: depoJobAgentRightsScript(f), AgentScript: depoJobAgentScript(f)} + return DepoJobView{Name: depoJobName, Proc: depoJobProcName(f), Every: depoJobEvery(f), GrantScript: depoJobGrantScript(f), AgentRights: depoJobAgentRightsScript(f), AgentScript: depoJobAgentScript(f), AdminScript: depoJobAgentAdminScript(f)} } // ---- выгрузка истории тестов (TEST3, банк Зенит / робот) в трансферные таблицы ---- diff --git a/internal/lkgateway/fancydb_handlers.go b/internal/lkgateway/fancydb_handlers.go index 21d53b9..4476ce3 100644 --- a/internal/lkgateway/fancydb_handlers.go +++ b/internal/lkgateway/fancydb_handlers.go @@ -25,6 +25,7 @@ func (h *setupHandlers) registerFancy(mux *http.ServeMux) { mux.HandleFunc("/admin/setup/fancy/depo-tables/check", h.checkFancyDepoTables) mux.HandleFunc("/admin/setup/fancy/depo-tables/script.sql", h.fancyDepoTablesScript) mux.HandleFunc("/admin/setup/fancy/depo-login/script.sql", h.fancyDepoLoginScript) + mux.HandleFunc("/admin/setup/fancy/depo-job/script.sql", h.fancyDepoJobScript) mux.HandleFunc("/admin/fancy-queue", h.fancyQueue) mux.HandleFunc("/admin/fancy-queue/requeue", h.fancyQueueRequeue) } @@ -321,3 +322,11 @@ func fancyDBLabel(s FancyMSSQLSettings) string { } return "MSSQL" } + +// fancyDepoJobScript — GET /admin/setup/fancy/depo-job/script.sql: скрипт джобы SQL Agent для администратора. +func (h *setupHandlers) fancyDepoJobScript(w http.ResponseWriter, r *http.Request) { + s := h.rc.Snapshot().Fancy + w.Header().Set("Content-Type", "application/sql; charset=utf-8") + w.Header().Set("Content-Disposition", `attachment; filename="bj-depo-job-mssql.sql"`) + _, _ = w.Write([]byte("\uFEFF" + depoJobAgentAdminScript(s))) // SSMS без BOM читает кириллицу как ANSI +} diff --git a/internal/lkgateway/web/templates/admin_wizard.html b/internal/lkgateway/web/templates/admin_wizard.html index 74da3ea..b7b3715 100644 --- a/internal/lkgateway/web/templates/admin_wizard.html +++ b/internal/lkgateway/web/templates/admin_wizard.html @@ -190,14 +190,17 @@ a.wstep:hover .bub { box-shadow:0 0 0 4px var(--accent-weak); } +

Нет логина администратора SQL или его не хотят давать — выберите ниже «Джоба SQL Server Agent, создаёт администратор по скрипту»: тот же результат, скрипт выполняет администратор.

- +
← Назад

Проверка: bj кладёт служебное событие и ждёт до 40 секунд, пока обработка его отметит.

{{else if eq $sub "done"}} diff --git a/internal/lkgateway/web/templates/part_fancy.html b/internal/lkgateway/web/templates/part_fancy.html index d5bedfc..4466546 100644 --- a/internal/lkgateway/web/templates/part_fancy.html +++ b/internal/lkgateway/web/templates/part_fancy.html @@ -99,7 +99,8 @@
{{.DepoJob.AgentRights}}
{{else if eq .Settings.Fancy.DepoJobMode "sql-manual"}}
Инструкция для администратора SQL клиента — создать джобу (SQL Agent должен быть запущен, служебная учётная запись Agent должна иметь право выполнять процедуру): -
{{.DepoJob.AgentScript}}
+ Скачать скрипт bj-depo-job-mssql.sql +
{{.DepoJob.AdminScript}}
{{end}} {{if .Settings.Fancy.DepoJobMode}}