django-bom 1.253__tar.gz → 1.258__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.
Files changed (201) hide show
  1. {django_bom-1.253/django_bom.egg-info → django_bom-1.258}/PKG-INFO +1 -1
  2. {django_bom-1.253 → django_bom-1.258}/bom/admin.py +34 -0
  3. {django_bom-1.253 → django_bom-1.258}/bom/constants.py +7 -0
  4. {django_bom-1.253 → django_bom-1.258}/bom/csv_headers.py +22 -44
  5. django_bom-1.258/bom/forms.py +1328 -0
  6. {django_bom-1.253 → django_bom-1.258}/bom/helpers.py +79 -4
  7. django_bom-1.258/bom/migrations/0052_remove_partrevision_attribute_and_more.py +584 -0
  8. {django_bom-1.253 → django_bom-1.258}/bom/models.py +191 -80
  9. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/css/style.css +19 -0
  10. django_bom-1.258/bom/static/bom/js/formset-handler.js +65 -0
  11. django_bom-1.258/bom/templates/bom/edit-part-class.html +120 -0
  12. django_bom-1.258/bom/templates/bom/edit-quantity-of-measure.html +119 -0
  13. django_bom-1.258/bom/templates/bom/edit-user-meta.html +70 -0
  14. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/part-info.html +10 -1
  15. django_bom-1.258/bom/templates/bom/part-revision-display.html +47 -0
  16. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/settings.html +138 -11
  17. {django_bom-1.253 → django_bom-1.258}/bom/tests.py +117 -31
  18. {django_bom-1.253 → django_bom-1.258}/bom/urls.py +6 -0
  19. {django_bom-1.253 → django_bom-1.258}/bom/views/views.py +179 -42
  20. {django_bom-1.253 → django_bom-1.258/django_bom.egg-info}/PKG-INFO +1 -1
  21. {django_bom-1.253 → django_bom-1.258}/django_bom.egg-info/SOURCES.txt +3 -0
  22. {django_bom-1.253 → django_bom-1.258}/pyproject.toml +1 -1
  23. django_bom-1.253/bom/forms.py +0 -1381
  24. django_bom-1.253/bom/templates/bom/edit-part-class.html +0 -33
  25. django_bom-1.253/bom/templates/bom/edit-user-meta.html +0 -38
  26. django_bom-1.253/bom/templates/bom/part-revision-display.html +0 -184
  27. {django_bom-1.253 → django_bom-1.258}/LICENSE +0 -0
  28. {django_bom-1.253 → django_bom-1.258}/MANIFEST.in +0 -0
  29. {django_bom-1.253 → django_bom-1.258}/README.md +0 -0
  30. {django_bom-1.253 → django_bom-1.258}/bom/__init__.py +0 -0
  31. {django_bom-1.253 → django_bom-1.258}/bom/apps.py +0 -0
  32. {django_bom-1.253 → django_bom-1.258}/bom/auth_backends.py +0 -0
  33. {django_bom-1.253 → django_bom-1.258}/bom/base_classes.py +0 -0
  34. {django_bom-1.253 → django_bom-1.258}/bom/context_processors.py +0 -0
  35. {django_bom-1.253 → django_bom-1.258}/bom/decorators.py +0 -0
  36. {django_bom-1.253 → django_bom-1.258}/bom/form_fields.py +0 -0
  37. {django_bom-1.253 → django_bom-1.258}/bom/local_settings.py +0 -0
  38. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0001_initial.py +0 -0
  39. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0002_auto_20180908_2151.py +0 -0
  40. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0003_sellerpart_data_source.py +0 -0
  41. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0004_auto_20180911_0011.py +0 -0
  42. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0005_auto_20181007_1934.py +0 -0
  43. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0006_auto_20181007_1949.py +0 -0
  44. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0007_auto_20181009_0256.py +0 -0
  45. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0008_auto_20181030_0427.py +0 -0
  46. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0009_subpart_reference.py +0 -0
  47. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0010_auto_20181202_0733.py +0 -0
  48. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0011_auto_20181202_2113.py +0 -0
  49. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0012_partchangehistory.py +0 -0
  50. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0013_auto_20190222_1631.py +0 -0
  51. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0014_auto_20190223_2353.py +0 -0
  52. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0015_auto_20190303_1915.py +0 -0
  53. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0016_auto_20190405_2308.py +0 -0
  54. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0017_auto_20190616_1912.py +0 -0
  55. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0018_auto_20190616_2143.py +0 -0
  56. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0019_auto_20190624_1246.py +0 -0
  57. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0020_auto_20190627_0207.py +0 -0
  58. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0021_auto_20190627_0428.py +0 -0
  59. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0022_auto_20190811_2140.py +0 -0
  60. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0023_auto_20191205_2351.py +0 -0
  61. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0024_auto_20191214_1342.py +0 -0
  62. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0025_auto_20191221_1907.py +0 -0
  63. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0026_auto_20191222_2258.py +0 -0
  64. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0027_auto_20191222_2347.py +0 -0
  65. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0028_partrevision_displayable_synopsis.py +0 -0
  66. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0029_auto_20191231_1630.py +0 -0
  67. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0030_auto_20200101_2253.py +0 -0
  68. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0031_auto_20200104_1352.py +0 -0
  69. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0032_auto_20200126_1806.py +0 -0
  70. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0033_auto_20200203_0618.py +0 -0
  71. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0034_auto_20200222_0359.py +0 -0
  72. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0035_auto_20200303_0111.py +0 -0
  73. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0036_auto_20200303_0538.py +0 -0
  74. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0037_auto_20200405_1642.py +0 -0
  75. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0038_auto_20200422_0504.py +0 -0
  76. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0039_auto_20200929_2315.py +0 -0
  77. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0040_alter_organization_currency.py +0 -0
  78. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0041_organization_subscription_quantity.py +0 -0
  79. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0042_auto_20210720_2137.py +0 -0
  80. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0043_auto_20211123_0157.py +0 -0
  81. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0044_auto_20220831_1241.py +0 -0
  82. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0045_sellerpart_link.py +0 -0
  83. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0046_alter_sellerpart_unique_together.py +0 -0
  84. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0047_sellerpart_seller_part_number.py +0 -0
  85. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0048_rename_part_organization_number_class_bom_part_organiz_b333d6_idx_and_more.py +0 -0
  86. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0049_alter_assembly_id_alter_assemblysubparts_id_and_more.py +0 -0
  87. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0050_alter_organization_options.py +0 -0
  88. {django_bom-1.253 → django_bom-1.258}/bom/migrations/0051_alter_manufacturer_organization_and_more.py +0 -0
  89. {django_bom-1.253 → django_bom-1.258}/bom/migrations/__init__.py +0 -0
  90. {django_bom-1.253 → django_bom-1.258}/bom/part_bom.py +0 -0
  91. {django_bom-1.253 → django_bom-1.258}/bom/settings.py +0 -0
  92. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/css/dashboard.css +0 -0
  93. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/css/jquery.treetable.css +0 -0
  94. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/css/materialize.min.css +0 -0
  95. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/css/part-info.css +0 -0
  96. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/css/tablesorter-theme.materialize.css +0 -0
  97. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/css/treetable-theme.css +0 -0
  98. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/doc/sample_part_classes.csv +0 -0
  99. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/doc/test_bom.csv +0 -0
  100. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/doc/test_bom_5_intelligent.csv +0 -0
  101. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/doc/test_full_bom.csv +0 -0
  102. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/doc/test_new_parts.csv +0 -0
  103. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/doc/test_new_parts_5_intelligent.csv +0 -0
  104. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/_ionicons_svg_md-arrow-dropdown.svg +0 -0
  105. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/_ionicons_svg_md-arrow-dropright.svg +0 -0
  106. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/favicon.ico +0 -0
  107. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/1x/btn_google_signin_dark_disabled_web.png +0 -0
  108. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/1x/btn_google_signin_dark_focus_web.png +0 -0
  109. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/1x/btn_google_signin_dark_normal_web.png +0 -0
  110. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/1x/btn_google_signin_dark_pressed_web.png +0 -0
  111. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/1x/btn_google_signin_light_disabled_web.png +0 -0
  112. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/1x/btn_google_signin_light_focus_web.png +0 -0
  113. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/1x/btn_google_signin_light_normal_web.png +0 -0
  114. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/1x/btn_google_signin_light_pressed_web.png +0 -0
  115. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/2x/btn_google_signin_dark_disabled_web@2x.png +0 -0
  116. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/2x/btn_google_signin_dark_focus_web@2x.png +0 -0
  117. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/2x/btn_google_signin_dark_normal_web@2x.png +0 -0
  118. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/2x/btn_google_signin_dark_pressed_web@2x.png +0 -0
  119. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/2x/btn_google_signin_light_disabled_web@2x.png +0 -0
  120. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/2x/btn_google_signin_light_focus_web@2x.png +0 -0
  121. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/2x/btn_google_signin_light_normal_web@2x.png +0 -0
  122. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/2x/btn_google_signin_light_pressed_web@2x.png +0 -0
  123. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/vector/btn_google_dark_disabled_ios.eps +0 -0
  124. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/vector/btn_google_dark_disabled_ios.svg +0 -0
  125. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/vector/btn_google_dark_focus_ios.eps +0 -0
  126. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/vector/btn_google_dark_focus_ios.svg +0 -0
  127. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/vector/btn_google_dark_normal_ios.eps +0 -0
  128. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/vector/btn_google_dark_normal_ios.svg +0 -0
  129. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/vector/btn_google_dark_pressed_ios.eps +0 -0
  130. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/vector/btn_google_dark_pressed_ios.svg +0 -0
  131. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/vector/btn_google_light_disabled_ios.eps +0 -0
  132. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/vector/btn_google_light_disabled_ios.svg +0 -0
  133. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/vector/btn_google_light_focus_ios.eps +0 -0
  134. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/vector/btn_google_light_focus_ios.svg +0 -0
  135. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/vector/btn_google_light_normal_ios.eps +0 -0
  136. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/vector/btn_google_light_normal_ios.svg +0 -0
  137. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/vector/btn_google_light_pressed_ios.eps +0 -0
  138. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google/web/vector/btn_google_light_pressed_ios.svg +0 -0
  139. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/google_drive_logo.svg +0 -0
  140. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/indabom.png +0 -0
  141. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/mouser.png +0 -0
  142. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/img/octopart_blue.svg +0 -0
  143. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/js/jquery-3.4.1.min.js +0 -0
  144. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/js/jquery.ba-floatingscrollbar.min.js +0 -0
  145. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/js/jquery.treetable.js +0 -0
  146. {django_bom-1.253 → django_bom-1.258}/bom/static/bom/js/materialize.min.js +0 -0
  147. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/account-delete.html +0 -0
  148. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/add-manufacturer-part.html +0 -0
  149. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/add-sellerpart.html +0 -0
  150. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/base-menu.html +0 -0
  151. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/base.html +0 -0
  152. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/bom-action-btn.html +0 -0
  153. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/bom-action-table.html +0 -0
  154. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/bom-base-menu.html +0 -0
  155. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/bom-base.html +0 -0
  156. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/bom-form-modal.html +0 -0
  157. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/bom-form.html +0 -0
  158. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/bom-modal-add-users.html +0 -0
  159. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/bom-signup.html +0 -0
  160. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/components/bom-flat.html +0 -0
  161. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/components/bom-indented.html +0 -0
  162. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/components/manufacturer-part-list.html +0 -0
  163. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/components/seller-part-list.html +0 -0
  164. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/create-part.html +0 -0
  165. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/dashboard-menu.html +0 -0
  166. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/dashboard.html +0 -0
  167. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/edit-manufacturer-part.html +0 -0
  168. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/edit-part.html +0 -0
  169. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/help.html +0 -0
  170. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/manufacturer-info.html +0 -0
  171. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/manufacturers.html +0 -0
  172. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/nothing-to-see.html +0 -0
  173. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/organization-create.html +0 -0
  174. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/part-revision-edit.html +0 -0
  175. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/part-revision-manage-bom.html +0 -0
  176. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/part-revision-new.html +0 -0
  177. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/part-revision-release.html +0 -0
  178. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/search-help.html +0 -0
  179. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/seller-info.html +0 -0
  180. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/sellers.html +0 -0
  181. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/signup.html +0 -0
  182. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/subscription_panel.html +0 -0
  183. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/table_of_contents.html +0 -0
  184. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/upload-bom.html +0 -0
  185. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/upload-parts-help.html +0 -0
  186. {django_bom-1.253 → django_bom-1.258}/bom/templates/bom/upload-parts.html +0 -0
  187. {django_bom-1.253 → django_bom-1.258}/bom/templates/registration/login.html +0 -0
  188. {django_bom-1.253 → django_bom-1.258}/bom/third_party_apis/__init__.py +0 -0
  189. {django_bom-1.253 → django_bom-1.258}/bom/third_party_apis/base_api.py +0 -0
  190. {django_bom-1.253 → django_bom-1.258}/bom/third_party_apis/google_drive.py +0 -0
  191. {django_bom-1.253 → django_bom-1.258}/bom/third_party_apis/mouser.py +0 -0
  192. {django_bom-1.253 → django_bom-1.258}/bom/third_party_apis/test_apis.py +0 -0
  193. {django_bom-1.253 → django_bom-1.258}/bom/utils.py +0 -0
  194. {django_bom-1.253 → django_bom-1.258}/bom/validators.py +0 -0
  195. {django_bom-1.253 → django_bom-1.258}/bom/views/__init__.py +0 -0
  196. {django_bom-1.253 → django_bom-1.258}/bom/views/json_views.py +0 -0
  197. {django_bom-1.253 → django_bom-1.258}/bom/wsgi.py +0 -0
  198. {django_bom-1.253 → django_bom-1.258}/django_bom.egg-info/dependency_links.txt +0 -0
  199. {django_bom-1.253 → django_bom-1.258}/django_bom.egg-info/requires.txt +0 -0
  200. {django_bom-1.253 → django_bom-1.258}/django_bom.egg-info/top_level.txt +0 -0
  201. {django_bom-1.253 → django_bom-1.258}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-bom
