Исходящие: удаление черновика (кнопка в карточке и в журнале) — только в статусе draft, с снятием поручения QUIK МНП, если бумаги заблокированы

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
zuevav
2026-09-25 15:22:08 +03:00
parent 4b81862a90
commit 16bfedb85f
6 changed files with 140 additions and 3 deletions
+56 -1
View File
@@ -6,7 +6,9 @@ import (
"encoding/json"
"fmt"
"html/template"
"log"
"net/http"
"net/url"
"path"
"strings"
"time"
@@ -392,6 +394,7 @@ type homeData struct {
type claimsData struct {
page
Items []ClaimView
Flash string
}
// claimData — данные карточки.
@@ -442,6 +445,9 @@ func RegisterAdmin(mux *http.ServeMux, svc *Service, rc *RuntimeConfig, getOpts
case strings.HasPrefix(p, "claims/") && strings.HasSuffix(p, "/export.zip"):
id := strings.TrimSuffix(strings.TrimPrefix(p, "claims/"), "/export.zip")
a.exportClaim(w, r, svc, id)
case strings.HasPrefix(p, "claims/") && strings.HasSuffix(p, "/delete-draft"):
id := strings.TrimSuffix(strings.TrimPrefix(p, "claims/"), "/delete-draft")
a.deleteDraft(w, r, svc, id)
case strings.HasPrefix(p, "claims/"):
id := strings.TrimPrefix(p, "claims/")
a.renderClaim(w, r, svc, id)
@@ -527,7 +533,56 @@ func (a *admin) renderClaims(w http.ResponseWriter, r *http.Request, svc *Servic
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
render(w, a.claims, claimsData{page: nowPage("Заявки", "claims"), Items: pageData.Items})
render(w, a.claims, claimsData{page: nowPage("Заявки", "claims"), Items: pageData.Items, Flash: r.URL.Query().Get("flash")})
}
// deleteDraft — POST /admin/claims/{id}/delete-draft: удалить черновик (заявка ещё не уходила в НРД).
// Если по нему бумаги уже заблокированы в QUIK МНП — сначала поручение снимается.
func (a *admin) deleteDraft(w http.ResponseWriter, r *http.Request, svc *Service, id string) {
if r.Method != http.MethodPost {
http.Error(w, "method", http.StatusMethodNotAllowed)
return
}
id = path.Base(id)
back := func(to, msg string) { http.Redirect(w, r, to+"?flash="+url.QueryEscape(msg), http.StatusSeeOther) }
d, err := svc.Repo().GetByID(r.Context(), id)
if err != nil {
back("/admin/claims", "Заявка не найдена")
return
}
if d.State != m2mcore.StateDraft {
back("/admin/claims/"+id, "Удалить можно только черновик: эта заявка уже ушла в НРД")
return
}
dd, ok := svc.Repo().(m2mcore.DraftDeleter)
if !ok {
back("/admin/claims/"+id, "Хранилище заявок не поддерживает удаление")
return
}
var notes []string
for _, l := range globalQuikLinks.ForGUID(string(d.GUID)) {
if l.State == "registered" && globalRC != nil {
if _, err := QuikOutDeny(r.Context(), globalRC, l.GUID, l.ISIN, "черновик удалён оператором"); err != nil {
back("/admin/claims/"+id, "Черновик не удалён: не удалось снять поручение в QUIK МНП по "+l.ISIN+" — "+err.Error())
return
}
notes = append(notes, "поручение QUIK по "+l.ISIN+" снято")
}
}
if err := dd.DeleteDraft(r.Context(), id); err != nil {
back("/admin/claims/"+id, "Черновик не удалён: "+err.Error())
return
}
actor := ""
if u := currentUser(w); u != nil {
actor = u.Login
}
log.Printf("admin: черновик %s (GUID %s) удалён %s; %s", id, d.GUID, actor, strings.Join(notes, "; "))
msg := "Черновик " + id[:8] + " удалён"
if len(notes) > 0 {
msg += ": " + strings.Join(notes, "; ")
}
back("/admin/claims", msg)
}
func (a *admin) renderClaim(w http.ResponseWriter, r *http.Request, svc *Service, id string) {