LP#1849212: (follow-up) fix adding an item to a course with alt call number
[Evergreen.git] / Open-ILS / src / eg2 / src / app / staff / share / course.service.ts
1 import {Observable} from 'rxjs';
2 import {tap} 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';
10
11 @Injectable()
12 export class CourseService {
13
14     constructor(
15         private auth: AuthService,
16         private evt: EventService,
17         private idl: IdlService,
18         private net: NetService,
19         private org: OrgService,
20         private pcrud: PcrudService
21     ) {}
22
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']);
27             });
28         });
29     }
30     getCourses(course_ids?: Number[]): Promise<IdlObject[]> {
31         const flesher = {flesh: 2, flesh_fields: {
32             'acmc': ['owning_lib'],
33             'aou': ['ou_type']}};
34         if (!course_ids) {
35             return this.pcrud.retrieveAll('acmc',
36                 flesher, {atomic: true}).toPromise();
37         } else {
38             return this.pcrud.search('acmc', {id: course_ids},
39                 flesher, {atomic: true}).toPromise();
40         }
41     }
42
43     getMaterials(course_ids?: Number[]): Promise<IdlObject[]> {
44         if (!course_ids) {
45             return this.pcrud.retrieveAll('acmcm',
46                 {}, {atomic: true}).toPromise();
47         } else {
48             return this.pcrud.search('acmcm', {course: course_ids},
49                 {}, {atomic: true}).toPromise();
50         }
51     }
52
53     getUsers(course_ids?: Number[]): Observable<IdlObject> {
54         const flesher = {
55             flesh: 1,
56             flesh_fields: {'acmcu': ['usr', 'usr_role']}
57         };
58         if (!course_ids) {
59             return this.pcrud.retrieveAll('acmcu',
60                 flesher);
61         } else {
62             return this.pcrud.search('acmcu', {course: course_ids},
63                 flesher);
64         }
65     }
66
67     getCoursesFromMaterial(copy_id): Promise<any> {
68         const id_list = [];
69         return new Promise((resolve, reject) => {
70
71             return this.pcrud.search('acmcm', {item: copy_id})
72             .subscribe(materials => {
73                 if (materials) {
74                     id_list.push(materials.course());
75                 }
76             }, err => {
77                 console.debug(err);
78                 reject(err);
79             }, () => {
80                 if (id_list.length) {
81                     return this.getCourses(id_list).then(courses => {
82                         resolve(courses);
83                     });
84                 }
85             });
86         });
87     }
88
89     fetchCoursesForRecord(recordId) {
90         const courseIds = new Set<number>();
91         return this.pcrud.search(
92             'acmcm', {record: recordId}, {atomic: false}
93         ).pipe(tap(material => {
94             courseIds.add(material.course());
95         })).toPromise()
96         .then(() => {
97             if (courseIds.size) {
98                 return this.getCourses(Array.from(courseIds));
99             }
100         });
101     }
102
103     // Creating a new acmcm Entry
104     associateMaterials(item, args) {
105         const material = this.idl.create('acmcm');
106         material.item(item.id());
107         if (item.call_number() && item.call_number().record()) {
108             material.record(item.call_number().record());
109         }
110         material.course(args.currentCourse.id());
111         if (args.relationship) { material.relationship(args.relationship); }
112
113         // Apply temporary fields to the item
114         if (args.isModifyingStatus && args.tempStatus) {
115             material.original_status(item.status());
116             item.status(args.tempStatus);
117         }
118         if (args.isModifyingLocation && args.tempLocation) {
119             material.original_location(item.location());
120             item.location(args.tempLocation);
121         }
122         if (args.isModifyingCircMod) {
123             material.original_circ_modifier(item.circ_modifier());
124             item.circ_modifier(args.tempCircMod);
125             if (!args.tempCircMod) { item.circ_modifier(null); }
126         }
127         if (args.isModifyingCallNumber) {
128             material.original_callnumber(item.call_number());
129         }
130         const response = {
131             item: item,
132             material: this.pcrud.create(material).toPromise()
133         };
134
135         return response;
136     }
137
138     associateUsers(patron_id, args) {
139         const new_user = this.idl.create('acmcu');
140         if (args.role) { new_user.usr_role(args.role); }
141         new_user.course(args.currentCourse.id());
142         new_user.usr(patron_id);
143         return this.pcrud.create(new_user).toPromise();
144     }
145
146     disassociateMaterials(courses) {
147         return new Promise((resolve, reject) => {
148             const course_ids = [];
149             const course_library_hash = {};
150             courses.forEach(course => {
151                 course_ids.push(course.id());
152                 course_library_hash[course.id()] = course.owning_lib();
153             });
154             this.pcrud.search('acmcm', {course: course_ids}).subscribe(material => {
155                 material.isdeleted(true);
156                 this.resetItemFields(material, course_library_hash[material.course()]);
157                 this.pcrud.autoApply(material).subscribe(() => {
158                 }, err => {
159                     reject(err);
160                 }, () => {
161                     resolve(material);
162                 });
163             }, err => {
164                 reject(err);
165             }, () => {
166                 resolve(courses);
167             });
168         });
169     }
170
171     disassociateUsers(user) {
172         return new Promise((resolve, reject) => {
173             const user_ids = [];
174             const course_library_hash = {};
175             user.forEach(course => {
176                 user_ids.push(course.id());
177                 course_library_hash[course.id()] = course.owning_lib();
178             });
179             this.pcrud.search('acmcu', {user: user_ids}).subscribe(u => {
180                 u.course(user_ids);
181                 this.pcrud.autoApply(user).subscribe(res => {
182                     console.debug(res);
183                 }, err => {
184                     reject(err);
185                 }, () => {
186                     resolve(user);
187                 });
188             }, err => {
189                 reject(err);
190             }, () => {
191                 resolve(user_ids);
192             });
193         });
194     }
195
196     resetItemFields(material, course_lib) {
197         this.pcrud.retrieve('acp', material.item(),
198             {flesh: 3, flesh_fields: {acp: ['call_number']}}).subscribe(copy => {
199             if (material.original_status()) {
200                 copy.status(material.original_status());
201             }
202             if (copy.circ_modifier() !== material.original_circ_modifier()) {
203                 copy.circ_modifier(material.original_circ_modifier());
204             }
205             if (material.original_location()) {
206                 copy.location(material.original_location());
207             }
208             if (material.original_callnumber()) {
209                 this.pcrud.retrieve('acn', material.original_callnumber()).subscribe(cn => {
210                     this.updateItem(copy, course_lib, cn.label(), true);
211                 });
212             } else {
213                 this.updateItem(copy, course_lib, copy.call_number().label(), false);
214             }
215         });
216     }
217
218
219     updateItem(item: IdlObject, courseLib, callNumber, updatingVolume) {
220         return new Promise((resolve, reject) => {
221             this.pcrud.update(item).subscribe(() => {
222                 if (updatingVolume) {
223                     const cn = item.call_number();
224                     const callNumberLibrary = this.org.canHaveVolumes(courseLib) ? courseLib.id() : cn.owning_lib();
225                     return this.net.request(
226                         'open-ils.cat', 'open-ils.cat.call_number.find_or_create',
227                         this.auth.token(), callNumber, cn.record(),
228                         callNumberLibrary, cn.prefix(), cn.suffix(),
229                         cn.label_class()
230                     ).subscribe(res => {
231                         const event = this.evt.parse(res);
232                         if (event) { return; }
233                         return this.net.request(
234                             'open-ils.cat', 'open-ils.cat.transfer_copies_to_volume',
235                             this.auth.token(), res.acn_id, [item.id()]
236                         ).subscribe(transfered_res => {
237                             console.debug('Copy transferred to volume with code ' + transfered_res);
238                         }, err => {
239                             reject(err);
240                         }, () => {
241                             resolve(item);
242                         });
243                     }, err => {
244                         reject(err);
245                     }, () => {
246                         resolve(item);
247                     });
248                 } else {
249                     this.pcrud.update(item).subscribe(() => {
250                         resolve(item);
251                     }, () => {
252                         reject(item);
253                     });
254                 }
255             });
256         });
257     }
258
259 }