Initial Database Setup

main
DustyP 4 years ago
parent 89e485efd7
commit 32153093cb

@ -0,0 +1,15 @@
package quartermaster
type Category struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
}
type CategoryService interface {
Category(int) (*Category, error)
AddCategory(*Category) (*Category, error)
UpdateCategory(*Category) error
DeleteCategory(*Category) error
GetItems(*Category) ([]*Item, error)
}

@ -0,0 +1,14 @@
package main
import (
"os"
"github.com/dustinpianalto/quartermaster/internal/postgres"
"github.com/dustinpianalto/quartermaster/internal/services"
)
func main() {
var migrationsVersion uint = 2 // Update when there is a new migration
postgres.ConnectDatabase(os.Getenv("DATABASE_URL"), migrationsVersion)
services.InitServices()
}

@ -0,0 +1,13 @@
module github.com/dustinpianalto/quartermaster
go 1.17
require (
github.com/gobuffalo/here v0.6.0 // indirect
github.com/golang-migrate/migrate/v4 v4.15.1 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-multierror v1.1.0 // indirect
github.com/lib/pq v1.10.4 // indirect
github.com/markbates/pkger v0.17.1 // indirect
go.uber.org/atomic v1.6.0 // indirect
)

1465
go.sum

File diff suppressed because it is too large Load Diff

@ -0,0 +1,15 @@
package quartermaster
type Group struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
}
type GroupService interface {
Group(int) (*Group, error)
AddGroup(*Group) (*Group, error)
UpdateGroup(*Group) error
DeleteGroup(*Group) error
GetItems(*Group) ([]*Item, error)
}

@ -0,0 +1,65 @@
package postgres
import (
"database/sql"
"log"
"github.com/dustinpianalto/quartermaster"
)
type categoryService struct {
db *sql.DB
}
func (s categoryService) Category(id int) (*quartermaster.Category, error) {
var c quartermaster.Category
queryString := "SELECT id, name, description FROM categories WHERE id = $1"
row := s.db.QueryRow(queryString, id)
err := row.Scan(&c.ID, &c.Name, &c.Description)
if err != nil {
return nil, err
}
return &c, nil
}
func (s categoryService) AddCategory(c *quartermaster.Category) (*quartermaster.Category, error) {
queryString := "INSERT INTO categories (name, description) VALUES ($1, $2) RETURNING id"
err := s.db.QueryRow(queryString, c.Name, c.Description).Scan(&c.ID)
return c, err
}
func (s categoryService) UpdateCategory(c *quartermaster.Category) error {
queryString := "UPDATE categories SET name = $2, description = $3 WHERE id = $1"
_, err := s.db.Exec(queryString, c.ID, c.Name, c.Description)
return err
}
func (s categoryService) DeleteCategory(c *quartermaster.Category) error {
queryString := "DELETE FROM categories WHERE id = $1"
_, err := s.db.Exec(queryString, c.ID)
return err
}
func (s categoryService) GetItems(c *quartermaster.Category) ([]*quartermaster.Item, error) {
var items []*quartermaster.Item
queryString := "SELECT item_id FROM x_items_categories WHERE category_id = $1"
rows, err := s.db.Query(queryString, c.ID)
if err != nil {
return nil, err
}
for rows.Next() {
var id int
err = rows.Scan(&id)
if err != nil {
log.Println(err)
continue
}
item, err := ItemService.Item(id)
if err != nil {
log.Println(err)
continue
}
items = append(items, item)
}
return items, nil
}

