aboutsummaryrefslogtreecommitdiffstats
path: root/core.go
blob: 65aff828adc67b51c0e58662ef6bf2bed25806e6 (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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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"`
	Available   uint32       `json:"avail"`
	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"`
	AggregateInfo map[string]string `json:"miscinfo"`
}

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() (*BomMeta, *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}}
	li2 := LineItem{Manufacturer: "Texas Instruments",
		Mpn:      "NE555",
		Elements: []string{"W1", "W2"},
		Offers:   []Offer{o}}
	li3 := LineItem{Manufacturer: "STMicroelectronics",
		Mpn:      "L7905CV",
		Elements: []string{"W1", "W2"},
		Offers:   []Offer{o}}
	//li.AddOffer(o)
	b := NewBom("test01")
	b.AddLineItem(&li)
    // tests that lines don't get duplicated
	b.AddLineItem(&li)
	b.AddLineItem(&li2)
	b.AddLineItem(&li3)
	bm := &BomMeta{Name: "Some Bom", Owner: "Some Owner", Description: "This is such a thing!", HeadVersion: b.Version, Homepage: "http://bommom.memeschemes.com", IsPublicView: true, IsPublicEdit: false}
	return bm, b
}