3
- Version: 1.253
3
+ Version: 1.258
4
4
  Summary: A simple Django app to manage a bill of materials.
5
5
  Author-email: Mike Kasparian <mpkasp@gmail.com>
6
6
  License: GPL-3.0-only
@@ -10,9 +10,13 @@ from .models import (
10
10
  Part,
11
11
  PartClass,
12
12
  PartRevision,
13
+ PartRevisionProperty,
14
+ PartRevisionPropertyDefinition,
13
15
  Seller,
14
16
  SellerPart,
15
17
  Subpart,
18
+ UnitDefinition,
19
+ QuantityOfMeasure,
16
20
  get_organization_model,
17
21
  get_user_meta_model
18
22
  )
@@ -87,7 +91,10 @@ class PartClassAdmin(admin.ModelAdmin):
87
91
 
88
92
  class PartRevisionAdminInline(admin.TabularInline):
89
93
  model = PartRevision
94
+ extra = 0
90
95
  raw_id_fields = ('assembly',)
96
+ readonly_fields = ('timestamp',)
97
+ show_change_link = True
91
98
 
92
99
 
93
100
  class PartAdmin(admin.ModelAdmin):
@@ -97,8 +104,10 @@ class PartAdmin(admin.ModelAdmin):
97
104
  'organization',
