866 {
867 if (workitem.workitem_uid.empty()) {
868 return make_error<int64_t>(-1, "UPS workitem UID is required",
869 "storage");
870 }
871
872 const char* sql = R"(
873 INSERT INTO ups_workitems (
874 workitem_uid, state, procedure_step_label, worklist_label,
875 priority, scheduled_start_datetime, expected_completion_datetime,
876 scheduled_station_name, scheduled_station_class,
877 scheduled_station_geographic, scheduled_human_performers,
878 input_information, performing_ae, progress_description,
879 progress_percent, output_information, transaction_uid,
880 updated_at
881 ) VALUES (?, 'SCHEDULED', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))
882 RETURNING workitem_pk;
883 )";
884
885 sqlite3_stmt* stmt = nullptr;
886 auto rc = sqlite3_prepare_v2(
db_, sql, -1, &stmt,
nullptr);
887 if (rc != SQLITE_OK) {
888 return make_error<int64_t>(
889 rc,
890 kcenon::pacs::compat::format("Failed to prepare UPS insert: {}",
891 sqlite3_errmsg(
db_)),
892 "storage");
893 }
894
895 sqlite3_bind_text(stmt, 1, workitem.workitem_uid.c_str(), -1,
896 SQLITE_TRANSIENT);
897 sqlite3_bind_text(stmt, 2, workitem.procedure_step_label.c_str(), -1,
898 SQLITE_TRANSIENT);
899 sqlite3_bind_text(stmt, 3, workitem.worklist_label.c_str(), -1,
900 SQLITE_TRANSIENT);
901 sqlite3_bind_text(
902 stmt, 4,
903 workitem.priority.empty() ? "MEDIUM" : workitem.priority.c_str(), -1,
904 SQLITE_TRANSIENT);
905 sqlite3_bind_text(stmt, 5, workitem.scheduled_start_datetime.c_str(), -1,
906 SQLITE_TRANSIENT);
907 sqlite3_bind_text(stmt, 6,
908 workitem.expected_completion_datetime.c_str(), -1,
909 SQLITE_TRANSIENT);
910 sqlite3_bind_text(stmt, 7, workitem.scheduled_station_name.c_str(), -1,
911 SQLITE_TRANSIENT);
912 sqlite3_bind_text(stmt, 8, workitem.scheduled_station_class.c_str(), -1,
913 SQLITE_TRANSIENT);
914 sqlite3_bind_text(stmt, 9,
915 workitem.scheduled_station_geographic.c_str(), -1,
916 SQLITE_TRANSIENT);
917 sqlite3_bind_text(stmt, 10,
918 workitem.scheduled_human_performers.c_str(), -1,
919 SQLITE_TRANSIENT);
920 sqlite3_bind_text(stmt, 11, workitem.input_information.c_str(), -1,
921 SQLITE_TRANSIENT);
922 sqlite3_bind_text(stmt, 12, workitem.performing_ae.c_str(), -1,
923 SQLITE_TRANSIENT);
924 sqlite3_bind_text(stmt, 13, workitem.progress_description.c_str(), -1,
925 SQLITE_TRANSIENT);
926 sqlite3_bind_int(stmt, 14, workitem.progress_percent);
927 sqlite3_bind_text(stmt, 15, workitem.output_information.c_str(), -1,
928 SQLITE_TRANSIENT);
929 sqlite3_bind_text(stmt, 16, workitem.transaction_uid.c_str(), -1,
930 SQLITE_TRANSIENT);
931
932 rc = sqlite3_step(stmt);
933 if (rc != SQLITE_ROW) {
934 auto error_msg = sqlite3_errmsg(
db_);
935 sqlite3_finalize(stmt);
936 return make_error<int64_t>(
937 rc,
938 kcenon::pacs::compat::format("Failed to create UPS workitem: {}",
939 error_msg),
940 "storage");
941 }
942
943 auto pk = sqlite3_column_int64(stmt, 0);
944 sqlite3_finalize(stmt);
945 return pk;
946}