headless_lms_credit_registration/registry/
mod.rs1mod answers;
6mod batch;
7mod ids;
8mod requests;
9
10pub(crate) use answers::{
11 CourseCodeVerdicts, EnrolmentAnswer, EnrolmentReading, FoundPerson, HeldCredit, ImportAnswer,
12 PersonAnswer, PersonReading, RosterListing, RosterSearch, VerificationAnswer,
13 VerificationReading,
14};
15pub use answers::{PersonLookupError, RegistryPerson};
16pub(crate) use batch::{
17 AnsweredRow, BatchEntry, BatchOptions, BatchReply, BatchRequest, ExchangeAudit, RefusedFor,
18 RefusedRow,
19};
20pub(crate) use ids::{AttainmentId, CourseCode, StudentNumber, SubmittedAttainmentRef};
21pub(crate) use requests::{
22 AttainmentSubmission, Credits, EnrolmentLookup, PersonLookup, RosterCode, VerificationRequest,
23};
24
25pub(crate) use headless_lms_models::library::credit_registration::study_registry::RegistryOperation;
26use headless_lms_models::library::credit_registration::study_registry::{
27 RegistryErrorKind, RosterPerson,
28};
29
30pub(crate) trait StudyRegistry {
36 fn allowance(&self, operation: RegistryOperation) -> usize;
39
40 fn roster_request_size(&self) -> usize;
43
44 async fn resolve_persons<K>(
45 &mut self,
46 entries: Vec<BatchEntry<K, PersonLookup>>,
47 options: BatchOptions,
48 ) -> BatchReply<K, PersonLookup, PersonAnswer>;
49
50 async fn resolve_enrolments<K>(
51 &mut self,
52 entries: Vec<BatchEntry<K, EnrolmentLookup>>,
53 options: BatchOptions,
54 ) -> BatchReply<K, EnrolmentLookup, EnrolmentAnswer>;
55
56 async fn import_attainments<K>(
58 &mut self,
59 entries: Vec<BatchEntry<K, AttainmentSubmission>>,
60 options: BatchOptions,
61 ) -> BatchReply<K, AttainmentSubmission, ImportAnswer>;
62
63 async fn verify_attainments<K>(
64 &mut self,
65 entries: Vec<BatchEntry<K, VerificationRequest>>,
66 options: BatchOptions,
67 ) -> BatchReply<K, VerificationRequest, VerificationAnswer>;
68
69 async fn list_course_roster(
71 &mut self,
72 request: &[RosterCode],
73 ) -> Result<RosterListing, RegistryError>;
74
75 async fn validate_course_codes(
78 &mut self,
79 codes: &[CourseCode],
80 ) -> Result<CourseCodeVerdicts, RegistryError>;
81}
82
83pub(crate) trait InteractiveStudyRegistry {
87 async fn look_up_person(
89 &self,
90 student_number: &StudentNumber,
91 ) -> Result<Option<RegistryPerson>, PersonLookupError>;
92
93 async fn fetch_course_roster(&self, code: &CourseCode) -> Option<Vec<RosterPerson>>;
96
97 async fn search_course_rosters(
99 &self,
100 codes: &[CourseCode],
101 student_number: &StudentNumber,
102 ) -> RosterSearch;
103}
104
105pub(crate) struct RegistryError {
108 pub kind: RegistryErrorKind,
109 pub message: String,
111}
112
113impl RegistryError {
114 pub(crate) fn new(kind: RegistryErrorKind, message: impl Into<String>) -> Self {
115 Self {
116 kind,
117 message: message.into(),
118 }
119 }
120
121 pub(crate) fn blames_request_items(&self) -> bool {
124 !matches!(
125 self.kind,
126 RegistryErrorKind::NotDelivered | RegistryErrorKind::AuthenticationFailure
127 )
128 }
129}