98
105
  'get_full_part_number',
99
106
  )
107
+ list_filter = ('organization', 'number_class',)
100
108
  raw_id_fields = ('number_class', 'primary_manufacturer_part',)
101
109
  inlines = [
110
+ PartRevisionAdminInline,
102
111
  ManufacturerPartAdminInline,
103
112
  ]
104
113
 
@@ -109,10 +118,22 @@ class PartAdmin(admin.ModelAdmin):
109
118
  get_full_part_number.admin_order_field = 'number_class__part_number'
110
119
 
111
120
 
121
+ class QuantityOfMeasureAdmin(admin.ModelAdmin):
122
+ list_display = ('name', 'organization')
123
+ list_filter = ('organization',)
124
+
125
+
126
+ class PartRevisionPropertyInline(admin.TabularInline):
127
+ model = PartRevisionProperty
128
+ extra = 1
129
+ raw_id_fields = ('property_definition', 'part_revision', 'unit_definition')
130
+
131
+
112
132
  class PartRevisionAdmin(admin.ModelAdmin):
113
133
  list_display = ('part', 'revision', 'description', 'get_assembly_size', 'timestamp',)
114
134
  raw_id_fields = ('assembly',)
115
135
  readonly_fields = ('timestamp',)
136
+ inlines = [PartRevisionPropertyInline]
116
137
 
