mirror of
https://github.com/shouptech/humulus.git
synced 2026-02-03 19:39:43 +00:00
Add yeast
This commit is contained in:
parent
c74ae966a3
commit
98404e38ef
3 changed files with 154 additions and 13 deletions
|
|
@ -20,7 +20,7 @@ from flask import Blueprint, flash, redirect, render_template, url_for
|
|||
from flask_wtf import FlaskForm
|
||||
from wtforms import (Form, StringField, DecimalField, TextAreaField, FieldList,
|
||||
FormField, SelectField)
|
||||
from wtforms.validators import DataRequired
|
||||
from wtforms.validators import DataRequired, Optional
|
||||
|
||||
from humulus.couch import get_doc_or_404, put_doc
|
||||
|
||||
|
|
@ -85,6 +85,62 @@ class HopForm(Form):
|
|||
'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):
|
||||
"""Form for recipes."""
|
||||
name = StringField('Name', validators=[DataRequired()])
|
||||
|
|
@ -102,6 +158,7 @@ class RecipeForm(FlaskForm):
|
|||
min_entries=0,
|
||||
max_entries=20
|
||||
)
|
||||
yeast = FormField(YeastForm)
|
||||
|
||||
@property
|
||||
def doc(self):
|
||||
|
|
@ -109,15 +166,21 @@ class RecipeForm(FlaskForm):
|
|||
|
||||
Used for putting into CouchDB.
|
||||
"""
|
||||
return {
|
||||
recipe = {
|
||||
'name': self.name.data,
|
||||
'efficiency': str(self.efficiency.data),
|
||||
'volume': str(self.volume.data),
|
||||
'notes': self.notes.data,
|
||||
'fermentables': [f.doc for f in self.fermentables],
|
||||
'hops': [h.doc for h in self.hops],
|
||||
'notes': self.notes.data
|
||||
}
|
||||
|
||||
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'))
|
||||
def create():
|
||||
|
|
@ -127,7 +190,6 @@ def create():
|
|||
response = put_doc(form.doc)
|
||||
flash('Created recipe: {}'.format(form.name.data), 'success')
|
||||
return redirect(url_for('recipes.info', id=response['_id']))
|
||||
|
||||
return render_template('recipes/create.html', form=form)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,28 @@
|
|||
<button type="button" id="add-hop" class="btn btn-secondary btn-sm">Add a hop</button>
|
||||
</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
|
||||
-#}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
from decimal import Decimal
|
||||
|
||||
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):
|
||||
|
|
@ -29,7 +29,10 @@ def test_create(client, app):
|
|||
'efficiency': '65',
|
||||
'name': '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)
|
||||
assert response.status_code == 302
|
||||
|
|
@ -55,6 +58,41 @@ def test_info(client):
|
|||
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):
|
||||
"""Test if a recipeform can be turned into a document.
|
||||
|
||||
|
|
@ -64,6 +102,18 @@ def test_recipe_form_doc(app):
|
|||
with app.app_context():
|
||||
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.name.data = 'Test'
|
||||
ferm.type.data = 'Grain'
|
||||
|
|
@ -78,12 +128,14 @@ def test_recipe_form_doc(app):
|
|||
hop.duration.data = Decimal('60')
|
||||
hop.amount.data = Decimal('0.5')
|
||||
|
||||
recipe.name.data = 'Test'
|
||||
recipe.efficiency.data = Decimal('65')
|
||||
recipe.volume.data = Decimal('5.5')
|
||||
recipe.notes.data = 'This is a test'
|
||||
yeast = YeastForm()
|
||||
yeast.name.data = 'Test'
|
||||
yeast.low_attenuation.data = '70'
|
||||
yeast.high_attenuation.data = '75'
|
||||
|
||||
recipe.fermentables = [ferm]
|
||||
recipe.hops = [hop]
|
||||
recipe.yeast = yeast
|
||||
|
||||
assert recipe.doc == {
|
||||
'name': 'Test',
|
||||
|
|
@ -103,5 +155,10 @@ def test_recipe_form_doc(app):
|
|||
'alpha': '12.5',
|
||||
'duration': '60',
|
||||
'amount': '0.5'
|
||||
}]
|
||||
}],
|
||||
'yeast': {
|
||||
'name': 'Test',
|
||||
'low_attenuation': '70',
|
||||
'high_attenuation': '75'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue