-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpartkeepr.py
187 lines (149 loc) · 8.06 KB
/
partkeepr.py
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
import io
import json
import os
import requests
class PartKeepr:
def __init__(self, base_url, username, password):
# base_url is something like https://my.partkeepr.host (no trailing slash)
self.base_url = base_url
self.session = requests.Session()
self.session.auth = (username, password)
self.user = self.login()
def login(self):
return self.session.post(self.base_url + "/api/users/login").json()
def get(self, url, params=None):
return self.session.get(self.base_url + url, params=params).json()
def create(self, url, data, params=None):
return self.session.post(self.base_url + url, json=data, params=params).json()
def update(self, url, data, params=None):
return self.session.put(self.base_url + url, json=data, params=params).json()
def delete(self, url, params=None):
self.session.delete(self.base_url + url, params=params)
def upload(self, url, file, params=None):
return self.session.post(self.base_url + url, files=file, params=params).json()
def get_paged(self, url, params=None):
result = []
next_page = url
while next_page:
data = self.get(next_page, params=params)
result.extend(data['hydra:member'])
next_page = data.get('hydra:nextPage')
return result
def get_parts(self, filter=None):
if filter:
params = {'filter': json.dumps([filter])}
else:
params = None
return self.get_paged("/api/parts", params=params)
def get_part(self, part_id):
return self.get("/api/parts/{}".format(part_id))
def get_manufacturers(self):
return self.get_paged("/api/manufacturers")
def get_distributors(self):
return self.get_paged("/api/distributors")
def get_storage_locations(self):
return self.get_paged("/api/storage_locations")
def get_project(self, project_id):
return self.get("/api/projects/{}".format(project_id))
def create_part(self, part):
return self.create("/api/parts", part)
def create_manufacturer(self, manufacturer):
return self.create("/api/manufacturers", manufacturer)
def create_part_manufacturer(self, part_manufacturer):
return self.create("/api/part_manufacturers", part_manufacturer)
def create_part_distributor(self, part_distributor):
return self.create("/api/part_distributors", part_distributor)
def create_storage_location(self, storage_location):
return self.create("/api/storage_locations", storage_location)
def create_project_part(self, project_part):
return self.create("/api/project_parts", project_part)
def update_part(self, part):
return self.update(part['@id'], part)
def update_part_manufacturer(self, part_manufacturer):
return self.update(part_manufacturer['@id'], part_manufacturer)
def update_part_distributor(self, part_distributor):
return self.update(part_distributor['@id'], part_distributor)
def update_project(self, project):
return self.update(project['@id'], project)
def upload_temp_file(self, file):
return self.upload("/api/temp_uploaded_files/upload", {'userfile': file})
def upload_temp_file_from_url(self, url):
return self.create("/api/temp_uploaded_files/upload", {'url': url})
def part_add_stock(self, part_id, quantity):
return self.update(part_id + "/addStock", {'quantity': quantity})
def part_remove_stock(self, part_id, quantity):
return self.update(part_id + "/removeStock", {'quantity': quantity})
def part_set_stock(self, part_id, quantity):
return self.update(part_id + "/setStock", {'quantity': quantity})
def update_part_data(self, part, part_data, distributor, manufacturer_ids_by_name=None):
if not manufacturer_ids_by_name:
print("Getting manufacturers")
manufacturers = self.get_manufacturers()
manufacturer_ids_by_name = dict([(mf['name'].lower(), mf['@id']) for mf in manufacturers])
part_manufacturers = part['manufacturers']
part_manufacturer_ids_by_name = dict([(mf['manufacturer']['name'].lower(), mf['@id']) for mf in part_manufacturers])
# Update description
if part_data['description']:
print(" Updating description")
part['description'] = part_data['description']
# Update manufacturer data if available
if part_data['manufacturer']:
print(" Manufacturer: {}".format(part_data['manufacturer']))
if part_data['manufacturer'].lower() in part_manufacturer_ids_by_name:
print(" Found part manufacturer entry")
part_mf_id = part_manufacturer_ids_by_name[part_data['manufacturer'].lower()]
for mf in part_manufacturers:
if mf['@id'] == part_mf_id:
print(" Updating part manufacturer entry")
mf['partNumber'] = part_data['manufacturer_part_no']
result = self.update_part_manufacturer(mf)
else:
if part_data['manufacturer'].lower() in manufacturer_ids_by_name:
print(" Found manufacturer in database")
mf_id = manufacturer_ids_by_name[part_data['manufacturer'].lower()]
else:
print(" Creating manufacturer entry")
mf_new = {'name': part_data['manufacturer']}
result = self.create_manufacturer(mf_new)
mf_id = result['@id']
manufacturer_ids_by_name[part_data['manufacturer'].lower()] = mf_id
print(" Creating part manufacturer entry")
part_mf_new = {'manufacturer': {'@id': mf_id}, 'partNumber': part_data['manufacturer_part_no']}
result = self.create_part_manufacturer(part_mf_new)
part_mf_id = result['@id']
print(" Linking part manufacturer to part")
part['manufacturers'].append({'@id': part_mf_id})
else:
print(" No manufacturer found!")
# Update pricing data
if part_data['prices']:
new_price = part_data['prices'][0]['price'] # Always use lowest quantity group
print(" Updating price from {} to {:.5f}".format(distributor['price'], new_price))
distributor['price'] = new_price
result = self.update_part_distributor(distributor)
# Update image if no image attachment is present and distributor has a photo
if not [a['isImage'] for a in part['attachments']] and part_data['photo']:
print(" Updating photo")
if isinstance(part_data['photo'], io.IOBase):
result = self.upload_temp_file(part_data['photo'])
part_data['photo'].close()
os.remove(part_data['photo'].name)
else:
result = self.upload_temp_file_from_url(part_data['photo'])
file_id = result['image']['@id']
part['attachments'].append({'@id': file_id})
# Update parameters
# For now, all parameters are treated as text and the PartKeepr Unit system is not used.
if part_data['parameters']:
print(" Updating parameters")
for param_name, param_value in part_data['parameters'].items():
param_found = False
for j, existing_param in enumerate(part['parameters']):
if existing_param['name'] == param_name:
part['parameters'][j]['stringValue'] = param_value
param_found = True
break
if not param_found:
part['parameters'].append({'name': param_name, 'stringValue': param_value})
# Update part in database
return self.update_part(part)