117
138
  def get_assembly_size(self, obj):
118
139
  return None if obj.assembly is None else obj.assembly.subparts.count()
@@ -141,6 +162,16 @@ class AssemblyAdmin(admin.ModelAdmin):
141
162
  ]
142
163
 
143
164
 
165
+ class UnitDefinitionAdmin(admin.ModelAdmin):
166
+ list_display = ('name', 'symbol', 'quantity_of_measure', 'base_multiplier', 'organization')
167
+ list_filter = ('organization',)
168
+
169
+
170
+ class PartRevisionPropertyDefinitionAdmin(admin.ModelAdmin):
171
+ list_display = ('code', 'name', 'type', 'organization', 'quantity_of_measure')
172
+ list_filter = ('organization',)
173
+
174
+
144
175
  if settings.BOM_USER_META_MODEL == 'bom.UserMeta':
145
176
  current_user_admin = admin.site._registry.get(User)
146
177
 
@@ -171,3 +202,6 @@ admin.site.register(PartRevision, PartRevisionAdmin)
171
202
  admin.site.register(Manufacturer, ManufacturerAdmin)
172
203
  admin.site.register(Assembly, AssemblyAdmin)
173
204
  admin.site.register(Subpart, SubpartAdmin)
205
+ admin.site.register(UnitDefinition, UnitDefinitionAdmin)
206
+ admin.site.register(PartRevisionPropertyDefinition, PartRevisionPropertyDefinitionAdmin)
207
+ admin.site.register(QuantityOfMeasure, QuantityOfMeasureAdmin)
@@ -34,6 +34,13 @@ DATA_SOURCES = (
34
34
  (DATA_SOURCE_MOUSER, 'mouser'),
35
35
  )
