1 import { Observable, merge, throwError } from 'rxjs';
2 import { tap, switchMap } from 'rxjs/operators';
3 import {Injectable} from '@angular/core';
4 import {AuthService} from '@eg/core/auth.service';
5 import {EventService} from '@eg/core/event.service';
6 import {IdlObject, IdlService} from '@eg/core/idl.service';
7 import {NetService} from '@eg/core/net.service';
8 import {OrgService} from '@eg/core/org.service';
9 import {PcrudService} from '@eg/core/pcrud.service';
12 export class CourseService {
15 private auth: AuthService,
16 private evt: EventService,
17 private idl: IdlService,
18 private net: NetService,
19 private org: OrgService,
20 private pcrud: PcrudService
23 isOptedIn(): Promise<any> {
24 return new Promise((resolve) => {
25 this.org.settings('circ.course_materials_opt_in').then(res => {
26 resolve(res['circ.course_materials_opt_in']);
30 getCourses(course_ids?: Number[]): Promise<IdlObject[]> {
31 const flesher = {flesh: 2, flesh_fields: {
32 'acmc': ['owning_lib'],
35 return this.pcrud.retrieveAll('acmc',
36 flesher, {atomic: true}).toPromise();
38 return this.pcrud.search('acmc', {id: course_ids},
39 flesher, {atomic: true}).toPromise();
43 getMaterials(course_ids?: Number[]): Promise<IdlObject[]> {
45 return this.pcrud.retrieveAll('acmcm',
46 {}, {atomic: true}).toPromise();
48 return this.pcrud.search('acmcm', {course: course_ids},
49 {}, {atomic: true}).toPromise();
53 getUsers(course_ids?: Number[]): Observable<IdlObject> {
56 flesh_fields: {'acmcu': ['usr', 'usr_role']}
59 return this.pcrud.retrieveAll('acmcu',
62 return this.pcrud.search('acmcu', {course: course_ids},
67 getCoursesFromMaterial(copy_id): Promise<any> {
69 return new Promise((resolve, reject) => {
71 return this.pcrud.search('acmcm', {item: copy_id})
72 .subscribe(materials => {
74 id_list.push(materials.course());
81 return this.getCourses(id_list).then(courses => {
89 getTermMaps(term_ids) {
90 const flesher = {flesh: 2, flesh_fields: {
91 'acmtcm': ['course']}};
94 return this.pcrud.retrieveAll('acmtcm',
97 return this.pcrud.search('acmtcm', {term: term_ids},
102 fetchCoursesForRecord(recordId) {
103 const courseIds = new Set<number>();
104 return this.pcrud.search(
105 'acmcm', {record: recordId}, {atomic: false}
106 ).pipe(tap(material => {
107 courseIds.add(material.course());
110 if (courseIds.size) {
111 return this.getCourses(Array.from(courseIds));
116 // Creating a new acmcm Entry
117 associateMaterials(item, args) {
118 const material = this.idl.create('acmcm');
119 material.item(item.id());
120 if (item.call_number() && item.call_number().record()) {
121 material.record(item.call_number().record());
123 material.course(args.currentCourse.id());
124 if (args.relationship) { material.relationship(args.relationship); }
126 // Apply temporary fields to the item
127 if (args.isModifyingStatus && args.tempStatus) {
128 material.original_status(item.status());
129 item.status(args.tempStatus);
131 if (args.isModifyingLocation && args.tempLocation) {
132 material.original_location(item.location());
133 item.location(args.tempLocation);
135 if (args.isModifyingCircMod) {
136 material.original_circ_modifier(item.circ_modifier());
137 item.circ_modifier(args.tempCircMod);
138 if (!args.tempCircMod) { item.circ_modifier(null); }
140 if (args.isModifyingCallNumber) {
141 material.original_callnumber(item.call_number());
143 if (args.isModifyingLibrary && args.tempLibrary && this.org.canHaveVolumes(args.tempLibrary)) {
144 material.original_circ_lib(item.circ_lib());
145 item.circ_lib(args.tempLibrary);
149 material: this.pcrud.create(material).toPromise()
155 associateUsers(patron_id, args) {
156 const new_user = this.idl.create('acmcu');
157 if (args.role) { new_user.usr_role(args.role); }
158 new_user.course(args.currentCourse.id());
159 new_user.usr(patron_id);
160 return this.pcrud.create(new_user).toPromise();
163 disassociateMaterials(courses) {
164 const deleteRequest$ = [];
166 return new Promise((resolve, reject) => {
167 const course_ids = [];
168 const course_library_hash = {};
169 courses.forEach(course => {
170 course_ids.push(course.id());
171 course_library_hash[course.id()] = course.owning_lib();
174 this.pcrud.search('acmcm', {course: course_ids}).subscribe(material => {
175 deleteRequest$.push(this.net.request(
176 'open-ils.courses', 'open-ils.courses.detach_material',
177 this.auth.token(), material.id()));
181 merge(...deleteRequest$).subscribe(val => {
192 detachMaterials(materials) {
193 const deleteRequest$ = [];
194 materials.forEach(material => {
195 deleteRequest$.push(this.net.request(
196 'open-ils.courses', 'open-ils.courses.detach_material',
197 this.auth.token(), material.id()));
200 return deleteRequest$;
203 disassociateUsers(user) {
204 return new Promise((resolve, reject) => {
206 const course_library_hash = {};
207 user.forEach(course => {
208 user_ids.push(course.id());
209 course_library_hash[course.id()] = course.owning_lib();
211 this.pcrud.search('acmcu', {user: user_ids}).subscribe(u => {
213 this.pcrud.autoApply(user).subscribe(res => {
229 updateItem(item: IdlObject, courseLib: IdlObject, callNumber: string, updatingVolume: boolean) {
230 const cn = item.call_number();
232 const itemObservable = this.pcrud.update(item);
233 const callNumberObservable = this.net.request(
234 'open-ils.cat', 'open-ils.cat.call_number.find_or_create',
235 this.auth.token(), callNumber, cn.record(),
236 cn.owning_lib(), cn.prefix(), cn.suffix(),
238 ).pipe(switchMap(res => {
239 const event = this.evt.parse(res);
240 if (event) { return throwError(event); }
241 // Not using open-ils.cat.transfer_copies_to_volume,
242 // because we don't necessarily want acp.circ_lib and
243 // acn.owning_lib to match in this scenario
244 item.call_number(res.acn_id)
245 return this.pcrud.update(item);
248 return updatingVolume ? itemObservable.pipe(switchMap(() => callNumberObservable)).toPromise() :
249 itemObservable.toPromise();