Compare commits

...

3 Commits

Author SHA1 Message Date
53b7a1b128 Just PEP8 stuff. 2024-06-26 14:56:29 -04:00
e8c9196fc0 Field help text.
Specify units used.
2024-06-26 14:56:09 -04:00
93b93a1448 make timestamp non-editable.
Hides from admin panel since it's generated automatically.
2024-06-26 14:53:35 -04:00
4 changed files with 217 additions and 25 deletions

View File

@ -7,7 +7,6 @@ from beer.models import Batch, Recipe, Mash, MashStep, \
from yeast.models import Yeast
from config.extras import BREWFATHER_APP_ROOT
from beer.extras import plato_sg
class SampleInline(admin.TabularInline):

View File

@ -0,0 +1,103 @@
# Generated by Django 5.0.6 on 2024-06-26 17:49
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('beer', '0015_batch_fermenter_topup_vol_batch_fermenter_vol_and_more'),
]
operations = [
migrations.AlterModelTableComment(
name='equipmentprofile',
table_comment='Volumes in liters and weights in kg.',
),
migrations.AlterField(
model_name='batch',
name='created_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AlterField(
model_name='equipmentprofile',
name='created_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AlterField(
model_name='equipmentprofile',
name='leaf_hop_trub',
field=models.DecimalField(db_comment='liters/gram', decimal_places=10, default=0.0083454045, max_digits=12),
),
migrations.AlterField(
model_name='equipmentprofile',
name='pellet_hop_trub',
field=models.DecimalField(db_comment='liters/gram', decimal_places=10, default=0.003338162, max_digits=12),
),
migrations.AlterField(
model_name='fermentable',
name='created_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AlterField(
model_name='hop',
name='created_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AlterField(
model_name='mash',
name='created_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AlterField(
model_name='mashstep',
name='created_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AlterField(
model_name='misc',
name='created_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AlterField(
model_name='recipe',
name='created_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AlterField(
model_name='recipefermentable',
name='created_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AlterField(
model_name='recipehop',
name='created_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AlterField(
model_name='recipemisc',
name='created_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AlterField(
model_name='recipeyeast',
name='created_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AlterField(
model_name='supplier',
name='created_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AlterField(
model_name='unit',
name='created_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AlterField(
model_name='userprofile',
name='created_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
]

View File

@ -0,0 +1,68 @@
# Generated by Django 5.0.6 on 2024-06-26 18:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('beer', '0016_alter_equipmentprofile_table_comment_and_more'),
]
operations = [
migrations.AlterField(
model_name='equipmentprofile',
name='batch_volume',
field=models.DecimalField(decimal_places=2, default=5.5, help_text='liters', max_digits=6),
),
migrations.AlterField(
model_name='equipmentprofile',
name='grain_absorption',
field=models.DecimalField(decimal_places=2, default=0.12, help_text='liters/kilogram', max_digits=6),
),
migrations.AlterField(
model_name='equipmentprofile',
name='hlt_deadspace',
field=models.DecimalField(decimal_places=2, default=0.25, help_text='liters', max_digits=6),
),
migrations.AlterField(
model_name='equipmentprofile',
name='kettle_boil_rate',
field=models.DecimalField(decimal_places=2, default=0.5, help_text='liters/hr', max_digits=6),
),
migrations.AlterField(
model_name='equipmentprofile',
name='kettle_deadspace',
field=models.DecimalField(decimal_places=2, default=0.25, help_text='liters', max_digits=6),
),
migrations.AlterField(
model_name='equipmentprofile',
name='kettle_plumbing_loss',
field=models.DecimalField(decimal_places=2, default=0.25, help_text='liters', max_digits=6),
),
migrations.AlterField(
model_name='equipmentprofile',
name='leaf_hop_trub',
field=models.DecimalField(decimal_places=10, default=0.0083454045, help_text='liters/gram', max_digits=12),
),
migrations.AlterField(
model_name='equipmentprofile',
name='mash_ratio',
field=models.DecimalField(decimal_places=2, default=2.6, help_text='liters/kilogram', max_digits=6),
),
migrations.AlterField(
model_name='equipmentprofile',
name='mt_capacity',
field=models.DecimalField(decimal_places=2, default=10, help_text='liters', max_digits=6),
),
migrations.AlterField(
model_name='equipmentprofile',
name='mt_deadspace',
field=models.DecimalField(decimal_places=2, default=0.25, help_text='liters', max_digits=6),
),
migrations.AlterField(
model_name='equipmentprofile',
name='pellet_hop_trub',
field=models.DecimalField(decimal_places=10, default=0.003338162, help_text='liters/gram', max_digits=12),
),
]

View File

