1
0
Fork 0
mirror of https://github.com/shouptech/humulus.git synced 2026-02-03 22:09:41 +00:00

Add yeast

This commit is contained in:
Emma 2019-06-22 21:51:39 -06:00
parent c74ae966a3
commit 98404e38ef
3 changed files with 154 additions and 13 deletions

View file

@ -20,7 +20,7 @@ from flask import Blueprint, flash, redirect, render_template, url_for
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import (Form, StringField, DecimalField, TextAreaField, FieldList, from wtforms import (Form, StringField, DecimalField, TextAreaField, FieldList,
FormField, SelectField) FormField, SelectField)
from wtforms.validators import DataRequired from wtforms.validators import DataRequired, Optional
from humulus.couch import get_doc_or_404, put_doc from humulus.couch import get_doc_or_404, put_doc
@ -85,6 +85,62 @@ class HopForm(Form):
'amount': str(self.amount.data) 'amount': str(self.amount.data)
} }
class YeastForm(Form):
"""Form for yeast.
CSRF is disabled for this subform (using `Form as parent class) because it
is never used by itself.
"""
name = StringField('Name', validators=[DataRequired()])
type = SelectField('Type', default='',
choices=[(c, c) for c in ['', 'Liquid', 'Dry']],
validators=[Optional()])
lab = StringField('Lab')
code = StringField('Lab Code')
flocculation = SelectField('Flocculation', default='',
choices=[(c, c) for c in ['', 'Low',
'Medium', 'High']],
validators=[Optional()])
low_attenuation = DecimalField('Low Attenuation',
validators=[DataRequired()])
high_attenuation = DecimalField('High Attenuation',
validators=[DataRequired()])
min_temperature = DecimalField('Min Temp (°F)',
validators=[Optional()])
max_temperature = DecimalField('Max Temp (°F)',
validators=[Optional()])
abv_tolerance = DecimalField('ABV % tolerance',
validators=[Optional()])
@property
def doc(self):
"""Returns a dictionary that can be deserialized into JSON.
Used for putting into CouchDB.
"""
yeast = {
'name': self.name.data,
'low_attenuation': str(self.low_attenuation.data),
'high_attenuation': str(self.high_attenuation.data)
}
if self.type.data:
yeast['type'] = self.type.data
if self.lab.data:
yeast['lab'] = self.lab.data
if self.code.data:
yeast['code'] = self.code.data
if self.flocculation.data:
yeast['flocculation'] = self.flocculation.data
if self.min_temperature.data:
yeast['min_temperature'] = str(self.min_temperature.data)
if self.max_temperature.data:
yeast['max_temperature'] = str(self.max_temperature.data)
if self.abv_tolerance.data:
yeast['abv_tolerance'] = str(self.abv_tolerance.data)
return yeast
class RecipeForm(FlaskForm): class RecipeForm(FlaskForm):
"""Form for recipes.""" """Form for recipes."""
name = StringField('Name', validators=[DataRequired()]) name = StringField('Name', validators=[DataRequired()])
@ -102,6 +158,7 @@ class RecipeForm(FlaskForm):
min_entries=0, min_entries=0,
max_entries=20 max_entries=20
) )
yeast = FormField(YeastForm)
@property @property
def doc(self): def doc(self):
@ -109,15 +166,21 @@ class RecipeForm(FlaskForm):
Used for putting into CouchDB. Used for putting into CouchDB.
""" """
return { recipe = {
'name': self.name.data, 'name': self.name.data,
'efficiency': str(self.efficiency.data), 'efficiency': str(self.efficiency.data),
'volume': str(self.volume.data), 'volume': str(self.volume.data),
'notes': self.notes.data, 'notes': self.notes.data
'fermentables': [f.doc for f in self.fermentables],
'hops': [h.doc for h in self.hops],
} }
if len(self.fermentables) > 0:
recipe['fermentables'] = [f.doc for f in self.fermentables]
if len(self.hops) > 0:
recipe['hops'] = [h.doc for h in self.hops]
if self.yeast.doc['name']:
recipe['yeast'] = self.yeast.doc
return recipe
@bp.route('/create', methods=('GET', 'POST')) @bp.route('/create', methods=('GET', 'POST'))
def create(): def create():
@ -127,7 +190,6 @@ def create():
response = put_doc(form.doc) response = put_doc(form.doc)
flash('Created recipe: {}'.format(form.name.data), 'success') flash('Created recipe: {}'.format(form.name.data), 'success')
return redirect(url_for('recipes.info', id=response['_id'])) return redirect(url_for('recipes.info', id=response['_id']))
return render_template('recipes/create.html', form=form) return render_template('recipes/create.html', form=form)

View file

@ -92,6 +92,28 @@
<button type="button" id="add-hop" class="btn btn-secondary btn-sm">Add a hop</button> <button type="button" id="add-hop" class="btn btn-secondary btn-sm">Add a hop</button>
</div> </div>
</div> </div>
{#-
Recipe Yeast
-#}
<div class="row"><div class="col"><h3>Yeast</h3></div></div>
<div id="yeast">
<div class="border pl-2 pr-2 pt-1 pb-1 yeast-form">
<div class="row">
<div class="col-sm-6">{{ render_field_with_errors(form.yeast.form.name, 'form-control-sm') }}</div>
<div class="col-sm-2">{{ render_field_with_errors(form.yeast.form.type, 'form-control-sm') }}</div>
<div class="col-sm-2">{{ render_field_with_errors(form.yeast.form.lab, 'form-control-sm') }}</div>
<div class="col-sm-2">{{ render_field_with_errors(form.yeast.form.code, 'form-control-sm') }}</div>
</div>
<div class="row">
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.low_attenuation, 'form-control-sm') }}</div>
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.high_attenuation, 'form-control-sm') }}</div>
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.flocculation, 'form-control-sm') }}</div>
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.min_temperature, 'form-control-sm') }}</div>
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.max_temperature, 'form-control-sm') }}</div>
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.abv_tolerance, 'form-control-sm') }}</div>
</div>
</div>
</div>
{#- {#-
Recipe Notes Recipe Notes
-#} -#}

View file

@ -15,7 +15,7 @@
from decimal import Decimal from decimal import Decimal
from humulus.couch import get_db from humulus.couch import get_db
from humulus.recipes import FermentableForm, HopForm, RecipeForm from humulus.recipes import FermentableForm, HopForm, RecipeForm, YeastForm
def test_create(client, app): def test_create(client, app):
@ -29,7 +29,10 @@ def test_create(client, app):
'efficiency': '65', 'efficiency': '65',
'name': 'Test', 'name': 'Test',
'notes': 'Test', 'notes': 'Test',
'volume': '5.5' 'volume': '5.5',
'yeast-name': 'Test',
'yeast-low_attenuation': '60',
'yeast-high_attenuation': '75',
} }
response = client.post('/recipes/create', data=data) response = client.post('/recipes/create', data=data)
assert response.status_code == 302 assert response.status_code == 302
@ -55,6 +58,41 @@ def test_info(client):
assert b'Awesome Lager' in response.data assert b'Awesome Lager' in response.data
def test_yeast_form_doc(app):
"""Evaluates conditionals in generation of doc from a yeast form."""
yeast = YeastForm()
yeast.name.data = 'Test'
yeast.low_attenuation.data = Decimal('60')
yeast.high_attenuation.data = Decimal('75')
assert yeast.doc == {
'name': 'Test',
'low_attenuation': '60',
'high_attenuation': '75'
}
yeast.type.data = 'Dry'
yeast.code.data = 'INIS-001'
yeast.lab.data = 'Inland Island'
yeast.flocculation.data = 'Low'
yeast.min_temperature.data = Decimal('40')
yeast.max_temperature.data = Decimal('50')
yeast.abv_tolerance.data = Decimal('15')
assert yeast.doc == {
'name': 'Test',
'low_attenuation': '60',
'high_attenuation': '75',
'flocculation': 'Low',
'type': 'Dry',
'code': 'INIS-001',
'lab': 'Inland Island',
'min_temperature': '40',
'max_temperature': '50',
'abv_tolerance': '15'
}
def test_recipe_form_doc(app): def test_recipe_form_doc(app):
"""Test if a recipeform can be turned into a document. """Test if a recipeform can be turned into a document.
@ -64,6 +102,18 @@ def test_recipe_form_doc(app):
with app.app_context(): with app.app_context():
recipe = RecipeForm() recipe = RecipeForm()
recipe.name.data = 'Test'
recipe.efficiency.data = Decimal('65')
recipe.volume.data = Decimal('5.5')
recipe.notes.data = 'This is a test'
assert recipe.doc == {
'name': 'Test',
'efficiency': '65',
'volume': '5.5',
'notes': 'This is a test',
}
ferm = FermentableForm() ferm = FermentableForm()
ferm.name.data = 'Test' ferm.name.data = 'Test'
ferm.type.data = 'Grain' ferm.type.data = 'Grain'
@ -78,12 +128,14 @@ def test_recipe_form_doc(app):
hop.duration.data = Decimal('60') hop.duration.data = Decimal('60')
hop.amount.data = Decimal('0.5') hop.amount.data = Decimal('0.5')
recipe.name.data = 'Test' yeast = YeastForm()
recipe.efficiency.data = Decimal('65') yeast.name.data = 'Test'
recipe.volume.data = Decimal('5.5') yeast.low_attenuation.data = '70'
recipe.notes.data = 'This is a test' yeast.high_attenuation.data = '75'
recipe.fermentables = [ferm] recipe.fermentables = [ferm]
recipe.hops = [hop] recipe.hops = [hop]
recipe.yeast = yeast
assert recipe.doc == { assert recipe.doc == {
'name': 'Test', 'name': 'Test',
@ -103,5 +155,10 @@ def test_recipe_form_doc(app):
'alpha': '12.5', 'alpha': '12.5',
'duration': '60', 'duration': '60',
'amount': '0.5' 'amount': '0.5'
}] }],
'yeast': {
'name': 'Test',
'low_attenuation': '70',
'high_attenuation': '75'
}
} }