36
36
 
37
+ PART_REVISION_PROPERTY_TYPE_STRING = 'S'
38
+ PART_REVISION_PROPERTY_TYPE_DECIMAL = 'D'
39
+ PART_REVISION_PROPERTY_TYPE_BOOLEAN = 'B'
40
+ PART_REVISION_PROPERTY_TYPES = ((PART_REVISION_PROPERTY_TYPE_STRING, 'String'),
41
+ (PART_REVISION_PROPERTY_TYPE_DECIMAL, 'Number'),
42
+ (PART_REVISION_PROPERTY_TYPE_BOOLEAN, 'Boolean'),)
43
+
37
44
  VALUE_UNITS = (
38
45
  NO_CHOICE,
39
46
  ('Ohms', '\u03A9'),
@@ -35,8 +35,11 @@ class CSVHeader:
35
35
  class CSVHeaders(ABC):
36
36
  all_headers_defns = []
37
37
 
38
+ def __init__(self, *args, **kwargs):
39
+ self.headers_defns = list(self.all_headers_defns)
40
+
38
41
  def get_synoynms(self, hdr_name):
39
- for defn in self.all_headers_defns:
42
+ for defn in self.headers_defns:
40
43
  if hdr_name in defn:
41
44
  return defn.synonyms()
42
45
  else:
@@ -53,7 +56,7 @@ class CSVHeaders(ABC):
53
56
 
54
57
  # Preserves order of definitions as listed in all_header_defns:
55
58
  def get_default_all(self):
56
- return [d.name for d in self.all_headers_defns]
59
+ return [d.name for d in self.headers_defns]
57
60
 
58
61
  # Given a list of header names returns the default name for each. The return list
59
62
  # matches the order of the input list. If a name is not recognized, then returns
@@ -151,6 +154,9 @@ class CSVHeaders(ABC):
151
154
  return True
152
155
  raise CSVHeaderError(f'Missing column named {header}')
153
156
 
157
+ def add_header(self, header):
158
+ self.headers_defns.append(header)
159
+
154
160
 
155
161
  #
156
162
  # For each CSV header class, a static data member dictionary uses the key as the default name for the header while the
@@ -190,52 +196,25 @@ class PartClassesCSVHeaders(CSVHeaders):
190
196
  ]
191
197
 
192
198
 