@ -0,0 +1,69 @@
package postgres
import (
"database/sql"
"errors"
"fmt"
"log"
"github.com/dustinpianalto/quartermaster"
migrate "github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database/postgres"
_ "github.com/golang-migrate/migrate/v4/source/pkger"
_ "github.com/lib/pq"
"github.com/markbates/pkger"
)
var (
ItemService quartermaster.ItemService
NutritionService quartermaster.NutritionService
LocationService quartermaster.LocationService
VitaminService quartermaster.VitaminService
GroupService quartermaster.GroupService
CategoryService quartermaster.CategoryService
)
func ConnectDatabase(dbConnString string, version uint) {
db, err := sql.Open("postgres", dbConnString)
if err != nil {
panic(fmt.Sprintf("Can't connect to the database. %v", err))
}
db.SetMaxOpenConns(75) // The RDS instance has a max of 75 open connections
db.SetMaxIdleConns(5)
db.SetConnMaxLifetime(300)
log.Println("Database Connected")
err = runMigrations(db, version)
if err != nil {
log.Fatal(err)
}
log.Println("Migrations Completed")
initServices(db)
log.Println("Postgres Database Initialized")
}
func runMigrations(db *sql.DB, version uint) error {
_ = pkger.Include("/internal/postgres/migrations")
driver, err := postgres.WithInstance(db, &postgres.Config{})
if err != nil {
return err
}
m, err := migrate.NewWithDatabaseInstance("pkger:///internal/postgres/migrations", "postgres", driver)
if err != nil {
log.Fatalln(err)
}
if err := m.Migrate(version); errors.Is(err, migrate.ErrNoChange) {
log.Println(err)
} else if err != nil {
return err
}
return nil
}
func initServices(db *sql.DB) {
ItemService = itemService{db: db}
NutritionService = nutritionService{db: db}
LocationService = locationService{db: db}
VitaminService = vitaminService{db: db}
GroupService = groupService{db: db}
CategoryService = categoryService{db: db}
}

@ -0,0 +1,65 @@
package postgres
import (
"database/sql"
"log"
"github.com/dustinpianalto/quartermaster"
)
type groupService struct {
db *sql.DB
}
func (s groupService) Group(id int) (*quartermaster.Group, error) {
var g quartermaster.Group
queryString := "SELECT id, name, description FROM groups WHERE id = $1"
row := s.db.QueryRow(queryString, id)
err := row.Scan(&g.ID, &g.Name, &g.Description)
if err != nil {
return nil, err
}
return &g, nil
}
func (s groupService) AddGroup(g *quartermaster.Group) (*quartermaster.Group, error) {
queryString := "INSERT INTO groups (name, description) VALUES ($1, $2) RETURNING id"
err := s.db.QueryRow(queryString, g.Name, g.Description).Scan(&g.ID)
return g, err
}
func (s groupService) UpdateGroup(g *quartermaster.Group) error {
queryString := "UPDATE groups SET name = $2, description = $3 WHERE id = $1"
_, err := s.db.Exec(queryString, g.ID, g.Name, g.Description)
return err
}
func (s groupService) DeleteGroup(g *quartermaster.Group) error {
queryString := "DELETE FROM groups WHERE id = $1"
_, err := s.db.Exec(queryString, g.ID)
return err
}
func (s groupService) GetItems(g *quartermaster.Group) ([]*quartermaster.Item, error) {
var items []*quartermaster.Item
queryString := "SELECT item_id FROM x_items_groups WHERE group_id = $1"
rows, err := s.db.Query(queryString, g.ID)
if err != nil {
return nil, err
}
for rows.Next() {
var id int
err = rows.Scan(&id)
if err != nil {
log.Println(err)
continue
}
item, err := ItemService.Item(id)
if err != nil {
log.Println(err)
continue
}
items = append(items, item)
}
return items, nil
}

