1 /* eslint-disable rxjs/no-nested-subscribe */
2 import { Observable, merge, throwError } from 'rxjs';
3 import { tap, switchMap } from 'rxjs/operators';
4 import {Injectable} from '@angular/core';
5 import {AuthService} from '@eg/core/auth.service';
6 import {EventService} from '@eg/core/event.service';
7 import {IdlObject, IdlService} from '@eg/core/idl.service';
8 import {NetService} from '@eg/core/net.service';
9 import {OrgService} from '@eg/core/org.service';
10 import {PcrudService} from '@eg/core/pcrud.service';
13 export class CourseService {
16 private auth: AuthService,
17 private evt: EventService,
18 private idl: IdlService,
19 private net: NetService,
20 private org: OrgService,
21 private pcrud: PcrudService
24 isOptedIn(): Promise<any> {
25 return new Promise((resolve) => {
26 this.org.settings('circ.course_materials_opt_in').then(res => {
27 resolve(res['circ.course_materials_opt_in']);
31 getCourses(course_ids?: Number[]): Promise<IdlObject[]> {
32 const flesher = {flesh: 2, flesh_fields: {
33 'acmc': ['owning_lib'],
36 return this.pcrud.retrieveAll('acmc',
37 flesher, {atomic: true}).toPromise();
39 return this.pcrud.search('acmc', {id: course_ids},
40 flesher, {atomic: true}).toPromise();
44 getMaterials(course_ids?: Number[]): Promise<IdlObject[]> {
46 return this.pcrud.retrieveAll('acmcm',
47 {}, {atomic: true}).toPromise();
49 return this.pcrud.search('acmcm', {course: course_ids},
50 {}, {atomic: true}).toPromise();
54 getUsers(course_ids?: Number[]): Observable<IdlObject> {
57 flesh_fields: {'acmcu': ['usr', 'usr_role']}
60 return this.pcrud.retrieveAll('acmcu',
63 return this.pcrud.search('acmcu', {course: course_ids},
68 getCoursesFromMaterial(copy_id): Promise<any> {
70 return new Promise((resolve, reject) => {
72 return this.pcrud.search('acmcm', {item: copy_id})
73 .subscribe(materials => {
75 id_list.push(materials.course());
77 }, (err: unknown) => {
82 return this.getCourses(id_list).then(courses => {
90 getTermMaps(term_ids) {
91 const flesher = {flesh: 2, flesh_fields: {
92 'acmtcm': ['course']}};
95 return this.pcrud.retrieveAll('acmtcm',
98 return this.pcrud.search('acmtcm', {term: term_ids},
103 fetchCoursesForRecord(recordId) {
104 const courseIds = new Set<number>();
105 return this.pcrud.search(
106 'acmcm', {record: recordId}, {atomic: false}
107 ).pipe(tap(material => {
108 courseIds.add(material.course());
111 if (courseIds.size) {
112 return this.getCourses(Array.from(courseIds));
117 // Creating a new acmcm Entry
118 associateMaterials(item, args) {
119 const material = this.idl.create('acmcm');
120 material.item(item.id());
121 if (item.call_number() && item.call_number().record()) {
122 material.record(item.call_number().record());
124 material.course(args.currentCourse.id());
125 if (args.relationship) { material.relationship(args.relationship); }
127 // Apply temporary fields to the item
128 if (args.isModifyingStatus && args.tempStatus) {
129 material.original_status(item.status());
130 item.status(args.tempStatus);
132 if (args.isModifyingLocation && args.tempLocation) {
133 material.original_location(item.location());
134 item.location(args.tempLocation);
136 if (args.isModifyingCircMod) {
137 material.original_circ_modifier(item.circ_modifier());
138 item.circ_modifier(args.tempCircMod);
139 if (!args.tempCircMod) { item.circ_modifier(null); }
141 if (args.isModifyingCallNumber) {
142 material.original_callnumber(item.call_number());
144 if (args.isModifyingLibrary && args.tempLibrary && this.org.canHaveVolumes(args.tempLibrary)) {
145 material.original_circ_lib(item.circ_lib());
146 item.circ_lib(args.tempLibrary);
150 material: this.pcrud.create(material).toPromise()
156 associateUsers(patron_id, args) {
157 const new_user = this.idl.create('acmcu');
158 if (args.role) { new_user.usr_role(args.role); }
159 new_user.course(args.currentCourse.id());
160 new_user.usr(patron_id);
161 return this.pcrud.create(new_user).toPromise();
164 disassociateMaterials(courses) {
165 const deleteRequest$ = [];
167 return new Promise((resolve, reject) => {
168 const course_ids = [];
169 const course_library_hash = {};
170 courses.forEach(course => {
171 course_ids.push(course.id());
172 course_library_hash[course.id()] = course.owning_lib();
175 this.pcrud.search('acmcm', {course: course_ids}).subscribe(material => {
176 deleteRequest$.push(this.net.request(
177 'open-ils.courses', 'open-ils.courses.detach_material',
178 this.auth.token(), material.id()));
179 }, (err: unknown) => {
182 merge(...deleteRequest$).subscribe(val => {
184 }, (err: unknown) => {
193 detachMaterials(materials) {
194 const deleteRequest$ = [];
195 materials.forEach(material => {
196 deleteRequest$.push(this.net.request(
197 'open-ils.courses', 'open-ils.courses.detach_material',
198 this.auth.token(), material.id()));
201 return deleteRequest$;
204 disassociateUsers(user) {
205 return new Promise((resolve, reject) => {
207 const course_library_hash = {};
208 user.forEach(course => {
209 user_ids.push(course.id());
210 course_library_hash[course.id()] = course.owning_lib();
212 this.pcrud.search('acmcu', {user: user_ids}).subscribe(u => {
214 this.pcrud.autoApply(user).subscribe(res => {
216 }, (err: unknown) => {
221 }, (err: unknown) => {
229 removeNonPublicUsers(courseID: Number) {
230 return new Promise((resolve, reject) => {
231 const acmcu_ids = [];
233 this.getUsers([courseID]).subscribe(nonPublicUser => {
234 if(nonPublicUser && nonPublicUser.usr_role().is_public() !== 't') {acmcu_ids.push(nonPublicUser.id());}
235 }, (err: unknown) => {
239 if (acmcu_ids.length) {
240 this.pcrud.search('acmcu', {course: courseID, id: acmcu_ids}).subscribe(userToDelete => {
241 userToDelete.isdeleted(true);
242 this.pcrud.autoApply(userToDelete).subscribe(val => {
243 console.debug('deleted: ' + val);
244 }, (err: unknown) => {
245 console.log('Error: ' + err);
248 console.log('Resolving');
249 resolve(userToDelete);
258 updateItem(item: IdlObject, courseLib: IdlObject, callNumber: string, updatingVolume: boolean) {
259 const cn = item.call_number();
261 const itemObservable = this.pcrud.update(item);
262 const callNumberObservable = this.net.request(
263 'open-ils.cat', 'open-ils.cat.call_number.find_or_create',
264 this.auth.token(), callNumber, cn.record(),
265 cn.owning_lib(), cn.prefix(), cn.suffix(),
267 ).pipe(switchMap(res => {
268 const event = this.evt.parse(res);
269 if (event) { return throwError(event); }
270 // Not using open-ils.cat.transfer_copies_to_volume,
271 // because we don't necessarily want acp.circ_lib and
272 // acn.owning_lib to match in this scenario
273 item.call_number(res.acn_id);
274 return this.pcrud.update(item);
277 return updatingVolume ? itemObservable.pipe(switchMap(() => callNumberObservable)).toPromise() :
278 itemObservable.toPromise();