DEPO: справочник участников снова записывается на бою; GUID событий — NULL
На 9 (FTV_DE_DATA) FTV_M2M_EVENTS.GUID NOT NULL (создано bj раньше), событие HANDBOOK без GUID падало и откатывало всю транзакцию — справочник в DEPO не обновлялся (с 11:50 при каждом справочнике). Теперь справочник пишется в своей транзакции, событие — отдельно (не записалось — предупреждение). Структура: GUID в FTV_M2M_EVENTS — NULL (как на тесте с 12.10); для существующих таблиц — ALTER COLUMN в наборе скриптов с правами администратора (плашка обновления, скрипт .sql). Проверено на тесте (BJ2_DEPO_DATA, транзакция с откатом). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
This commit is contained in:
@@ -87,9 +87,20 @@ func depoProcOrderText(sep string) string {
|
|||||||
return strings.Join(parts, sep)
|
return strings.Join(parts, sep)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// depoSchemaFixes — правки структуры трансферных таблиц, которые логин bj сделать не может (нужны права
|
||||||
|
// администратора БД); выполняются вместе с процедурами. Повторный запуск безопасен.
|
||||||
|
var depoSchemaFixes = []struct{ Name, SQL string }{
|
||||||
|
// 22.10.2026: служебные события (HANDBOOK) — без GUID; в таблицах, созданных bj до этого, GUID NOT NULL
|
||||||
|
{"FTV_M2M_EVENTS.GUID NULL", `IF EXISTS (SELECT 1 FROM sys.columns WHERE object_id=OBJECT_ID(N'dbo.FTV_M2M_EVENTS') AND name=N'GUID' AND is_nullable=0)
|
||||||
|
ALTER TABLE dbo.FTV_M2M_EVENTS ALTER COLUMN GUID uniqueidentifier NULL`},
|
||||||
|
}
|
||||||
|
|
||||||
// depoProcsHash — отпечаток набора процедур, который bj установит (с учётом правки под клиента).
|
// depoProcsHash — отпечаток набора процедур, который bj установит (с учётом правки под клиента).
|
||||||
func depoProcsHash(f FancyMSSQLSettings) string {
|
func depoProcsHash(f FancyMSSQLSettings) string {
|
||||||
h := sha256.New()
|
h := sha256.New()
|
||||||
|
for _, fx := range depoSchemaFixes {
|
||||||
|
h.Write([]byte(fx.Name + "\n" + fx.SQL + "\n"))
|
||||||
|
}
|
||||||
for _, p := range depoProcInstallOrder {
|
for _, p := range depoProcInstallOrder {
|
||||||
h.Write([]byte(p.Name + "\n" + strings.TrimSpace(depoProcEffective(f, p.Name)) + "\n"))
|
h.Write([]byte(p.Name + "\n" + strings.TrimSpace(depoProcEffective(f, p.Name)) + "\n"))
|
||||||
}
|
}
|
||||||
@@ -125,6 +136,9 @@ func depoProcsScriptFor(f FancyMSSQLSettings, db, login string) string {
|
|||||||
b.WriteString(" Порядок " + depoProcOrderText(" -> ") + ". Запуск под sysadmin в SSMS.\n")
|
b.WriteString(" Порядок " + depoProcOrderText(" -> ") + ". Запуск под sysadmin в SSMS.\n")
|
||||||
b.WriteString(" CREATE OR ALTER — повторный запуск безопасен (данные не меняются). */\n")
|
b.WriteString(" CREATE OR ALTER — повторный запуск безопасен (данные не меняются). */\n")
|
||||||
fmt.Fprintf(&b, "USE %s;\nGO\n\n", quoteIdent(db))
|
fmt.Fprintf(&b, "USE %s;\nGO\n\n", quoteIdent(db))
|
||||||
|
for _, fx := range depoSchemaFixes {
|
||||||
|
fmt.Fprintf(&b, "/* ===== структура: %s ===== */\n%s;\nGO\n\n", fx.Name, fx.SQL)
|
||||||
|
}
|
||||||
for _, p := range depoProcInstallOrder {
|
for _, p := range depoProcInstallOrder {
|
||||||
body := depoProcEffective(f, p.Name)
|
body := depoProcEffective(f, p.Name)
|
||||||
if strings.TrimSpace(body) == "" {
|
if strings.TrimSpace(body) == "" {
|
||||||
@@ -150,6 +164,11 @@ func depoProcsInstallInto(ctx context.Context, adm, f FancyMSSQLSettings, dbName
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
for _, fx := range depoSchemaFixes {
|
||||||
|
if _, err := db.ExecContext(ctx, fx.SQL); err != nil {
|
||||||
|
return fmt.Errorf("структура таблиц (%s): %s", fx.Name, quikErrorDetail(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
for _, p := range depoProcInstallOrder {
|
for _, p := range depoProcInstallOrder {
|
||||||
body := depoProcEffective(f, p.Name)
|
body := depoProcEffective(f, p.Name)
|
||||||
if strings.TrimSpace(body) == "" {
|
if strings.TrimSpace(body) == "" {
|
||||||
|
|||||||
@@ -698,16 +698,17 @@ func depoWriteHandbookCtx(pctx context.Context, rc *RuntimeConfig) error {
|
|||||||
}
|
}
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
// Сигнал Fancy, что справочник обновился: событие HANDBOOK в FTV_M2M_EVENTS (в той же
|
|
||||||
// транзакции, что и перезапись таблицы) — по нему джоба bj2depo может перечитать справочник.
|
|
||||||
if _, err := tx.ExecContext(ctx, fsql.QEv10); err != nil {
|
|
||||||
tx.Rollback()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := tx.Commit(); err != nil {
|
if err := tx.Commit(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
depoHandbookWritten = time.Now()
|
depoHandbookWritten = time.Now()
|
||||||
|
// Сигнал Fancy, что справочник обновился: событие HANDBOOK в FTV_M2M_EVENTS — по нему джоба bj2depo
|
||||||
|
// переносит справочник в юрлица Fancy (FTV_M2M_UPDATE_HANDBOOK). Отдельно от записи справочника: не
|
||||||
|
// записалось (в старой таблице GUID NOT NULL) — справочник всё равно в DEPO, а событие ждёт скриптов.
|
||||||
|
if _, err := db.ExecContext(ctx, fsql.QEv10); err != nil {
|
||||||
|
log.Printf("depo-events: справочник записан в FTV_M2M_HANDBOOK (%d строк), но событие HANDBOOK — нет: %v — примените скрипты DEPO (плашка «Обновление bj требует применить скрипты»)", n, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
log.Printf("depo-events: справочник участников записан в FTV_M2M_HANDBOOK: %d строк + событие HANDBOOK", n)
|
log.Printf("depo-events: справочник участников записан в FTV_M2M_HANDBOOK: %d строк + событие HANDBOOK", n)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ var depoTableSpecs = []depoTableSpec{
|
|||||||
depoColComment,
|
depoColComment,
|
||||||
}, Indexes: [][]string{{"GUID"}}},
|
}, Indexes: [][]string{{"GUID"}}},
|
||||||
{Name: "FTV_M2M_EVENTS", Cols: []depoCol{
|
{Name: "FTV_M2M_EVENTS", Cols: []depoCol{
|
||||||
depoColGUID,
|
depoNull("GUID", "uniqueidentifier", "uuid"), // NULL — служебные события без перевода (HANDBOOK), как в DEPO Фонтвьель с 12.10.2026
|
||||||
depoNull("REFERENCE", "varchar(36)", "varchar(36)"),
|
depoNull("REFERENCE", "varchar(36)", "varchar(36)"),
|
||||||
depoColState, depoColTimeNew, depoColTimeBeg, depoColTimeEnd, depoColComment,
|
depoColState, depoColTimeNew, depoColTimeBeg, depoColTimeEnd, depoColComment,
|
||||||
depoNotNull("EVENT_TYPE", "varchar(64)", "varchar(64)"),
|
depoNotNull("EVENT_TYPE", "varchar(64)", "varchar(64)"),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{{define "depoProcsBanner"}}{{if and (can "settings") depoProcsPending}}<div class="card" id="depo-procs-pending" style="border-color:var(--warn);background:var(--warn-weak)">
|
{{define "depoProcsBanner"}}{{if and (can "settings") depoProcsPending}}<div class="card" id="depo-procs-pending" style="border-color:var(--warn);background:var(--warn-weak)">
|
||||||
<h2 style="margin:0 0 6px">Обновление bj требует применить скрипты в базе DEPO</h2>
|
<h2 style="margin:0 0 6px">Обновление bj требует применить скрипты в базе DEPO</h2>
|
||||||
<p style="margin:0 0 8px">В этой версии bj обновлены процедуры обработки M2M в DEPO ({{depoProcOrder}}). Для их установки нужны <b>повышенные права на базу данных</b>: введите логин и пароль администратора SQL (sysadmin, обычно sa). Они используются один раз и не сохраняются.</p>
|
<p style="margin:0 0 8px">В этой версии bj обновлены процедуры обработки M2M в DEPO ({{depoProcOrder}}) и структура трансферных таблиц (FTV_M2M_EVENTS.GUID — NULL для событий справочника). Для их установки нужны <b>повышенные права на базу данных</b>: введите логин и пароль администратора SQL (sysadmin, обычно sa). Они используются один раз и не сохраняются.</p>
|
||||||
<form method="post" action="/admin/setup/fancy/depo-procs/install" style="display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end" onsubmit="return confirm('Применить обновлённые процедуры в базе DEPO? CREATE OR ALTER — данные не меняются.')">
|
<form method="post" action="/admin/setup/fancy/depo-procs/install" style="display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end" onsubmit="return confirm('Применить обновлённые процедуры в базе DEPO? CREATE OR ALTER — данные не меняются.')">
|
||||||
<input type="hidden" name="section" value="sec-fancy-depo-procs">
|
<input type="hidden" name="section" value="sec-fancy-depo-procs">
|
||||||
<label style="display:flex;flex-direction:column;gap:3px">Логин администратора SQL<input type="text" name="admin_user" autocomplete="off" placeholder="sa" required></label>
|
<label style="display:flex;flex-direction:column;gap:3px">Логин администратора SQL<input type="text" name="admin_user" autocomplete="off" placeholder="sa" required></label>
|
||||||
|
|||||||
Reference in New Issue
Block a user