def add_test(connection, filmTypeID): """ Add a new film test """ userID = current_user.get_id() json = request.get_json() nextFilmTestID = next_id(connection, 'filmTestID', 'FilmTests') qry = text("""INSERT INTO FilmTests (userID, filmTestID, filmTypeID, enlargerID, enlargerLensID, filterID, stepTabletID, headHeight, filmSize, lux, fstop, exposureTime, developer, devTime, devTemperature, prebath, stop, agitation, rotaryRPM, notes) VALUES (:userID, :filmTestID, :filmTypeID, :enlargerID, :enlargerLensID, :filterID, :stepTabletID, :headHeight, :filmSize, :lux, :fstop, :exposureTime, :developer, :devTime, :devTemperature, :prebath, :stop, :agitation, :rotaryRPM, :notes)""") try: connection.execute(qry, userID=userID, filmTestID=nextFilmTestID, filmTypeID=filmTypeID, enlargerID=json['data']['enlargerID'], enlargerLensID=json['data']['enlargerLensID'], filterID=json['data']['filterID'], stepTabletID=json['data']['stepTabletID'], headHeight=zero_to_none(json['data']['headHeight']), filmSize=json['data']['filmSize'], lux=json['data']['lux'], fstop=json['data']['fstop'], exposureTime=key_or_none(json, 'exposureTime'), developer=json['data']['developer'], devTime=time_to_seconds(json['data']['devTime']), devTemperature=json['data']['devTemperature'], prebath=json['data']['prebath'], stop=json['data']['stop'], agitation=json['data']['agitation'], rotaryRPM=zero_to_none(json['data']['rotaryRPM']), notes=json['data']['notes']) except IntegrityError: log("Failed to create new film test via API") return "FAILED", status.HTTP_409_CONFLICT json['data']['id'] = str(nextFilmTestID) json['data']['created_on'] = datetime.datetime.now() resp = make_response(jsonify(json)) log("Created new film test via API") return resp, status.HTTP_201_CREATED
def user_developer_log(developerID, developerLogID): """ Developer Log Details """ connection = engine.connect() transaction = connection.begin() userID = current_user.get_id() developer_log_form = DeveloperLogForm() developer_log_film_form = DeveloperLogFilmForm() developer_log_film_form.populate_select_fields(connection) if request.method == 'POST': if request.form['button'] == 'updateLog': try: devTime = functions.time_to_seconds(developer_log_form.devTime.data) except ValidationError as e: app.logger.info("Bad dev time format: %s" % e) devTime = None qry = text("""UPDATE DeveloperLogs SET loggedOn = :loggedOn, mlReplaced = :mlReplaced, mlUsed = :mlUsed, temperature = :temperature, devTime = :devTime, notes = :notes WHERE userID = :userID AND developerLogID = :developerLogID""") connection.execute(qry, userID=userID, developerLogID=developerLogID, loggedOn=developer_log_form.loggedOn.data, mlReplaced=developer_log_form.mlReplaced.data, mlUsed=developer_log_form.mlUsed.data, temperature=developer_log_form.temperature.data, devTime=devTime, notes=developer_log_form.notes.data) if request.form['button'] == 'deleteLog': qry = text("""DELETE FROM DeveloperLogs WHERE userID = :userID AND developerLogID = :developerLogID""") connection.execute(qry, userID=userID, developerLogID=developerLogID) transaction.commit() return redirect('/developing/developer/' + str(developerID)) if request.form['button'] == 'addFilm': if developer_log_film_form.validate_on_submit(): qry = text("""REPLACE INTO DeveloperLogFilms (userID, developerLogFilmID, developerLogID, filmSizeID, filmTypeID, qty, compensation) VALUES (:userID, :developerLogFilmID, :developerLogID, :filmSizeID, :filmTypeID, :qty, :compensation)""") # pylint: disable=line-too-long # Haven't found a great way to format this without it being # more ugly. connection.execute(qry, userID=userID, developerLogFilmID=functions.next_id(connection, 'developerLogFilmID', 'DeveloperLogFilms'), developerLogID=developerLogID, filmSizeID=developer_log_film_form.filmSizeID.data, filmTypeID=developer_log_film_form.filmTypeID.data, qty=developer_log_film_form.qty.data, compensation=developer_log_film_form.compensation.data) if request.form['button'] == 'deleteFilm': qry = text("""DELETE FROM DeveloperLogFilms WHERE userID = :userID AND developerLogFilmID = :developerLogFilmID""") connection.execute(qry, userID=userID, developerLogFilmID=int(request.form['developerLogFilmID'])) # Grab the log qry = text("""SELECT developerLogID, loggedOn, mlReplaced, mlUsed, temperature, SECONDS_TO_DURATION(devTime) AS devTime, notes FROM DeveloperLogs WHERE userID = :userID AND developerLogID = :developerLogID ORDER BY loggedOn DESC""") developer_log_results = connection.execute(qry, userID=userID, developerID=developerID, developerLogID=developerLogID).fetchone() developer_log = dict(developer_log_results) # For each log entry we grab the films used and stuff them into the # data dictionary for teh logs. I feel like there is a cleaner way # but this works. qry = text("""SELECT developerLogFilmID, size AS filmSize, DeveloperLogFilms.filmTypeID, FilmTypes.name AS filmName, iso, qty, IF(compensation > 0, CONCAT('+', compensation), compensation) AS compensation FROM DeveloperLogFilms LEFT OUTER JOIN FilmTypes On FilmTypes.filmTypeID = DeveloperLogFilms.filmTypeID JOIN FilmSizes ON FilmSizes.filmSizeID = DeveloperLogFilms.filmSizeID WHERE DeveloperLogFilms.userID = :userID AND developerLogID = :developerLogID""") films = connection.execute(qry, userID=userID, developerLogID=developerLogID).fetchall() transaction.commit() developer_log['films'] = films developer_log_form = DeveloperLogForm(data=developer_log) return render_template('/developing/developer_log.html', developerID=developerID, developerLogID=developerLogID, developer_log=developer_log, developer_log_form=developer_log_form, developer_log_film_form=developer_log_film_form)
def user_developer(developerID): """ Developer details """ connection = engine.connect() transaction = connection.begin() userID = current_user.get_id() developer_form = DeveloperForm() developer_log_form = DeveloperLogForm() if request.method == 'POST': if request.form['button'] == 'retireDeveloper': qry = text("""UPDATE Developers SET state='Retired' WHERE userID = :userID AND developerID = :developerID""") connection.execute(qry, userID=userID, developerID=developerID) if request.form['button'] == 'unretireDeveloper': qry = text("""UPDATE Developers SET state='Active' WHERE userID = :userID AND developerID = :developerID""") connection.execute(qry, userID=userID, developerID=developerID) if request.form['button'] == 'updateDeveloper': if developer_form.validate_on_submit(): qry = text("""UPDATE Developers SET name = :name, mixedOn = :mixedOn, type = :type, kind = :kind, capacity = :capacity, state = :state, notes = :notes WHERE userID = :userID AND developerID = :developerID""") connection.execute(qry, name=developer_form.name.data, mixedOn=developer_form.mixedOn.data, type=developer_form.type.data, kind=developer_form.kind.data, capacity=developer_form.capacity.data, state=developer_form.state.data, notes=developer_form.notes.data, userID=userID, developerID=developerID) if request.form['button'] == 'addLog': if developer_log_form.validate_on_submit(): try: devTime = functions.time_to_seconds(developer_log_form.devTime.data) except ValidationError as e: app.logger.info("Bad dev time format: %s" % e) devTime = None qry = text("""INSERT INTO DeveloperLogs (userID, developerID, developerLogID, loggedOn, mlReplaced, mlUsed, temperature, devTime, notes) VALUES (:userID, :developerID, :developerLogID, :loggedOn, :mlReplaced, :mlUsed, :temperature, :devTime, :notes)""") connection.execute(qry, userID=userID, developerID=developerID, developerLogID=functions.next_id(connection, 'developerLogID', 'DeveloperLogs'), loggedOn=developer_log_form.loggedOn.data, mlReplaced=developer_log_form.mlReplaced.data, mlUsed=developer_log_form.mlUsed.data, temperature=developer_log_form.temperature.data, devTime=devTime, notes=developer_log_form.notes.data) # Grab the main info for the developer qry = text("""SELECT developerID, name, mixedOn, capacity, type, kind, state, notes, DATEDIFF(NOW(), mixedOn) AS age FROM Developers WHERE userID = :userID AND developerID = :developerID""") developer_results = connection.execute(qry, userID=userID, developerID=developerID).fetchone() developer = dict(developer_results) # If it's a replenished developer, figure out how long it's been since # last replenishment if developer['kind'] == 'Replenishment': qry = text("""SELECT DATEDIFF(NOW(), loggedOn) AS last_replenished FROM DeveloperLogs WHERE userID = :userID AND developerID = :developerID AND mlReplaced != 0 ORDER BY developerLogID DESC LIMIT 1""") last_replenished = connection.execute(qry, userID=userID, developerID=developerID).fetchone() if not last_replenished: qry = text("""SELECT DATEDIFF(NOW(), mixedOn) AS last_replenished FROM Developers WHERE userID = :userID AND developerID = :developerID""") last_replenished = connection.execute(qry, userID=userID, developerID=developerID).fetchone() last_replenished_dict = dict(last_replenished) developer['last_replenished'] = last_replenished_dict['last_replenished'] # Grab the logs qry = text("""SELECT developerLogID, loggedOn, mlReplaced, mlUsed, temperature, SECONDS_TO_DURATION(devTime) AS devTime, notes FROM DeveloperLogs WHERE userID = :userID AND developerID = :developerID ORDER BY loggedOn DESC""") developer_log_results = connection.execute(qry, userID=userID, developerID=developerID).fetchall() # pylint complains but this took a while to get working so leaving as is. # pylint: disable=unnecessary-comprehension developer_logs = [{key: value for (key, value) in row.items()} for row in developer_log_results] # For each log entry we grab the films used and stuff them into the # data dictionary for teh logs. I feel like there is a cleaner way # but this works. qry = text("""SELECT developerLogFilmID, size AS filmSize, DeveloperLogFilms.filmTypeID, FilmTypes.name AS filmName, iso, qty, IF(compensation > 0, CONCAT('+', compensation), compensation) FROM DeveloperLogFilms LEFT OUTER JOIN FilmTypes On FilmTypes.filmTypeID = DeveloperLogFilms.filmTypeID AND FilmTypes.userID = DeveloperLogFilms.userID JOIN FilmSizes ON FilmSizes.filmSizeID = DeveloperLogFilms.filmSizeID WHERE DeveloperLogFilms.userID = :userID AND developerLogID = :developerLogID""") for index, log in enumerate(developer_logs): films = connection.execute(qry, userID=userID, developerLogID=log['developerLogID']).fetchall() developer_logs[index]['films'] = films # Grab film statistics qry = text("""SELECT FilmTypes.name AS filmName, iso, size AS filmSize, SUM(qty) AS qty FROM DeveloperLogs JOIN DeveloperLogFilms ON DeveloperLogFilms.userID = DeveloperLogs.userID AND DeveloperLogFilms.developerLogID = DeveloperLogs.developerLogID LEFT OUTER JOIN FilmTypes On FilmTypes.filmTypeID = DeveloperLogFilms.filmTypeID AND FilmTypes.userID = DeveloperLogFilms.userID JOIN FilmSizes ON FilmSizes.filmSizeID = DeveloperLogFilms.filmSizeID WHERE DeveloperLogs.userID = :userID AND DeveloperLogs.developerID = :developerID GROUP BY DeveloperLogFilms.filmTypeID, DeveloperLogFilms.filmSizeID ORDER BY filmName""") film_stats = connection.execute(qry, userID=userID, developerID=developerID).fetchall() transaction.commit() if not developer_form.errors: developer_form = DeveloperForm(data=developer) return render_template('/developing/developer.html', developer=developer, developer_logs=developer_logs, film_stats=film_stats, developer_form=developer_form, developer_log_form=developer_log_form)
def contactsheet(binderID, projectID, filmID): """ Manage a contact sheet """ connection = engine.connect() transaction = connection.begin() userID = current_user.get_id() form = ContactSheetForm() form.populate_select_fields(connection) # Upload a new contact sheet if request.method == 'POST': nextFileID = None # See if there is a contact sheet already qry = text("""SELECT fileID FROM ContactSheets WHERE filmID = :filmID AND userID = :userID""") result = connection.execute(qry, filmID=filmID, userID=userID).fetchone() if result: if result[0]: fileID = int(result[0]) else: fileID = None else: fileID = None if request.form['button'] == 'deleteCS': qry = text("""DELETE FROM ContactSheets WHERE filmID = :filmID AND userID = :userID""") connection.execute(qry, filmID=filmID, userID=userID) if fileID: files.delete_file(connection, transaction, fileID) elif request.form['button'] == 'updateCS' and form.validate_on_submit( ): # If user included a file, let's upload it. Otherwise skip it. if 'file' in request.files: file_upload = request.files['file'] if file_upload.filename != '': nextFileID = functions.next_id(connection, 'fileID', 'Files') files.upload_file(request, connection, transaction, nextFileID) # If we're updating an existing sheet and the user didn't upload # a new file, use the old one. else: nextFileID = fileID qry = text( """REPLACE INTO ContactSheets (filmID, userID, fileID, paperID, paperFilterID, enlargerLensID, enlargerID, aperture, headHeight, exposureTime, notes) VALUES (:filmID, :userID, :fileID, :paperID, :paperFilterID, :enlargerLensID, :enlargerID, :aperture, :headHeight, :exposureTime, :notes)""" ) connection.execute( qry, filmID=filmID, userID=userID, fileID=nextFileID, paperID=zero_to_none(form.paperID.data), paperFilterID=zero_to_none(form.paperFilterID.data), enlargerLensID=zero_to_none(form.enlargerLensID.data), enlargerID=zero_to_none(form.enlargerID.data), aperture=form.aperture.data, headHeight=form.headHeight.data, exposureTime=functions.time_to_seconds(form.exposureTime.data), notes=form.notes.data) film = functions.get_film_details(connection, binderID, projectID, filmID) # Get contact sheet info qry = text("""SELECT fileID, Papers.name AS paperName, PaperFilters.name AS paperFilterName, EnlargerLenses.name AS lens, Enlargers.name AS enlarger, aperture, headHeight, ContactSheets.notes, ContactSheets.paperID AS paperID, ContactSheets.paperFilterID AS paperFilterID, ContactSheets.enlargerLensID AS enlargerLensID, SECONDS_TO_DURATION(exposureTime) AS exposureTime FROM ContactSheets LEFT OUTER JOIN Papers ON Papers.paperID = ContactSheets.paperID AND Papers.userID = ContactSheets.userID LEFT OUTER JOIN PaperFilters ON PaperFilters.paperFilterID = ContactSheets.paperFilterID LEFT OUTER JOIN EnlargerLenses ON EnlargerLenses.enlargerLensID = ContactSheets.enlargerLensID AND EnlargerLenses.userID = ContactSheets.userID LEFT OUTER JOIN Enlargers ON Enlargers.enlargerID = ContactSheets.enlargerID AND Enlargers.userID = ContactSheets.userID WHERE filmID = :filmID AND ContactSheets.userID = :userID""") contactSheet = connection.execute(qry, userID=userID, binderID=binderID, filmID=filmID).fetchone() if contactSheet: form = ContactSheetForm(data=contactSheet) form.populate_select_fields(connection) transaction.commit() return render_template('darkroom/contactsheet.html', binderID=binderID, projectID=projectID, film=film, contactSheet=contactSheet, form=form, view='contactsheet')
def print_exposure(binderID, projectID, filmID, printID): """ Manage a specific exposure print """ connection = engine.connect() transaction = connection.begin() userID = current_user.get_id() form = PrintForm() form.populate_select_fields(connection, filmID) if request.method == 'POST': if request.form['button'] == 'deletePrint': fileID = check_for_print_file(connection, printID) qry = text("""DELETE FROM Prints WHERE printID = :printID AND userID = :userID""") connection.execute(qry, printID=printID, userID=userID) if fileID: files.delete_file(connection, transaction, fileID) transaction.commit() return redirect('/binders/' + str(binderID) + '/projects/' + str(projectID) + '/films/' + str(filmID) + '/prints') if request.form['button'] == 'updatePrint': if form.validate_on_submit(): # See if there is a fileID fileID = check_for_print_file(connection, printID) # If the user has a file already, delete it first. # Otherwise treat it like a new file. if form.file.data: if fileID: app.logger.info('Replace File') files.delete_file(connection, transaction, fileID) files.upload_file(request, connection, transaction, fileID) else: app.logger.info('Brand New File') fileID = functions.next_id(connection, 'fileID', 'Files') files.upload_file(request, connection, transaction, fileID) qry = text("""REPLACE INTO Prints (printID, filmID, exposureNumber, userID, paperID, paperFilterID, enlargerLensID, enlargerID, fileID, aperture, ndFilter, headHeight, exposureTime, printType, size, notes) VALUES (:printID, :filmID, :exposureNumber, :userID, :paperID, :paperFilterID, :enlargerLensID, :enlargerID, :fileID, :aperture, :ndFilter, :headHeight, :exposureTime, :printType, :size, :notes)""") insert( connection, qry, "Print", printID=printID, filmID=filmID, userID=userID, fileID=fileID, exposureNumber=form.exposureNumber.data, paperID=zero_to_none(form.paperID.data), paperFilterID=zero_to_none(form.paperFilterID.data), enlargerLensID=zero_to_none(form.enlargerLensID.data), enlargerID=zero_to_none(form.enlargerID.data), aperture=form.aperture.data, ndFilter=form.ndFilter.data, headHeight=form.headHeight.data, exposureTime=functions.time_to_seconds( form.exposureTime.data), #exposureTime=form.exposureTime.data, printType=form.printType.data, size=form.size.data, notes=form.notes.data) transaction.commit() return redirect('/binders/' + str(binderID) + '/projects/' + str(projectID) + '/films/' + str(filmID) + '/prints') film = functions.get_film_details(connection, binderID, projectID, filmID) qry = text("""SELECT printID, exposureNumber, Papers.name AS paperName, PaperDevelopers.name AS paperDeveloperName, PaperDevelopers.dilution AS paperDeveloperDilution, Papers.paperID, PaperFilters.paperFilterID, PaperFilters.name AS paperFilterName, EnlargerLenses.enlargerLensID, EnlargerLenses.name AS enlargerLensName, Enlargers.enlargerID, Enlargers.name AS enlargerName, printType, size, aperture, ndFilter, headHeight, Prints.notes, fileID, SECONDS_TO_DURATION(exposureTime) AS exposureTime FROM Prints LEFT OUTER JOIN Papers ON Papers.paperID = Prints.paperID AND Papers.userID = Prints.userID LEFT OUTER JOIN PaperDevelopers ON PaperDevelopers.paperDeveloperID = Prints.paperDeveloperID LEFT OUTER JOIN PaperFilters ON PaperFilters.paperFilterID = Prints.paperFilterID LEFT OUTER JOIN EnlargerLenses ON EnlargerLenses.enlargerLensID = Prints.enlargerLensID AND EnlargerLenses.userID = Prints.userID LEFT OUTER JOIN Enlargers ON Enlargers.enlargerID = Prints.enlargerID AND Enlargers.userID = Prints.userID WHERE Prints.userID = :userID AND Prints.printID = :printID""") print_details = connection.execute(qry, userID=userID, printID=printID).fetchone() transaction.commit() form = PrintForm(data=print_details) form.populate_select_fields(connection, filmID) return render_template('darkroom/print.html', form=form, film=film, binderID=binderID, projectID=projectID, printID=printID, print_details=print_details, view='prints')
def user_prints(binderID, projectID, filmID): """ Manage user's prints for a film """ connection = engine.connect() transaction = connection.begin() userID = current_user.get_id() form = PrintForm() form.populate_select_fields(connection, filmID) if request.method == 'POST': if request.form['button'] == 'addPrint': if form.validate_on_submit(): nextPrintID = functions.next_id(connection, 'printID', 'Prints') log("Next Print ID: %s" % nextPrintID) # If user included a file, let's upload it. Otherwise skip it. if form.file.data: nextFileID = functions.next_id(connection, 'fileID', 'Files') files.upload_file(request, connection, transaction, nextFileID) else: nextFileID = None qry = text("""INSERT INTO Prints (printID, paperDeveloperID, filmID, exposureNumber, userID, paperID, paperFilterID, enlargerLensID, enlargerID, fileID, aperture, ndFilter, headHeight, exposureTime, printType, size, notes) VALUES (:printID, :paperDeveloperID, :filmID, :exposureNumber, :userID, :paperID, :paperFilterID, :enlargerLensID, :enlargerID, :fileID, :aperture, :ndFilter, :headHeight, :exposureTime, :printType, :size, :notes)""") insert(connection, qry, "Print", printID=nextPrintID, filmID=filmID, userID=userID, fileID=nextFileID, paperDeveloperID=zero_to_none( form.paperDeveloperID.data), exposureNumber=form.exposureNumber.data, paperID=zero_to_none(form.paperID.data), paperFilterID=zero_to_none(form.paperFilterID.data), enlargerLensID=zero_to_none(form.enlargerLensID.data), enlargerID=zero_to_none(form.enlargerID.data), aperture=form.aperture.data, ndFilter=form.ndFilter.data, headHeight=form.headHeight.data, exposureTime=functions.time_to_seconds( form.exposureTime.data), printType=form.printType.data, size=form.size.data, notes=form.notes.data) film = functions.get_film_details(connection, binderID, projectID, filmID) qry = text("""SELECT printID, exposureNumber, PaperDevelopers.name AS paperDeveloperName, PaperDevelopers.dilution AS paperDeveloperDilution, Papers.name AS paperName, PaperFilters.name AS paperFilterName, printType, size, aperture, ndFilter, headHeight, Prints.notes, fileID, EnlargerLenses.name AS lens, Enlargers.name AS enlarger, SECONDS_TO_DURATION(exposureTime) AS exposureTime FROM Prints LEFT OUTER JOIN Papers ON Papers.paperID = Prints.paperID AND Papers.userID = Prints.userID LEFT OUTER JOIN PaperFilters ON PaperFilters.paperFilterID = Prints.paperFilterID LEFT OUTER JOIN PaperDevelopers ON PaperDevelopers.paperDeveloperID = Prints.paperDeveloperID LEFT OUTER JOIN EnlargerLenses ON EnlargerLenses.enlargerLensID = Prints.enlargerLensID AND EnlargerLenses.userID = Prints.userID LEFT OUTER JOIN Enlargers ON Enlargers.enlargerID = Prints.enlargerID AND Enlargers.userID = Prints.userID WHERE filmID = :filmID AND Prints.userID = :userID""") prints = connection.execute(qry, userID=userID, filmID=filmID) transaction.commit() return render_template('darkroom/prints.html', form=form, binderID=binderID, projectID=projectID, film=film, prints=prints, view='prints')