fix: transaction-safe AcceptSuggestionWith + safe eventIds fallback + debug logging

Root cause: s.eventIds may be undefined in JavaScript even when s.events
has data (Wails v2 marshalling of []string in nested struct response).
On calling AcceptSuggestionWith(eventIDs []string), empty array reached Go,
no INSERTs executed, events silently lost.

Changes:
- Frontend: extractEventIds() fallback — s.eventIds || s.events[].id || []
- Frontend: console.log debug for eventIds/events in accept handler
- Backend: AcceptSuggestionWith wrapped in tx (Begin/Commit/Rollback) so
  entry creation + event linking is atomic
- Backend: AddWithSourceTx method for transaction-aware insert
- Backend: buildEntry helper extracted
- Backend: fmt.Printf debug logging for received eventIDs + link count
- Backend: verification query after commit
- Cleanup: removed stale frontend-dist assets, .gitignore build.log
This commit is contained in:
2026-06-03 15:10:25 +08:00
parent 7076980954
commit 21a595c3ce
26 changed files with 100 additions and 66 deletions
+37 -5
View File
@@ -116,25 +116,57 @@ func (a *App) AcceptSuggestion(nodeID, summary string, minutes int, date string,
return a.AcceptSuggestionWith(nodeID, summary, minutes, date, eventIDs)
}
// AcceptSuggestionWith creates a worklog entry and links events. Uses flat fields to avoid Wails marshalling issues.
// AcceptSuggestionWith creates a worklog entry and links events in a single transaction.
// Uses flat fields to avoid Wails marshalling issues.
func (a *App) AcceptSuggestionWith(nodeID, summary string, minutes int, date string, eventIDs []string) (*WorklogDTO, error) {
d := date
if d == "" {
d = time.Now().Format("2006-01-02")
}
entry, err := a.worklog.AddWithSource(nodeID, summary, "", d, minutes, true, false, worklog.SourceSuggestion)
// Log what we received from the frontend
fmt.Printf("DEBUG AcceptSuggestionWith: nodeID=%q summary=%q minutes=%d date=%q eventIDs=%v (len=%d)\n",
nodeID, summary, minutes, d, eventIDs, len(eventIDs))
// Use a transaction to atomically create entry + link events
tx, err := a.db.Begin()
if err != nil {
return nil, err
return nil, fmt.Errorf("begin tx: %w", err)
}
// Link activity events to this worklog entry.
defer tx.Rollback()
entry, err := a.worklog.AddWithSourceTx(tx, nodeID, summary, "", d, minutes, true, false, worklog.SourceSuggestion)
if err != nil {
return nil, fmt.Errorf("create entry: %w", err)
}
fmt.Printf("DEBUG AcceptSuggestionWith: entry created id=%s\n", entry.ID)
linked := 0
for _, eid := range eventIDs {
_, err := a.db.Exec(
res, err := tx.Exec(
`INSERT OR IGNORE INTO worklog_entry_events (entry_id, event_id) VALUES (?,?)`,
entry.ID, eid)
if err != nil {
return nil, fmt.Errorf("link event %s: %w", eid, err)
}
n, _ := res.RowsAffected()
linked += int(n)
}
fmt.Printf("DEBUG AcceptSuggestionWith: linked %d events (out of %d eventIDs)\n", linked, len(eventIDs))
if err := tx.Commit(); err != nil {
return nil, fmt.Errorf("commit tx: %w", err)
}
// Verify the links were stored
if len(eventIDs) > 0 {
var count int
a.db.QueryRow("SELECT COUNT(*) FROM worklog_entry_events WHERE entry_id = ?", entry.ID).Scan(&count)
fmt.Printf("DEBUG AcceptSuggestionWith: verification COUNT(*) = %d\n", count)
}
_ = a.sync.RecordOp(syncsvc.EntityWorklog, entry.ID, syncsvc.OpCreate, worklogPayload(entry))
mins := 0
if entry.Minutes != nil {
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -16,7 +16,7 @@
background: #13131f;
}
</style>
<script type="module" crossorigin src="/assets/main-cq32hqy7.js"></script>
<script type="module" crossorigin src="/assets/main-DQ318Oic.js"></script>
<link rel="stylesheet" crossorigin href="/assets/main-BafVhx43.css">
</head>
<body>