193
- class PartsListCSVHeaders(CSVHeaders):
194
- part_attributes = [
195
- CSVHeader('value', name_options=['val', 'val.', ]),
196
- CSVHeader('value_units', name_options=['value units', 'val. units', 'val units', ]),
197
- CSVHeader('tolerance', name_options=[]),
198
- CSVHeader('attribute', name_options=[]),
199
- CSVHeader('package', name_options=[]),
200
- CSVHeader('pin_count', name_options=[]),
201
- CSVHeader('frequency', name_options=[]),
202
- CSVHeader('frequency_units', name_options=[]),
203
- CSVHeader('wavelength', name_options=[]),
204
- CSVHeader('wavelength_units', name_options=[]),
205
- CSVHeader('memory', name_options=[]),
206
- CSVHeader('memory_units', name_options=[]),
207
- CSVHeader('interface', name_options=[]),
208
- CSVHeader('supply_voltage', name_options=[]),
209
- CSVHeader('supply_voltage_units', name_options=[]),
210
- CSVHeader('temperature_rating', name_options=[]),
211
- CSVHeader('temperature_rating_units', name_options=[]),
212
- CSVHeader('power_rating', name_options=[]),
213
- CSVHeader('power_rating_units', name_options=[]),
214
- CSVHeader('voltage_rating', name_options=[]),
215
- CSVHeader('voltage_rating_units', name_options=[]),
216
- CSVHeader('current_rating', name_options=[]),
217
- CSVHeader('current_rating_units', name_options=[]),
218
- CSVHeader('material', name_options=[]),
219
- CSVHeader('color', name_options=[]),
220
- CSVHeader('finish', name_options=[]),
221
- CSVHeader('length', name_options=[]),
222
- CSVHeader('length_units', name_options=[]),
223
- CSVHeader('width', name_options=[]),
224
- CSVHeader('width_units', name_options=[]),
225
- CSVHeader('height', name_options=[]),
226
- CSVHeader('height_units', name_options=[]),
227
- CSVHeader('weight', name_options=[]),
228
- CSVHeader('weight_units', name_options=[]),
229
- ]
199
+ class PartRevisionPropertyCSVHeaders(CSVHeaders):
200
+ def add_dynamic_headers(self, definitions):
201
+ for defn in definitions:
202
+ self.add_header(
203
+ CSVHeader(defn.form_field_name,
204
+ name_options=[defn.name, f'property_{defn.code}', f'property_{defn.name}', 'p']))
205
+ if defn.quantity_of_measure:
206
+ self.add_header(
207
+ CSVHeader(defn.form_unit_field_name, name_options=[f'{defn.name} Units', f'{defn.code}_units']))
208
+
230
209
 
210
+ class PartsListCSVHeaders(PartRevisionPropertyCSVHeaders):
231
211
  all_headers_defns = [
232
212
  CSVHeader('description', name_options=['desc', 'desc.', ]),
233
213
  CSVHeader('manufacturer_name', name_options=['mfg_name', 'manufacturer_name', 'part_manufacturer', 'mfg', 'manufacturer', 'manufacturer name', ]),
234
214
  CSVHeader('manufacturer_part_number', name_options=['mpn', 'mfg_part_number', 'part_manufacturer_part_number', 'mfg part number', 'manufacturer part number']),
235
215
  CSVHeader('part_number', name_options=['part number', 'part no', ]),
236
216
  CSVHeader('revision', name_options=['rev', 'part_revision', ]),
237
- ] + part_attributes \
238
- + SellerPartCSVHeaders.all_headers_defns
217
+ ] + SellerPartCSVHeaders.all_headers_defns
239
218
 
240
219
 
241
220
  class PartsListCSVHeadersSemiIntelligent(PartsListCSVHeaders):
@@ -246,11 +225,10 @@ class PartsListCSVHeadersSemiIntelligent(PartsListCSVHeaders):
246
225
  CSVHeader('part_class', name_options=['class', 'part_category']),
247
226
  CSVHeader('part_number', name_options=['part number', 'part no', ]),
248
227
  CSVHeader('revision', name_options=['rev', 'part_revision', ]),
249
- ] + PartsListCSVHeaders.part_attributes \
250
- + SellerPartCSVHeaders.all_headers_defns
228
+ ] + SellerPartCSVHeaders.all_headers_defns
251
229
 
252
230
 
253
- class BOMFlatCSVHeaders(CSVHeaders):
231
+ class BOMFlatCSVHeaders(PartRevisionPropertyCSVHeaders):
254
232
  all_headers_defns = [
255
233
  CSVHeader('part_number', name_options=['part number', 'part no', ]),
256
234
  CSVHeader('quantity', name_options=['count', 'qty', 'quantity', ]),