@ -14,7 +14,10 @@ logger = logging.getLogger('django')
class CustomModel(models.Model):
""" Custom model class with default fields to use. """
created_date = models.DateTimeField(default=timezone.now)
created_date = models.DateTimeField(
default=timezone.now,
editable=False
)
class Meta:
abstract = True
@ -41,13 +44,13 @@ class Batch(CustomModel):
# Brewday Measurements
# -------------------------------------------------------------------------
## Mash
# Mash
first_runnings = models.DecimalField(
max_digits=8, decimal_places=4, null=True, blank=True)
mash_ph = models.DecimalField(
max_digits=4, decimal_places=3, null=True, blank=True)
## Boil
# Boil
pre_boil_vol = models.DecimalField(
max_digits=8, decimal_places=4, null=True, blank=True)
pre_boil_sg = models.DecimalField(
@ -57,7 +60,7 @@ class Batch(CustomModel):
post_boil_sg = models.DecimalField(
max_digits=5, decimal_places=4, null=True, blank=True)
## Ferment
# Ferment
fermenter_topup_vol = models.DecimalField(
max_digits=8, decimal_places=4, null=True, blank=True)
fermenter_vol = models.DecimalField(
@ -67,11 +70,11 @@ class Batch(CustomModel):
final_sg = models.DecimalField(
max_digits=5, decimal_places=4, null=True, blank=True)
# Properties Needed: (https://braukaiser.com/wiki/index.php/Troubleshooting_Brewhouse_Efficiency)
# Properties Needed:
# braukaiser.com/wiki/index.php/Troubleshooting_Brewhouse_Efficiency
# - Mash Efficiency
# - ABV
# - Attenuation
# - Actual Boil-Off Rate
# - Actual Trub/Chiller Loss
# -------------------------------------------------------------------------
@ -80,7 +83,7 @@ class Batch(CustomModel):
@property
def brewhouse_efficiency(self):
try:
return round(self.boil_extract_kg/self.recipe.total_extract_kg,4)
return round(self.boil_extract_kg/self.recipe.total_extract_kg, 4)
except ZeroDivisionError:
return 0
@ -91,17 +94,23 @@ class Batch(CustomModel):
@property
def conversion_efficiency(self):
""" Calculate conversion efficiency of mash."""
if self.first_runnings is None or self.recipe.fermentable_weight_kg == 0:
if (self.first_runnings is None
or self.recipe.fermentable_weight_kg == 0):
return '-'
return round((sg_plato(self.first_runnings)/self.recipe.fw_max)
* (100-self.recipe.fw_max) / (100-sg_plato(self.first_runnings))
, 4)
* (100-self.recipe.fw_max)
/ (100-sg_plato(self.first_runnings)), 4)
@property
def boil_off_calcualted(self):
return float(self.pre_boil_vol - self.post_boil_vol) * .96
@property
def trub_loss_calculated(self):
transfered_volume = self.fermenter_vol - self.fermenter_topup_vol
return self.post_boil_vol-transfered_volume
@property
def brewfather_url(self):
return '{}/tabs/batches/batch/{}'.format(
@ -144,7 +153,10 @@ class Supplier(CustomModel):
class CustomIngredient(CustomModel):
""" Custom model class with default fields to use. """
created_date = models.DateTimeField(default=timezone.now)
created_date = models.DateTimeField(
default=timezone.now,
editable=False
)
name = models.CharField(max_length=50)
units = models.ForeignKey(Unit, on_delete=models.PROTECT)
unit_cost = models.DecimalField(
@ -386,7 +398,8 @@ class Fermentable(CustomIngredient):
@property
def extract_percent(self):
return ((float(self.potential)-1)*1000/46.17) * (1-float(self.moisture)/100)
return (((float(self.potential)-1)*1000/46.17)
* (1-float(self.moisture)/100))
def __str__(self):
return self.name
@ -479,7 +492,8 @@ class RecipeHop(CustomModel):
+ (self.recipe.original_sg-1)) / 2)
if self.use == 1:
conc = (float((self.hop.alpha/100)) * float(self.quantity)*0.0352739619
conc = (float(self.hop.alpha/100)
* convert(self.quantity, 'g', 'oz')
* 7490/convert(self.recipe.final_volume, 'l', 'gal'))
util = (hop_bonus*1.65*0.000125**average_wort_sg
* ((1-2.71828182845904**(-0.04*self.time)) / 4.15))
@ -575,31 +589,39 @@ class EquipmentProfile(CustomModel):
# Water managment stuff
hlt_deadspace = models.DecimalField(
max_digits=6, decimal_places=2, default=0.25)
max_digits=6, decimal_places=2, default=0.25, help_text='liters')
mt_deadspace = models.DecimalField(
max_digits=6, decimal_places=2, default=0.25)
max_digits=6, decimal_places=2, default=0.25, help_text='liters')
mt_capacity = models.DecimalField(
max_digits=6, decimal_places=2, default=10)
max_digits=6, decimal_places=2, default=10, help_text='liters')
grain_absorption = models.DecimalField(
max_digits=6, decimal_places=2, default=0.12) # gal/lb
max_digits=6, decimal_places=2,
default=0.12, help_text='liters/kilogram')
kettle_deadspace = models.DecimalField(
max_digits=6, decimal_places=2, default=0.25)
max_digits=6, decimal_places=2, default=0.25, help_text='liters')
kettle_plumbing_loss = models.DecimalField(
max_digits=6, decimal_places=2, default=0.25)
max_digits=6, decimal_places=2, default=0.25, help_text='liters')
kettle_boil_rate = models.DecimalField(
max_digits=6, decimal_places=2, default=0.5) # gal/hr
max_digits=6, decimal_places=2,
default=0.5, help_text='liters/hr')
batch_volume = models.DecimalField(
max_digits=6, decimal_places=2, default=5.5)
max_digits=6, decimal_places=2, default=5.5, help_text='liters')
leaf_hop_trub = models.DecimalField(
max_digits=6, decimal_places=4, default=0.0625)
max_digits=12, decimal_places=10,
default=0.0083454045, help_text='liters/gram')
pellet_hop_trub = models.DecimalField(
max_digits=6, decimal_places=4, default=0.025)
max_digits=12, decimal_places=10,
default=0.0033381620, help_text='liters/gram')
hops_remain_kettle = models.BooleanField(default=True)
mash_ratio = models.DecimalField(
max_digits=6, decimal_places=2, default=2.6) # 1.25 qt/lb
max_digits=6, decimal_places=2,
default=2.6, help_text='liters/kilogram')
# Thermal Properties
mt_initial_hear = models.DecimalField(
max_digits=6, decimal_places=4, default=0.74)
mt_heat_loss_hour = models.DecimalField(
max_digits=6, decimal_places=4, default=2.0)
class Meta:
db_table_comment = 'Volumes in liters and weights in kg.'