aboutsummaryrefslogtreecommitdiffstats
path: root/octopart/bom_quote.py
diff options
context:
space:
mode:
Diffstat (limited to 'octopart/bom_quote.py')
-rw-r--r--octopart/bom_quote.py85
1 files changed, 85 insertions, 0 deletions
diff --git a/octopart/bom_quote.py b/octopart/bom_quote.py
new file mode 100644
index 0000000..9c7e087
--- /dev/null
+++ b/octopart/bom_quote.py
@@ -0,0 +1,85 @@
+# Section 1
+# Convert csv file into line items and queries
+# This code assumes a file format similar to the one on the
+# Arduino BOM
+import csv
+
+
+csv_file = open("arduino_bom.csv", "r")
+csv_reader = csv.DictReader(csv_file)
+line_items = []
+queries = []
+for line_item in csv_reader:
+ # Skip line items without part numbers and manufacturers
+ if not line_item['Part Number'] or not line_item['Manufacturer']:
+ continue
+ line_items.append(line_item)
+ queries.append({'mpn': line_item['Part Number'],
+ 'brand': line_item['Manufacturer'],
+ 'reference': len(line_items) - 1})
+
+
+# Section 2
+# Send queries to REST API for part matching.
+import json
+import urllib
+
+
+results = []
+for i in range(0, len(queries), 20):
+ # Batch queries in groups of 20, query limit of
+ # parts match endpoint
+ batched_queries = queries[i: i + 20]
+
+ url = 'http://octopart.com/api/v3/parts/match?queries=%s' \
+ % urllib.quote(json.dumps(batched_queries))
+ url += '&apikey=e3d61a07'
+ data = urllib.urlopen(url).read()
+ response = json.loads(data)
+ print response
+
+ # Record results for analysis
+ results.extend(response['results'])
+
+
+# Section 3
+# Analyze results sent back by Octopart API
+from decimal import Decimal
+
+
+print "Found %s line items in BOM." % len(line_items)
+# Price BOM
+hits = 0
+total_avg_price = 0
+for result in results:
+ line_item = line_items[result['reference']]
+ if len(result['items']) == 0:
+ print "Did not find match on line item %s" % line_item
+ continue
+
+ # Get pricing from the first item for desired quantity
+ quantity = Decimal(line_items[result['reference']]['Qty'])
+ prices = []
+ for offer in result['items'][0]['offers']:
+ if 'USD' not in offer['prices'].keys():
+ continue
+ price = None
+ for price_tuple in offer['prices']['USD']:
+ # Find correct price break
+ if price_tuple[0] > quantity:
+ break
+ # Cast pricing string to Decimal for precision
+ # calculations
+ price = Decimal(price_tuple[1])
+ if price is not None:
+ prices.append(price)
+
+ if len(prices) == 0:
+ print "Did not find pricing on line item %s" % line_item
+ continue
+ avg_price = quantity * sum(prices) / len(prices)
+ total_avg_price += avg_price
+ hits += 1
+
+print "Matched on %.2f of BOM, total average price is USD %.2f" % ( \
+ hits / float(len(line_items)), total_avg_price)