@ -0,0 +1,138 @@
package postgres
import (
"database/sql"
"log"
"github.com/dustinpianalto/quartermaster"
)
type itemService struct {
db *sql.DB
}
func (s itemService) Item(id int) (*quartermaster.Item, error) {
var i quartermaster.Item
queryString := "SELECT id, name, description, size, unit, barcode, nutrition_id FROM items WHERE id = $1"
row := s.db.QueryRow(queryString, id)
var nutrition_id sql.NullInt32
err := row.Scan(&i.ID, &i.Name, &i.Description, &i.Size, &i.Unit, &i.Barcode, &nutrition_id)
if err != nil {
return nil, err
}
if nutrition_id.Valid {
n, err := NutritionService.Nutrition(int(nutrition_id.Int32))
if err != nil {
return nil, err
}
i.Nutrition = n
} else {
i.Nutrition = nil
}
return &i, nil
}
func (s itemService) AddItem(i *quartermaster.Item, l *quartermaster.Location) (*quartermaster.Item, error) {
var err error
if i.ID == 0 {
if i.Nutrition != nil {
i.Nutrition, err = NutritionService.AddNutrition(i.Nutrition)
if err != nil {
log.Println(err)
}
}
queryString := "INSERT INTO items (name, description, size, unit, barcode, nutrition_id) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id"
err := s.db.QueryRow(queryString, i.Name, i.Description, i.Size, i.Unit, i.Barcode, i.Nutrition.ID).Scan(&i.ID)
if err != nil {
return nil, err
}
}
queryString := "INSERT INTO x_items_locations (item_id, location_id, count) VALUES ($1, $2, 1) ON DUPLICATE KEY UPDATE count = count + 1"
_, err = s.db.Exec(queryString, i.ID, l.ID)
return i, err
}
func (s itemService) AddCategory(i *quartermaster.Item, c *quartermaster.Category) error {
queryString := "INSERT INTO x_items_categories (item_id, category_id) VALUES ($1, $2) ON DUPLICATE KEY DO NOTHING"
_, err := s.db.Exec(queryString, i.ID, c.ID)
return err
}
func (s itemService) AddGroup(i *quartermaster.Item, g *quartermaster.Group) error {
queryString := "INSERT INTO x_items_groups (item_id, group_id) VALUES ($1, $2) ON DUPLICATE KEY DO NOTHING"
_, err := s.db.Exec(queryString, i.ID, g.ID)
return err
}
func (s itemService) RemoveCategory(i *quartermaster.Item, c *quartermaster.Category) error {
queryString := "DELETE FROM x_items_categories WHERE item_id = $1 AND category_id = $2"
_, err := s.db.Exec(queryString, i.ID, c.ID)
return err
}
func (s itemService) RemoveGroup(i *quartermaster.Item, g *quartermaster.Group) error {
queryString := "DELETE FROM x_items_groups WHERE item_id = $1 AND group_id = $2"
_, err := s.db.Exec(queryString, i.ID, g.ID)
return err
}
func (s itemService) DeleteItem(i *quartermaster.Item) error {
queryString := "DELETE FROM items WHERE id = $1"
_, err := s.db.Exec(queryString, i.ID)
return err
}
func (s itemService) GetItemByBarcode(b string) (*quartermaster.Item, error) {
queryString := "SELECT id FROM items WHERE barcode = $1"
row := s.db.QueryRow(queryString, b)
var id int
err := row.Scan(&id)
if err != nil {
return nil, err
}
return s.Item(id)
}
func (s itemService) RemoveItem(i *quartermaster.Item, l *quartermaster.Location) error {
queryString := "UPDATE x_items_locations SET count = count - 1 WHERE item_id = $1 AND location_id = $2 RETURNING count"
var count int
err := s.db.QueryRow(queryString, i.ID, l.ID).Scan(&count)
if err != nil {
return err
}
if count <= 0 {
queryString = "DELETE FROM x_items_locations WHERE item_id = $1 AND location_id = $2"
_, err := s.db.Exec(queryString, i.ID, l.ID)
return err
}
return nil
}
func (s itemService) MoveItem(i *quartermaster.Item, old, new *quartermaster.Location) error {
err := s.RemoveItem(i, old)
if err != nil {
return err
}
_, err = s.AddItem(i, new)
return err
}
func (s itemService) UpdateItem(i *quartermaster.Item) error {
var err error
if i.Nutrition != nil {
if i.Nutrition.ID == 0 {
i.Nutrition, err = NutritionService.AddNutrition(i.Nutrition)
if err != nil {
return err
}
} else {
err = NutritionService.UpdateNutrition(i.Nutrition)
if err != nil {
return err
}
}
}
queryString := "UPDATE items SET name = $2, description = $3, size = $4, unit = $5, barcode = $6, nutrition_id = $7, WHERE id = $1"
_, err = s.db.Exec(queryString, i.ID, i.Name, i.Description, i.Size, i.Unit, i.Barcode, i.Nutrition.ID)
return err
}

