Home manager is a system to keep track of user's house inventory. Basically it is a small warehousing system. It is mainly focused on groceries and other supplies that need to be purchased on regular basis based on their expiration or consumption. The supplies need to be purchased, stored, used and sometimes removed. Also the supplies are often shared among the whole household and not only used by single user. The system should allow parallel operations over the multiple households as well as in the single household. The user interface should be completely web based with optimization for desktop and mobile device. The first prototype should support just two areas of control over the supplies:
- purchase - it should be possible to list multiple items that need to purchased and in what amounts.
- storage - it should be possible to manage items that exist in the system and in what amounts.
- User - any subject that authenticates to the system and is able to call it's functions. In the first prototype version there will be only two user roles - user and admin. User can do anything in the system with exception of managing other users, this functionality should be handled by admin role only.
- Household - a group of users that share the common assets in the system. Each user can be part of multiple households, each household can have multiple users. In the first prototype version, each user can fully manage the households he is assigned to. Household can be created by any user.
- Item - generic item in the system. The items have name, expiration date, base unit of measure and category.
- Category - items can be grouped into categories, each item can have at most one category.
- Storage - when items exist in the system, it is useful to know where they are and in future what conditions this storage provides that can have impact on item's durability - like difference in temperature between fridge and a pantry.
- Shopping list - when going shopping it is useful (if not even necessary) to prepare a list of items to be purchased. It is worth to keep a history of shopping lists but only in an archived form.
As was mentioned earlier, there are no rights or roles defined for the prototype all users have similar capabilities in the system, the following description of two users serves for more meaningful description of user stories and for possible future extension of the access control system.
- Adam - User A - Typical user of the system. an living in an appartment who wants to have control over the household inventory.
- Beata - User B - Another typical user of the system. Adam's wife who also wants to have control over the common household.
- Pooka - Admin - Administrator of the system.
User stories are stored as issues with label user-story.
- Security
- users must be able to access their household data only
- user data are separated on per-household basis (DB schema based separation is sufficient)
- OAuth2 authorization framework should be used for user authentication
- HTTPS should be used
- Performance
- the system should keep the response times for each API call under 2 seconds (TODO: review this)
- the system should minimize amount API requests - ewbsockets or messaging for UI should be used instead of infinite data refresh loop
- Stability
- the system should not be restarted because of unplanned outages more than once per month
- Reliability
- for the prototype phase no HA is requested
- Capacity
- each household should be able to keep history of one year of using the system (TODO: analyze the data demands after prototype implementation and testing)
- Documentation
- each component of the system must be specified before implementation
- the component specification turns into documentation during implemetation
- the component specifications are part of this Software Guidebook
- the Software Guidebook is updated whenever business or technical requirements change
- user manual is not requested for the prototype
- Portability
- the system must be able to run on Linux and Windows
- the system must not be dependent on any specific hosting solution
- Quality
- each component in the system has to have reasonable amount of unit tests (TODO: study something about reasonable code coverage)
- each component in the system has to have an integration test
- Internationalization
- the prototype must provide English and Czech languages only but with possibility to add other languages seamlessly
- the system must provide a possibility to translate dynamic as well as static texts
- Backup
- there is no backup requested for the prototype
- Extensibility
- the prototype should provide a platform for future extensions like connectivity to some super market APIs, supplies prices, etc.
- Spring - As there is currently no better IoC framework available and I'm really proficient with Spring already.
- OSGi - It's not really necessary for this application but this project should serve also as a playground for prototyping and testing interesting technologies. In this context, I would like to try microservice oriented and event driven architecture based on OSGi.
- Angular2 - It's hot, it's single-page approach, it uses TypeScript on top of that dumb JavaScript
- Decomposition - For the prototype the application is decomposed to frontend and backend part only. Internal decomposition is described in Components chapter but in reality the whole backend is just a single monolithic application. However decomposition in later stages should be prepared as effortless as possible.
- Single model codebase - In previous projects it was almost always necessary to create multiple levels of model classes - DBOs, DTOs and VOs, let's try something old - benefit from JPA entities and easy JSON serialization. It may also be beneficial for later testing of NoSQL databases.
- Automated testing - For each compacted unit of code (basically public methods) there should be a unit test, at least one integration test should be present to prove that the application is able start. UI and REST API testing is not part of scope of the prototype but should be added as soon as the prototype is functional.
There really is not much to say about the context of the simple system as Home manager is in a prototype phase. There is a system and it has it's users and admin. The admin uses UI, REST API and direct SSH access to server to monitor and manage the whole system. Users access the UI to manage and view their household(s).
TODO: add event sourcing technologies - Kafka + MongoDB The prototype version of Home Manager uses pretty straightforward three tier architecture. All data are:
- stored in the PostgreSQL database
- retrieved, processed and provided via REST API by Karaf based Backend server and
- displayed by Angular2 based single-page UI application.
TODO: rework for NoSQL and event based approach (get rid of the ugly diagram) High level components of the system are feature oriented. For the prototype, almost all features are entity based.
UI part of the system should be implemented as an Angular2 single-page app. It is composed of multiple screens (components, pages, whatever) and communicates with the backend via REST API. Following diagram describes the detailed flow inside of the application:
Default page will be shown to unauthenticated users. It will allow users to login and/or register new account. It will communicate with User service to provide following features:
- User registration (#3)
- User login (#4)
- Password reset (#10)
URL path - /
All pages except the default page will display a top menu. It will show:
- Home manager logo
- drop-down menu language selection - the default language to be set shoudl be retrieved from browser information (#11) if this information is missing all the language is not implemented English will be chosen. When the language is changed by the user it is persisted to his account (#12) and the page should refresh with changed localization.
- drop-down menu with:
- user's email address - it doesn't provide any action
- account settings button (#10) - clicking it will take user to Account settings page
- logout button - clicking it will invalidate current authentication token and take user to Default page
- drop-down menu to:
- select household (#29) - clicking it will switch current user's context to the selected household and take user to Inventory page
- edit household - clicking it will take user to Household edit page for selected household
- add new household (#29) - clicking it will take user to Household edit page for new household
All pages except the Default page, Household edit page and Account settings page will display a navigation menu. It will show list of links/buttons to navigate to all available listings in the system:
- Inventory
- Shopping list
- Items page
- Item categories
- Storages
- Storage types
- Shopping list history
- UoMs
It is useful to prepare a common component that will display system entities and their interesting properties in a table. Each row should display information about a single entity and by clicking the row, it should display the detail component for the entity in a hover window. The component will provide:
- table header - dynamically defined according to displayed entity. Filtering and sorting is not a part of the prototype, but the component should be extendable as this functionality will have a high priority in future releases
- Table of values - each entity name will open a Common detail component for the entity, each line will have a "Remove" column on the last position to remove the entity
- Add button - on click it will display a Create hover window
- Internal scrolling (only the table values are scrolled), the header and add button should stay at the same position
URL path - /<entity_name>
Same as common listing, it will be useful to provide a generic component for displaying details about entities in the system. The component should be shown as a hover window over the listing and should display all properties of selected component.
In the addition it should show an "Edit" button that will switch the component to Common edit component and a "Dismiss" button as a cross in top-right corner.
URL path - /<entity_name>/<entity_id>
The same as Common detail component but all entity properties (including name but excluding ID) are displayed as editable text inputs. It provides three buttons:
- Save - will update the system entity to current state of the edit component
- Reset - will reset all local changes to the values saved in the system
- Delete - will remove the entity from the system
Create is the same component as edit but the entity ID is not filled yet.
URL path - /<entity_name>/<entity_id> (stays the same as detail, edit should not be available for bookmarking)
Selecting the "Add new" option from Top menu's Household selection or clicking the icon next to a name of any existing one will open a Common edit component for households. The only exception to other entity editors, the household editor is not shown as hover window but fills the whole page.
User stories covered: (#5, #6)
Selecting the "Account settings" option from Top menu's user name drop-down box will open a Common edit component for user. Same as household edit, the user edit is not shown as hover window but fills the whole page.
This page by default provides possibility to change password.
Clicking the "Inventory" navigation button from Navigation menu will show Common list component for storage items.
URL path - /inventory
Clicking the "Items" navigation button from Navigation menu will show Common list component for items. This page should serve as an example for all other list/edit/create pages in the system (because I'm lazy to do the same mockup again and again).
URL path - /items
Clicking the "Shopping List" navigation button from Navigation menu will show Shopping list page. This page will show the date and when the shopping list was open and list of entered items, their amounts, UoMs and a check box to mark the item as checked. Whenever an item is added to the list, new line for next item appears. In the addition there is a button to purchase all items, close shopping list and move all unchecked items to the new shopping list.
URL path - /shopping-list
Shopping list history provides only listing of closed shopping lists and their details on row click, it has no possibility to add and edit.
TODO: rework data model according to current implementation To provide real data separation for households, each household should have its own DB schema. In the addition the "Master data" schema needs to be present to store data that need to be accessed globally - for the prototype the Master data schema should contain just Users and Households. All other data are stored in household schemas.
Data model should be defined on Java level as JPA entities, the DDL for prototype should be generated fully by JPA framework. TODO: find the best JEE world alternative for Spring Data JPA.
As the entities managed by the system are very similar in many aspects, a common service to provide basic CRUD operations will help to speed up the development. Especially when there is such common component present in frontend. An abstract Entity class should be created that contains following field:
- id: String - ID of the entity, for future extensibility, use String UUIDs for all IDs in the system.
The service should provide following methods:
- create entity - this method will create new entity in the system based on input object, it will create and assign new ID to the entity
- find entity by ID - this method will return the entity identified by given ID
- list entities - this method will list all the entities in the system, it should be parametrized to allow filtering and ordering
- update entity - this method will update the entity in the system according to the given object - the existing entity is fully overwritten with the given one
- delete entity by ID - this method will delete the entity identified by given ID
Special implementation of Common CRUD service focused on master data entity User. Its main entity is User class, descendant of Entity class with following additional fields:
- givenName: String - First name of the user
- surname: String - Last name of the user
- email: String - Email address of the user
- password: String - User's current password (TODO: think about best way to store it)
- laguage: String - Preffered language of the user
Additional methods:
- authenticate user - (#4) this method will check combination of email address and password to determine whether the user exists in the system and whether the password matches the stored value, it will return the User object if successful, throw AuthenticationException otherwise.
- is user online - (#9) this method will check whether the given user is currently online
Special implementation of Common CRUD service focused on master data entity Household. Its main entity is Household class, descendant of Entity class with following additional fields:
- name: String - name of the household - the name shouldn't be unique on the database level, to allow multiple users to create households with same names as other users.
- schemaName: String - name of the database schema where the household data are stored
- schemaPassword: String - password to the database schema of the household (TODO: think about the best way to store it and whether it is really a good approach to to store the information here (maybe an automatically managed Datasource object provided by application server is better?))
Additional methods:
- get households for user - this method will return list of all households that given user is member of
Special implementation of Common CRUD service focused on household data entity Item. Its main entity is Item class, descendant of Entity class with following additional fields:
- name: String - Name of the item (TODO: think about a best way to localize entity names - create some set of default items and fill it to each household? make item a master data entity?)
- description: String - Description of the item (TODO: think of localization the same way as for name)
- category: Category - Category that the item is assigned to
- baseUoM: UoM - base unit of measure for the item
Additional methods:
- get items by category - this method will return all items that belong to given category
Special implementation of Common CRUD service focused on household data entity ItemCategory. Its main entity is ItemCategory class, descendant of Entity class with following additional fields:
- name: String - Name of the item category (TODO: think about a best way to localize entity names - create some set of default item categories and fill it to each household? make item category a master data entity?)
- description: String - Description of the item category (TODO: think of localization the same way as for name)
Special implementation of Common CRUD service focused on household data entity UoM. Its main entity is UoM class, descendant of Entity class with following additional fields:
- name: String - Name of the unit (TODO: think about a best way to localize entity names - create some set of default items and fill it to each household? make item a master data entity?)
- abbreviation: String - common abbreviation of the unit (TODO: think of localization the same way as for name)
- base: UoM - base unit for current unit or null if it's a base unit itself
- ratioToBase: double - ratio to convert the unit to the base unit, or null if it's a base unit itself
Additional methods:
- convert amount - this method converts given amount from one unit to another, only works for units that share the same base unit, otherwise an IllegalArgumentException is thrown
Special implementation of Common CRUD service focused on household data entity Storage. Its main entity is Storage class, descendant of Entity class with following additional fields:
- name: String - Name of the storage (TODO: think about a best way to localize entity names)
- description: String - Description of the item (TODO: think of localization the same way as for name)
- type: StorageType - Type of the storage
Additional methods:
- get storages by type - this method will return all items that belond to given category
Special implementation of Common CRUD service focused on household data entity StorageItem. Its main entity is StorageItem class, descendant of Entity class with following additional fields:
- item: Item - reference to item stored
- uom: UoM - unit of measure used for measuring the stored amount
- amount: double - stored amount of item
- storage: Storage - the storage where the item is stored
Additional methods:
- add item to storage - adds given amount of given item into the given storage
- remove item from storage - removes given amount of given item from the given storage
- list stored items - returns the invetory based on provided filter
Special implementation of Common CRUD service focused on household data entity StorageType. Its main entity is StorageType class, descendant of Entity class with following additional fields:
- name: String - Name of the storage type (TODO: think about a best way to localize entity names - create some set of default storage types and fill it to each household? make storage a master data entity?)
- description: String - Description of the storage type (TODO: think of localization the same way as for name)
Special implementation of Common CRUD service on household data entity ShoppingList. Its main entity is ShoppingList class, descendant of Entity class with following additional fields:
- created: Date - date when the shopping list was open
- closed: Date - date when the shopping list was closed (or null if still open)
- items: List - list of ShoppingItems currently present in the shopping list
Part of the ShoppingList class is ShoppingItem class, descendant of Entity class with following additional fields:
- item: Item - reference to item to be shopped
- uom: UoM - unit of measure used for measuring the wanted amount
- amount: double - wanted amount of item
- shoppingList: ShoppingList - the shopping list where the item is mentioned
- checked: boolean - tag stating that the item should be add to storage after the shopping list is closed
Additional methods:
- get open shopping list - return currently open shopping list
- close shopping list - closes currently open shopping list and moves all its checked items to inventory without storage assigned
- add item to list - adds given amount of given item into the given shopping list
- remove item from list - removes given amount of given item from the given shopping list