added location admin, updated readme with features and todos
This commit is contained in:
parent
c61e36acfc
commit
e55a312771
36
README.md
36
README.md
|
@ -4,6 +4,17 @@ Pantry inventory management
|
|||
# Inventory management system written in django - python
|
||||
The object of this django app is to keep track of which goods you own, when they will expire, when you should consume them and when you shoud buy more.
|
||||
|
||||
## features
|
||||
- Enter items in your pantry (or other locations, with their location) with their expiry date
|
||||
- Items can have a minimum quantity you always want to keep in the pantry
|
||||
- a shopping list is automatically populated with items whose quantity is below this minimum quantity
|
||||
- You get an overview of items per expiry date so you know what to consume first (or throw away)
|
||||
|
||||
- Extensive search and filtering and grouping on locations, categories, units, expiry date using the auto generated django admin
|
||||
interface
|
||||
- Locations are recursive so things can be in the kitchen pantry closet on the 3rd shelf on the right and still be in
|
||||
the kitchen
|
||||
|
||||
# Getting started
|
||||
`pip3 install django`
|
||||
|
||||
|
@ -29,18 +40,39 @@ The object of this django app is to keep track of which goods you own, when they
|
|||
# feature requests
|
||||
## High
|
||||
- make expirations a calendar view, generate ics file to import
|
||||
- add locations to items
|
||||
- public wishlist
|
||||
- one off shoping list
|
||||
- easy clearing of shopping list
|
||||
- add easy consume view
|
||||
- save date consumed in history
|
||||
|
||||
# medium high
|
||||
- mobile app
|
||||
- (requires rest api?)
|
||||
|
||||
# medium
|
||||
- make work offline
|
||||
- add users
|
||||
- federated? use sqrl instead of passwords?
|
||||
|
||||
# medium low
|
||||
- allow for lending stuff out
|
||||
- auto mailings when things should be returned?
|
||||
- double bookkeeping of where things are if both parties have this set up
|
||||
- ipfs (+ blockchain?)
|
||||
- will be done in a seperate app, oos for inventory
|
||||
|
||||
- make it look something like this https://getbootstrap.com/docs/4.0/examples/dashboard/
|
||||
|
||||
- easy clearing of shopping list
|
||||
|
||||
- figure out average usage of items over time and predict how much to buy in shopping list based on average expiry
|
||||
dates
|
||||
- figure out how long a certain item can last given current stock and average usage
|
||||
|
||||
- easily deploy somewhere (docker? on synology?)
|
||||
|
||||
## low
|
||||
- add recepies
|
||||
- shopping list created based on recepy ingredients
|
||||
- auto proposal of recepy based on next expiry dates
|
||||
- offer to buy things that have been on shopping list for a while online (in bulk/aggregated)
|
||||
|
|
|
@ -8,6 +8,11 @@ class PantryItemInLine(admin.TabularInline):
|
|||
extra = 1
|
||||
|
||||
|
||||
|
||||
class LocationInLine(admin.TabularInline):
|
||||
model = Location
|
||||
extra = 1
|
||||
|
||||
def upper_case_name(obj):
|
||||
return obj.name.upper()
|
||||
upper_case_name.short_description = 'Name'
|
||||
|
@ -18,7 +23,7 @@ def capitalize_name(obj):
|
|||
upper_case_name.short_description = 'Name'
|
||||
|
||||
|
||||
class PantryItemInLineAdmin(admin.ModelAdmin):
|
||||
class PantryItemLineAdmin(admin.ModelAdmin):
|
||||
list_filter = ['expiry_date', 'pantry_item__unit', 'pantry_item', 'pantry_item__min_quantity']
|
||||
search_fields = ['info', 'pantry_item__name', 'pantry_item__info']
|
||||
autocomplete_fields = ['pantry_item']
|
||||
|
@ -47,6 +52,10 @@ class AutocompleteAdmin(admin.ModelAdmin):
|
|||
search_fields = ["name"]
|
||||
|
||||
|
||||
class LocationAdmin(AutocompleteAdmin):
|
||||
inlines = [LocationInLine]
|
||||
|
||||
|
||||
class PantryItemAdmin(admin.ModelAdmin):
|
||||
list_filter = ['category', 'unit', 'min_quantity', 'location']
|
||||
search_fields = ['info', 'name', 'category__name', 'unit__name']
|
||||
|
@ -73,7 +82,7 @@ class PantryItemAdmin(admin.ModelAdmin):
|
|||
)
|
||||
|
||||
admin.site.register(PantryItem, PantryItemAdmin)
|
||||
admin.site.register(PantryItemLine, PantryItemInLineAdmin)
|
||||
admin.site.register(PantryItemLine, PantryItemLineAdmin)
|
||||
admin.site.register(Unit, AutocompleteAdmin)
|
||||
admin.site.register(Category, AutocompleteAdmin)
|
||||
admin.site.register(Location, AutocompleteAdmin)
|
||||
admin.site.register(Location, LocationAdmin)
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# Generated by Django 2.1.2 on 2018-10-07 11:08
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0016_auto_20180930_1409'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ShoppingListItem',
|
||||
fields=[
|
||||
('pantryitem_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='inventory.PantryItem')),
|
||||
],
|
||||
bases=('inventory.pantryitem',),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='pantryitem',
|
||||
name='location',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='inventory.Location'),
|
||||
),
|
||||
]
|
|
@ -46,26 +46,32 @@ class Location(models.Model):
|
|||
return self.name + ' ' + str(self.in_location)
|
||||
return self.name
|
||||
|
||||
|
||||
class PantryItem(models.Model):
|
||||
"""A think you keep in your pantry """
|
||||
name = models.CharField(max_length=200)
|
||||
category = models.ForeignKey(Category, on_delete=models.PROTECT)
|
||||
min_quantity = models.IntegerField(default=1) #, decimal_places=3, max_digits=32)
|
||||
unit = models.ForeignKey(Unit, on_delete=models.PROTECT, null=True)
|
||||
info = models.CharField(max_length=200, null=True, blank=True)
|
||||
# some things don't have a fixed expiry date, like legumes or garlic, we can specify a default expiration for
|
||||
# this.
|
||||
# if expiry duration is set the expiration date for a pantryitemline will be set to now + duration on save
|
||||
# represents days
|
||||
expiry_duration = models.IntegerField(null=True, blank=True)
|
||||
# location is saved on a per pantryitem base, not pantryitemline
|
||||
name = models.CharField(max_length=200)
|
||||
unit = models.ForeignKey(Unit, on_delete=models.PROTECT, null=True)
|
||||
info = models.CharField(max_length=200, null=True, blank=True)
|
||||
# location is saved on a per item base, not itemline
|
||||
# you can have multiple pantries with subpantries
|
||||
# if a pantryitem moves to the kitchen or fridge it is no longer a pantry item
|
||||
location = models.ForeignKey(Location, on_delete=models.PROTECT, null=True)
|
||||
location = models.ForeignKey(Location, on_delete=models.PROTECT, null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ShoppingListItem(PantryItem):
|
||||
"""Items to buy now that aren't meant for the pantry but for imidiate usage"""
|
||||
pass
|
||||
|
||||
|
||||
class PantryItemLine(models.Model):
|
||||
# user?
|
||||
pantry_item = models.ForeignKey(PantryItem, on_delete=models.PROTECT)
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<a class="nav-link" href="{% url 'im:consume' %} ">Consume</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'admin:inventory_pantryitemline_add' %} ">Add</a>
|
||||
<a class="nav-link" href="{% url 'admin:inventory_pantryitem_changelist' %} ">Add</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<li>
|
||||
{{ pi|title }} (We have
|
||||
{{ pi.total_quantity }} {{pi.unit}} but we want at least
|
||||
{{ pi.min_quantity }} {{pi.unit }})
|
||||
{{ pi.min_quantity }} {{pi.unit }} in {{ pi.location}})
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
|
Loading…
Reference in New Issue