@ -0,0 +1,131 @@
package postgres
import (
"database/sql"
"log"
"github.com/dustinpianalto/quartermaster"
)
type locationService struct {
db *sql.DB
}
func (s locationService) Location(id int) (*quartermaster.Location, error) {
var l quartermaster.Location
var parent_id sql.NullInt32
queryString := "SELECT id, name, description, parent_id FROM locations WHERE id = $1"
row := s.db.QueryRow(queryString, id)
err := row.Scan(&l.ID, &l.Name, &l.Description, &parent_id)
if err != nil {
return nil, err
}
if parent_id.Valid {
p, err := s.Location(int(parent_id.Int32))
if err != nil {
return nil, err
}
l.Parent = p
}
return &l, nil
}
func (s locationService) AddLocation(l *quartermaster.Location) (*quartermaster.Location, error) {
queryString := "INSERT INTO locations (name, description, parent_id VALUES ($1, $2, $3) RETURNING id"
var err error
if l.Parent != nil {
err = s.db.QueryRow(queryString, l.Name, l.Description, l.Parent.ID).Scan(&l.ID)
} else {
err = s.db.QueryRow(queryString, l.Name, l.Description, nil).Scan(&l.ID)
}
return l, err
}
func (s locationService) UpdateLocation(l *quartermaster.Location) error {
queryString := "UPDATE locations SET name = $2, description = $3, parent_id = $4 WHERE id = $1"
var err error
if l.Parent != nil {
_, err = s.db.Exec(queryString, l.ID, l.Name, l.Description, l.Parent.ID)
} else {
_, err = s.db.Exec(queryString, l.ID, l.Name, l.Description, nil)
}
return err
}
func (s locationService) DeleteLocation(l *quartermaster.Location) error {
queryString := "DELETE FROM locations WHERE id = $1"
_, err := s.db.Exec(queryString, l.ID)
return err
}
func (s locationService) GetChildren(l *quartermaster.Location) ([]*quartermaster.Location, error) {
var locations []*quartermaster.Location
queryString := "SELECT id FROM locations WHERE parent_id = $1"
rows, err := s.db.Query(queryString, l.ID)
if err != nil {
return nil, err
}
for rows.Next() {
var id int
err = rows.Scan(&id)
if err != nil {
log.Println(err)
continue
}
location, err := s.Location(id)
if err != nil {
log.Println(err)
continue
}
locations = append(locations, location)
}
return locations, nil
}
func (s locationService) GetItems(l *quartermaster.Location) (map[*quartermaster.Item]int, error) {
items := make(map[*quartermaster.Item]int)
queryString := "SELECT item_id, count FROM x_items_locations WHERE location_id = $1"
rows, err := s.db.Query(queryString, l.ID)
if err != nil {
return nil, err
}
for rows.Next() {
var id, count int
err = rows.Scan(&id, &count)
if err != nil {
log.Println(err)
continue
}
item, err := ItemService.Item(id)
if err != nil {
log.Println(err)
continue
}
items[item] = count
}
return items, nil
}
func (s locationService) GetTopLocations() ([]*quartermaster.Location, error) {
var locations []*quartermaster.Location
queryString := "SELECT id FROM locations WHERE parent_id IS NULL"
rows, err := s.db.Query(queryString)
if err != nil {
return nil, err
}
for rows.Next() {
var id int
err = rows.Scan(&id)
if err != nil {
log.Println(err)
continue
}
l, err := s.Location(id)
if err != nil {
log.Println(err)
continue
}
locations = append(locations, l)
}
return locations, nil
}

@ -0,0 +1,15 @@
BEGIN;
DROP TABLE IF EXISTS x_items_groups;
DROP TABLE IF EXISTS x_items_categories;
DROP TABLE IF EXISTS x_items_locations;
DROP TABLE IF EXISTS groups;
DROP TABLE IF EXISTS categories;
DROP TABLE IF EXISTS vitamins;
DROP TABLE IF EXISTS items;
DROP TABLE IF EXISTS locations;
DROP TABLE IF EXISTS nutrition;
DROP TYPE unit;
DROP TYPE vitamin;
COMMIT;

