aboutsummaryrefslogtreecommitdiffstats
path: root/core.go
blob: da92854eed25e248684142771d01f476625f4c80 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package main

import (
	"time"
)

type OfferPrice struct {
	Currency string  `json:"currency"`
	MinQty   uint32  `json:"min_qty"`
	Price    float32 `json:"price"`
}

type Offer struct {
	Distributor string       `json:"distributor_name"`
	Sku         string       `json:"sku"`
	Url         string       `json:"distributor_url"`
	Comment     string       `json:"comment"`
	Prices      []OfferPrice `json:"prices"`
}

type LineItem struct {
	Manufacturer string   `json:"manufacturer"`
	Mpn          string   `json:"mpn"`
	Description  string   `json:"description"`
	FormFactor   string   `json:"form_factor"` // type:string
	Specs        string   `json:"specs"`       // comma seperated list
	Comment      string   `json:"comment"`
	Tag          string   `json:"tag"`      // comma seperated list
	Category     string   `json:"category"` // hierarchy as comma seperated list
	Elements     []string `json:"elements"`
	Offers       []Offer  `json:"offers"`
}

func (li *LineItem) Id() string {
	return li.Manufacturer + "::" + li.Mpn
}

// The main anchor of a BOM as a cohesive whole, with a name and permissions.
// Multiple BOMs are associated with a single BomMeta; the currently active one
// is the 'head'.
type BomMeta struct {
	Name         string `json:"name"`
	Owner        string `json:"owner_name"`
	Description  string `json:"description"`
	HeadVersion  string `json:"head_version"`
	Homepage     Url    `json:"homepage_url"`
	IsPublicView bool   `json:"is_publicview",omitempty`
	IsPublicEdit bool   `json:"is_publicedit",omitempty`
}

// An actual list of parts/elements. Intended to be immutable once persisted. 
type Bom struct {
	Version string `json:"version"`
	// TODO: unix timestamp?
	Created time.Time `json:"created_ts"`
	// "where did this BOM come from?"
	Progeny   string     `json:"progeny",omitifempty`
	LineItems []LineItem `json:"line_items"`
}

func NewBom(version string) *Bom {
	return &Bom{Version: version, Created: time.Now()}
}

func (b *Bom) GetLineItem(mfg, mpn string) *LineItem {
	for _, li := range b.LineItems {
		if li.Manufacturer == mfg && li.Mpn == mpn {
			return &li
		}
	}
	return nil
}

func (b *Bom) AddLineItem(li *LineItem) error {
	if eli := b.GetLineItem(li.Manufacturer, li.Mpn); eli != nil {
		return Error("This BOM already had an identical LineItem")
	}
	b.LineItems = append(b.LineItems, *li)
	return nil
}

func (b *Bom) Validate() error {
	if !isShortName(b.Version) {
		return Error("version not a ShortName: \"" + b.Version + "\"")
	}
	if b.Created.IsZero() {
		return Error("created timestamp not defined")
	}
	return nil
}

func (bm *BomMeta) Validate() error {
	if !isShortName(bm.Name) {
		return Error("name not a ShortName: \"" + bm.Name + "\"")
	}
	if !isShortName(bm.Owner) {
		return Error("owner name not a ShortName: \"" + bm.Owner + "\"")
	}
	return nil
}

// ---------- testing
func makeTestBom() *Bom {
	op1 := OfferPrice{Currency: "usd", Price: 1.0, MinQty: 1}
	op2 := OfferPrice{Currency: "usd", Price: 0.8, MinQty: 100}
	o := Offer{Sku: "A123", Distributor: "Acme", Prices: []OfferPrice{op1, op2}}
	//o.AddOfferPrice(op1)
	//o.AddOfferPrice(op2)
	li := LineItem{Manufacturer: "WidgetCo",
		Mpn:      "WIDG0001",
		Elements: []string{"W1", "W2"},
		Offers:   []Offer{o}}
	//li.AddOffer(o)
	b := NewBom("test01")
	b.AddLineItem(&li)
	return b
}