From: Kyle Huckins Date: Sun, 13 Mar 2022 09:15:38 +0000 (+0000) Subject: lp1922388 Academic Departments X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=refs%2Fheads%2Fuser%2Fkhuckins%2Flp1922388-course-academic-departments-submodule;p=working%2FEvergreen.git lp1922388 Academic Departments - Add DB and IDL structure for Academic Departments, Department Contacts, and Course/Department Map - Add Departments to Course List - Add Edit page for Departments similar to Course Edit Page, including Department Contacts Tab Signed-off-by: Kyle Huckins Changes to be committed: modified: Open-ILS/examples/fm_IDL.xml new file: Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list-department.component.html new file: Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list-department.component.ts modified: Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.html modified: Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.ts modified: Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-reserves.module.ts new file: Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/department-contact-grid.component.html new file: Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/department-contact-grid.component.ts new file: Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/department-page.component.html new file: Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/department-page.component.ts modified: Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/routing.module.ts modified: Open-ILS/src/eg2/src/app/staff/share/course.service.ts modified: Open-ILS/src/sql/Pg/040.schema.asset.sql modified: Open-ILS/src/sql/Pg/950.data.seed-values.sql new file: Open-ILS/src/sql/Pg/upgrade/xxxx.schema.lp1922388-academic-departments.sql --- diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index 6d8199f011..08d3c043aa 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -3253,16 +3253,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + + + @@ -3401,6 +3405,84 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list-department.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list-department.component.html new file mode 100644 index 0000000000..dd5f03423b --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list-department.component.html @@ -0,0 +1,29 @@ + +
+
+ + +
+
+
+ +
+ + + + + + + + + + +
+
\ No newline at end of file diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list-department.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list-department.component.ts new file mode 100644 index 0000000000..e47f20c5f2 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list-department.component.ts @@ -0,0 +1,167 @@ +import {Component, Input, ViewChild, OnInit, AfterViewInit} from '@angular/core'; +import {Router} from '@angular/router'; +import {IdlObject, IdlService} from '@eg/core/idl.service'; +import {PcrudService} from '@eg/core/pcrud.service'; +import {CourseService} from '@eg/staff/share/course.service'; +import {GridComponent} from '@eg/share/grid/grid.component'; +import {Pager} from '@eg/share/util/pager'; +import {GridDataSource, GridColumn} from '@eg/share/grid/grid'; +import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component'; +import {StringComponent} from '@eg/share/string/string.component'; +import {ToastService} from '@eg/share/toast/toast.service'; +import {LocaleService} from '@eg/core/locale.service'; +import {AuthService} from '@eg/core/auth.service'; +import {OrgService} from '@eg/core/org.service'; +import {OrgFamily} from '@eg/share/org-family-select/org-family-select.component'; + +import {DepartmentContactGridComponent + } from './department-contact-grid.component'; + +@Component({ + selector: 'eg-department-list', + templateUrl: './course-list-department.component.html' +}) + +export class DepartmentListComponent implements OnInit, AfterViewInit { + + @ViewChild('editDialog', { static: true }) editDialog: FmRecordEditorComponent; + @ViewChild('grid') grid: GridComponent; + @ViewChild('successString', { static: true }) successString: StringComponent; + @ViewChild('createString') createString: StringComponent; + @ViewChild('createErrString') createErrString: StringComponent; + @ViewChild('updateFailedString') updateFailedString: StringComponent; + @ViewChild('deleteFailedString', { static: true }) deleteFailedString: StringComponent; + @ViewChild('deleteSuccessString', { static: true }) deleteSuccessString: StringComponent; + @ViewChild('departmentContactGrid', {static: true}) + private departmentContactGrid: DepartmentContactGridComponent; + + @Input() sortField: string; + @Input() idlClass = 'acmd'; + @Input() dialog_size: 'sm' | 'lg' = 'lg'; + @Input() tableName = 'Academic Department'; + grid_source: GridDataSource = new GridDataSource(); + search_value = ''; + defaultOuId: number; + searchOrgs: OrgFamily; + + + constructor( + private courseSvc: CourseService, + private locale: LocaleService, + private auth: AuthService, + private idl: IdlService, + private org: OrgService, + private pcrud: PcrudService, + private router: Router, + private toast: ToastService + ) {} + + ngOnInit() { + this.getSource(); + this.defaultOuId = this.auth.user().ws_ou() || this.org.root().id(); + this.searchOrgs = {primaryOrgId: this.defaultOuId}; + } + + ngAfterViewInit() { + this.grid.onRowActivate.subscribe((department: IdlObject) => { + const idToEdit = department.id(); + this.navigateToDepartmentPage(idToEdit); + }); + + } + + /** + * Gets the data, specified by the class, that is available. + */ + getSource() { + this.grid_source.getRows = (pager: Pager, sort: any[]) => { + const orderBy: any = {}; + if (sort.length) { + // Sort specified from grid + orderBy[this.idlClass] = sort[0].name + ' ' + sort[0].dir; + } else if (this.sortField) { + // Default sort field + orderBy[this.idlClass] = this.sortField; + } + const search: any = new Array(); + const orgFilter: any = {}; + orgFilter['owning_lib'] = + this.searchOrgs.orgIds || [this.defaultOuId]; + search.push(orgFilter); + const searchOps = { + offset: pager.offset, + limit: pager.limit, + order_by: orderBy + }; + return this.pcrud.search(this.idlClass, search, searchOps, {fleshSelectors: true}); + }; + } + + navigateToDepartmentPage(id_arr: IdlObject[]) { + if (typeof id_arr === 'number') { id_arr = [id_arr]; } + const urls = []; + id_arr.forEach(id => {console.log(this.router.url); + urls.push([this.locale.currentLocaleCode() + this.router.url + '/' + id]); + }); + if (id_arr.length === 1) { + this.router.navigate([this.router.url + '/department/' + id_arr[0]]); + } else { + urls.forEach(url => { + window.open(url); + }); + } + } + + createNew() { + this.editDialog.mode = 'create'; + const course_module_department = this.idl.create('acmd'); + course_module_department.owning_lib(this.auth.user().ws_ou()); + this.editDialog.recordId = null; + this.editDialog.record = course_module_department; + this.editDialog.open({size: this.dialog_size}).subscribe( + ok => { + this.createString.current() + .then(str => this.toast.success(str)); + this.grid.reload(); + }, + rejection => { + if (!rejection.dismissed) { + this.createErrString.current() + .then(str => this.toast.danger(str)); + } + } + ); + } + + editSelected(fields: IdlObject[]) { + // Edit each IDL thing one at a time + const department_ids = []; + fields.forEach(field => { + if (typeof field['id'] === 'function') { + department_ids.push(field.id()); + } else { + department_ids.push(field['id']); + } + }); + this.navigateToDepartmentPage(department_ids); + } + + deleteSelected(idlObject: IdlObject[]) { + idlObject.forEach(object => { + object.isdeleted(true); + }); + this.pcrud.autoApply(idlObject).subscribe( + val => { + console.debug('deleted: ' + val); + this.deleteSuccessString.current() + .then(str => this.toast.success(str)); + }, + err => { + this.deleteFailedString.current() + .then(str => this.toast.danger(str)); + }, + () => this.grid.reload() + ); + } +} + diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.html index 6fb0972429..84edd676e8 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.html +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.html @@ -60,6 +60,12 @@ +
  • + Departments + + + +
  • diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.ts index 2ba9d400b9..78f6355438 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-list.component.ts @@ -14,6 +14,9 @@ import {AuthService} from '@eg/core/auth.service'; import {OrgService} from '@eg/core/org.service'; import {OrgFamily} from '@eg/share/org-family-select/org-family-select.component'; +import {DepartmentListComponent + } from './course-list-department.component'; + import {CourseAssociateMaterialComponent } from './course-associate-material.component'; diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-reserves.module.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-reserves.module.ts index 149a39aa53..70833283e6 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-reserves.module.ts +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/course-reserves.module.ts @@ -12,6 +12,9 @@ import {MarcSimplifiedEditorModule} from '@eg/staff/share/marc-edit/simplified-e import {PatronModule} from '@eg/staff/share/patron/patron.module'; import {CourseTermMapComponent} from './course-term-map.component'; import {CourseTermMapGridComponent} from './course-term-map-grid.component'; +import {DepartmentContactGridComponent} from './department-contact-grid.component'; +import {DepartmentPageComponent} from './department-page.component'; +import {DepartmentListComponent} from './course-list-department.component'; @NgModule({ declarations: [ @@ -20,7 +23,10 @@ import {CourseTermMapGridComponent} from './course-term-map-grid.component'; CourseAssociateMaterialComponent, CourseAssociateUsersComponent, CourseTermMapComponent, - CourseTermMapGridComponent + CourseTermMapGridComponent, + DepartmentContactGridComponent, + DepartmentPageComponent, + DepartmentListComponent ], imports: [ StaffCommonModule, diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/department-contact-grid.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/department-contact-grid.component.html new file mode 100644 index 0000000000..82f773f4f0 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/department-contact-grid.component.html @@ -0,0 +1,80 @@ + + + + + + + + + + +
    +
    +
    +
    +
    +
    +
    + +
    + + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + + + + + + + + + + + + +
    +
    +
    + + + + + + + + + \ No newline at end of file diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/department-contact-grid.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/department-contact-grid.component.ts new file mode 100644 index 0000000000..aeb75315a8 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/department-contact-grid.component.ts @@ -0,0 +1,157 @@ +import {Component, Input, ViewChild, OnInit} from '@angular/core'; +import {DialogComponent} from '@eg/share/dialog/dialog.component'; +import {AuthService} from '@eg/core/auth.service'; +import {NetService} from '@eg/core/net.service'; +import {PcrudService} from '@eg/core/pcrud.service'; +import {Pager} from '@eg/share/util/pager'; +import {NgbModal} from '@ng-bootstrap/ng-bootstrap'; +import {GridDataSource} from '@eg/share/grid/grid'; +import {GridComponent} from '@eg/share/grid/grid.component'; +import {IdlObject} from '@eg/core/idl.service'; +import {StringComponent} from '@eg/share/string/string.component'; +import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component'; +import {PatronSearchDialogComponent} from '@eg/staff/share/patron/search-dialog.component'; +import {ToastService} from '@eg/share/toast/toast.service'; +import {CourseService} from '@eg/staff/share/course.service'; +import {ComboboxEntry} from '@eg/share/combobox/combobox.component'; + +@Component({ + selector: 'eg-department-contact-grid', + templateUrl: './department-contact-grid.component.html' +}) + +export class DepartmentContactGridComponent extends DialogComponent implements OnInit { + @Input() currentDepartment: IdlObject; + @Input() departmentId: number; + @Input() displayMode: String; + users: any[] = []; + @ViewChild('editDialog', { static: true }) editDialog: FmRecordEditorComponent; + @ViewChild('patronSearch') patronSearch: PatronSearchDialogComponent; + @ViewChild('contactsGrid') contactsGrid: GridComponent; + @ViewChild('userDeleteFailedString', { static: true }) + userDeleteFailedString: StringComponent; + @ViewChild('userDeleteSuccessString', { static: true }) + userDeleteSuccessString: StringComponent; + @ViewChild('userAddSuccessString', { static: true }) + userAddSuccessString: StringComponent; + @ViewChild('userAddFailedString', { static: true }) + userAddFailedString: StringComponent; + @ViewChild('userEditSuccessString', { static: true }) + userEditSuccessString: StringComponent; + @ViewChild('userEditFailedString', { static: true }) + userEditFailedString: StringComponent; + contactsDataSource: GridDataSource; + contactBarcode: String; + contactRoleInput: ComboboxEntry; + + constructor( + private auth: AuthService, + private course: CourseService, + private net: NetService, + private pcrud: PcrudService, + private toast: ToastService, + private modal: NgbModal + ) { + super(modal); + this.contactsDataSource = new GridDataSource(); + } + + ngOnInit() { + this.contactsDataSource.getRows = (pager: Pager, sort: any[]) => { + return this.course.getDepartmentContacts([this.departmentId]); + }; + } + + isDialog(): boolean { + return this.displayMode === 'dialog'; + } + + editSelectedContacts(contactFields: IdlObject[]) { + // Edit each IDL thing one at a time + const editOneThing = (contact: IdlObject) => { + if (!contact) { return; } + + this.showEditDialog(contact).then( + () => editOneThing(contactFields.shift())); + }; + + editOneThing(contactFields.shift()); + } + + searchPatrons() { + this.patronSearch.open({size: 'xl'}).toPromise().then( + patrons => { + if (!patrons || patrons.length === 0) { return; } + const contact = patrons[0]; + this.contactBarcode = contact.card().barcode(); + } + ); + } + + associateContacts(barcode) { + if (barcode) { + const args = { + currentDepartment: this.currentDepartment, + barcode: barcode.trim(), + }; + + if (this.contactRoleInput) { + args['role'] = this.contactRoleInput.id; + } + + this.contactBarcode = null; + + this.net.request( + 'open-ils.actor', + 'open-ils.actor.user.retrieve_id_by_barcode_or_username', + this.auth.token(), barcode.trim() + ).subscribe(patron => { + this.course.associateContacts(patron, args) + .then(() => this.contactsGrid.reload()); + }, err => { + this.userAddFailedString.current().then(str => this.toast.danger(str)); + } + ); + } + + } + + showEditDialog(contact: IdlObject): Promise { + this.editDialog.mode = 'update'; + this.editDialog.recordId = contact.id(); + return new Promise((resolve, reject) => { + this.editDialog.open({size: 'lg'}).subscribe( + result => { + this.userEditSuccessString.current() + .then(str => this.toast.success(str)); + this.contactsGrid.reload(); + resolve(result); + }, + error => { + this.userEditFailedString.current() + .then(str => this.toast.danger(str)); + reject(error); + } + ); + }); + } + + deleteSelectedContacts(contacts) { + const acmdc_ids = contacts.map(u => u.id()); + this.pcrud.search('acmdc', {id: acmdc_ids}).subscribe(contact => { + contact.isdeleted(true); + this.pcrud.autoApply(contact).subscribe( + val => { + console.debug('deleted: ' + val); + this.userDeleteSuccessString.current().then(str => this.toast.success(str)); + this.contactsGrid.reload(); + }, + err => { + this.userDeleteFailedString.current() + .then(str => this.toast.danger(str)); + } + ); + }).add(() => this.contactsGrid.reload()); + } + +} diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/department-page.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/department-page.component.html new file mode 100644 index 0000000000..1f932c2e00 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/department-page.component.html @@ -0,0 +1,48 @@ + + + + + +
    diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/department-page.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/department-page.component.ts new file mode 100644 index 0000000000..cb01167576 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/department-page.component.ts @@ -0,0 +1,39 @@ +import {Component, ViewChild, OnInit} from '@angular/core'; +import {ActivatedRoute} from '@angular/router'; +import {PcrudService} from '@eg/core/pcrud.service'; +import {IdlObject} from '@eg/core/idl.service'; +import {StringComponent} from '@eg/share/string/string.component'; +import {ToastService} from '@eg/share/toast/toast.service'; +import {CourseService} from '@eg/staff/share/course.service'; +import {DepartmentContactGridComponent} from './department-contact-grid.component'; + +@Component({ + selector: 'eg-department-page', + templateUrl: './department-page.component.html' +}) + +export class DepartmentPageComponent implements OnInit { + + currentDepartment: IdlObject; + departmentId: any; + + // Supplemental Tabs - possibly add a tab for a grid displaying all courses associated with the department here + @ViewChild('departmentContactGrid', {static: true}) + private departmentContactGrid: DepartmentContactGridComponent; + + constructor( + private course: CourseService, + private pcrud: PcrudService, + private route: ActivatedRoute, + private toast: ToastService + ) { + } + + ngOnInit() { + this.departmentId = +this.route.snapshot.paramMap.get('id'); + this.course.getDepartments([this.departmentId]).then(department => { + this.currentDepartment = department[0]; + }); + } + +} diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/routing.module.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/routing.module.ts index fcd9cd5a75..eab1e64646 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/routing.module.ts +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/course-reserves/routing.module.ts @@ -2,6 +2,7 @@ import {NgModule} from '@angular/core'; import {RouterModule, Routes} from '@angular/router'; import {CourseListComponent} from './course-list.component'; import {CoursePageComponent} from './course-page.component'; +import {DepartmentPageComponent} from './department-page.component'; const routes: Routes = [{ path: ':id', @@ -9,6 +10,9 @@ const routes: Routes = [{ }, { path: '', component: CourseListComponent +}, { + path: 'department/:id', + component: DepartmentPageComponent }]; @NgModule({ diff --git a/Open-ILS/src/eg2/src/app/staff/share/course.service.ts b/Open-ILS/src/eg2/src/app/staff/share/course.service.ts index 080626b8ef..0d18d76bea 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/course.service.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/course.service.ts @@ -64,6 +64,33 @@ export class CourseService { } } + getDepartments(department_ids?: Number[]): Promise { + const flesher = {flesh: 2, flesh_fields: { + 'acmc': ['owning_lib'], + 'aou': ['ou_type']}}; + if (!department_ids) { + return this.pcrud.retrieveAll('acmd', + flesher, {atomic: true}).toPromise(); + } else { + return this.pcrud.search('acmd', {id: department_ids}, + flesher, {atomic: true}).toPromise(); + } + } + + getDepartmentContacts(department_ids?: Number[]): Observable { + const flesher = { + flesh: 1, + flesh_fields: {'acmdc': ['usr', 'usr_role']} + }; + if (!department_ids) { + return this.pcrud.retrieveAll('acmdc', + flesher); + } else { + return this.pcrud.search('acmdc', {department: department_ids}, + flesher); + } + } + getCoursesFromMaterial(copy_id): Promise { const id_list = []; return new Promise((resolve, reject) => { @@ -143,6 +170,14 @@ export class CourseService { return this.pcrud.create(new_user).toPromise(); } + associateContacts(patron_id, args) { + const new_user = this.idl.create('acmdc'); + if (args.role) { new_user.usr_role(args.role); } + new_user.department(args.currentDepartment.id()); + new_user.usr(patron_id); + return this.pcrud.create(new_user).toPromise(); + } + disassociateMaterials(courses) { return new Promise((resolve, reject) => { const course_ids = []; diff --git a/Open-ILS/src/sql/Pg/040.schema.asset.sql b/Open-ILS/src/sql/Pg/040.schema.asset.sql index e2692381ca..ba14bb4caf 100644 --- a/Open-ILS/src/sql/Pg/040.schema.asset.sql +++ b/Open-ILS/src/sql/Pg/040.schema.asset.sql @@ -1099,6 +1099,7 @@ CREATE TABLE asset.course_module_course ( name TEXT NOT NULL, course_number TEXT NOT NULL, section_number TEXT, + department INT REFERENCES asset.course_module_department (id), owning_lib INT REFERENCES actor.org_unit (id), is_archived BOOLEAN DEFAULT false ); @@ -1145,5 +1146,24 @@ CREATE TABLE asset.course_module_term_course_map ( course INT NOT NULL REFERENCES asset.course_module_course (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED ); +CREATE TABLE asset.course_module_department ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + owning_lib INT REFERENCES actor.org_unit (id) +); + +CREATE TABLE asset.course_module_department_contacts ( + id SERIAL PRIMARY KEY, + department INT NOT NULL REFERENCES asset.course_module_department (id), + usr INT NOT NULL REFERENCES actor.usr (id), + usr_role INT REFERENCES asset.course_module_role (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED +); + +CREATE TABLE asset.course_module_department_course_map ( + id BIGSERIAL PRIMARY KEY, + department INT NOT NULL REFERENCES asset.course_module_department (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, + course INT NOT NULL REFERENCES asset.course_module_course (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED +); + COMMIT; diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql index 58f4a18fcc..e634195487 100644 --- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql +++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql @@ -20962,7 +20962,8 @@ INSERT INTO actor.org_unit_setting (org_unit, name, value) INSERT INTO asset.course_module_role (id, name, is_public) VALUES (1, oils_i18n_gettext(1, 'Instructor', 'acmr', 'name'), true), (2, oils_i18n_gettext(2, 'Teaching assistant', 'acmr', 'name'), true), -(3, oils_i18n_gettext(3, 'Student', 'acmr', 'name'), false); +(3, oils_i18n_gettext(3, 'Student', 'acmr', 'name'), false), +(4, oils_i18n_gettext(4, 'Department Head', 'acmr', 'name'), true); SELECT SETVAL('asset.course_module_role_id_seq'::TEXT, 100); diff --git a/Open-ILS/src/sql/Pg/upgrade/xxxx.schema.lp1922388-academic-departments.sql b/Open-ILS/src/sql/Pg/upgrade/xxxx.schema.lp1922388-academic-departments.sql new file mode 100644 index 0000000000..81817ec7fb --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/xxxx.schema.lp1922388-academic-departments.sql @@ -0,0 +1,30 @@ +BEGIN; + +SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version); + +CREATE TABLE asset.course_module_department ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + owning_lib INT REFERENCES actor.org_unit (id) +); + +CREATE TABLE asset.course_module_department_contacts ( + id SERIAL PRIMARY KEY, + department INT NOT NULL REFERENCES asset.course_module_department (id), + usr INT NOT NULL REFERENCES actor.usr (id), + usr_role INT REFERENCES asset.course_module_role (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED +); + +CREATE TABLE asset.course_module_department_course_map ( + id BIGSERIAL PRIMARY KEY, + department INT NOT NULL REFERENCES asset.course_module_department (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, + course INT NOT NULL REFERENCES asset.course_module_course (id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED +); + +ALTER TABLE asset.course_module_course + ADD COLUMN department INT REFERENCES asset.course_module_department (id); + +INSERT INTO asset.course_module_role (id, name, is_public) VALUES +(4, oils_i18n_gettext(4, 'Department Head', 'acmr', 'name'), true); + +COMMIT; \ No newline at end of file