@ -0,0 +1,125 @@
BEGIN;
CREATE TABLE IF NOT EXISTS locations (
id SERIAL PRIMARY KEY ,
name VARCHAR(30) NOT NULL,
description TEXT NOT NULL,
parent_id INTEGER,
CONSTRAINT fk_parent
FOREIGN KEY (parent_id)
REFERENCES locations (id)
ON DELETE SET NULL
);
CREATE TABLE IF NOT EXISTS groups (
id SERIAL PRIMARY KEY ,
name VARCHAR(30) NOT NULL,
description TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS categories (
id SERIAL PRIMARY KEY ,
name VARCHAR(30) NOT NULL,
description TEXT NOT NULL
);
CREATE TYPE unit AS ENUM (
'Teaspoon',
'Tablespoon',
'Cup',
'Ounce',
'Gram',
'Pound'
);
CREATE TABLE IF NOT EXISTS nutrition (
id SERIAL PRIMARY KEY ,
unit unit NOT NULL,
calories FLOAT NOT NULL,
fat FLOAT NOT NULL,
sodium FLOAT NOT NULL,
protein FLOAT NOT NULL
);
CREATE TYPE vitamin AS ENUM (
'A',
'B',
'C',
'Iron'
);
CREATE TABLE IF NOT EXISTS vitamins (
nutrition_id INTEGER NOT NULL,
vitamin vitamin NOT NULL,
amount FLOAT NOT NULL,
CONSTRAINT fk_nutrition
FOREIGN KEY (nutrition_id)
REFERENCES nutrition(id)
ON DELETE CASCADE,
CONSTRAINT uniq_nutrition_vitamin
UNIQUE (nutrition_id, vitamin)
);
CREATE TABLE IF NOT EXISTS items (
id SERIAL PRIMARY KEY ,
name VARCHAR(30) NOT NULL,
description TEXT NOT NULL,
size FLOAT NOT NULL,
unit unit NOT NULL,
barcode VARCHAR(100),
nutrition_id INTEGER,
CONSTRAINT fk_item_nutrition
FOREIGN KEY (nutrition_id)
REFERENCES nutrition (id)
ON DELETE SET NULL,
CONSTRAINT uniq_barcode
UNIQUE (barcode)
);
CREATE TABLE IF NOT EXISTS x_items_locations (
item_id INTEGER NOT NULL,
location_id INTEGER NOT NULL,
count INTEGER NOT NULL,
CONSTRAINT fk_item
FOREIGN KEY (item_id)
REFERENCES items (id)
ON DELETE CASCADE,
CONSTRAINT fk_location
FOREIGN KEY (location_id)
REFERENCES locations (id)
ON DELETE CASCADE,
CONSTRAINT uniq_item_location
UNIQUE (item_id, location_id)
);
CREATE TABLE IF NOT EXISTS x_items_categories (
item_id INTEGER NOT NULL,
category_id INTEGER NOT NULL,
CONSTRAINT fk_item
FOREIGN KEY (item_id)
REFERENCES items (id)
ON DELETE CASCADE,
CONSTRAINT fk_category
FOREIGN KEY (category_id)
REFERENCES categories (id)
ON DELETE CASCADE,
CONSTRAINT uniq_item_category
UNIQUE (item_id, category_id)
);
CREATE TABLE IF NOT EXISTS x_items_groups (
item_id INTEGER NOT NULL,
group_id INTEGER NOT NULL,
CONSTRAINT fk_item
FOREIGN KEY (item_id)
REFERENCES items (id)
ON DELETE CASCADE,
CONSTRAINT fk_group
FOREIGN KEY (group_id)
REFERENCES groups (id)
ON DELETE CASCADE,
CONSTRAINT uniq_item_group
UNIQUE (item_id, group_id)
);
COMMIT;

@ -0,0 +1 @@
ALTER TYPE unit ADD VALUE 'Individual';

@ -0,0 +1,116 @@
package postgres
import (
"database/sql"
"log"
"github.com/dustinpianalto/quartermaster"
)
type nutritionService struct {
db *sql.DB
}
func (s nutritionService) Nutrition(id int) (*quartermaster.Nutrition, error) {
var n quartermaster.Nutrition
queryString := "SELECT id, unit, calories, fat, sodium, protein FROM nutrition WHERE id = $1"
row := s.db.QueryRow(queryString, id)
err := row.Scan(&n.ID, &n.Unit, &n.Calories, &n.Fat, &n.Sodium, &n.Protein)
if err != nil {
return nil, err
}
return &n, nil
}
func (s nutritionService) AddNutrition(n *quartermaster.Nutrition) (*quartermaster.Nutrition, error) {
queryString := "INSERT INTO nutrition (unit, calories, fat, sodium, protein) VALUES ($1, $2, $3, $4, $5) RETURNING id"
err := s.db.QueryRow(queryString, n.Unit, n.Calories, n.Fat, n.Sodium, n.Protein).Scan(&n.ID)
if err != nil {
return nil, err
}
for _, v := range n.Vitamins {
err := VitaminService.AddVitamin(v, n)
if err != nil {
s.DeleteNutrition(n)
return nil, err
}
}
return n, err
}
func (s nutritionService) UpdateNutrition(n *quartermaster.Nutrition) error {
queryString := "UPDATE nutrition SET unit = $2, calories = $3, fat = $4, sodium = $5, protein = $6 WHERE id = $1"
_, err := s.db.Exec(queryString, n.ID, n.Unit, n.Calories, n.Fat, n.Sodium, n.Protein)
currVitamins, _ := VitaminService.GetNutritionVitamins(n)
for _, v := range n.Vitamins {
VitaminService.UpdateVitamin(v, n)
}
outloop:
for _, v := range currVitamins {
for _, w := range n.Vitamins {
if v == w {
continue outloop
}
}
VitaminService.DeleteVitamin(v, n)
}
return err
}
func (s nutritionService) DeleteNutrition(n *quartermaster.Nutrition) error {
queryString := "DELETE FROM nutrition WHERE nutrition_id = $1"
_, err := s.db.Exec(queryString, n.ID)
return err
}
type vitaminService struct {
db *sql.DB
}
func (s vitaminService) Vitamin(vitamin quartermaster.VitaminType, n *quartermaster.Nutrition) (*quartermaster.Vitamin, error) {
var v quartermaster.Vitamin
queryString := "SELECT vitamin, amount FROM vitamins WHERE vitamin = $1 AND nutrition_id = $2"
row := s.db.QueryRow(queryString, vitamin, n.ID)
err := row.Scan(&v.Vitamin, &v.Amount)
if err != nil {
return nil, err
}
return &v, nil
}
func (s vitaminService) AddVitamin(v *quartermaster.Vitamin, n *quartermaster.Nutrition) error {
queryString := "INSERT INTO vitamins (nutrition_id, vitamin, amount) VALUES ($1, $2, $3)"
_, err := s.db.Exec(queryString, n.ID, v.Vitamin, v.Amount)
return err
}
func (s vitaminService) UpdateVitamin(v *quartermaster.Vitamin, n *quartermaster.Nutrition) error {
queryString := "INSERT INTO vitamins (nutrition_id, vitamin, amount) VALUES ($1, $2, $3) ON DUPLICATE KEY UPDATE amount = $3"
_, err := s.db.Exec(queryString, n.ID, v.Vitamin, v.Amount)
return err
}
func (s vitaminService) DeleteVitamin(v *quartermaster.Vitamin, n *quartermaster.Nutrition) error {
queryString := "DELETE FROM vitamins WHERE vitamin = $1 AND nutrition_id = $2"
_, err := s.db.Exec(queryString, v.Vitamin, n.ID)
return err
}
func (s vitaminService) GetNutritionVitamins(n *quartermaster.Nutrition) ([]*quartermaster.Vitamin, error) {
var vitamins []*quartermaster.Vitamin
queryString := "SELECT vitamin, amount FROM vitamins WHERE nutrition_id = $1"
rows, err := s.db.Query(queryString, n.ID)
if err != nil {
return nil, err
}
for rows.Next() {
var vitamin quartermaster.Vitamin
err := rows.Scan(&vitamin.Vitamin, &vitamin.Amount)
if err != nil {
log.Println(err)
continue
}
vitamins = append(vitamins, &vitamin)
}
return vitamins, nil
}

@ -0,0 +1,27 @@
package services
import (
"log"
"github.com/dustinpianalto/quartermaster"
"github.com/dustinpianalto/quartermaster/internal/postgres"
)
var (
ItemService quartermaster.ItemService
NutritionService quartermaster.NutritionService
LocationService quartermaster.LocationService
VitaminService quartermaster.VitaminService
GroupService quartermaster.GroupService
CategoryService quartermaster.CategoryService
)
func InitServices() {
ItemService = postgres.ItemService
NutritionService = postgres.NutritionService
LocationService = postgres.LocationService
VitaminService = postgres.VitaminService
GroupService = postgres.GroupService
CategoryService = postgres.CategoryService
log.Println("Services Initialized")
}

@ -0,0 +1,27 @@
package quartermaster
import "database/sql"
type Item struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Size float32 `json:"size"`
Unit Unit `json:"unit"`
Barcode sql.NullString `json:"barcode"`
Nutrition *Nutrition `json:"nutrition,omitempty"`
}
type ItemService interface {
Item(int) (*Item, error)
AddItem(*Item, *Location) (*Item, error)
UpdateItem(*Item) error
MoveItem(item *Item, old *Location, new *Location) error
RemoveItem(*Item, *Location) error
DeleteItem(*Item) error
GetItemByBarcode(barcode string) (*Item, error)
AddGroup(*Item, *Group) error
AddCategory(*Item, *Category) error
RemoveGroup(*Item, *Group) error
RemoveCategory(*Item, *Category) error
}

