OpenPartsLibrary 0.1.7__tar.gz → 0.1.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openpartslibrary-0.1.7 → openpartslibrary-0.1.9/OpenPartsLibrary.egg-info}/PKG-INFO +3 -1
- {openpartslibrary-0.1.7 → openpartslibrary-0.1.9}/OpenPartsLibrary.egg-info/SOURCES.txt +1 -0
- {openpartslibrary-0.1.7/OpenPartsLibrary.egg-info → openpartslibrary-0.1.9}/PKG-INFO +3 -1
- {openpartslibrary-0.1.7 → openpartslibrary-0.1.9}/README.md +3 -1
- openpartslibrary-0.1.9/openpartslibrary/cli.py +51 -0
- openpartslibrary-0.1.9/openpartslibrary/db.py +218 -0
- openpartslibrary-0.1.9/openpartslibrary/models.py +153 -0
- {openpartslibrary-0.1.7 → openpartslibrary-0.1.9}/setup.py +1 -1
- openpartslibrary-0.1.7/openpartslibrary/db.py +0 -87
- openpartslibrary-0.1.7/openpartslibrary/models.py +0 -71
- {openpartslibrary-0.1.7 → openpartslibrary-0.1.9}/LICENSE +0 -0
- {openpartslibrary-0.1.7 → openpartslibrary-0.1.9}/OpenPartsLibrary.egg-info/dependency_links.txt +0 -0
- {openpartslibrary-0.1.7 → openpartslibrary-0.1.9}/OpenPartsLibrary.egg-info/requires.txt +0 -0
- {openpartslibrary-0.1.7 → openpartslibrary-0.1.9}/OpenPartsLibrary.egg-info/top_level.txt +0 -0
- {openpartslibrary-0.1.7 → openpartslibrary-0.1.9}/openpartslibrary/__init__.py +0 -0
- {openpartslibrary-0.1.7 → openpartslibrary-0.1.9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: OpenPartsLibrary
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.9
|
4
4
|
Summary: Python library for creating a database of hardware components for manufacturing
|
5
5
|
Home-page: https://github.com/alekssadowski95/OpenPartsLibrary
|
6
6
|
Author: Aleksander Sadowski
|
@@ -130,6 +130,8 @@ Creating parts from a parts list in a Excel-spreadsheet (*.xlsx). Take note, tha
|
|
130
130
|
```python
|
131
131
|
pl.create_parts_from_spreadsheet('C:/Users/Work/Documents/Github/OpenPartsLibrary/openpartslibrary/sample/parts_data_sample.xlsx')
|
132
132
|
```
|
133
|
+
## Database structure
|
134
|
+
<img src="./openpartslibrary/images/Database-structure-openpartslibrary.png" width="100%" alt="OpenPartsLibrary database structure"></img>
|
133
135
|
|
134
136
|
## Part schema
|
135
137
|
This table outlines the `Part` properties used in the OpenPartsLibrary.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: OpenPartsLibrary
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.9
|
4
4
|
Summary: Python library for creating a database of hardware components for manufacturing
|
5
5
|
Home-page: https://github.com/alekssadowski95/OpenPartsLibrary
|
6
6
|
Author: Aleksander Sadowski
|
@@ -130,6 +130,8 @@ Creating parts from a parts list in a Excel-spreadsheet (*.xlsx). Take note, tha
|
|
130
130
|
```python
|
131
131
|
pl.create_parts_from_spreadsheet('C:/Users/Work/Documents/Github/OpenPartsLibrary/openpartslibrary/sample/parts_data_sample.xlsx')
|
132
132
|
```
|
133
|
+
## Database structure
|
134
|
+
<img src="./openpartslibrary/images/Database-structure-openpartslibrary.png" width="100%" alt="OpenPartsLibrary database structure"></img>
|
133
135
|
|
134
136
|
## Part schema
|
135
137
|
This table outlines the `Part` properties used in the OpenPartsLibrary.
|
@@ -101,6 +101,8 @@ Creating parts from a parts list in a Excel-spreadsheet (*.xlsx). Take note, tha
|
|
101
101
|
```python
|
102
102
|
pl.create_parts_from_spreadsheet('C:/Users/Work/Documents/Github/OpenPartsLibrary/openpartslibrary/sample/parts_data_sample.xlsx')
|
103
103
|
```
|
104
|
+
## Database structure
|
105
|
+
<img src="./openpartslibrary/images/Database-structure-openpartslibrary.png" width="100%" alt="OpenPartsLibrary database structure"></img>
|
104
106
|
|
105
107
|
## Part schema
|
106
108
|
This table outlines the `Part` properties used in the OpenPartsLibrary.
|
@@ -137,4 +139,4 @@ Credits:
|
|
137
139
|
icon: <a href="https://www.flaticon.com/free-icons/database" title="database icons">Database icons created by Smashicons - Flaticon</a>
|
138
140
|
|
139
141
|
## How to Contribute
|
140
|
-
This section helps in understanding how to contribute to the project.
|
142
|
+
This section helps in understanding how to contribute to the project.
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class PartsLibraryCLI:
|
2
|
+
def __init__(self):
|
3
|
+
''' CLI to be moved to its own object OpenPartsLibraryCLI in cli.py
|
4
|
+
'''
|
5
|
+
'''
|
6
|
+
command_history = []
|
7
|
+
while True:
|
8
|
+
os.system('cls')
|
9
|
+
print('************************************************************')
|
10
|
+
print('* OpenPartsLibrary *')
|
11
|
+
print('* Aleksander Sadowski, Nandana Gopala Krishnan (C) 2025 *')
|
12
|
+
print('************************************************************')
|
13
|
+
pl.display()
|
14
|
+
commands = 'add part', 'add supplier', 'modify part', 'modify supplier', 'remove part', 'remove supplier'
|
15
|
+
commands_str = ''
|
16
|
+
for command in commands:
|
17
|
+
commands_str = commands_str + '[' + str(command) + '] '
|
18
|
+
print('Commands: ' + commands_str)
|
19
|
+
print('Last commands:' + str([command for command in command_history][-5:]))
|
20
|
+
input_cmd = input('Enter command: ')
|
21
|
+
command_history.append(input_cmd)
|
22
|
+
if input_cmd in commands:
|
23
|
+
if input_cmd == 'add part':
|
24
|
+
pass
|
25
|
+
if input_cmd == 'add supplier':
|
26
|
+
pass
|
27
|
+
if input_cmd == 'modify part':
|
28
|
+
os.system('cls')
|
29
|
+
print('************************************************************')
|
30
|
+
print('* OpenPartsLibrary *')
|
31
|
+
print('* Aleksander Sadowski, Nandana Gopala Krishnan (C) 2025 *')
|
32
|
+
print('************************************************************')
|
33
|
+
pl.display_parts()
|
34
|
+
selected_part = int(input('Enter part id: '))
|
35
|
+
pass
|
36
|
+
if input_cmd == 'modify supplier':
|
37
|
+
os.system('cls')
|
38
|
+
print('************************************************************')
|
39
|
+
print('* OpenPartsLibrary *')
|
40
|
+
print('* Aleksander Sadowski, Nandana Gopala Krishnan (C) 2025 *')
|
41
|
+
print('************************************************************')
|
42
|
+
print()
|
43
|
+
pl.display_suppliers()
|
44
|
+
selected_part = int(input('Enter supplier id: '))
|
45
|
+
pass
|
46
|
+
if input_cmd == 'remove part':
|
47
|
+
pass
|
48
|
+
if input_cmd == 'remove supplier':
|
49
|
+
pass
|
50
|
+
'''
|
51
|
+
pass
|
@@ -0,0 +1,218 @@
|
|
1
|
+
from sqlalchemy import create_engine
|
2
|
+
from sqlalchemy.orm import sessionmaker
|
3
|
+
|
4
|
+
import pandas as pd
|
5
|
+
|
6
|
+
from datetime import datetime
|
7
|
+
|
8
|
+
from .models import Base, Part, Supplier, File, Component, ComponentComponent
|
9
|
+
|
10
|
+
import uuid
|
11
|
+
|
12
|
+
import os
|
13
|
+
|
14
|
+
|
15
|
+
class PartsLibrary:
|
16
|
+
def __init__(self):
|
17
|
+
import os
|
18
|
+
sqlite_path = os.path.join(os.path.dirname(__file__), 'data', 'parts.db')
|
19
|
+
print(sqlite_path)
|
20
|
+
self.engine = create_engine('sqlite:///' + sqlite_path)
|
21
|
+
|
22
|
+
Base.metadata.create_all(self.engine)
|
23
|
+
|
24
|
+
self.session_factory = sessionmaker(bind=self.engine)
|
25
|
+
self.session = self.session_factory()
|
26
|
+
|
27
|
+
def display(self):
|
28
|
+
# Print the components table to the terminal
|
29
|
+
component_component_table = pd.read_sql_table(table_name="component_component", con=self.engine)
|
30
|
+
print('ComponentComponent:')
|
31
|
+
print('===================')
|
32
|
+
print(component_component_table)
|
33
|
+
print('')
|
34
|
+
|
35
|
+
# Print the components table to the terminal
|
36
|
+
components_table = pd.read_sql_table(table_name="components", con=self.engine)
|
37
|
+
print('Components:')
|
38
|
+
print('===========')
|
39
|
+
print(components_table)
|
40
|
+
print('')
|
41
|
+
|
42
|
+
# Print the parts table to the terminal
|
43
|
+
part_table = pd.read_sql_table(table_name="parts", con=self.engine)
|
44
|
+
print('Parts:')
|
45
|
+
print('======')
|
46
|
+
print(part_table)
|
47
|
+
print('')
|
48
|
+
|
49
|
+
# Print the suppliers table to the terminal
|
50
|
+
supplier_table = pd.read_sql_table(table_name="suppliers", con=self.engine)
|
51
|
+
print('Suppliers:')
|
52
|
+
print('==========')
|
53
|
+
print(supplier_table)
|
54
|
+
print('')
|
55
|
+
|
56
|
+
# Print the files table to the terminal
|
57
|
+
files_table = pd.read_sql_table(table_name="files", con=self.engine)
|
58
|
+
print('Files:')
|
59
|
+
print('==========')
|
60
|
+
print(files_table)
|
61
|
+
print('')
|
62
|
+
|
63
|
+
def display_reduced(self):
|
64
|
+
# Print the parts table to the terminal in reduced form
|
65
|
+
pass
|
66
|
+
|
67
|
+
def display_parts(self):
|
68
|
+
# Print the parts table to the terminal
|
69
|
+
part_table = pd.read_sql_table(table_name="parts", con=self.engine)
|
70
|
+
print('Parts:')
|
71
|
+
print('======')
|
72
|
+
print(part_table)
|
73
|
+
print('')
|
74
|
+
|
75
|
+
def display_suppliers(self):
|
76
|
+
# Print the suppliers table to the terminal
|
77
|
+
supplier_table = pd.read_sql_table(table_name="suppliers", con=self.engine)
|
78
|
+
print('Suppliers:')
|
79
|
+
print('==========')
|
80
|
+
print(supplier_table)
|
81
|
+
print('')
|
82
|
+
|
83
|
+
def display_files(self):
|
84
|
+
# Print the files table to the terminal
|
85
|
+
files_table = pd.read_sql_table(table_name="files", con=self.engine)
|
86
|
+
print('Files:')
|
87
|
+
print('==========')
|
88
|
+
print(files_table)
|
89
|
+
print('')
|
90
|
+
|
91
|
+
def delete_all(self):
|
92
|
+
print('[ INFO ] Clearing the parts library.')
|
93
|
+
self.session.query(ComponentComponent).delete()
|
94
|
+
self.session.query(Component).delete()
|
95
|
+
self.session.query(Part).delete()
|
96
|
+
self.session.query(Supplier).delete()
|
97
|
+
self.session.query(File).delete()
|
98
|
+
self.session.commit()
|
99
|
+
|
100
|
+
directory_to_empty = os.path.join(os.path.dirname(__file__), 'data', 'files')
|
101
|
+
|
102
|
+
for filename in os.listdir(directory_to_empty):
|
103
|
+
filepath = os.path.join(directory_to_empty, filename)
|
104
|
+
if os.path.isfile(filepath) and filename != "README.md":
|
105
|
+
os.remove(filepath)
|
106
|
+
print(f"[ INFO ] Deleted: {filename}")
|
107
|
+
|
108
|
+
def total_value(self):
|
109
|
+
from decimal import Decimal
|
110
|
+
all_parts = self.session.query(Part).all()
|
111
|
+
|
112
|
+
total_value = Decimal(0.0)
|
113
|
+
for part in all_parts:
|
114
|
+
total_value = Decimal(total_value) + (Decimal(part.unit_price) * part.quantity)
|
115
|
+
|
116
|
+
return total_value
|
117
|
+
|
118
|
+
def create_parts_from_spreadsheet(self, file_path):
|
119
|
+
df = pd.read_excel(file_path)
|
120
|
+
|
121
|
+
parts = []
|
122
|
+
for _, row in df.iterrows():
|
123
|
+
part = Part(
|
124
|
+
uuid=row["uuid"],
|
125
|
+
number=row["number"],
|
126
|
+
name=row["name"],
|
127
|
+
description=row.get("description", "No description"),
|
128
|
+
revision=str(row.get("revision", "1")),
|
129
|
+
lifecycle_state=row.get("lifecycle_state", "In Work"),
|
130
|
+
owner=row.get("owner", "system"),
|
131
|
+
date_created=row.get("date_created", datetime.utcnow()),
|
132
|
+
date_modified=row.get("date_modified", datetime.utcnow()),
|
133
|
+
material=row.get("material"),
|
134
|
+
mass=row.get("mass"),
|
135
|
+
dimension_x=row.get("dimension_x"),
|
136
|
+
dimension_y=row.get("dimension_y"),
|
137
|
+
dimension_z=row.get("dimension_z"),
|
138
|
+
quantity=row.get("quantity", 0),
|
139
|
+
cad_reference=row.get("cad_reference"),
|
140
|
+
attached_documents_reference=row.get("attached_documents_reference"),
|
141
|
+
lead_time=row.get("lead_time"),
|
142
|
+
make_or_buy=row.get("make_or_buy"),
|
143
|
+
manufacturer_number=row.get("manufacturer_number"),
|
144
|
+
unit_price=row.get("unit_price"),
|
145
|
+
currency=row.get("currency")
|
146
|
+
)
|
147
|
+
parts.append(part)
|
148
|
+
|
149
|
+
self.session.add_all(parts)
|
150
|
+
self.session.commit()
|
151
|
+
print(f"Imported {len(parts)} parts successfully from {file_path}")
|
152
|
+
|
153
|
+
def create_suppliers_from_spreadsheet(self, file_path):
|
154
|
+
self.session.query(Supplier).delete()
|
155
|
+
self.session.commit()
|
156
|
+
|
157
|
+
df = pd.read_excel(file_path)
|
158
|
+
|
159
|
+
suppliers = []
|
160
|
+
for _, row in df.iterrows():
|
161
|
+
supplier = Supplier(
|
162
|
+
uuid=row.get("uuid", str(uuid.uuid4())),
|
163
|
+
name=row["name"],
|
164
|
+
description=row.get("description", "No description"),
|
165
|
+
street=row.get("street"),
|
166
|
+
city=row.get("city"),
|
167
|
+
postal_code=row.get("postal_code"),
|
168
|
+
house_number=row.get("house_number"),
|
169
|
+
country=row.get("country")
|
170
|
+
)
|
171
|
+
suppliers.append(supplier)
|
172
|
+
|
173
|
+
self.session.add_all(suppliers)
|
174
|
+
self.session.commit()
|
175
|
+
print(f"Imported {len(suppliers)} suppliers successfully from {file_path}")
|
176
|
+
|
177
|
+
def display_suppliers_table(self):
|
178
|
+
from tabulate import tabulate
|
179
|
+
import textwrap
|
180
|
+
query="SELECT * FROM suppliers"
|
181
|
+
suppliers_table = pd.read_sql_query(sql=query, con=self.engine)
|
182
|
+
suppliers_table["house_number"] = suppliers_table["house_number"].astype(str)
|
183
|
+
suppliers_table["postal_code"] = suppliers_table["postal_code"].astype(str)
|
184
|
+
pd.set_option('display.max_columns', 7)
|
185
|
+
pd.set_option('display.width', 200)
|
186
|
+
print(tabulate(suppliers_table, headers='keys', tablefmt='github'))
|
187
|
+
|
188
|
+
def add_sample_suppliers(self):
|
189
|
+
from .models import Supplier
|
190
|
+
siemens = Supplier(
|
191
|
+
uuid=str(uuid.uuid4()),
|
192
|
+
name="Siemens AG",
|
193
|
+
description="Siemens AG is a global powerhouse focusing on the areas of electrification, automation, and digitalization. One of the world's largest producers of energy-efficient, resource-saving technologies",
|
194
|
+
street="Werner-von-Siemens-Straße",
|
195
|
+
house_number="1",
|
196
|
+
postal_code="80333",
|
197
|
+
city="Munich",
|
198
|
+
country="Germany",
|
199
|
+
date_created=datetime.utcnow(),
|
200
|
+
date_modified=datetime.utcnow()
|
201
|
+
)
|
202
|
+
|
203
|
+
kuka = Supplier(
|
204
|
+
uuid=str(uuid.uuid4()),
|
205
|
+
name="KUKA AG",
|
206
|
+
description="The KUKA Group is an internationally active automation group with revenue of approximately EUR 3.7 billion and approximately 15,000 employees. As one of the world's leading providers of intelligent, resource-efficient automation solutions, KUKA offers industrial robots, autonomous mobile robots (AMR) including controllers, software, and cloud-based digital services, as well as fully networked production systems for various industries and markets, such as automotive with a focus on e-mobility and batteries, electronics, metal and plastics, consumer goods, food, e-commerce, retail, and healthcare",
|
207
|
+
street="Zugspitzstraße",
|
208
|
+
house_number="140",
|
209
|
+
postal_code="86165",
|
210
|
+
city="Augsburg",
|
211
|
+
country="Germany",
|
212
|
+
date_created=datetime.utcnow(),
|
213
|
+
date_modified=datetime.utcnow()
|
214
|
+
)
|
215
|
+
self.session.add(siemens)
|
216
|
+
self.session.add(kuka)
|
217
|
+
self.session.commit()
|
218
|
+
print("Added sample suppliers: Siemens AG and KUKA AG")
|
@@ -0,0 +1,153 @@
|
|
1
|
+
from sqlalchemy import Column, Integer, String, Float, DateTime, Numeric, Enum, ForeignKey, UniqueConstraint
|
2
|
+
from sqlalchemy.orm import DeclarativeBase, relationship, backref
|
3
|
+
from datetime import datetime
|
4
|
+
|
5
|
+
|
6
|
+
class Base(DeclarativeBase):
|
7
|
+
pass
|
8
|
+
|
9
|
+
class ComponentComponent(Base):
|
10
|
+
__tablename__ = 'component_component'
|
11
|
+
|
12
|
+
id = Column(Integer, primary_key=True)
|
13
|
+
|
14
|
+
parent_component_id = Column(Integer, ForeignKey("components.id"), nullable=False)
|
15
|
+
child_component_id = Column(Integer, ForeignKey("components.id"), nullable=False)
|
16
|
+
|
17
|
+
__table_args__ = (UniqueConstraint("parent_component_id", "child_component_id", name="uq_parent_child"),)
|
18
|
+
|
19
|
+
def __repr__(self):
|
20
|
+
return f"<ComponentComponent(id={self.id}, parent_component_id={self.parent_component_id}, child_component_id={self.child_component_id})>"
|
21
|
+
|
22
|
+
class Component(Base):
|
23
|
+
__tablename__ = 'components'
|
24
|
+
|
25
|
+
id = Column(Integer, primary_key=True)
|
26
|
+
uuid = Column(String(32), unique=True, nullable=False)
|
27
|
+
name = Column(String(200), nullable=False)
|
28
|
+
|
29
|
+
part = relationship('Part', back_populates='component', uselist=False)
|
30
|
+
|
31
|
+
# children: Components that this component is parent of
|
32
|
+
children = relationship(
|
33
|
+
"Component",
|
34
|
+
secondary="component_component",
|
35
|
+
primaryjoin=id == ComponentComponent.parent_component_id,
|
36
|
+
secondaryjoin=id == ComponentComponent.child_component_id,
|
37
|
+
backref=backref("parents", lazy="joined"),
|
38
|
+
lazy="joined",
|
39
|
+
)
|
40
|
+
|
41
|
+
class File(Base):
|
42
|
+
__tablename__ = 'files'
|
43
|
+
|
44
|
+
id = Column(Integer, primary_key=True)
|
45
|
+
uuid = Column(String(32), unique=True, nullable=False)
|
46
|
+
name = Column(String(200), nullable=False)
|
47
|
+
description = Column(String(1000))
|
48
|
+
date_created = Column(DateTime, default=datetime.utcnow)
|
49
|
+
date_modified = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
50
|
+
|
51
|
+
part_id = Column(ForeignKey('parts.id'))
|
52
|
+
part = relationship('Part', back_populates='cad_reference')
|
53
|
+
|
54
|
+
|
55
|
+
class Part(Base):
|
56
|
+
__tablename__ = 'parts'
|
57
|
+
|
58
|
+
id = Column(Integer, primary_key=True)
|
59
|
+
uuid = Column(String(32), unique=True, nullable=False)
|
60
|
+
number = Column(String(50), nullable=False)
|
61
|
+
name = Column(String(200), nullable=False)
|
62
|
+
description = Column(String(1000), default="No description")
|
63
|
+
revision = Column(String(10), default="1")
|
64
|
+
lifecycle_state = Column(String(50), default="In Work")
|
65
|
+
owner = Column(String(100), default="system")
|
66
|
+
date_created = Column(DateTime, default=datetime.utcnow)
|
67
|
+
date_modified = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
68
|
+
material = Column(String(100))
|
69
|
+
mass = Column(Float)
|
70
|
+
dimension_x = Column(Float)
|
71
|
+
dimension_y = Column(Float)
|
72
|
+
dimension_z = Column(Float)
|
73
|
+
quantity = Column(Integer, default=0)
|
74
|
+
attached_documents_reference = Column(String(200))
|
75
|
+
lead_time = Column(Integer)
|
76
|
+
make_or_buy = Column(Enum('make', 'buy', name='make_or_buy_enum'))
|
77
|
+
manufacturer_number = Column(String(100))
|
78
|
+
unit_price = Column(Numeric(10, 2))
|
79
|
+
currency = Column(String(3))
|
80
|
+
|
81
|
+
cad_reference = relationship('File', back_populates='part', uselist=False)
|
82
|
+
|
83
|
+
supplier_id = Column(ForeignKey('suppliers.id'))
|
84
|
+
supplier = relationship('Supplier', back_populates='parts')
|
85
|
+
|
86
|
+
component_id = Column(ForeignKey('components.id'))
|
87
|
+
component = relationship('Component', back_populates='part')
|
88
|
+
|
89
|
+
def __repr__(self):
|
90
|
+
return f"<Part(id={self.id}, number={self.number}, name={self.name})>"
|
91
|
+
|
92
|
+
def to_dict(self):
|
93
|
+
return {column.name: getattr(self, column.name) for column in self.__table__.columns}
|
94
|
+
|
95
|
+
class Supplier(Base):
|
96
|
+
__tablename__ = 'suppliers'
|
97
|
+
|
98
|
+
id = Column(Integer, primary_key=True)
|
99
|
+
uuid = Column(String(32), unique=True, nullable=False)
|
100
|
+
name = Column(String(200), nullable=False)
|
101
|
+
description = Column(String(1000), default="No description")
|
102
|
+
street = Column(String(200))
|
103
|
+
house_number = Column(String(20))
|
104
|
+
postal_code = Column(String(20))
|
105
|
+
city = Column(String(100))
|
106
|
+
country = Column(String(100))
|
107
|
+
date_created = Column(DateTime, default=datetime.utcnow)
|
108
|
+
date_modified = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
109
|
+
|
110
|
+
parts = relationship(Part)
|
111
|
+
|
112
|
+
def to_dict(self):
|
113
|
+
return {column.name: getattr(self, column.name) for column in self.__table__.columns}
|
114
|
+
|
115
|
+
class Adress(Base):
|
116
|
+
__tablename__ = 'adresses'
|
117
|
+
|
118
|
+
id = Column(Integer, primary_key=True)
|
119
|
+
uuid = Column(String(32), unique=True, nullable=False)
|
120
|
+
street = Column(String(200))
|
121
|
+
house_number = Column(String(20))
|
122
|
+
postal_code = Column(String(20))
|
123
|
+
city = Column(String(100))
|
124
|
+
country = Column(String(100))
|
125
|
+
|
126
|
+
|
127
|
+
'''
|
128
|
+
Relationship tables
|
129
|
+
'''
|
130
|
+
|
131
|
+
class PartSupplier(Base):
|
132
|
+
__tablename__ = 'part_supplier'
|
133
|
+
|
134
|
+
id = Column(Integer, primary_key=True)
|
135
|
+
|
136
|
+
class PartFile(Base):
|
137
|
+
__tablename__ = 'part_file'
|
138
|
+
|
139
|
+
id = Column(Integer, primary_key=True)
|
140
|
+
|
141
|
+
class SupplierAdress(Base):
|
142
|
+
__tablename__ = 'supplier_adress'
|
143
|
+
|
144
|
+
id = Column(Integer, primary_key=True)
|
145
|
+
|
146
|
+
class SupplierFile(Base):
|
147
|
+
__tablename__ = 'supplier_file'
|
148
|
+
|
149
|
+
id = Column(Integer, primary_key=True)
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
|
@@ -8,7 +8,7 @@ long_description = (this_directory / "README.md").read_text()
|
|
8
8
|
|
9
9
|
setup(
|
10
10
|
name='OpenPartsLibrary',
|
11
|
-
version='0.1.
|
11
|
+
version='0.1.9',
|
12
12
|
description='Python library for creating a database of hardware components for manufacturing',
|
13
13
|
long_description=long_description,
|
14
14
|
long_description_content_type='text/markdown',
|
@@ -1,87 +0,0 @@
|
|
1
|
-
from sqlalchemy import create_engine
|
2
|
-
from sqlalchemy.orm import sessionmaker
|
3
|
-
|
4
|
-
import pandas as pd
|
5
|
-
|
6
|
-
from datetime import datetime
|
7
|
-
|
8
|
-
from .models import Base, Part
|
9
|
-
|
10
|
-
|
11
|
-
class PartsLibrary:
|
12
|
-
def __init__(self):
|
13
|
-
import os
|
14
|
-
sqlite_path = os.path.join(os.path.dirname(__file__), 'data', 'parts.db')
|
15
|
-
print(sqlite_path)
|
16
|
-
self.engine = create_engine('sqlite:///' + sqlite_path)
|
17
|
-
|
18
|
-
Base.metadata.create_all(self.engine)
|
19
|
-
|
20
|
-
self.session_factory = sessionmaker(bind=self.engine)
|
21
|
-
self.session = self.session_factory()
|
22
|
-
|
23
|
-
def display(self):
|
24
|
-
part_table = pd.read_sql_table(table_name="parts", con=self.engine)
|
25
|
-
|
26
|
-
pd.set_option('display.max_columns', 8)
|
27
|
-
pd.set_option('display.width', 240)
|
28
|
-
|
29
|
-
print(part_table)
|
30
|
-
|
31
|
-
def display_reduced(self):
|
32
|
-
part_table = pd.read_sql_table(table_name="parts", con=self.engine)
|
33
|
-
reduced_part_table = part_table[["id", "number", "name", "quantity", "mass", "lead_time", "supplier", "unit_price", "currency"]]
|
34
|
-
pd.set_option('display.max_columns', 9)
|
35
|
-
pd.set_option('display.width', 200)
|
36
|
-
print(reduced_part_table)
|
37
|
-
|
38
|
-
|
39
|
-
def delete_all(self):
|
40
|
-
self.session.query(Part).delete()
|
41
|
-
self.session.commit()
|
42
|
-
|
43
|
-
def create_parts_from_spreadsheet(self, file_path):
|
44
|
-
df = pd.read_excel(file_path)
|
45
|
-
|
46
|
-
parts = []
|
47
|
-
for _, row in df.iterrows():
|
48
|
-
part = Part(
|
49
|
-
uuid=row["uuid"],
|
50
|
-
number=row["number"],
|
51
|
-
name=row["name"],
|
52
|
-
description=row.get("description", "No description"),
|
53
|
-
revision=str(row.get("revision", "1")),
|
54
|
-
lifecycle_state=row.get("lifecycle_state", "In Work"),
|
55
|
-
owner=row.get("owner", "system"),
|
56
|
-
date_created=row.get("date_created", datetime.utcnow()),
|
57
|
-
date_modified=row.get("date_modified", datetime.utcnow()),
|
58
|
-
material=row.get("material"),
|
59
|
-
mass=row.get("mass"),
|
60
|
-
dimension_x=row.get("dimension_x"),
|
61
|
-
dimension_y=row.get("dimension_y"),
|
62
|
-
dimension_z=row.get("dimension_z"),
|
63
|
-
quantity=row.get("quantity", 0),
|
64
|
-
cad_reference=row.get("cad_reference"),
|
65
|
-
attached_documents_reference=row.get("attached_documents_reference"),
|
66
|
-
lead_time=row.get("lead_time"),
|
67
|
-
make_or_buy=row.get("make_or_buy"),
|
68
|
-
supplier=row.get("supplier"),
|
69
|
-
manufacturer_number=row.get("manufacturer_number"),
|
70
|
-
unit_price=row.get("unit_price"),
|
71
|
-
currency=row.get("currency")
|
72
|
-
)
|
73
|
-
parts.append(part)
|
74
|
-
|
75
|
-
self.session.add_all(parts)
|
76
|
-
self.session.commit()
|
77
|
-
print(f"Imported {len(parts)} parts successfully from {file_path}")
|
78
|
-
|
79
|
-
def total_value(self):
|
80
|
-
from decimal import Decimal
|
81
|
-
all_parts = self.session.query(Part).all()
|
82
|
-
|
83
|
-
total_value = Decimal(0.0)
|
84
|
-
for part in all_parts:
|
85
|
-
total_value = Decimal(total_value) + (Decimal(part.unit_price) * part.quantity)
|
86
|
-
|
87
|
-
return total_value
|
@@ -1,71 +0,0 @@
|
|
1
|
-
from sqlalchemy import Column, Integer, String, Float, DateTime, Numeric, Enum
|
2
|
-
from sqlalchemy.orm import DeclarativeBase
|
3
|
-
from datetime import datetime
|
4
|
-
|
5
|
-
import uuid
|
6
|
-
|
7
|
-
class Base(DeclarativeBase):
|
8
|
-
pass
|
9
|
-
|
10
|
-
class Part(Base):
|
11
|
-
__tablename__ = 'parts'
|
12
|
-
|
13
|
-
id = Column(Integer, primary_key=True)
|
14
|
-
uuid = Column(String(32), unique=True, nullable=False, default=str(uuid.uuid4()))
|
15
|
-
number = Column(String(50), nullable=False)
|
16
|
-
name = Column(String(200), nullable=False)
|
17
|
-
description = Column(String(1000), default="No description")
|
18
|
-
revision = Column(String(10), default="1")
|
19
|
-
lifecycle_state = Column(String(50), default="In Work")
|
20
|
-
owner = Column(String(100), default="system")
|
21
|
-
date_created = Column(DateTime, default=datetime.utcnow)
|
22
|
-
date_modified = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
23
|
-
material = Column(String(100))
|
24
|
-
mass = Column(Float)
|
25
|
-
dimension_x = Column(Float)
|
26
|
-
dimension_y = Column(Float)
|
27
|
-
dimension_z = Column(Float)
|
28
|
-
quantity = Column(Integer, default=0)
|
29
|
-
cad_reference = Column(String(200))
|
30
|
-
attached_documents_reference = Column(String(200))
|
31
|
-
lead_time = Column(Integer)
|
32
|
-
make_or_buy = Column(Enum('make', 'buy', name='make_or_buy_enum'))
|
33
|
-
supplier = Column(String(100))
|
34
|
-
manufacturer_number = Column(String(100))
|
35
|
-
unit_price = Column(Numeric(10, 2))
|
36
|
-
currency = Column(String(3))
|
37
|
-
|
38
|
-
def __repr__(self):
|
39
|
-
return f"<Part(id={self.id}, number={self.number}, name={self.name})>"
|
40
|
-
|
41
|
-
def to_dict(self):
|
42
|
-
return {column.name: getattr(self, column.name) for column in self.__table__.columns}
|
43
|
-
|
44
|
-
|
45
|
-
class Supplier(Base):
|
46
|
-
__tablename__ = 'suppliers'
|
47
|
-
|
48
|
-
id = Column(Integer, primary_key=True)
|
49
|
-
uuid = Column(String(32), unique=True, nullable=False)
|
50
|
-
name = Column(String(200), nullable=False)
|
51
|
-
description = Column(String(1000))
|
52
|
-
date_created = Column(DateTime, default=datetime.utcnow)
|
53
|
-
date_modified = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
54
|
-
|
55
|
-
class File(Base):
|
56
|
-
__tablename__ = 'files'
|
57
|
-
|
58
|
-
id = Column(Integer, primary_key=True)
|
59
|
-
uuid = Column(String(32), unique=True, nullable=False)
|
60
|
-
name = Column(String(200), nullable=False)
|
61
|
-
description = Column(String(1000))
|
62
|
-
date_created = Column(DateTime, default=datetime.utcnow)
|
63
|
-
date_modified = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
64
|
-
|
65
|
-
class NumberRange(Base):
|
66
|
-
__tablename__ = 'number_ranges'
|
67
|
-
|
68
|
-
id = Column(Integer, primary_key=True)
|
69
|
-
name = Column(String(200), nullable=False)
|
70
|
-
description = Column(String(1000))
|
71
|
-
date_created = Column(DateTime, default=datetime.utcnow)
|
File without changes
|
{openpartslibrary-0.1.7 → openpartslibrary-0.1.9}/OpenPartsLibrary.egg-info/dependency_links.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|