def __insert_contributions(book, form, session): """ Insert the contributions in the form to the session. No commits will take place. """ from flask_login import current_user # Create the Contributors authors = __create_bookperson(form.authors.data) illustrators = __create_bookperson(form.illustrators.data) editors = __create_bookperson(form.editors.data) translators = __create_bookperson(form.translators.data) author_role = Role.get_preset_role("Author") illus_role = Role.get_preset_role("Illustrator") editor_role = Role.get_preset_role("Editor") trans_role = Role.get_preset_role("Translator") # Assign participation for author in authors: author_part = BookContribution(book=book, contributor=author, role=author_role, creator=current_user) if not author.active: author.active = True session.add(author) session.add(author_part) for illustrator in illustrators: illus_part = BookContribution(book=book, contributor=illustrator, role=illus_role, creator=current_user) if not illustrator.active: illustrator.active = True session.add(illustrator) session.add(illus_part) for editor in editors: editor_part = BookContribution(book=book, contributor=editor, role=editor_role, creator=current_user) if not editor.active: editor.active = True session.add(editor) session.add(editor_part) for translator in translators: translator_part = BookContribution(book=book, contributor=translator, role=trans_role, creator=current_user) if not translator.active: translator.active = True session.add(translator) session.add(translator_part)
def edit_book(): def contribution_exists(all_contribs, role_id, person): """ Check if the given person contributed for the given role in all the contributions related to the present book being edited. Where `all_contribs` is all the BookContribution records for the book being edited. person is an instance of librarian.utils.Person. Returns the BookContribution object if it exists, else False. """ the_contribution = [ contrib for contrib in all_contribs if (contrib.role_id == role_id and contrib.contributor.firstname == person.firstname and contrib.contributor.lastname == person.lastname) ] if len(the_contribution) > 1: raise InvalidRecordState( "uniqueness of contribution role + person + book %s" % spam) if the_contribution: return the_contribution[0] else: return False def edit_contrib(book, all_contribs, role, submitted_persons): """ Adds all new contributors to the session and deletes all removed contributors to the session. Where `submitted_persons` is the data straight out of the form (hence it is a JSON string), `all_contribs` are all the active contributions in the book as recorded in the DB (pre-edit). """ app.logger.debug("considering role %s" % role) parsons = json.loads(submitted_persons) form_records = set() # Create or load all the contributions mentioned in the form. for p in parsons: ce = contribution_exists(all_contribs, role.id, Person(**p)) if ce is not False: form_records.add(ce) else: contributor_record = get_or_create(Contributor, will_commit=False, firstname=p["firstname"], lastname=p["lastname"], creator=current_user) app.logger.debug("got contributor record %s" % contributor_record) app.logger.debug("will attach role %s" % role) if not contributor_record.active: contributor_record.active = True contribution = BookContribution(book=book, contributor=contributor_record, role=role, creator=current_user) db.session.add(contribution) form_records.add(contribution) recorded_contribs = set([ contrib for contrib in all_contribs if contrib.role.id == role.id ]) app.logger.debug("recorded contribs for %s %s" % (role, recorded_contribs)) app.logger.debug("form records %s" % form_records) deletables = recorded_contribs - form_records app.logger.debug("The deletables %s" % deletables) for d in deletables: d.active = False other_contrib = (BookContribution.query.filter( BookContribution.contributor_id == d.contributor_id).filter( or_(BookContribution.book_id != book.id, BookContribution.role_id != d.role_id)).filter( BookContribution.active).first()) app.logger.debug( "Contributor %s has another contribution %s (checked from %s)" % (d.contributor_id, other_contrib, role.name)) if other_contrib is None: app.logger.debug("Deactivating %s" % d) d.contributor.active = False from flask_login import current_user form = EditBookForm(request.form) app.logger.info(str(form)) app.logger.debug(form.debug_validate()) if form.validate_on_submit(): book_id = int(form.book_id.data) try: # Update records in books table genre = get_or_create(Genre, will_commit=False, session=db.session, name=form.genre.data, creator=current_user) publisher = get_or_create(BookCompany, will_commit=False, name=form.publisher.data, creator=current_user) book = db.session.query(Book).filter(Book.id == book_id).first() book.isbn = form.isbn.data book.title = form.title.data book.publish_year = form.year.data book.genre_id = genre.id book.publisher_id = publisher.id # Get all the contributions for this book all_contribs = (BookContribution.query.filter( BookContribution.book_id == book_id).filter(BookContribution.active).filter( BookContribution.contributor_id == Contributor.id).filter( Contributor.active).all()) edit_contrib(book, all_contribs, Role.get_preset_role("Author"), form.authors.data) r_illustrator = Role.get_preset_role("Illustrator") edit_contrib(book, all_contribs, r_illustrator, form.illustrators.data) edit_contrib(book, all_contribs, Role.get_preset_role("Editor"), form.editors.data) edit_contrib(book, all_contribs, Role.get_preset_role("Translator"), form.translators.data) db.session.commit() return "Accepted", 200 except IntegrityError, ierr: db.session.rollback() app.logger.error("Integrity Error occurred") app.logger.exception(traceback.format_exc()) return "IntegrityError", 409 except Exception as ex: db.session.rollback() app.logger.error("error except. traceback follows:") import traceback traceback.print_exc() return "Unknown error", 500