Исходящие: удаление черновика (кнопка в карточке и в журнале) — только в статусе 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:
@@ -0,0 +1,32 @@
|
||||
package m2mcore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMemoryDeleteDraft(t *testing.T) {
|
||||
r := NewMemoryRepository()
|
||||
ctx := context.Background()
|
||||
d := &Deal{ID: "d1", GUID: "g1", State: StateDraft}
|
||||
if _, err := r.Create(ctx, d); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s := &Deal{ID: "d2", GUID: "g2", State: StateSubmittedToNSD}
|
||||
if _, err := r.Create(ctx, s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := r.DeleteDraft(ctx, "d2"); !errors.Is(err, ErrNotDraft) {
|
||||
t.Fatalf("ушедшую в НРД удалять нельзя: %v", err)
|
||||
}
|
||||
if err := r.DeleteDraft(ctx, "d1"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := r.GetByID(ctx, "d1"); err == nil {
|
||||
t.Fatal("черновик должен быть удалён")
|
||||
}
|
||||
if _, err := r.GetByGUID(ctx, "g1"); err == nil {
|
||||
t.Fatal("черновик должен быть удалён и по GUID")
|
||||
}
|
||||
}
|
||||
@@ -299,3 +299,27 @@ func marshalXMLIfPresent(v any) ([]byte, error) {
|
||||
var (
|
||||
_ Repository = (*PostgresRepository)(nil)
|
||||
)
|
||||
|
||||
// DeleteDraft удаляет сделку в состоянии draft вместе с её событиями (одной транзакцией; состояние
|
||||
// проверяется в самом запросе — заявку, успевшую уйти в НРД, не удалить).
|
||||
func (r *PostgresRepository) DeleteDraft(ctx context.Context, id string) error {
|
||||
tx, err := r.pool.Begin(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("PostgresRepository.DeleteDraft: %w", err)
|
||||
}
|
||||
defer func() { _ = tx.Rollback(ctx) }()
|
||||
var state string
|
||||
if err := tx.QueryRow(ctx, `SELECT state FROM m2m_core.deals WHERE id=$1::uuid FOR UPDATE`, id).Scan(&state); err != nil {
|
||||
return ErrNotFound
|
||||
}
|
||||
if state != string(StateDraft) {
|
||||
return ErrNotDraft
|
||||
}
|
||||
if _, err := tx.Exec(ctx, `DELETE FROM m2m_core.deal_events WHERE deal_id=$1::uuid`, id); err != nil {
|
||||
return fmt.Errorf("PostgresRepository.DeleteDraft events: %w", err)
|
||||
}
|
||||
if _, err := tx.Exec(ctx, `DELETE FROM m2m_core.deals WHERE id=$1::uuid AND state=$2`, id, string(StateDraft)); err != nil {
|
||||
return fmt.Errorf("PostgresRepository.DeleteDraft: %w", err)
|
||||
}
|
||||
return tx.Commit(ctx)
|
||||
}
|
||||
|
||||
@@ -153,3 +153,28 @@ func (r *MemoryRepository) EventsOf(dealID string) []Event {
|
||||
copy(out, src)
|
||||
return out
|
||||
}
|
||||
|
||||
// ErrNotDraft — удалить можно только черновик (заявку, которая ещё не уходила в НРД).
|
||||
var ErrNotDraft = errors.New("m2mcore: удалить можно только черновик")
|
||||
|
||||
// DraftDeleter — хранилище умеет удалять черновики (сделка в состоянии draft вместе с событиями).
|
||||
type DraftDeleter interface {
|
||||
DeleteDraft(ctx context.Context, id string) error
|
||||
}
|
||||
|
||||
// DeleteDraft удаляет сделку, если она в состоянии draft.
|
||||
func (r *MemoryRepository) DeleteDraft(_ context.Context, id string) error {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
d, ok := r.byID[id]
|
||||
if !ok {
|
||||
return ErrNotFound
|
||||
}
|
||||
if d.State != StateDraft {
|
||||
return ErrNotDraft
|
||||
}
|
||||
delete(r.byID, id)
|
||||
delete(r.byGUID, d.GUID)
|
||||
delete(r.events, id)
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user