671 {
672 if (new_status != "COMPLETED" && new_status != "DISCONTINUED" &&
673 new_status != "IN PROGRESS") {
674 return make_error<std::monostate>(
675 -1,
676 "Invalid status. Must be 'IN PROGRESS', 'COMPLETED', or "
677 "'DISCONTINUED'",
678 "storage");
679 }
680
682 if (!current.has_value()) {
683 return make_error<std::monostate>(-1, "MPPS not found", "storage");
684 }
685
686 if (current->status == "COMPLETED" || current->status == "DISCONTINUED") {
687 return make_error<std::monostate>(
688 -1,
689 kcenon::pacs::compat::format(
690 "Cannot update MPPS in final state '{}'. COMPLETED and "
691 "DISCONTINUED are final states.",
692 current->status),
693 "storage");
694 }
695
696 const char* sql = R"(
697 UPDATE mpps
698 SET status = ?,
699 end_datetime = CASE WHEN ? != '' THEN ? ELSE end_datetime END,
700 performed_series = CASE WHEN ? != '' THEN ? ELSE performed_series END,
701 updated_at = datetime('now')
702 WHERE mpps_uid = ?;
703 )";
704
705 sqlite3_stmt* stmt = nullptr;
706 auto rc = sqlite3_prepare_v2(
db_, sql, -1, &stmt,
nullptr);
707 if (rc != SQLITE_OK) {
708 return make_error<std::monostate>(
709 rc,
710 kcenon::pacs::compat::format("Failed to prepare statement: {}",
711 sqlite3_errmsg(
db_)),
712 "storage");
713 }
714
715 sqlite3_bind_text(stmt, 1, new_status.data(),
716 static_cast<int>(new_status.size()), SQLITE_TRANSIENT);
717 sqlite3_bind_text(stmt, 2, end_datetime.data(),
718 static_cast<int>(end_datetime.size()), SQLITE_TRANSIENT);
719 sqlite3_bind_text(stmt, 3, end_datetime.data(),
720 static_cast<int>(end_datetime.size()), SQLITE_TRANSIENT);
721 sqlite3_bind_text(stmt, 4, performed_series.data(),
722 static_cast<int>(performed_series.size()),
723 SQLITE_TRANSIENT);
724 sqlite3_bind_text(stmt, 5, performed_series.data(),
725 static_cast<int>(performed_series.size()),
726 SQLITE_TRANSIENT);
727 sqlite3_bind_text(stmt, 6, mpps_uid.data(),
728 static_cast<int>(mpps_uid.size()), SQLITE_TRANSIENT);
729
730 rc = sqlite3_step(stmt);
731 sqlite3_finalize(stmt);
732
733 if (rc != SQLITE_DONE) {
734 return make_error<std::monostate>(
735 rc,
736 kcenon::pacs::compat::format("Failed to update MPPS: {}",
737 sqlite3_errmsg(
db_)),
738 "storage");
739 }
740
741 return ok();
742}
auto find_mpps(std::string_view mpps_uid) const -> std::optional< mpps_record >