@ -0,0 +1,18 @@
package quartermaster
type Location struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Parent *Location `json:"parent,omitempty"`
}
type LocationService interface {
Location(int) (*Location, error)
AddLocation(*Location) (*Location, error)
UpdateLocation(*Location) error
DeleteLocation(*Location) error
GetChildren(*Location) ([]*Location, error)
GetItems(*Location) (map[*Item]int, error)
GetTopLocations() ([]*Location, error)
}

@ -0,0 +1,31 @@
package quartermaster
type Nutrition struct {
ID int `json:"id"`
Unit Unit `json:"unit"`
Calories float32 `json:"calories"`
Fat float32 `json:"fat"`
Sodium float32 `json:"sodium"`
Protein float32 `json:"protein"`
Vitamins []*Vitamin `json:"vitamins"`
}
type Vitamin struct {
Vitamin VitaminType `json:"vitamin"`
Amount float32 `json:"amount"`
}
type NutritionService interface {
Nutrition(int) (*Nutrition, error)
AddNutrition(*Nutrition) (*Nutrition, error)
UpdateNutrition(*Nutrition) error
DeleteNutrition(*Nutrition) error
}
type VitaminService interface {
Vitamin(VitaminType, *Nutrition) (*Vitamin, error)
AddVitamin(*Vitamin, *Nutrition) error
UpdateVitamin(*Vitamin, *Nutrition) error
DeleteVitamin(*Vitamin, *Nutrition) error
GetNutritionVitamins(*Nutrition) ([]*Vitamin, error)
}

@ -0,0 +1,56 @@
package quartermaster
type Unit int
const (
Teaspoon Unit = iota
Tablespoon
Cup
Ounce
Gram
Pound
Individual
)
func (u Unit) String() string {
switch u {
case Teaspoon:
return "Teaspoon"
case Tablespoon:
return "Tablespoon"
case Cup:
return "Cup"
case Ounce:
return "Ounce"
case Gram:
return "Gram"
case Pound:
return "Pound"
case Individual:
return "Individual"
}
return "Unknown"
}
type VitaminType int
const (
A VitaminType = iota
B
C
Iron
)
func (v VitaminType) String() string {
switch v {
case A:
return "A"
case B:
return "B"
case C:
return "C"
case Iron:
return "Iron"
}
return "Unknown"
}
Loading…
Cancel
Save