django-bom 1.262__py3-none-any.whl
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.
Potentially problematic release.
This version of django-bom might be problematic. Click here for more details.
- bom/__init__.py +1 -0
- bom/admin.py +207 -0
- bom/apps.py +8 -0
- bom/auth_backends.py +47 -0
- bom/base_classes.py +31 -0
- bom/constants.py +217 -0
- bom/context_processors.py +9 -0
- bom/csv_headers.py +252 -0
- bom/decorators.py +32 -0
- bom/form_fields.py +59 -0
- bom/forms.py +1328 -0
- bom/helpers.py +367 -0
- bom/local_settings.py +35 -0
- bom/migrations/0001_initial.py +135 -0
- bom/migrations/0002_auto_20180908_2151.py +24 -0
- bom/migrations/0003_sellerpart_data_source.py +18 -0
- bom/migrations/0004_auto_20180911_0011.py +18 -0
- bom/migrations/0005_auto_20181007_1934.py +56 -0
- bom/migrations/0006_auto_20181007_1949.py +41 -0
- bom/migrations/0007_auto_20181009_0256.py +19 -0
- bom/migrations/0008_auto_20181030_0427.py +19 -0
- bom/migrations/0009_subpart_reference.py +18 -0
- bom/migrations/0010_auto_20181202_0733.py +23 -0
- bom/migrations/0011_auto_20181202_2113.py +22 -0
- bom/migrations/0012_partchangehistory.py +30 -0
- bom/migrations/0013_auto_20190222_1631.py +19 -0
- bom/migrations/0014_auto_20190223_2353.py +18 -0
- bom/migrations/0015_auto_20190303_1915.py +136 -0
- bom/migrations/0016_auto_20190405_2308.py +58 -0
- bom/migrations/0017_auto_20190616_1912.py +19 -0
- bom/migrations/0018_auto_20190616_2143.py +24 -0
- bom/migrations/0019_auto_20190624_1246.py +45 -0
- bom/migrations/0020_auto_20190627_0207.py +38 -0
- bom/migrations/0021_auto_20190627_0428.py +23 -0
- bom/migrations/0022_auto_20190811_2140.py +35 -0
- bom/migrations/0023_auto_20191205_2351.py +255 -0
- bom/migrations/0024_auto_20191214_1342.py +89 -0
- bom/migrations/0025_auto_20191221_1907.py +38 -0
- bom/migrations/0026_auto_20191222_2258.py +22 -0
- bom/migrations/0027_auto_20191222_2347.py +17 -0
- bom/migrations/0028_partrevision_displayable_synopsis.py +74 -0
- bom/migrations/0029_auto_20191231_1630.py +23 -0
- bom/migrations/0030_auto_20200101_2253.py +22 -0
- bom/migrations/0031_auto_20200104_1352.py +38 -0
- bom/migrations/0032_auto_20200126_1806.py +27 -0
- bom/migrations/0033_auto_20200203_0618.py +29 -0
- bom/migrations/0034_auto_20200222_0359.py +30 -0
- bom/migrations/0035_auto_20200303_0111.py +34 -0
- bom/migrations/0036_auto_20200303_0538.py +17 -0
- bom/migrations/0037_auto_20200405_1642.py +44 -0
- bom/migrations/0038_auto_20200422_0504.py +19 -0
- bom/migrations/0039_auto_20200929_2315.py +41 -0
- bom/migrations/0040_alter_organization_currency.py +19 -0
- bom/migrations/0041_organization_subscription_quantity.py +18 -0
- bom/migrations/0042_auto_20210720_2137.py +23 -0
- bom/migrations/0043_auto_20211123_0157.py +24 -0
- bom/migrations/0044_auto_20220831_1241.py +23 -0
- bom/migrations/0045_sellerpart_link.py +18 -0
- bom/migrations/0046_alter_sellerpart_unique_together.py +17 -0
- bom/migrations/0047_sellerpart_seller_part_number.py +18 -0
- bom/migrations/0048_rename_part_organization_number_class_bom_part_organiz_b333d6_idx_and_more.py +1017 -0
- bom/migrations/0049_alter_assembly_id_alter_assemblysubparts_id_and_more.py +99 -0
- bom/migrations/0050_alter_organization_options.py +17 -0
- bom/migrations/0051_alter_manufacturer_organization_and_more.py +41 -0
- bom/migrations/0052_remove_partrevision_attribute_and_more.py +584 -0
- bom/migrations/__init__.py +0 -0
- bom/models.py +886 -0
- bom/part_bom.py +192 -0
- bom/settings.py +262 -0
- bom/static/bom/css/dashboard.css +17 -0
- bom/static/bom/css/jquery.treetable.css +28 -0
- bom/static/bom/css/materialize.min.css +13 -0
- bom/static/bom/css/part-info.css +15 -0
- bom/static/bom/css/style.css +482 -0
- bom/static/bom/css/tablesorter-theme.materialize.css +176 -0
- bom/static/bom/css/treetable-theme.css +42 -0
- bom/static/bom/doc/sample_part_classes.csv +38 -0
- bom/static/bom/doc/test_bom.csv +6 -0
- bom/static/bom/doc/test_bom_5_intelligent.csv +4 -0
- bom/static/bom/doc/test_full_bom.csv +37 -0
- bom/static/bom/doc/test_new_parts.csv +5 -0
- bom/static/bom/doc/test_new_parts_5_intelligent.csv +5 -0
- bom/static/bom/img/_ionicons_svg_md-arrow-dropdown.svg +1 -0
- bom/static/bom/img/_ionicons_svg_md-arrow-dropright.svg +1 -0
- bom/static/bom/img/favicon.ico +0 -0
- bom/static/bom/img/google/web/1x/btn_google_signin_dark_disabled_web.png +0 -0
- bom/static/bom/img/google/web/1x/btn_google_signin_dark_focus_web.png +0 -0
- bom/static/bom/img/google/web/1x/btn_google_signin_dark_normal_web.png +0 -0
- bom/static/bom/img/google/web/1x/btn_google_signin_dark_pressed_web.png +0 -0
- bom/static/bom/img/google/web/1x/btn_google_signin_light_disabled_web.png +0 -0
- bom/static/bom/img/google/web/1x/btn_google_signin_light_focus_web.png +0 -0
- bom/static/bom/img/google/web/1x/btn_google_signin_light_normal_web.png +0 -0
- bom/static/bom/img/google/web/1x/btn_google_signin_light_pressed_web.png +0 -0
- bom/static/bom/img/google/web/2x/btn_google_signin_dark_disabled_web@2x.png +0 -0
- bom/static/bom/img/google/web/2x/btn_google_signin_dark_focus_web@2x.png +0 -0
- bom/static/bom/img/google/web/2x/btn_google_signin_dark_normal_web@2x.png +0 -0
- bom/static/bom/img/google/web/2x/btn_google_signin_dark_pressed_web@2x.png +0 -0
- bom/static/bom/img/google/web/2x/btn_google_signin_light_disabled_web@2x.png +0 -0
- bom/static/bom/img/google/web/2x/btn_google_signin_light_focus_web@2x.png +0 -0
- bom/static/bom/img/google/web/2x/btn_google_signin_light_normal_web@2x.png +0 -0
- bom/static/bom/img/google/web/2x/btn_google_signin_light_pressed_web@2x.png +0 -0
- bom/static/bom/img/google/web/vector/btn_google_dark_disabled_ios.eps +814 -0
- bom/static/bom/img/google/web/vector/btn_google_dark_disabled_ios.svg +24 -0
- bom/static/bom/img/google/web/vector/btn_google_dark_focus_ios.eps +1866 -0
- bom/static/bom/img/google/web/vector/btn_google_dark_focus_ios.svg +51 -0
- bom/static/bom/img/google/web/vector/btn_google_dark_normal_ios.eps +1031 -0
- bom/static/bom/img/google/web/vector/btn_google_dark_normal_ios.svg +50 -0
- bom/static/bom/img/google/web/vector/btn_google_dark_pressed_ios.eps +1031 -0
- bom/static/bom/img/google/web/vector/btn_google_dark_pressed_ios.svg +50 -0
- bom/static/bom/img/google/web/vector/btn_google_light_disabled_ios.eps +814 -0
- bom/static/bom/img/google/web/vector/btn_google_light_disabled_ios.svg +24 -0
- bom/static/bom/img/google/web/vector/btn_google_light_focus_ios.eps +1837 -0
- bom/static/bom/img/google/web/vector/btn_google_light_focus_ios.svg +44 -0
- bom/static/bom/img/google/web/vector/btn_google_light_normal_ios.eps +1002 -0
- bom/static/bom/img/google/web/vector/btn_google_light_normal_ios.svg +43 -0
- bom/static/bom/img/google/web/vector/btn_google_light_pressed_ios.eps +1002 -0
- bom/static/bom/img/google/web/vector/btn_google_light_pressed_ios.svg +43 -0
- bom/static/bom/img/google_drive_logo.svg +1 -0
- bom/static/bom/img/indabom.png +0 -0
- bom/static/bom/img/mouser.png +0 -0
- bom/static/bom/img/octopart_blue.svg +19 -0
- bom/static/bom/js/formset-handler.js +65 -0
- bom/static/bom/js/jquery-3.4.1.min.js +2 -0
- bom/static/bom/js/jquery.ba-floatingscrollbar.min.js +10 -0
- bom/static/bom/js/jquery.treetable.js +629 -0
- bom/static/bom/js/materialize.min.js +6 -0
- bom/templates/bom/account-delete.html +23 -0
- bom/templates/bom/add-manufacturer-part.html +66 -0
- bom/templates/bom/add-sellerpart.html +93 -0
- bom/templates/bom/base-menu.html +16 -0
- bom/templates/bom/base.html +129 -0
- bom/templates/bom/bom-action-btn.html +23 -0
- bom/templates/bom/bom-action-table.html +57 -0
- bom/templates/bom/bom-base-menu.html +6 -0
- bom/templates/bom/bom-base.html +24 -0
- bom/templates/bom/bom-form-modal.html +36 -0
- bom/templates/bom/bom-form.html +30 -0
- bom/templates/bom/bom-modal-add-users.html +49 -0
- bom/templates/bom/bom-signup.html +12 -0
- bom/templates/bom/components/bom-flat.html +131 -0
- bom/templates/bom/components/bom-indented.html +237 -0
- bom/templates/bom/components/manufacturer-part-list.html +270 -0
- bom/templates/bom/components/seller-part-list.html +62 -0
- bom/templates/bom/create-part.html +65 -0
- bom/templates/bom/dashboard-menu.html +15 -0
- bom/templates/bom/dashboard.html +303 -0
- bom/templates/bom/edit-manufacturer-part.html +72 -0
- bom/templates/bom/edit-part-class.html +120 -0
- bom/templates/bom/edit-part.html +67 -0
- bom/templates/bom/edit-quantity-of-measure.html +119 -0
- bom/templates/bom/edit-user-meta.html +70 -0
- bom/templates/bom/help.html +1356 -0
- bom/templates/bom/manufacturer-info.html +82 -0
- bom/templates/bom/manufacturers.html +97 -0
- bom/templates/bom/nothing-to-see.html +15 -0
- bom/templates/bom/organization-create.html +135 -0
- bom/templates/bom/part-info.html +448 -0
- bom/templates/bom/part-revision-display.html +50 -0
- bom/templates/bom/part-revision-edit.html +39 -0
- bom/templates/bom/part-revision-manage-bom.html +115 -0
- bom/templates/bom/part-revision-new.html +57 -0
- bom/templates/bom/part-revision-release.html +41 -0
- bom/templates/bom/search-help.html +101 -0
- bom/templates/bom/seller-info.html +82 -0
- bom/templates/bom/sellers.html +97 -0
- bom/templates/bom/settings.html +734 -0
- bom/templates/bom/signup.html +28 -0
- bom/templates/bom/subscription_panel.html +16 -0
- bom/templates/bom/table_of_contents.html +47 -0
- bom/templates/bom/upload-bom.html +111 -0
- bom/templates/bom/upload-parts-help.html +103 -0
- bom/templates/bom/upload-parts.html +50 -0
- bom/templates/registration/login.html +39 -0
- bom/tests.py +1592 -0
- bom/third_party_apis/__init__.py +0 -0
- bom/third_party_apis/base_api.py +51 -0
- bom/third_party_apis/google_drive.py +166 -0
- bom/third_party_apis/mouser.py +132 -0
- bom/third_party_apis/test_apis.py +24 -0
- bom/urls.py +100 -0
- bom/utils.py +228 -0
- bom/validators.py +23 -0
- bom/views/__init__.py +0 -0
- bom/views/json_views.py +55 -0
- bom/views/views.py +1773 -0
- bom/wsgi.py +16 -0
- django_bom-1.262.dist-info/METADATA +206 -0
- django_bom-1.262.dist-info/RECORD +191 -0
- django_bom-1.262.dist-info/WHEEL +5 -0
- django_bom-1.262.dist-info/licenses/LICENSE +674 -0
- django_bom-1.262.dist-info/top_level.txt +1 -0
bom/helpers.py
ADDED
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
from bom import constants
|
|
2
|
+
from bom.models import (
|
|
3
|
+
Assembly,
|
|
4
|
+
Manufacturer,
|
|
5
|
+
ManufacturerPart,
|
|
6
|
+
Organization,
|
|
7
|
+
Part,
|
|
8
|
+
PartClass,
|
|
9
|
+
PartRevision,
|
|
10
|
+
QuantityOfMeasure,
|
|
11
|
+
UnitDefinition,
|
|
12
|
+
PartRevisionProperty,
|
|
13
|
+
PartRevisionPropertyDefinition,
|
|
14
|
+
Seller,
|
|
15
|
+
SellerPart,
|
|
16
|
+
Subpart,
|
|
17
|
+
User,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def create_a_fake_organization(user, free=False, number_scheme=constants.NUMBER_SCHEME_SEMI_INTELLIGENT, number_variation_len=constants.NUMBER_VARIATION_LEN_DEFAULT):
|
|
22
|
+
org, created = Organization.objects.get_or_create(
|
|
23
|
+
name="Atlas",
|
|
24
|
+
subscription=constants.SUBSCRIPTION_TYPE_FREE if free else constants.SUBSCRIPTION_TYPE_PRO,
|
|
25
|
+
number_scheme=number_scheme,
|
|
26
|
+
number_item_len=4,
|
|
27
|
+
number_variation_len=number_variation_len,
|
|
28
|
+
owner=user)
|
|
29
|
+
return org
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def create_user_and_organization(free=False, number_scheme=constants.NUMBER_SCHEME_SEMI_INTELLIGENT, number_variation_len=constants.NUMBER_VARIATION_LEN_DEFAULT):
|
|
33
|
+
user = User.objects.create_user('kasper', 'kasper@McFadden.com', 'ghostpassword')
|
|
34
|
+
organization = create_a_fake_organization(user, free, number_scheme, number_variation_len)
|
|
35
|
+
profile = user.bom_profile(organization=organization)
|
|
36
|
+
profile.role = 'A'
|
|
37
|
+
profile.save()
|
|
38
|
+
return user, organization
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def create_some_fake_part_classes(organization):
|
|
42
|
+
pc1, c = PartClass.objects.get_or_create(code=500, name='Wendy', comment='Mechanical Switches', organization=organization)
|
|
43
|
+
pc2, c = PartClass.objects.get_or_create(code=200, name='Archibald', comment='', organization=organization)
|
|
44
|
+
pc3, c = PartClass.objects.get_or_create(code='50A', name='Ghost', comment='Like Kasper', organization=organization)
|
|
45
|
+
return pc1, pc2, pc3
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def create_a_fake_subpart(part_revision, reference="U1", count=4):
|
|
49
|
+
sp1 = Subpart(
|
|
50
|
+
part_revision=part_revision,
|
|
51
|
+
reference=reference,
|
|
52
|
+
count=count)
|
|
53
|
+
sp1.save()
|
|
54
|
+
|
|
55
|
+
return sp1
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def create_a_fake_assembly():
|
|
59
|
+
assy = Assembly.objects.create()
|
|
60
|
+
return assy
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def create_a_fake_assembly_with_subpart(part_revision, reference="D4", count=4):
|
|
64
|
+
assy = create_a_fake_assembly()
|
|
65
|
+
subpart = create_a_fake_subpart(part_revision, reference, count)
|
|
66
|
+
assy.subparts.add(subpart)
|
|
67
|
+
return assy
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def create_some_fake_quantities_of_measure(organization=None):
|
|
71
|
+
qom_each, _ = QuantityOfMeasure.objects.get_or_create(name='Each')
|
|
72
|
+
qom_volt, _ = QuantityOfMeasure.objects.get_or_create(name='Voltage')
|
|
73
|
+
qom_custom = None
|
|
74
|
+
if organization is not None:
|
|
75
|
+
qom_custom, _ = QuantityOfMeasure.objects.get_or_create(name='Custom', organization=organization)
|
|
76
|
+
return qom_each, qom_volt, qom_custom
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def create_some_fake_unit_definitions(organization=None):
|
|
80
|
+
qom_each, qom_volt, qom_custom = create_some_fake_quantities_of_measure(organization)
|
|
81
|
+
v, _ = UnitDefinition.objects.get_or_create(name='Volts', symbol='V', quantity_of_measure=qom_volt,
|
|
82
|
+
base_multiplier=1.0)
|
|
83
|
+
mv, _ = UnitDefinition.objects.get_or_create(name='Millivolts', symbol='mV', quantity_of_measure=qom_volt,
|
|
84
|
+
base_multiplier=0.001)
|
|
85
|
+
uv, _ = UnitDefinition.objects.get_or_create(name='Microvolts', symbol='uV', quantity_of_measure=qom_volt,
|
|
86
|
+
base_multiplier=0.000001)
|
|
87
|
+
kv, _ = UnitDefinition.objects.get_or_create(name='Kilovolts', symbol='kV', quantity_of_measure=qom_volt,
|
|
88
|
+
base_multiplier=1000)
|
|
89
|
+
sv = None
|
|
90
|
+
if organization is not None:
|
|
91
|
+
sv, _ = UnitDefinition.objects.get_or_create(name='Supervolts', symbol='SV', quantity_of_measure=qom_custom,
|
|
92
|
+
base_multiplier=1000000)
|
|
93
|
+
return v, mv, uv, kv, sv
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def create_some_fake_part_revision_property_definitions(organization=None, some_required=True, part_class=None):
|
|
97
|
+
qom_each, qom_volt, qom_custom = create_some_fake_quantities_of_measure(organization)
|
|
98
|
+
sheen, _ = PartRevisionPropertyDefinition.objects.get_or_create(name='Sheen', code='sheen',
|
|
99
|
+
type=constants.PART_REVISION_PROPERTY_TYPE_STRING,
|
|
100
|
+
quantity_of_measure=None,
|
|
101
|
+
defaults={'required': some_required})
|
|
102
|
+
voltage, _ = PartRevisionPropertyDefinition.objects.get_or_create(name='Voltage', code='voltage',
|
|
103
|
+
type=constants.PART_REVISION_PROPERTY_TYPE_DECIMAL,
|
|
104
|
+
quantity_of_measure=qom_volt,
|
|
105
|
+
defaults={'required': some_required})
|
|
106
|
+
max_voltage, _ = PartRevisionPropertyDefinition.objects.get_or_create(name='Max Voltage', code='max_voltage',
|
|
107
|
+
type=constants.PART_REVISION_PROPERTY_TYPE_DECIMAL,
|
|
108
|
+
required=False, quantity_of_measure=qom_volt)
|
|
109
|
+
count, _ = PartRevisionPropertyDefinition.objects.get_or_create(name='Count', code='count',
|
|
110
|
+
type=constants.PART_REVISION_PROPERTY_TYPE_DECIMAL,
|
|
111
|
+
required=False, quantity_of_measure=qom_each)
|
|
112
|
+
|
|
113
|
+
defs = [sheen, voltage, max_voltage, count]
|
|
114
|
+
|
|
115
|
+
custom = None
|
|
116
|
+
if organization is not None:
|
|
117
|
+
custom, _ = PartRevisionPropertyDefinition.objects.get_or_create(name='Custom', code='custom',
|
|
118
|
+
type=constants.PART_REVISION_PROPERTY_TYPE_BOOLEAN,
|
|
119
|
+
required=False, quantity_of_measure=qom_custom)
|
|
120
|
+
defs.append(custom)
|
|
121
|
+
|
|
122
|
+
if part_class is not None:
|
|
123
|
+
part_class.property_definitions.add(*defs)
|
|
124
|
+
|
|
125
|
+
return sheen, voltage, max_voltage, count, custom
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def create_a_fake_part_revision(part, assembly, description="Brown dog", revision="1", some_required_definitions=True):
|
|
129
|
+
pch, created = PartRevision.objects.get_or_create(part=part, revision=revision, defaults={
|
|
130
|
+
'description': description,
|
|
131
|
+
'revision': revision,
|
|
132
|
+
'assembly': assembly,
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
organization = part.organization
|
|
136
|
+
part_class = part.number_class if part else None
|
|
137
|
+
_, voltage, max_voltage, count, custom = create_some_fake_part_revision_property_definitions(organization,
|
|
138
|
+
some_required_definitions,
|
|
139
|
+
part_class=part_class)
|
|
140
|
+
v, mv, _, _, sv = create_some_fake_unit_definitions(organization)
|
|
141
|
+
|
|
142
|
+
PartRevisionProperty.objects.get_or_create(part_revision=pch, property_definition=voltage, unit_definition=v,
|
|
143
|
+
value_raw=".01")
|
|
144
|
+
PartRevisionProperty.objects.get_or_create(part_revision=pch, property_definition=max_voltage, unit_definition=v,
|
|
145
|
+
value_raw="3.5")
|
|
146
|
+
PartRevisionProperty.objects.get_or_create(part_revision=pch, property_definition=count, value_raw="5.2")
|
|
147
|
+
PartRevisionProperty.objects.get_or_create(part_revision=pch, property_definition=custom, unit_definition=sv,
|
|
148
|
+
value_raw="True")
|
|
149
|
+
|
|
150
|
+
return pch
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def create_some_fake_sellers(organization):
|
|
154
|
+
s1, c = Seller.objects.get_or_create(name='Mouser', organization=organization)
|
|
155
|
+
s2, c = Seller.objects.get_or_create(name='Digi-Key', organization=organization)
|
|
156
|
+
s3, c = Seller.objects.get_or_create(name='Archibald', organization=organization)
|
|
157
|
+
return s1, s2, s3
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def create_some_fake_manufacturers(organization):
|
|
161
|
+
m1, c = Manufacturer.objects.get_or_create(name='STMicroelectronics', organization=organization)
|
|
162
|
+
m2, c = Manufacturer.objects.get_or_create(name='Nordic Semiconductor', organization=organization)
|
|
163
|
+
m3, c = Manufacturer.objects.get_or_create(name='Murata', organization=organization)
|
|
164
|
+
return m1, m2, m3
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def create_a_fake_seller_part(
|
|
168
|
+
seller,
|
|
169
|
+
manufacturer_part,
|
|
170
|
+
moq,
|
|
171
|
+
mpq,
|
|
172
|
+
unit_cost,
|
|
173
|
+
lead_time_days,
|
|
174
|
+
nre_cost=None):
|
|
175
|
+
sp1 = SellerPart(
|
|
176
|
+
seller=seller,
|
|
177
|
+
manufacturer_part=manufacturer_part,
|
|
178
|
+
minimum_order_quantity=moq,
|
|
179
|
+
minimum_pack_quantity=mpq,
|
|
180
|
+
unit_cost=unit_cost,
|
|
181
|
+
lead_time_days=lead_time_days,
|
|
182
|
+
nre_cost=nre_cost)
|
|
183
|
+
sp1.save()
|
|
184
|
+
|
|
185
|
+
return sp1
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def create_some_fake_intelligent_parts(organization):
|
|
189
|
+
pt1 = Part(number_item=('3' * organization.number_item_len), organization=organization)
|
|
190
|
+
pt1.save()
|
|
191
|
+
|
|
192
|
+
pt2 = Part(number_item='4' * organization.number_item_len, organization=organization)
|
|
193
|
+
pt2.save()
|
|
194
|
+
|
|
195
|
+
pt3 = Part(number_item='A' * organization.number_item_len, organization=organization)
|
|
196
|
+
pt3.save()
|
|
197
|
+
|
|
198
|
+
# pt4 is a part with no PartRevision
|
|
199
|
+
pt4 = Part(number_item='B' * organization.number_item_len, organization=organization)
|
|
200
|
+
pt4.save(no_part_revision=True)
|
|
201
|
+
|
|
202
|
+
pt5 = Part(number_item='5' * organization.number_item_len, organization=organization)
|
|
203
|
+
pt5.save()
|
|
204
|
+
return pt1, pt2, pt3, pt4, pt5
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def create_some_fake_semi_intelligent_parts(organization):
|
|
208
|
+
(pc1, pc2, pc3) = create_some_fake_part_classes(organization=organization)
|
|
209
|
+
pt1 = Part(number_class=pc2, number_item='3333', organization=organization)
|
|
210
|
+
pt1.save()
|
|
211
|
+
|
|
212
|
+
pt2 = Part(number_class=pc1, organization=organization)
|
|
213
|
+
pt2.save()
|
|
214
|
+
|
|
215
|
+
pt3 = Part(number_class=pc3, organization=organization)
|
|
216
|
+
pt3.save()
|
|
217
|
+
|
|
218
|
+
# pt4 is a part with no PartRevision
|
|
219
|
+
pt4 = Part(number_class=pc1, number_item='4444', organization=organization)
|
|
220
|
+
pt4.save(no_part_revision=True)
|
|
221
|
+
|
|
222
|
+
pt5 = Part(number_class=pc1, number_item='5555', organization=organization)
|
|
223
|
+
pt5.save()
|
|
224
|
+
return pt1, pt2, pt3, pt4, pt5
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def create_some_fake_parts(organization):
|
|
228
|
+
(m1, m2, m3) = create_some_fake_manufacturers(organization=organization)
|
|
229
|
+
|
|
230
|
+
if organization.number_scheme == 'I':
|
|
231
|
+
pt1, pt2, pt3, pt4, pt5 = create_some_fake_intelligent_parts(organization)
|
|
232
|
+
elif organization.number_scheme == 'S':
|
|
233
|
+
pt1, pt2, pt3, pt4, pt5 = create_some_fake_semi_intelligent_parts(organization)
|
|
234
|
+
else:
|
|
235
|
+
return None
|
|
236
|
+
|
|
237
|
+
mp1 = ManufacturerPart(part=pt1, manufacturer=m1, manufacturer_part_number='STM32F401CEU6')
|
|
238
|
+
mp1.save()
|
|
239
|
+
pt1.primary_manufacturer_part = mp1
|
|
240
|
+
pt1.save()
|
|
241
|
+
assy = create_a_fake_assembly()
|
|
242
|
+
pr1 = create_a_fake_part_revision(part=pt1, assembly=None)
|
|
243
|
+
|
|
244
|
+
mp2 = ManufacturerPart(part=pt2, manufacturer=m2, manufacturer_part_number='GRM1555C1H100JA01D')
|
|
245
|
+
mp2.save()
|
|
246
|
+
mp22 = ManufacturerPart(part=pt2, manufacturer=None, manufacturer_part_number='ThisPartHasNoManufacturer')
|
|
247
|
+
mp22.save()
|
|
248
|
+
pt2.primary_manufacturer_part = mp2
|
|
249
|
+
pt2.save()
|
|
250
|
+
assy2 = create_a_fake_assembly_with_subpart(part_revision=pr1)
|
|
251
|
+
pr2 = create_a_fake_part_revision(part=pt2, assembly=assy2)
|
|
252
|
+
|
|
253
|
+
mp3 = ManufacturerPart(part=pt3, manufacturer=m3, manufacturer_part_number='NRF51822')
|
|
254
|
+
mp3.save()
|
|
255
|
+
assy3 = create_a_fake_assembly_with_subpart(part_revision=pr2)
|
|
256
|
+
subpart3 = create_a_fake_subpart(pr1, count=10, reference="")
|
|
257
|
+
subpart32 = create_a_fake_subpart(pr2, count=3, reference="")
|
|
258
|
+
assy3.subparts.add(subpart3)
|
|
259
|
+
assy3.subparts.add(subpart32)
|
|
260
|
+
assy3.save()
|
|
261
|
+
create_a_fake_part_revision(part=pt3, assembly=assy3)
|
|
262
|
+
create_a_fake_part_revision(part=pt3, assembly=assy3, revision="2")
|
|
263
|
+
|
|
264
|
+
# Create a part with a PartRevision with no assembly - no longer happens due to PartRevision save override
|
|
265
|
+
create_a_fake_part_revision(pt5, None)
|
|
266
|
+
|
|
267
|
+
(s1, s2, s3) = create_some_fake_sellers(organization=organization)
|
|
268
|
+
|
|
269
|
+
create_a_fake_seller_part(s1, mp1, moq=0, mpq=1, unit_cost=0, lead_time_days=None, nre_cost=0,)
|
|
270
|
+
create_a_fake_seller_part(s1, mp1, moq=1, mpq=2, unit_cost=10, lead_time_days=None, nre_cost=0, )
|
|
271
|
+
create_a_fake_seller_part(s1, mp1, moq=1, mpq=1, unit_cost=1.2, lead_time_days=20, nre_cost=500)
|
|
272
|
+
create_a_fake_seller_part(s2, mp1, moq=1000, mpq=5000, unit_cost=0.1005, lead_time_days=7, nre_cost=0)
|
|
273
|
+
create_a_fake_seller_part(s2, mp2, moq=200, mpq=200, unit_cost=0.5, lead_time_days=47, nre_cost=1)
|
|
274
|
+
create_a_fake_seller_part(s2, mp2, moq=2000, mpq=200, unit_cost=0.4, lead_time_days=47, nre_cost=10)
|
|
275
|
+
create_a_fake_seller_part(s1, mp2, moq=2000, mpq=200, unit_cost=0.4, lead_time_days=47, nre_cost=10)
|
|
276
|
+
create_a_fake_seller_part(s1, mp2, moq=3000, mpq=200, unit_cost=0.3, lead_time_days=47, nre_cost=10)
|
|
277
|
+
return pt1, pt2, pt3, pt4
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def create_some_fake_data(user):
|
|
281
|
+
o = create_a_fake_organization(user)
|
|
282
|
+
return create_some_fake_parts(o)
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def create_all_part_classes():
|
|
286
|
+
PartClass.objects.get_or_create(code=100, name='Assembly, Top Level SKU\'s, Finished Goods',
|
|
287
|
+
comment='Ready to ship product; Includes packout and literature')
|
|
288
|
+
PartClass.objects.get_or_create(code=101, name='Assembly, Final, Elec/Mech',
|
|
289
|
+
comment='Fully built product without Literature or packout materials')
|
|
290
|
+
PartClass.objects.get_or_create(code=102, name='Assembly, Sub-Assy, Elec/Mech', comment='')
|
|
291
|
+
PartClass.objects.get_or_create(code=103, name='Assembly, Cable', comment='')
|
|
292
|
+
PartClass.objects.get_or_create(code=104, name='Assembly, Packaging', comment='')
|
|
293
|
+
PartClass.objects.get_or_create(code=105, name='Kit, Spare/Upgrade',
|
|
294
|
+
comment='Includes Spares, Documentation Kits, Upgrade Kits')
|
|
295
|
+
PartClass.objects.get_or_create(code=106, name='Assembly, Printed Circuit Board (PBCA)', comment='')
|
|
296
|
+
PartClass.objects.get_or_create(code=107, name='PCB, Fab', comment='')
|
|
297
|
+
PartClass.objects.get_or_create(code=108, name='Gerber File/X-Y data/CAD data', comment='')
|
|
298
|
+
PartClass.objects.get_or_create(code=109, name='Schematic/Test Diagram', comment='')
|
|
299
|
+
PartClass.objects.get_or_create(code=110, name='Mechanical Reference, PCB', comment='')
|
|
300
|
+
PartClass.objects.get_or_create(code=111, name='Mechanical Reference, PCBA', comment='')
|
|
301
|
+
PartClass.objects.get_or_create(code=112, name='Programmed Device, Firmware/Software', comment='')
|
|
302
|
+
PartClass.objects.get_or_create(code=113, name='Program File, Firmware, Software', comment='')
|
|
303
|
+
PartClass.objects.get_or_create(code=114, name='Build-To-Print, Sheet Metal', comment='')
|
|
304
|
+
PartClass.objects.get_or_create(code=115, name='Build-To-Print, Cast Metal', comment='')
|
|
305
|
+
PartClass.objects.get_or_create(code=116, name='Build-To-Print, Extruded',
|
|
306
|
+
comment='Applies for both plastic and metal')
|
|
307
|
+
PartClass.objects.get_or_create(code=117, name='Build-To-Print, Machined',
|
|
308
|
+
comment='Applies for both plastic and metal')
|
|
309
|
+
PartClass.objects.get_or_create(code=118, name='Build-To-Print, Molded',
|
|
310
|
+
comment='Applies for both Injection and Compression molded')
|
|
311
|
+
PartClass.objects.get_or_create(code=119, name='Build-To-Print, Formed',
|
|
312
|
+
comment='Applies for plastic only; Formed sheet metal goes under sheet metal')
|
|
313
|
+
PartClass.objects.get_or_create(code=120, name='Build-To-Print, Die-Cut',
|
|
314
|
+
comment='Applied to foams and PSAs (Pressure Sensitive Adhesives)')
|
|
315
|
+
PartClass.objects.get_or_create(code=121, name='Build-To-Print, Mechanical',
|
|
316
|
+
comment='Applies to all Build-To-Print Mech Parts that do not fall into one of the other specific groups.')
|
|
317
|
+
PartClass.objects.get_or_create(code=122, name='Build-To-Print, Printed Material',
|
|
318
|
+
comment='Includes Custom Labels, Product Literature, etc.')
|
|
319
|
+
PartClass.objects.get_or_create(code=123, name='Build-To-Print, Packaging', comment='')
|
|
320
|
+
PartClass.objects.get_or_create(code=124, name='Drawing',
|
|
321
|
+
comment='For any drawing that does not use the Item PN as the dwg PN')
|
|
322
|
+
PartClass.objects.get_or_create(code=125, name='Artwork',
|
|
323
|
+
comment='A/W for printing, silkscreening of labels, sheetmetal, etc.')
|
|
324
|
+
PartClass.objects.get_or_create(code=126, name='Release Notes/Protocols', comment='')
|
|
325
|
+
PartClass.objects.get_or_create(code=127, name='Custom Electronic Components', comment='Example: Custom Sensors')
|
|
326
|
+
PartClass.objects.get_or_create(code=200, name='Adhesive', comment='Includes Loctite, Epoxy, Tape, etc.')
|
|
327
|
+
PartClass.objects.get_or_create(code=201, name='Battery/Charger', comment='')
|
|
328
|
+
PartClass.objects.get_or_create(code=202, name='Cable & Wire', comment='')
|
|
329
|
+
PartClass.objects.get_or_create(code=203, name='Connector, Cable/Harness', comment='')
|
|
330
|
+
PartClass.objects.get_or_create(code=204, name='Connector, PC Mountable', comment='')
|
|
331
|
+
PartClass.objects.get_or_create(code=205, name='Connector, Misc', comment='')
|
|
332
|
+
PartClass.objects.get_or_create(code=206, name='Cable Hardware', comment='Includes Clamps, Ties, etc.')
|
|
333
|
+
PartClass.objects.get_or_create(code=207, name='Capacitor', comment='')
|
|
334
|
+
PartClass.objects.get_or_create(code=208, name='Circuit Breaker/Filter', comment='')
|
|
335
|
+
PartClass.objects.get_or_create(code=209, name='Crystal', comment='')
|
|
336
|
+
PartClass.objects.get_or_create(code=210, name='Delay Line', comment='')
|
|
337
|
+
PartClass.objects.get_or_create(code=211, name='Diode', comment='')
|
|
338
|
+
PartClass.objects.get_or_create(code=212, name='Fan & Fan Accessories', comment='')
|
|
339
|
+
PartClass.objects.get_or_create(code=213, name='Fuse & Fuse Hardware', comment='')
|
|
340
|
+
PartClass.objects.get_or_create(code=214, name='Hardware',
|
|
341
|
+
comment='Includes Screws, Nuts, Washers, Springs, Std-offs, Inserts, Fasteners, etc')
|
|
342
|
+
PartClass.objects.get_or_create(code=215, name='Heatsink', comment='')
|
|
343
|
+
PartClass.objects.get_or_create(code=216, name='IC', comment='')
|
|
344
|
+
PartClass.objects.get_or_create(code=217, name='Inductor', comment='')
|
|
345
|
+
PartClass.objects.get_or_create(code=218, name='Insulator', comment='')
|
|
346
|
+
PartClass.objects.get_or_create(code=219, name='Label', comment='')
|
|
347
|
+
PartClass.objects.get_or_create(code=220, name='Led', comment='/Light')
|
|
348
|
+
PartClass.objects.get_or_create(code=221, name='Packaging Material',
|
|
349
|
+
comment='Includes Bags, Boxes, Pallets, etc. Non-Custom only.')
|
|
350
|
+
PartClass.objects.get_or_create(code=222, name='Rectifier', comment='')
|
|
351
|
+
PartClass.objects.get_or_create(code=223, name='Resistor', comment='')
|
|
352
|
+
PartClass.objects.get_or_create(code=224, name='Resistor Network', comment='')
|
|
353
|
+
PartClass.objects.get_or_create(code=225, name='Socket', comment='')
|
|
354
|
+
PartClass.objects.get_or_create(code=226, name='Switch', comment='')
|
|
355
|
+
PartClass.objects.get_or_create(code=227, name='Terminal', comment='Includes Ring, Spade, Butt, etc.')
|
|
356
|
+
PartClass.objects.get_or_create(code=228, name='Transformer', comment='')
|
|
357
|
+
PartClass.objects.get_or_create(code=229, name='Transistor', comment='')
|
|
358
|
+
PartClass.objects.get_or_create(code=230, name='Tubing', comment='All types')
|
|
359
|
+
PartClass.objects.get_or_create(code=231, name='Sensor', comment='')
|
|
360
|
+
PartClass.objects.get_or_create(code=232, name='Power Supply', comment='')
|
|
361
|
+
PartClass.objects.get_or_create(code=233, name='Enclosures', comment='Off-The-Shelf Enclosures')
|
|
362
|
+
PartClass.objects.get_or_create(code=234, name='Varistor', comment='')
|
|
363
|
+
PartClass.objects.get_or_create(code=235, name='Ferrites', comment='')
|
|
364
|
+
PartClass.objects.get_or_create(code=236, name='Suppressor', comment='')
|
|
365
|
+
PartClass.objects.get_or_create(code=237, name='Misc Material', comment='')
|
|
366
|
+
PartClass.objects.get_or_create(code=238, name='Electronic Assy (Non-Custom)', comment='')
|
|
367
|
+
PartClass.objects.get_or_create(code=239, name='Antenna', comment='')
|
bom/local_settings.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
BASE_DIR = Path(__file__).resolve().parent.parent
|
|
4
|
+
|
|
5
|
+
# SECURITY WARNING: keep the secret key used in production secret!
|
|
6
|
+
SECRET_KEY = 'supersecretkey'
|
|
7
|
+
|
|
8
|
+
# SECURITY WARNING: don't run with debug turned on in production!
|
|
9
|
+
DEBUG = True
|
|
10
|
+
|
|
11
|
+
ALLOWED_HOSTS = ['*']
|
|
12
|
+
|
|
13
|
+
BOM_CONFIG = {
|
|
14
|
+
'mouser_api_key': 'secretkey',
|
|
15
|
+
'admin_dashboard': {
|
|
16
|
+
'enable_autocomplete': False,
|
|
17
|
+
'page_size': 50,
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
# google GoogleOAuth
|
|
22
|
+
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = 'secretkey'
|
|
23
|
+
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = 'secretkey'
|
|
24
|
+
|
|
25
|
+
# Database
|
|
26
|
+
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
|
|
27
|
+
|
|
28
|
+
DATABASES = {
|
|
29
|
+
'default': {
|
|
30
|
+
'ENGINE': 'django.db.backends.sqlite3',
|
|
31
|
+
'NAME': BASE_DIR / 'db.sqlite3',
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
FIXER_ACCESS_KEY = 'secretkey from fixer.io' # for exchange rate conversions
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Generated by Django 2.1.1 on 2018-09-06 02:40
|
|
2
|
+
|
|
3
|
+
from django.conf import settings
|
|
4
|
+
import django.core.validators
|
|
5
|
+
from django.db import migrations, models
|
|
6
|
+
import django.db.models.deletion
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Migration(migrations.Migration):
|
|
10
|
+
|
|
11
|
+
initial = True
|
|
12
|
+
|
|
13
|
+
dependencies = [
|
|
14
|
+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
operations = [
|
|
18
|
+
migrations.CreateModel(
|
|
19
|
+
name='Manufacturer',
|
|
20
|
+
fields=[
|
|
21
|
+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
22
|
+
('name', models.CharField(default=None, max_length=128)),
|
|
23
|
+
],
|
|
24
|
+
options={
|
|
25
|
+
'ordering': ['name'],
|
|
26
|
+
},
|
|
27
|
+
),
|
|
28
|
+
migrations.CreateModel(
|
|
29
|
+
name='Organization',
|
|
30
|
+
fields=[
|
|
31
|
+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
32
|
+
('name', models.CharField(default=None, max_length=255)),
|
|
33
|
+
('subscription', models.CharField(choices=[('F', 'Free'), ('P', 'Pro')], max_length=1)),
|
|
34
|
+
('owner', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
|
|
35
|
+
],
|
|
36
|
+
),
|
|
37
|
+
migrations.CreateModel(
|
|
38
|
+
name='Part',
|
|
39
|
+
fields=[
|
|
40
|
+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
41
|
+
('number_item', models.CharField(blank=True, default=None, max_length=4, validators=[django.core.validators.RegexValidator('^[0-9]*$', 'Only numeric characters are allowed.')])),
|
|
42
|
+
('number_variation', models.CharField(blank=True, default=None, max_length=2, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z]*$', 'Only alphanumeric characters are allowed.')])),
|
|
43
|
+
('description', models.CharField(default=None, max_length=255)),
|
|
44
|
+
('revision', models.CharField(max_length=2)),
|
|
45
|
+
('manufacturer_part_number', models.CharField(blank=True, default='', max_length=128)),
|
|
46
|
+
('manufacturer', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.PROTECT, to='bom.Manufacturer')),
|
|
47
|
+
],
|
|
48
|
+
),
|
|
49
|
+
migrations.CreateModel(
|
|
50
|
+
name='PartClass',
|
|
51
|
+
fields=[
|
|
52
|
+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
53
|
+
('code', models.CharField(max_length=3, unique=True)),
|
|
54
|
+
('name', models.CharField(default=None, max_length=255)),
|
|
55
|
+
('comment', models.CharField(blank=True, default=None, max_length=255)),
|
|
56
|
+
],
|
|
57
|
+
),
|
|
58
|
+
migrations.CreateModel(
|
|
59
|
+
name='PartFile',
|
|
60
|
+
fields=[
|
|
61
|
+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
62
|
+
('file', models.FileField(upload_to='partfiles/')),
|
|
63
|
+
('upload_date', models.DateField(auto_now=True)),
|
|
64
|
+
('part', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='bom.Part')),
|
|
65
|
+
],
|
|
66
|
+
),
|
|
67
|
+
migrations.CreateModel(
|
|
68
|
+
name='Seller',
|
|
69
|
+
fields=[
|
|
70
|
+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
71
|
+
('name', models.CharField(default=None, max_length=128)),
|
|
72
|
+
('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='bom.Organization')),
|
|
73
|
+
],
|
|
74
|
+
),
|
|
75
|
+
migrations.CreateModel(
|
|
76
|
+
name='SellerPart',
|
|
77
|
+
fields=[
|
|
78
|
+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
79
|
+
('minimum_order_quantity', models.IntegerField(blank=True, null=True)),
|
|
80
|
+
('minimum_pack_quantity', models.IntegerField(blank=True, null=True)),
|
|
81
|
+
('unit_cost', models.DecimalField(blank=True, decimal_places=4, max_digits=8, null=True)),
|
|
82
|
+
('lead_time_days', models.IntegerField(blank=True, null=True)),
|
|
83
|
+
('nre_cost', models.DecimalField(blank=True, decimal_places=4, max_digits=8, null=True)),
|
|
84
|
+
('ncnr', models.BooleanField(default=False)),
|
|
85
|
+
('part', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='bom.Part')),
|
|
86
|
+
('seller', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='bom.Seller')),
|
|
87
|
+
],
|
|
88
|
+
),
|
|
89
|
+
migrations.CreateModel(
|
|
90
|
+
name='Subpart',
|
|
91
|
+
fields=[
|
|
92
|
+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
93
|
+
('count', models.IntegerField(default=1)),
|
|
94
|
+
('assembly_part', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='assembly_part', to='bom.Part')),
|
|
95
|
+
('assembly_subpart', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='assembly_subpart', to='bom.Part')),
|
|
96
|
+
],
|
|
97
|
+
),
|
|
98
|
+
migrations.CreateModel(
|
|
99
|
+
name='UserMeta',
|
|
100
|
+
fields=[
|
|
101
|
+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
102
|
+
('role', models.CharField(choices=[('A', 'Admin'), ('V', 'Viewer')], max_length=1)),
|
|
103
|
+
('organization', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='bom.Organization')),
|
|
104
|
+
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
|
105
|
+
],
|
|
106
|
+
),
|
|
107
|
+
migrations.AddField(
|
|
108
|
+
model_name='part',
|
|
109
|
+
name='number_class',
|
|
110
|
+
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.PROTECT, related_name='number_class', to='bom.PartClass'),
|
|
111
|
+
),
|
|
112
|
+
migrations.AddField(
|
|
113
|
+
model_name='part',
|
|
114
|
+
name='organization',
|
|
115
|
+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='bom.Organization'),
|
|
116
|
+
),
|
|
117
|
+
migrations.AddField(
|
|
118
|
+
model_name='part',
|
|
119
|
+
name='subparts',
|
|
120
|
+
field=models.ManyToManyField(blank=True, through='bom.Subpart', to='bom.Part'),
|
|
121
|
+
),
|
|
122
|
+
migrations.AddField(
|
|
123
|
+
model_name='manufacturer',
|
|
124
|
+
name='organization',
|
|
125
|
+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='bom.Organization'),
|
|
126
|
+
),
|
|
127
|
+
migrations.AlterUniqueTogether(
|
|
128
|
+
name='sellerpart',
|
|
129
|
+
unique_together={('seller', 'part', 'minimum_order_quantity', 'unit_cost')},
|
|
130
|
+
),
|
|
131
|
+
migrations.AlterUniqueTogether(
|
|
132
|
+
name='part',
|
|
133
|
+
unique_together={('number_class', 'number_item', 'number_variation', 'organization')},
|
|
134
|
+
),
|
|
135
|
+
]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Generated by Django 2.1.1 on 2018-09-08 21:51
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
import django.db.models.deletion
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
('bom', '0001_initial'),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AlterField(
|
|
15
|
+
model_name='subpart',
|
|
16
|
+
name='assembly_part',
|
|
17
|
+
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='assembly_part', to='bom.Part'),
|
|
18
|
+
),
|
|
19
|
+
migrations.AlterField(
|
|
20
|
+
model_name='subpart',
|
|
21
|
+
name='assembly_subpart',
|
|
22
|
+
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='assembly_subpart', to='bom.Part'),
|
|
23
|
+
),
|
|
24
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 2.1.1 on 2018-09-10 23:42
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('bom', '0002_auto_20180908_2151'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AddField(
|
|
14
|
+
model_name='sellerpart',
|
|
15
|
+
name='data_source',
|
|
16
|
+
field=models.CharField(default=None, max_length=32, null=True),
|
|
17
|
+
),
|
|
18
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 2.1.1 on 2018-09-11 00:11
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('bom', '0003_sellerpart_data_source'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name='sellerpart',
|
|
15
|
+
name='data_source',
|
|
16
|
+
field=models.CharField(blank=True, default=None, max_length=32, null=True),
|
|
17
|
+
),
|
|
18
|
+
]
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Generated by Django 2.1.1 on 2018-10-07 19:34
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
import django.db.models.deletion
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def update_sellerpart_fk(apps, schema_editor):
|
|
8
|
+
Part = apps.get_model('bom', 'Part')
|
|
9
|
+
SellerPart = apps.get_model('bom', 'SellerPart')
|
|
10
|
+
ManufacturerPart = apps.get_model('bom', 'ManufacturerPart')
|
|
11
|
+
|
|
12
|
+
for sp in SellerPart.objects.all():
|
|
13
|
+
(mp, created) = ManufacturerPart.objects.get_or_create(part=sp.part, manufacturer_part_number=sp.part.manufacturer_part_number, manufacturer=sp.part.manufacturer)
|
|
14
|
+
sp.manufacturer_part = mp
|
|
15
|
+
sp.save()
|
|
16
|
+
|
|
17
|
+
for p in Part.objects.all():
|
|
18
|
+
(mp, created) = ManufacturerPart.objects.get_or_create(part=p, manufacturer_part_number=p.manufacturer_part_number, manufacturer=p.manufacturer)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Migration(migrations.Migration):
|
|
22
|
+
|
|
23
|
+
dependencies = [
|
|
24
|
+
('bom', '0004_auto_20180911_0011'),
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
operations = [
|
|
28
|
+
migrations.CreateModel(
|
|
29
|
+
name='ManufacturerPart',
|
|
30
|
+
fields=[
|
|
31
|
+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
32
|
+
('manufacturer_part_number', models.CharField(blank=True, default='', max_length=128)),
|
|
33
|
+
('manufacturer', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.PROTECT, to='bom.Manufacturer')),
|
|
34
|
+
('part', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='bom.Part')),
|
|
35
|
+
],
|
|
36
|
+
),
|
|
37
|
+
migrations.AddField(
|
|
38
|
+
model_name='sellerpart',
|
|
39
|
+
name='manufacturer_part',
|
|
40
|
+
field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to='bom.ManufacturerPart'),
|
|
41
|
+
),
|
|
42
|
+
migrations.RunPython(update_sellerpart_fk),
|
|
43
|
+
migrations.AlterField(
|
|
44
|
+
model_name='sellerpart',
|
|
45
|
+
name='manufacturer_part',
|
|
46
|
+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='bom.ManufacturerPart'),
|
|
47
|
+
),
|
|
48
|
+
migrations.AlterUniqueTogether(
|
|
49
|
+
name='sellerpart',
|
|
50
|
+
unique_together={('seller', 'manufacturer_part', 'minimum_order_quantity', 'unit_cost')},
|
|
51
|
+
),
|
|
52
|
+
migrations.AlterUniqueTogether(
|
|
53
|
+
name='manufacturerpart',
|
|
54
|
+
unique_together={('part', 'manufacturer_part_number', 'manufacturer')},
|
|
55
|
+
),
|
|
56
|
+
]
|