From 767b76314e2fcfdaa57aa0ed3286babdeb3f3e07 Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 12 Jul 2024 14:37:32 +1000 Subject: [PATCH] Revision Improvements (#7585) * Bump djangorestframework from 3.14.0 to 3.15.2 in /src/backend Bumps [djangorestframework](https://github.com/encode/django-rest-framework) from 3.14.0 to 3.15.2. - [Release notes](https://github.com/encode/django-rest-framework/releases) - [Commits](https://github.com/encode/django-rest-framework/compare/3.14.0...3.15.2) --- updated-dependencies: - dependency-name: djangorestframework dependency-type: direct:production ... Signed-off-by: dependabot[bot] * fix req * fix deps again * patch serializer * bump api version * Fix "min_value" for DRF decimal fields * Add default serializer values for 'IPN' and 'revision' * Add specific serializer for email field * Fix API version * Add 'revision_of' field to Part model * Add validation checks for new revision_of field * Update migration * Add unit test for 'revision' rules * Add API filters for revision control * Add table filters for PUI * Add "revision_of" field to PUI form * Update part forms for PUI * Render part revision selection dropdown in PUI * Prevent refetch on focus * Ensure select renders above other items * Disable searching * Cleanup * UI tweak * Add setting to control revisions for assemblies * Hide revision selection drop-down if revisions are not enabled * Query updates * Validate entire BOM table from PUI * Sort revisions * Fix requirements files * Fix api_version.py * Reintroduce previous check for IPN / revision uniqueness * Set default value for refetchOnWindowFocus (false) * Revert serializer change * Further CI fixes * Further unit test updates * Fix defaults for query client * Add docs * Add link to "revision_of" in CUI * Add playwright test for revisions * Ignore notification errors for playwright --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Matthias Mair --- .../images/part/part_create_revision.png | Bin 0 -> 69658 bytes .../assets/images/part/part_revision_b.png | Bin 0 -> 16550 bytes .../images/part/part_revision_select.png | Bin 0 -> 33632 bytes .../images/part/part_revision_settings.png | Bin 0 -> 5549 bytes docs/docs/part/revision.md | 78 +++++++ docs/docs/part/views.md | 5 +- docs/mkdocs.yml | 1 + .../InvenTree/InvenTree/api_version.py | 6 +- src/backend/InvenTree/build/serializers.py | 8 +- src/backend/InvenTree/common/models.py | 6 + src/backend/InvenTree/company/test_api.py | 8 +- src/backend/InvenTree/order/serializers.py | 4 +- src/backend/InvenTree/part/api.py | 24 ++- .../part/migrations/0126_part_revision_of.py | 19 ++ src/backend/InvenTree/part/models.py | 81 +++++++- src/backend/InvenTree/part/serializers.py | 6 + .../part/templates/part/part_base.html | 9 + src/backend/InvenTree/part/test_part.py | 77 +++++++ src/backend/InvenTree/stock/serializers.py | 2 +- .../templates/InvenTree/settings/part.html | 1 + .../InvenTree/templates/js/translated/part.js | 2 + src/frontend/src/App.tsx | 8 +- .../src/components/details/Details.tsx | 11 - .../src/components/details/PartIcons.tsx | 92 --------- src/frontend/src/components/forms/ApiForm.tsx | 1 - .../src/components/items/ActionDropdown.tsx | 6 +- src/frontend/src/components/nav/Header.tsx | 3 +- .../src/components/nav/NotificationDrawer.tsx | 3 +- .../src/components/nav/SearchDrawer.tsx | 3 +- .../src/components/render/Instance.tsx | 7 +- src/frontend/src/components/render/Part.tsx | 28 ++- src/frontend/src/enums/ApiEndpoints.tsx | 1 + src/frontend/src/forms/PartForms.tsx | 34 +++- src/frontend/src/functions/icons.tsx | 4 +- src/frontend/src/hooks/UseInstance.tsx | 2 +- .../pages/Index/Settings/SystemSettings.tsx | 3 +- src/frontend/src/pages/part/PartDetail.tsx | 192 +++++++++++++++--- src/frontend/src/tables/InvenTreeTable.tsx | 2 - src/frontend/src/tables/bom/BomTable.tsx | 31 ++- .../src/tables/part/PartParameterTable.tsx | 2 +- src/frontend/src/tables/part/PartTable.tsx | 14 ++ src/frontend/tests/baseFixtures.ts | 3 +- src/frontend/tests/pages/pui_part.spec.ts | 18 ++ 43 files changed, 620 insertions(+), 185 deletions(-) create mode 100644 docs/docs/assets/images/part/part_create_revision.png create mode 100644 docs/docs/assets/images/part/part_revision_b.png create mode 100644 docs/docs/assets/images/part/part_revision_select.png create mode 100644 docs/docs/assets/images/part/part_revision_settings.png create mode 100644 docs/docs/part/revision.md create mode 100644 src/backend/InvenTree/part/migrations/0126_part_revision_of.py delete mode 100644 src/frontend/src/components/details/PartIcons.tsx diff --git a/docs/docs/assets/images/part/part_create_revision.png b/docs/docs/assets/images/part/part_create_revision.png new file mode 100644 index 0000000000000000000000000000000000000000..a3a901d3c64e62b8fcfaace8c9b9fb3fca3f42d9 GIT binary patch literal 69658 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
  • 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 literal 0 HcmV?d00001 diff --git a/docs/docs/assets/images/part/part_revision_b.png b/docs/docs/assets/images/part/part_revision_b.png new file mode 100644 index 0000000000000000000000000000000000000000..501d638a0412eb6878e002845c86802ae6035af7 GIT binary patch literal 16550 zcmch8XIN9)wzeWgL?8%=fp@$MkzJ+CPJ?GqepL_4Q-;X?b)=Ji#W6m|_c;7k3JD%LoQl&q}e(cbp zL-cBYDBnDE=*ZnehYq_Rr2y_6cH>$*_=4Y5y>=+S(6 zz5j;+{LmqWPY0jFP0m^OfSV`WRPMOxI$OJWn!8#ZQgyYma)R49yP4`81s;KNswpep zdSHsHql?w+^D9&U@i9%8NDOCTqOwvNdwJ|EEYqkR?XwSC(%#}eA(2t0mV)-*OAydx z=QCE;sJ&a++#vXd;<`%L-CH*v=_oQe-1xw;WnP(e6d4xqVh>@zj2-vEN!ULY`y?OY z&ah0Z?Yv4{8j-o8KF}r$Yphl{3>bLm4hVVh^*jw9aqxZUWG?t%#83tbrh`k@A3p~{ zDS@kiGn70Bcc;LhgNMO1fkzK6WsWKzd^Icn%SS)aqt}U!JwgY68RS3v-+1zW(dmEm zXr<3dalG`*j0EJo(;dRN>e~I`NJmv{?R7#kY5Us{4O1b3+onBD*c$R!nzO^zna0Kq z`%YSCkrA8ScfQT*riAx3s@T#-m#NyV&9Jr0uH(^Z&Q8+18PsY@UZQIM2pX>;jRfU?YHLLkmaR^@Lm(k=>eN3qt{k=<@huiQ$z6I8fowHe5RAF!Rl`gQZ`hHdS?BR`PwxSy5?19!A?veaSa_-_ zUvRv?u$#K_}oMF8tttM&L6X==2v-`%bB9ca*w!hI^iCo z_KZ!ksNs1HB_Yyh^J;voA9YbMf2ek)Lw3Guqe`riqK16X_IL=lndBztP`&qz&nhNe z0(NOEEv5Hh;|$g;b-_T6NjA)>?&$5TsV~D16osqGb?RF^e67QFZ0^>`2iXv`C5Y2G z4hhprUX63QPiAte8_(>2zG}H~8r?XPq8K*7G~NC{|Un-Xm@tlOX7xeSAE%Zs9;QS{FK{m;L6T92GPm1PY%m=n-zpwy|i}L4k>8;IM zyKF!x(FZ|Ncv*%EAI732>u-c%OSJSsM#m&*(UwlnC`1jxFO3><0y>;!FIiFPa5X9~ zOQ1NGrIs~S)n5V49qMc5@}utJKxTC2cJjtIRCV75rLVWgNtK=Q!03ZCM=*nD3U<=D zMa9*Za|vs=7YMv4v@Wv^}Ig9i5uO?JfimuE6#;n!0nUhccz>QtAviscGNWzhL| zg}&aomFkO=arqQk;dxyUxyq#{Tkw(7dCQLZw78q) zZ@#}P8Tt|qVq#({x@|@E?}Cnh-Lop-R|oPHkx1lEC(!Q-*er}_)FpwB(g?t;r`%?s3pD@Hc`hYv6azPfracG zo{g-_>Nq3+W6si6pozO*lz^2}%kuRD4Y%)Dq4~1&{@oV)f)oU4r#REH=~;}i_k8H9 zoJ4gHQxWUpY~6O7S;RDUl=jjQ`)V%2(5l8?^c({Md7aC_xbgzx4?4AmGi{=_UY}%2$`94s~rC>+?bAI>BgkJdl(YWW!Jov9l#@u)=?Az`tn)B_u2!?U{2tSJ6i zX)06`Qx|mIJo0jCHfpe&^$~j`M7#oF&~o|_1E=iXP|AKBT-+FQZ#jP>H_|V;j63%x zU!k|=9WH0}lz9SIE_miChVxn;KR6JXZwv15!c)J@!XBNXK%1 z8)l~b_Vf0D7{6toRbn&EnfvcM{RvnO>C%p{6s0%X^SX^~?)Xj_NBlTl0N_ zPafZ)C@L>KBKkB>9Aw4YRG3lRS6K575&$o1O$taxlJC-Zd1NF7&7yIN~*CT(g#(IpJ7OijQ(>7#g{>z*+ zP)|r4q4ov#*_fyH_7Y4%kdZtgBG2oy>rWivly!R^!e)H`L*#&IOq3Pk6_v%<7uvOk zct2Y7aQ89g^{vDE*O$+OqB=@C+uNTtN_8fGtaq$6XXGC;$PA3lvuaEqT$(DiD#>by ze+g|@1Y3l^1NP%FM)daA8KGrHt}AchvmM2{bNzWEy4sjOweuUHiOiS}wvYMl$Bw+sHbc>MMKjcfM?2vY zgW{s$V#oE)i!8SrjlmgM0OnlxobCvc!(@2Y< z$D26GBj9mKIU}-v+zZ}&5Pm6^?iY6zbYv4#;i>BF(=9onPJMe*$`nP7e$MOBMV^}8 zQ>&Rrl>x6UkpXyPfs3F_$X=m_J+^MCIL6FNVr=LtNMW#lV=78}ec{N*J;fSLC^S|#4cv?bXWA>|u}@p}OW2+h zFU)KdfT~g~%FP_FG){<})+)od4|R@RUXz5u?DmXKnEAltN>Cqv@#CS#(2b2{s%Ko3 z#Vz|baU-5Pp|6U2Xwfto@()H`ni^*Jrug+6<#M3>pq@*gpI{jjqnI3zqHQv?J5(Js zeU5&Wx8E~e&xOs@mHED!3Y~$d$X9P{3?n9NG=< z&sz@yZK){O?B4I*XH@6)t}{nJxbVkpWb3aE;xfomUrO9}*^HD9IPge0z#GK+Le`pj zC$T{S92H|8K1azpH_#U^?~a;ZBgD|7Jtdu7qZu2l1oaVxc`Y*Vf~;TM%~g;kxo~c} zzs@+B1j z+M0C$NY?`h$IBB3kpv%xzevOXfPYXQ9L8P+{$LTnbR3YpkHK_Uf1;z`@k57*03ZIw zICP#tN2}cz0}dal_FNtZctSO@(+>}4GjZ$UjkuZ$1CEeJ51f0VcSMA;Q{+%pB0}Eo zL;|O`>EKVM^EFV~hv3kn_~fG!BV=QlOj<6eU29$T->TtHa_c4$mqp}6s-_}^jLPTU z0VAQf8S?3I#A%;_w?6oU{?P}tXV-Ob*@v){>An8gv7!9w$!fl0FN>{3pN_&*0L zT_(L|llWC5uC6sVJY`!n1rC0k2lNFX3B*Zmh5jZl_5sHS_~77Ou)|N%@gAB8@hRWH z&MJ_1^i91~JS8S~7YkzG)gHKNILw}m(hB%|N29ggeIA}To82OzuXOE4y##J%^toexf?Hr~_Zqk1HcI4%sGm=WNT0Y_wwZtKP|Fyi9^lT#hF#~5dBhS>l zJb9-Rv7no>JC_#WrvF7;Bhs$$!ibw-Syy91!a!r>O`YZx^5-{7dsqqzCIXKwSf02? zL5t4FV4U1%C_q(dJgcu+h4`J}`neizf&FLYurFL){SR4ZMn*LGo^#H56bSw49-rKoqVHSfde3Gf7zFxvFlcxJ#Vr`OI|9 zXwz<=HQ6y%OUR3=o#3d6PsKv8R=xS1nXGYhr<2HetdVe{xK#DI;l-;-JAxsRqukjq z#6c;E>!T~8o{e$|>jXItJ`na!wJ~?dPa4g_iVWfQ-)5^{q4Fz~OMWmx8&~+4o+BgT zNE5BHQt&`H5NxyJc_&MjlFApy)H{6jkP5W%D~T_dvWjWv?5^1gUM~Twd$JY?9|a zL3Ntu3yYL*0{k=M9EcacUFXBh&%VproZP}g(hkY9%3qOd(&HO zqfQIIJe71+T*}QJc-6Jkz99^3pAiI= z%&2pp@65j=az3K!l|}0rqNmqJSDQJA{TrwTe74W5?pavTTU)7WM^c!;H;0G61xC?Kd+}7&XXt?^kHva zMjD&D$L+H&acyXYI#tfqRhduLbL|G4W(?1%P{4{L2zF)KlPn^k4kS1H`vAMCbd{%R zDe^YH4UE-j z>AHn`E#}#MX8cdx#Fi27IcsCdtqKqlgHIVdi$Fphv`Q41Gv7a&<4D>QZQa?${XuqE z$JV?Ru}YNQYOxfqQ1FX&n5DV1He5V#xAESZMSFSjl8-DbOi{1c(Wqy;hF?K;(w3qN z`h#BrJi(yEy5;RQH+hwNSK6W{LsN&R&jgNPtTSY+V%Orsjy;N?Eh^G^xv>=hH^i{z9(zhe7g)^fDj1@dd*^jR` zO$%~lknpQ!;iph}@6UNGvY7+EyAch z*D*cTSZJw@seTpn1WU_tIoDGqwYJS-Y}v|Vvk+a-8sY&102wjIlt zi+T^$T<=mvBwpF{>_(b8pOPUV%oujbZrVQ_Jr#B8W%x|{Ck8orMoVp@Ob-buHYy4}AZbw$K}O@)g-hI_^!EMu<0QD; zPp|6$KDJy>bOP{~wc@3)Nj1O-IlZ|`82}KM_{-^WAw_|XPfOU{0#>!sw^RI#vzmtQ5oI}>}zXA~d-Z;qbUHwU`EE5W_ zs!)KgK2HO>%sF7{e4vWuK_Hm$?e@PhGGY&QvfsTwzAhr3YcRQ_s*E<&`#aL2QxEl> z8Jd+}kNdR9Ljn#21{Pg1hnbk{wSS2+>`)XD4Pa{Q{<9NLfr%DrZG7p2SWFB+BFi#= zA*8;64|;V}aVRpWSk!;d@dR>!ycR>yQC7}X`-N~$)1d)&D{Qi@&!2c7&7|7g2#Go` z#}DSQ!2QBg1r3zuP6AuxJRY5 zq|KnkT@B;ur42jbWeIbyl6@<9$9sVmntnNA5vy6P<;afbpn~$|*E#=@>mnN5c;o%7 zUk$4>Pt}B#*jDK zCIwG&a7ic3JCa=olVKO?jJs~%Z11SAY|p*-^5I@fTAoPYvYI7sW>{RiZ3b`VON*dD zX8%2TLD12>ob!ZMef|B{p_h)8^MWwyR=7e=N%4L3#dFL`O1M`aZ%#x&m2dqrm8?h6 zTo7+*VvfeFpCe(S2T>|waz&cN%{MX|#{%}`<@_bI{vSqz>W<$slRKtm9VX?@xWFI!Mq^R*r z!0)95h=%brPm$|qMH(S5ocrtzJzG?pgQG}_bk<0921hhj6m-4{)x$5P1>;Ot*s#c z-n*M!U2-Y1#9KhdY|AKox|SnhItl({^v|9=`oLIJm6u~za21=a>Ko4c1i!VAJ(2hR z`O)Qh0|8mTp3#_)_Wk1i)1^Ic=@=nPg|L(aA0S|7RRf$RKjovwWlFqz!{Eo-{q-vz zLBmcSWgg~0&YZ9Ee4b~`2ik&$pL@qGB!rV0N-3z8&dyya7V!+~?zmEQ&dcbwV_E0T zyh1T4Pp1ww8}d)8?^zWy4$IR>AzcY>^OQpLjEGHv} zZg;C*&VHOlFZh;94ul8Q5p!s4OU$ORJ)0N#4H3huq!D%7 zhxoemy!{iMJQ9Y101ZUuw#WrPsv@x0d~?)uepR-~J@+ zIrJdfap6@DiQvq^F+jp#_re`~u!{9-tvOSlg;1nTAY2z2zCcpQ1xH&u;T#LtsZuvj zidlI5vTs>VAh{jvW$~4hZ+9$!z&YhI*~@FDoqsb7`L$wnA~E2Oy`)*tsLu)HozuVg zrC`d`!NE!binN$Ho3s@U9EDQ~j4H-u;&;(ur`gP0)e21O@bx|q;YW+EhoxSYcrMFA ztDGD5%dSkN0MZ^hzgY7BBMR}~4uyn8Q@DJ1C<_Ek`rQ|9^ctXll9U5$2c4{T?*sQj z&hUYlOuj|@fV;Tcvtix8g8N8b$LaK+WF?()LT(YOsH_}T#(y+P?9X4*9}ZCj$~W-q zwm;$x-!dSM-N|6L4gvbV*bNZe(Hv%e^h=Xg^ytm-MHnWwYXSx1Nw{2;ykLhit?KMOpc~=eyZLxzHQ&WkjV{?`^z?di9Bdi&b(lkI>A}Ri zkd#(gAl;*9uMLugy#&VfE#1Vzfh<7n?zWI;r<{_ig&z0^!vCmU2+euRi9)PyCG7(| zN#*yE0&(yH=k2m{Us%bm!6oGM9g$54YB?$bG6amvVsfF8+izKQQZ>R;i>^1u2_>+5 zE`6Bnvi0bMZ!MyYEuLuRMpVZT*cLYeyB4{(D@(X}7o82ph-NNdUeI!nFYtLXZa^ulvcmFT%7siaw#RBRg@jL;TC^hj#=#9=#|Nm_EUX5)n~1RMx+}y8iPY@T8)Am3 ztSv;Je59ao*&p^nlhK!Ogu9Hh%t0MqEz&2xe8!+uF&iGjV=Y3<9gJjoiMWUKUfAymZD7E>pbFU4GM$ z^_9^|+kz0PBc`DGfzIXb1n=7}@i-&)yf$2>`ndhG4)Iy^!K~L+HAnSKWZGAH-Y(Hk z51B~nr?dZxu}6E@{No}jNl6^5fMF|4fwW1=ZjieFN<|8J@Z*)C(N8*h~UuJzaiUi_&q`^~Cm z!LuOEM_!ZNR|FNjc;F95HKV$oeRLQZ#X7aN^<-XlkG-lgirCFwQqPTPI>vLd0HQdT zsKfsES*JfEBR`V0QoIViXYq#8;0!EcOZy_Gwb&S3ofl1Qaq?x+klt-&_I2&Ck6Mc- zC|o>;S*JzvqA5gC3Z~#*$F?bwEyZ~b!i0rKFFj^ydb*<`WvoisDZL;RivIY!{{WDk z-d;*0PTFcN;7x?~7Am63ZYR5@2@7%fTsWKJH!j0cYG4u<&?eNC{`C|`Q(_`_uwi_d zw`=tbj9sTgJ4i&R%9pAUX19)$2f?+?OI@R&qe(lVk%Psz*9;laHeMo`ocEu2`J%X6%{oR$v`o*pwIxeQ`slf;k*v;n0`a8#zi$g5Lcg#wT9BBK(fvx_cs_AuH>V(F zH%@o+5rfI{DR>C{TII02Re98ns6X4N46y=8ZP}^Qf)6n(HbjrkejbuR8RF$E@_b=>l=?^ow z=?`;lv$j)`eVkrDC{CX)ClE!^Z&6dh7LREC(MgYT9qXLecJiR@=t z+;+~h(^^dO^SvzGMlC0cyZmY(3i$nxciK!4ch{)xWN(@ZPG(x=OU6DAKg*vf7euO8mw(|8TfdNx^-cs#mv=N8C)SvRn{_XRGuGj91t-0&-ACqO? zKF#PiYOKbRZLitZOr3DvQwg6-{F2;r4IG-mwCPHu1eR4ixNSUfGmj;7zNSUNKDT0P z7CT;co8)?3+kE!!OV1%q^d(Tk65m*N?96y}Mjw+&0#(bepwiw_*d%V@{O(kfET9#MDT|@!*oL` z^?%2!1M$HB5IqklLAly*@8Mg5MAG&*`@iA+`QKJIAf8}i8hQKMrUzi2$0Fh1W*op4 zJ_Z*67B&JeL4*65?9<<(2^{(bKu!f<5=fk!hwQ?oiGO4hUwhwVl^}nHlD;Kn4#Y>UZr?GVW!Q2uTjfM+6P!t?<*$=n;du%%g#N>|cF$o0uT zLL&17+@)nQ=VmU0xNDcs&Z7!^34$(k$veSfMpxZ@ zJ&rOl8F}t*@P{1V*<4@^?;s75O}4WWzbsw)S52rgqVy)5zjRW!5&-Jr-F=upJ>>eh z_@4~)yE}Iwy)tqKHp$`MG=-ST@r;{Rewl8G;&wgB)G*?dAinRZoo_H5(QE|m>Cu4A3$GPF6`=e}0R_dND04xb2O2`weZsgh_zy2N?LCyG zhmk$m?Q;v`XaaHh7At~!HQ0si{QTWo*J__@v|6a*X*$fl$Qk0blKnd}e4rlZ4;wi< z9(V6%1WNCFit&MB>dQXL$L~7q)46W+>6>~I*z*5zHH6YDi!yxR&*;2Q&@VdwB|k2o zF`espj?`%&EY2_a6xpaGJ3Z!peC868kYp;JEwY1%*Q$>JiS{&(_%l@1NKOVw4Q(lPlV z9IynXRfEcZ5R@2zpwwjKB(b$95ihQLz3k za}5`nkqVU?*q$N%t2?iwQsP%j{jPl;4zwx9G3KO;zPO%j;xm-+$^dLgwG(37lLQT0 zxV+_2?oJjLNQ*aTE%_sl6`l2EhvhIeUtnwy6wR&+q&jbbL758TCWJ&nRZso8Hd|XG zVw3pJ7m~ARFi-o&KK1fDBkaQ6y&J>A`JtCYa*NxkQfo*tKR7}a-l1IUi4VZ%Fx(>h z;b(WI+F=tZ@@GNxlsx^hfLJSS5NcfSX4NUy8S|W7%FeeMK4c`AKdozl1LALIG)B^OD;GRrd>E?LB5Z4y167HhcyrWZ>-jcMEeA2mOS)xw6%5$}N`hI8$(JP& z01)s0cFtlsg=Ai?Ry{ueN4btiAhx6OIjcPudvT*Z9VL)=>uSYh%s{j(+v9vrq|1U; zj`vQoy10FazNsbovI9F3amrn@+sk&{Y89r{mfTja0Eo(VP1ip$Dy&Y>A@2Kr-HAD` zQAr-QSH0xdLpC}=*P9GZlx1;0x%%_GMnydl%QSfoRDef>J9v(ujLNy91mv9AJxcu4 z++!J)O&mkn;@aPAaDP5lX@es7JnHsn;Tzw6%HAdO0TKdL9+fgFv%uggw4<+Y$ZiZX z-F)7`H~slv^wOiQ?D`A~T4|rPFV+EWKmxP34ycm7HiPX;?IXQU5eG6O}rX zomWZiQ4G@Wwg!Aq+rC2zG(kw@E8w*7`#2h?0Tk)4{YSt1e+CKvXAJ{EbO3hiWd9kK zD*gq4<^40%c?kA|qyg|ZB>(FejXX>p+LPw2_L;k-9|TRHwP6NPQ z3P@1j%hUciH3M452>IQ)eZq({keKJa9`+nsyV}UH3AA&d-2JY}1j6}1#-=-%hSTjc zzx*ogP^`2|DxgIT@H_ESO{ohOzEk)GNT}ZmVc;ERZ5cT$AX!{H}tOcC?OP zV$Lb+@X4_<++K~x+>uYuiuTLHP2Ms-+KiBD;ExSoEGLqzqSfOwXm*`tpaMU;mZ5N& zZhZwvWNb3Ek^pH0R!zg?{s*cU6OTBDW_?K7@Es|GiO-=QAFCAtj4v+%Mxy`KrLR?8n$;Lo| zPS*~Z*=EA?vq~Ga7cIs=S69D*Zz`&Rka~@~IDLaB)~+kEKIw%o0{}s+2jkD!11l0p z<1Oi zT;e4nBUYLR2boWuG`4L&MZDeh@gDkl)efwsqhh2tQQ_WAH}ZHC7nh;u*SAZijs_QlVH4#5$^g&CJ z(OYh`A~E(S5dAk(5>IlvIwzP!DgZ(-;swe@bK#S3AhD5RdND*VmJ)Ne1Xg6r4z0nI z4ELS(^h`e>^8Trd9zEta&h*;w=dQX&;WF76e!>@!rLM5*8y`gY0jVh3nY%L?Vnjgf zw3&^UJ0@H`*e26o-(@E6Vx0YTC53@KHn;HE*3U)jne{eMbwFsd)PhF|*P-7*<@m;w zW@vKKDqf{ufX6`PKL4rC#t@YpwZD`7^oXd@pJ8geBHS-M!11pdrpBi3)CF-OA65m) zWbYikA@_45oDCERJ0)s?+9yP9&-cFT87#82>U>1Y+-(Mj14%T;@mhoAEI?Vinrs;X z@tE&UUoCqxDLijgd3KHteR2U)8{v=#He9|@qs^S{ic*Q_~5Qo#bE8O@!VmraNp$_45r~1W{FW?(M8kHeCA(g!>~O z-6fOuJ0V-fLzRHkWn#ZAMg*}l9pi}`W>v_g)(DyQr&Lz(j?Kf(%Zx+ajBdPu7lU33 zTv`=FYT3ufFOAg%`v;dZ6|5N0!y;F!Ge$Y;hd#c!WpeW2`I*ROG4;o`a`E>!{HePd z8PJ@TQ3CDJT)!A|8N~SvLKr;AG~gASMy21SY|qB$urb3k~dKmT+SB*f$u~VBCZ+}G6tEKE( zD>b9GVm8l0HGe`lkdBo1+qIccZjTdFWelM45iQpI1H3kQLD4e$EF|agAtE5<|1J@$ zhZ+MZ=U_I|L0}CX=*SPeY~2@L!(@j}XHoHG-5UE)&|16gOJxTokF(3U~S2}-!TY;SIH^Kg2vFrb>jz8@hki$Qa z^8KaSe{J`T1bmkwQrrT#>R&p5P&CbhFwD>%Q<=5#v&;MVgMCAM*D@ zdVsRlwD*yLgVD?9JSmw@5vc^jKX+Vmx^t_?Nl# ziUTwdy?uS*959lg2fk{y#iKP#C(UZM6X9Pb|Lm0anEU*+qJ8J0wOrZ&y02dbFRM!j zSLlCC$#c6y9HgJ`bVky*eZ^?mZQ(}ZWv_*T>tP6+-Q&cMb*bMHMFH7wfGkmshlz2> z$HAh>C8bVG62BZ7N5ocm*6;M+9NHK&@Hnm+!7EfJT?#a>jzsV2EX#ffd zsQa2m0C~S!jafNH>ejOi1oLHQDb?fIofKWZX}sQ=xe+2yv?M?Ajyn>18T(ZUSiwj| zi!sSM$$D+VrPNK?5`7CSy?viJX!h#XL&}K^q2&=(T{DBV$7f7xNRBW>@HZ9e(Hjx~ z%|ED`(9j1W9@%|4R?0*dF~r1)#6EnBlA2~y$< zB{t`p%UYx$7aOFPG;HkJ(=8iMUwz?XYzWIR88ieN7NEU(a!vkojXki0f+;PQ=DI3c zZ+R}}S>E#j@?VptVW(wWZ~1me3>^P#;_f~`&vA13xQUNxXXonB)jT3@Gt*f6?&l0_ z|L%vn^IE;<#YSd~;wUZH9gAG5W&ARpKJ$>UmRk?v?>~JGlibFEtkUQ4{3GN{e>SBB zP$>JF;^hSpYBijzn3MdxHNb3-hjf;8wVucgL<06E*rw-zQlqE`u(|S6$Sc|-_6lA8 zC2yjn0`EZVK4DJVAo`s1Ssgvb8yKUu+ptZP7F_V06BMHF>ckJjwe6@ZxE>qieLEr_ zz6gz@SOtXO(T>C{Tn5HyYEEBE4l~4^ z&=a|dn!Nd_|MDN5E#oESm(GF`@|en5ka)ks@^AY2L#(eg0v|NS!CDEx^nehe_rDma z$Fy_|U?1p~TXk+BR*uMcx1`5p3{dBBAnU7SD$Hh_#a=KY``&u#4w5zi@f}s_&>yHb z)^fYg5|)c+#gMYp6H$6tXtD5<0nSP0ZfGfmxZ$g?3Y`8!;=^?_ZyC}&^MQ7Z;#L3! zkY=jEN7F9hYxtW9z^az@SQ22g^e3(7Sk3C`Zw@rMy92EG%QCmmr8-F)zjbdsW!Dfl zW@83+JGLR`y4<`*bUOEv`VrA_Zc8!?oaO1`QEkzLvoD^r-1E(-O5j8u;XhxYnGa~j zYd(Ya3rqHoF?Z(_TK|Li{^*UvK+L@Ys5@$Gk6W&-5%nJ|v<|--W>RJMYRRD9!fNk6 zVM)eFVen+iZ7M+Q(PIM!Z3&gwDPIZ^gDH4^Y92{UdbjGV=8Mx@e}*yrUK$1MyKxuX zpNl(&exMQx9nBO+2!4@!HZAU7;MFg-K5kgwx*DD?h(~M}9q7btOUM=HZfktYUVrnJ zmHgMac{G~+%jhi(_Fm6_Qrl9v6h624m}xQ{oTPrS;D=8*@V&Xh*rCc619_I1JmdWj z<>zPH|8f}zKmX8&13U8|@cE;X>u@$u0rpoJ7qky34*OZdMVSRuJ^WR`_1$&I zsxzEPfhUeC2YeX>s5QYuz_z(EyLGD^7hne00S8AMcdYUoB~V$4tM`~dHtQe dd2O$Iv3( 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 R0T|(ol$e}op74tg{{_{$h(Z7W literal 0 HcmV?d00001 diff --git a/docs/docs/assets/images/part/part_revision_settings.png b/docs/docs/assets/images/part/part_revision_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..31940f53dd7db719c2ddbf3e5ba44d577b5e0310 GIT binary patch literal 5549 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

    A Part is defined in the system by the following parameters: @@ -38,7 +37,7 @@ A Part is defined in the system by the following parameters: **Description** - Longer form text field describing the Part -**Revision** - An optional revision code denoting the particular version for the part. Used when there are multiple revisions of the same master part object. +**Revision** - An optional revision code denoting the particular version for the part. Used when there are multiple revisions of the same master part object. Read [more about part revisions here](./revision.md). **Keywords** - Optional few words to describe the part and make the part search more efficient. @@ -62,7 +61,7 @@ Parts can have multiple defined parameters. If a part is a *Template Part* then the *Variants* tab will be visible. -[Read about Part templates](./template.md) +[Read about Part templates and variants](./template.md) ### Stock diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 14c8ddd832..75974387d7 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -106,6 +106,7 @@ nav: - Part Views: part/views.md - Tracking: part/trackable.md - Parameters: part/parameter.md + - Revisions: part/revision.md - Templates: part/template.md - Tests: part/test.md - Pricing: part/pricing.md diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index bdb4330d90..b11316cb69 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,12 +1,16 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 219 +INVENTREE_API_VERSION = 220 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v220 - 2024-07-11 : https://github.com/inventree/InvenTree/pull/7585 + - Adds "revision_of" field to Part serializer + - Adds new API filters for "revision" status + v219 - 2024-07-11 : https://github.com/inventree/InvenTree/pull/7611 - Adds new fields to the BuildItem API endpoints - Adds new ordering / filtering options to the BuildItem API endpoints diff --git a/src/backend/InvenTree/build/serializers.py b/src/backend/InvenTree/build/serializers.py index ef84817123..7c8bb2a0aa 100644 --- a/src/backend/InvenTree/build/serializers.py +++ b/src/backend/InvenTree/build/serializers.py @@ -1,5 +1,7 @@ """JSON serializers for Build API.""" +from decimal import Decimal + from django.db import transaction from django.core.exceptions import ValidationError as DjangoValidationError from django.utils.translation import gettext_lazy as _ @@ -209,7 +211,7 @@ class BuildOutputQuantitySerializer(BuildOutputSerializer): quantity = serializers.DecimalField( max_digits=15, decimal_places=5, - min_value=0, + min_value=Decimal(0), required=True, label=_('Quantity'), help_text=_('Enter quantity for build output'), @@ -256,7 +258,7 @@ class BuildOutputCreateSerializer(serializers.Serializer): quantity = serializers.DecimalField( max_digits=15, decimal_places=5, - min_value=0, + min_value=Decimal(0), required=True, label=_('Quantity'), help_text=_('Enter quantity for build output'), @@ -864,7 +866,7 @@ class BuildAllocationItemSerializer(serializers.Serializer): quantity = serializers.DecimalField( max_digits=15, decimal_places=5, - min_value=0, + min_value=Decimal(0), required=True ) diff --git a/src/backend/InvenTree/common/models.py b/src/backend/InvenTree/common/models.py index 9d41d06f39..a55e829cc8 100644 --- a/src/backend/InvenTree/common/models.py +++ b/src/backend/InvenTree/common/models.py @@ -1408,6 +1408,12 @@ class InvenTreeSetting(BaseInvenTreeSetting): 'validator': bool, 'default': True, }, + 'PART_REVISION_ASSEMBLY_ONLY': { + 'name': _('Assembly Revision Only'), + 'description': _('Only allow revisions for assembly parts'), + 'validator': bool, + 'default': False, + }, 'PART_ALLOW_DELETE_FROM_ASSEMBLY': { 'name': _('Allow Deletion from Assembly'), 'description': _('Allow deletion of parts which are used in an assembly'), diff --git a/src/backend/InvenTree/company/test_api.py b/src/backend/InvenTree/company/test_api.py index 65b55089a3..afe04e6653 100644 --- a/src/backend/InvenTree/company/test_api.py +++ b/src/backend/InvenTree/company/test_api.py @@ -57,22 +57,20 @@ class CompanyTest(InvenTreeAPITestCase): def test_company_detail(self): """Tests for the Company detail endpoint.""" url = reverse('api-company-detail', kwargs={'pk': self.acme.pk}) - response = self.get(url) + response = self.get(url, expected_code=200) + self.assertIn('name', response.data.keys()) self.assertEqual(response.data['name'], 'ACME') # Change the name of the company # Note we should not have the correct permissions (yet) data = response.data - response = self.client.patch(url, data, format='json', expected_code=400) - - self.assignRole('company.change') # Update the name and set the currency to a valid value data['name'] = 'ACMOO' data['currency'] = 'NZD' - response = self.client.patch(url, data, format='json', expected_code=200) + response = self.patch(url, data, expected_code=200) self.assertEqual(response.data['name'], 'ACMOO') self.assertEqual(response.data['currency'], 'NZD') diff --git a/src/backend/InvenTree/order/serializers.py b/src/backend/InvenTree/order/serializers.py index 1226e753ce..be46b497c7 100644 --- a/src/backend/InvenTree/order/serializers.py +++ b/src/backend/InvenTree/order/serializers.py @@ -616,7 +616,7 @@ class PurchaseOrderLineItemReceiveSerializer(serializers.Serializer): ) quantity = serializers.DecimalField( - max_digits=15, decimal_places=5, min_value=0, required=True + max_digits=15, decimal_places=5, min_value=Decimal(0), required=True ) def validate_quantity(self, quantity): @@ -1250,7 +1250,7 @@ class SalesOrderShipmentAllocationItemSerializer(serializers.Serializer): ) quantity = serializers.DecimalField( - max_digits=15, decimal_places=5, min_value=0, required=True + max_digits=15, decimal_places=5, min_value=Decimal(0), required=True ) def validate_quantity(self, quantity): diff --git a/src/backend/InvenTree/part/api.py b/src/backend/InvenTree/part/api.py index 07a8c56793..2d9be8b099 100644 --- a/src/backend/InvenTree/part/api.py +++ b/src/backend/InvenTree/part/api.py @@ -911,7 +911,27 @@ class PartFilter(rest_filters.FilterSet): """Metaclass options for this filter set.""" model = Part - fields = [] + fields = ['revision_of'] + + is_revision = rest_filters.BooleanFilter( + label=_('Is Revision'), method='filter_is_revision' + ) + + def filter_is_revision(self, queryset, name, value): + """Filter by whether the Part is a revision or not.""" + if str2bool(value): + return queryset.exclude(revision_of=None) + return queryset.filter(revision_of=None) + + has_revisions = rest_filters.BooleanFilter( + label=_('Has Revisions'), method='filter_has_revisions' + ) + + def filter_has_revisions(self, queryset, name, value): + """Filter by whether the Part has any revisions or not.""" + if str2bool(value): + return queryset.exclude(revision_count=0) + return queryset.filter(revision_count=0) has_units = rest_filters.BooleanFilter(label='Has units', method='filter_has_units') @@ -1361,6 +1381,8 @@ class PartList(PartMixin, DataExportViewMixin, ListCreateAPI): 'pricing_min', 'pricing_max', 'pricing_updated', + 'revision', + 'revision_count', ] ordering_field_aliases = { diff --git a/src/backend/InvenTree/part/migrations/0126_part_revision_of.py b/src/backend/InvenTree/part/migrations/0126_part_revision_of.py new file mode 100644 index 0000000000..e5324d60a9 --- /dev/null +++ b/src/backend/InvenTree/part/migrations/0126_part_revision_of.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.12 on 2024-07-07 04:42 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('part', '0125_part_locked'), + ] + + operations = [ + migrations.AddField( + model_name='part', + name='revision_of', + field=models.ForeignKey(help_text='Is this part a revision of another part?', null=True, blank=True, on_delete=django.db.models.deletion.SET_NULL, related_name='revisions', to='part.part', verbose_name='Revision Of'), + ), + ] diff --git a/src/backend/InvenTree/part/models.py b/src/backend/InvenTree/part/models.py index af017e188b..730cf5a270 100644 --- a/src/backend/InvenTree/part/models.py +++ b/src/backend/InvenTree/part/models.py @@ -662,6 +662,49 @@ class Part( if match is None: raise ValidationError(_(f'IPN must match regex pattern {pattern}')) + def validate_revision(self): + """Check the 'revision' and 'revision_of' fields.""" + # Part cannot be a revision of itself + if self.revision_of: + if self.revision_of == self: + raise ValidationError({ + 'revision_of': _('Part cannot be a revision of itself') + }) + + # Part cannot be a revision of a part which is itself a revision + if self.revision_of.revision_of: + raise ValidationError({ + 'revision_of': _( + 'Cannot make a revision of a part which is already a revision' + ) + }) + + # If this part is a revision, it must have a revision code + if not self.revision: + raise ValidationError({ + 'revision': _('Revision code must be specified') + }) + + if get_global_setting('PART_REVISION_ASSEMBLY_ONLY'): + if not self.assembly or not self.revision_of.assembly: + raise ValidationError({ + 'revision_of': _( + 'Revisions are only allowed for assembly parts' + ) + }) + + # Cannot have a revision of a "template" part + if self.revision_of.is_template: + raise ValidationError({ + 'revision_of': _('Cannot make a revision of a template part') + }) + + # parent part must point to the same template (via variant_of) + if self.variant_of != self.revision_of.variant_of: + raise ValidationError({ + 'revision_of': _('Parent part must point to the same template') + }) + def validate_serial_number( self, serial: str, @@ -842,15 +885,24 @@ class Part( 'IPN': _('Duplicate IPN not allowed in part settings') }) + if self.revision_of and self.revision: + if ( + Part.objects.exclude(pk=self.pk) + .filter(revision_of=self.revision_of, revision=self.revision) + .exists() + ): + raise ValidationError(_('Duplicate part revision already exists.')) + # Ensure unique across (Name, revision, IPN) (as specified) - if ( - Part.objects.exclude(pk=self.pk) - .filter(name=self.name, revision=self.revision, IPN=self.IPN) - .exists() - ): - raise ValidationError( - _('Part with this Name, IPN and Revision already exists.') - ) + if self.revision or self.IPN: + if ( + Part.objects.exclude(pk=self.pk) + .filter(name=self.name, revision=self.revision, IPN=self.IPN) + .exists() + ): + raise ValidationError( + _('Part with this Name, IPN and Revision already exists.') + ) def clean(self): """Perform cleaning operations for the Part model. @@ -867,6 +919,9 @@ class Part( 'category': _('Parts cannot be assigned to structural part categories!') }) + # Check the 'revision' and 'revision_of' fields + self.validate_revision() + super().clean() # Strip IPN field @@ -954,6 +1009,16 @@ class Part( verbose_name=_('Revision'), ) + revision_of = models.ForeignKey( + 'part.Part', + related_name='revisions', + null=True, + blank=True, + on_delete=models.SET_NULL, + help_text=_('Is this part a revision of another part?'), + verbose_name=_('Revision Of'), + ) + link = InvenTreeURLField( blank=True, null=True, diff --git a/src/backend/InvenTree/part/serializers.py b/src/backend/InvenTree/part/serializers.py index c2aa330339..a5e4f783d6 100644 --- a/src/backend/InvenTree/part/serializers.py +++ b/src/backend/InvenTree/part/serializers.py @@ -658,6 +658,8 @@ class PartSerializer( 'pk', 'purchaseable', 'revision', + 'revision_of', + 'revision_count', 'salable', 'starred', 'thumbnail', @@ -762,6 +764,9 @@ class PartSerializer( """ queryset = queryset.prefetch_related('category', 'default_location') + # Annotate with the total number of revisions + queryset = queryset.annotate(revision_count=SubqueryCount('revisions')) + # Annotate with the total number of stock items queryset = queryset.annotate(stock_item_count=SubqueryCount('stock_items')) @@ -883,6 +888,7 @@ class PartSerializer( required_for_build_orders = serializers.IntegerField(read_only=True) required_for_sales_orders = serializers.IntegerField(read_only=True) stock_item_count = serializers.IntegerField(read_only=True, label=_('Stock Items')) + revision_count = serializers.IntegerField(read_only=True, label=_('Revisions')) suppliers = serializers.IntegerField(read_only=True, label=_('Suppliers')) total_in_stock = serializers.FloatField(read_only=True, label=_('Total Stock')) external_stock = serializers.FloatField(read_only=True, label=_('External Stock')) diff --git a/src/backend/InvenTree/part/templates/part/part_base.html b/src/backend/InvenTree/part/templates/part/part_base.html index 3b6b57542d..835258c8ea 100644 --- a/src/backend/InvenTree/part/templates/part/part_base.html +++ b/src/backend/InvenTree/part/templates/part/part_base.html @@ -271,6 +271,15 @@ {% endif %} {% settings_value "PART_ENABLE_REVISION" as show_revision %} + {% if show_revision and part.revision_of %} + + + {% trans "Revision Of" %} + + {{ part.revision_of.full_name }} + + + {% endif %} {% if show_revision and part.revision %} diff --git a/src/backend/InvenTree/part/test_part.py b/src/backend/InvenTree/part/test_part.py index 6e85c11cc0..6f0eb5beba 100644 --- a/src/backend/InvenTree/part/test_part.py +++ b/src/backend/InvenTree/part/test_part.py @@ -389,6 +389,83 @@ class PartTest(TestCase): part.delete() + def test_revisions(self): + """Test the 'revision' and 'revision_of' field.""" + template = Part.objects.create( + name='Template part', description='A template part', is_template=True + ) + + # Create a new part + part = Part.objects.create( + name='Master Part', + description='Master part (will have revisions)', + variant_of=template, + ) + + self.assertEqual(part.revisions.count(), 0) + + # Try to set as revision of itself + with self.assertRaises(ValidationError) as exc: + part.revision_of = part + part.save() + + self.assertIn('Part cannot be a revision of itself', str(exc.exception)) + + part.refresh_from_db() + + rev_a = Part.objects.create( + name='Master Part', description='Master part (revision A)' + ) + + with self.assertRaises(ValidationError) as exc: + print('rev a:', rev_a.revision_of, part.revision_of) + rev_a.revision_of = part + rev_a.save() + + self.assertIn('Revision code must be specified', str(exc.exception)) + + with self.assertRaises(ValidationError) as exc: + rev_a.revision_of = template + rev_a.revision = 'A' + rev_a.save() + + self.assertIn('Cannot make a revision of a template part', str(exc.exception)) + + with self.assertRaises(ValidationError) as exc: + rev_a.revision_of = part + rev_a.revision = 'A' + rev_a.save() + + self.assertIn('Parent part must point to the same template', str(exc.exception)) + + rev_a.variant_of = template + rev_a.revision_of = part + rev_a.revision = 'A' + rev_a.save() + + self.assertEqual(part.revisions.count(), 1) + + rev_b = Part.objects.create( + name='Master Part', description='Master part (revision B)' + ) + + with self.assertRaises(ValidationError) as exc: + rev_b.revision_of = rev_a + rev_b.revision = 'B' + rev_b.save() + + self.assertIn( + 'Cannot make a revision of a part which is already a revision', + str(exc.exception), + ) + + rev_b.variant_of = template + rev_b.revision_of = part + rev_b.revision = 'B' + rev_b.save() + + self.assertEqual(part.revisions.count(), 2) + class TestTemplateTest(TestCase): """Unit test for the TestTemplate class.""" diff --git a/src/backend/InvenTree/stock/serializers.py b/src/backend/InvenTree/stock/serializers.py index 7560bc2632..fa9e060e72 100644 --- a/src/backend/InvenTree/stock/serializers.py +++ b/src/backend/InvenTree/stock/serializers.py @@ -1518,7 +1518,7 @@ class StockAdjustmentItemSerializer(serializers.Serializer): ) quantity = serializers.DecimalField( - max_digits=15, decimal_places=5, min_value=0, required=True + max_digits=15, decimal_places=5, min_value=Decimal(0), required=True ) batch = serializers.CharField( diff --git a/src/backend/InvenTree/templates/InvenTree/settings/part.html b/src/backend/InvenTree/templates/InvenTree/settings/part.html index dae8368b7f..96aafc3f30 100644 --- a/src/backend/InvenTree/templates/InvenTree/settings/part.html +++ b/src/backend/InvenTree/templates/InvenTree/settings/part.html @@ -12,6 +12,7 @@ {% include "InvenTree/settings/setting.html" with key="PART_ENABLE_REVISION" %} + {% include "InvenTree/settings/setting.html" with key="PART_REVISION_ASSEMBLY_ONLY" %} {% include "InvenTree/settings/setting.html" with key="PART_IPN_REGEX" %} {% include "InvenTree/settings/setting.html" with key="PART_ALLOW_DUPLICATE_IPN" %} {% include "InvenTree/settings/setting.html" with key="PART_ALLOW_EDIT_IPN" %} diff --git a/src/backend/InvenTree/templates/js/translated/part.js b/src/backend/InvenTree/templates/js/translated/part.js index d369f26cbc..8606c3b84b 100644 --- a/src/backend/InvenTree/templates/js/translated/part.js +++ b/src/backend/InvenTree/templates/js/translated/part.js @@ -135,6 +135,7 @@ function partFields(options={}) { }, name: {}, IPN: {}, + revision_of: {}, revision: { icon: 'fa-code-branch', }, @@ -227,6 +228,7 @@ function partFields(options={}) { // Pop 'revision' field if (!global_settings.PART_ENABLE_REVISION) { delete fields['revision']; + delete fields['revision_of']; } if (options.create || options.duplicate) { diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx index 1adaf03d04..24818dccbe 100644 --- a/src/frontend/src/App.tsx +++ b/src/frontend/src/App.tsx @@ -29,4 +29,10 @@ export function setApiDefaults() { } } -export const queryClient = new QueryClient(); +export const queryClient = new QueryClient({ + defaultOptions: { + queries: { + refetchOnWindowFocus: false + } + } +}); diff --git a/src/frontend/src/components/details/Details.tsx b/src/frontend/src/components/details/Details.tsx index c140c98dac..d3675bceaa 100644 --- a/src/frontend/src/components/details/Details.tsx +++ b/src/frontend/src/components/details/Details.tsx @@ -30,17 +30,6 @@ import { StylishText } from '../items/StylishText'; import { getModelInfo } from '../render/ModelType'; import { StatusRenderer } from '../render/StatusRenderer'; -export type PartIconsType = { - assembly: boolean; - template: boolean; - component: boolean; - trackable: boolean; - purchaseable: boolean; - saleable: boolean; - virtual: boolean; - active: boolean; -}; - export type DetailsField = | { hidden?: boolean; diff --git a/src/frontend/src/components/details/PartIcons.tsx b/src/frontend/src/components/details/PartIcons.tsx deleted file mode 100644 index 78086bc628..0000000000 --- a/src/frontend/src/components/details/PartIcons.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import { Trans, t } from '@lingui/macro'; -import { Badge, Tooltip } from '@mantine/core'; - -import { InvenTreeIcon, InvenTreeIconType } from '../../functions/icons'; - -/** - * Fetches and wraps an InvenTreeIcon in a flex div - * @param icon name of icon - * - */ -function PartIcon(icon: InvenTreeIconType) { - return ( -
    - -
    - ); -} - -/** - * Generates a table cell with Part icons. - * Only used for Part Model Details - */ -export function PartIcons({ part }: { part: any }) { - return ( - - ); -} diff --git a/src/frontend/src/components/forms/ApiForm.tsx b/src/frontend/src/components/forms/ApiForm.tsx index f58ca69cda..3456b2e07b 100644 --- a/src/frontend/src/components/forms/ApiForm.tsx +++ b/src/frontend/src/components/forms/ApiForm.tsx @@ -125,7 +125,6 @@ export function OptionsApiForm({ const optionsQuery = useQuery({ enabled: true, refetchOnMount: false, - refetchOnWindowFocus: false, queryKey: [ 'form-options-data', id, diff --git a/src/frontend/src/components/items/ActionDropdown.tsx b/src/frontend/src/components/items/ActionDropdown.tsx index 5515858e0c..7d04fb0d56 100644 --- a/src/frontend/src/components/items/ActionDropdown.tsx +++ b/src/frontend/src/components/items/ActionDropdown.tsx @@ -39,12 +39,14 @@ export function ActionDropdown({ icon, tooltip, actions, - disabled = false + disabled = false, + hidden = false }: { icon: ReactNode; tooltip: string; actions: ActionDropdownItem[]; disabled?: boolean; + hidden?: boolean; }) { const hasActions = useMemo(() => { return actions.some((action) => !action.hidden); @@ -58,7 +60,7 @@ export function ActionDropdown({ return identifierString(`action-menu-${tooltip}`); }, [tooltip]); - return hasActions ? ( + return !hidden && hasActions ? ( diff --git a/src/frontend/src/components/nav/Header.tsx b/src/frontend/src/components/nav/Header.tsx index 4e3eece8bf..49426d599b 100644 --- a/src/frontend/src/components/nav/Header.tsx +++ b/src/frontend/src/components/nav/Header.tsx @@ -70,8 +70,7 @@ export function Header() { } }, refetchInterval: 30000, - refetchOnMount: true, - refetchOnWindowFocus: false + refetchOnMount: true }); // Sync Navigation Drawer state with zustand diff --git a/src/frontend/src/components/nav/NotificationDrawer.tsx b/src/frontend/src/components/nav/NotificationDrawer.tsx index 8d9a85483d..28464b4895 100644 --- a/src/frontend/src/components/nav/NotificationDrawer.tsx +++ b/src/frontend/src/components/nav/NotificationDrawer.tsx @@ -53,8 +53,7 @@ export function NotificationDrawer({ .catch((error) => { return error; }), - refetchOnMount: false, - refetchOnWindowFocus: false + refetchOnMount: false }); const hasNotifications: boolean = useMemo(() => { diff --git a/src/frontend/src/components/nav/SearchDrawer.tsx b/src/frontend/src/components/nav/SearchDrawer.tsx index 30287e9631..429af00f0c 100644 --- a/src/frontend/src/components/nav/SearchDrawer.tsx +++ b/src/frontend/src/components/nav/SearchDrawer.tsx @@ -275,8 +275,7 @@ export function SearchDrawer({ // Search query manager const searchQuery = useQuery({ queryKey: ['search', searchText, searchRegex, searchWhole], - queryFn: performSearch, - refetchOnWindowFocus: false + queryFn: performSearch }); // A list of queries which return valid results diff --git a/src/frontend/src/components/render/Instance.tsx b/src/frontend/src/components/render/Instance.tsx index 58a7261834..38ad0ac76d 100644 --- a/src/frontend/src/components/render/Instance.tsx +++ b/src/frontend/src/components/render/Instance.tsx @@ -47,6 +47,7 @@ export interface InstanceRenderInterface { instance: any; link?: boolean; navigate?: any; + showSecondary?: boolean; } /** @@ -149,10 +150,12 @@ export function RenderInlineModel({ image, labels, url, - navigate + navigate, + showSecondary = true }: { primary: string; secondary?: string; + showSecondary?: boolean; suffix?: ReactNode; image?: string; labels?: string[]; @@ -181,7 +184,7 @@ export function RenderInlineModel({ ) : ( {primary} )} - {secondary && {secondary}} + {showSecondary && secondary && {secondary}} {suffix && ( <> diff --git a/src/frontend/src/components/render/Part.tsx b/src/frontend/src/components/render/Part.tsx index fa35f697dd..f303b89acb 100644 --- a/src/frontend/src/components/render/Part.tsx +++ b/src/frontend/src/components/render/Part.tsx @@ -1,4 +1,5 @@ import { t } from '@lingui/macro'; +import { Badge } from '@mantine/core'; import { ReactNode } from 'react'; import { ModelType } from '../../enums/ModelType'; @@ -12,14 +13,35 @@ export function RenderPart( props: Readonly ): ReactNode { const { instance } = props; - const stock = t`Stock` + `: ${instance.in_stock}`; + + let badgeText = ''; + let badgeColor = 'green'; + + let stock = instance.total_in_stock; + + if (instance.active == false) { + badgeColor = 'red'; + badgeText = t`Inactive`; + } else if (stock <= 0) { + badgeColor = 'orange'; + badgeText = t`No stock`; + } else { + badgeText = t`Stock` + `: ${stock}`; + badgeColor = instance.minimum_stock > stock ? 'yellow' : 'green'; + } + + const badge = ( + + {badgeText} + + ); return ( diff --git a/src/frontend/src/enums/ApiEndpoints.tsx b/src/frontend/src/enums/ApiEndpoints.tsx index 5e8aeda199..a3b49824e0 100644 --- a/src/frontend/src/enums/ApiEndpoints.tsx +++ b/src/frontend/src/enums/ApiEndpoints.tsx @@ -69,6 +69,7 @@ export enum ApiEndpoints { bom_list = 'bom/', bom_item_validate = 'bom/:id/validate/', + bom_validate = 'part/:id/bom-validate/', // Part API endpoints part_list = 'part/', diff --git a/src/frontend/src/forms/PartForms.tsx b/src/frontend/src/forms/PartForms.tsx index 729b158c98..352dd3d53d 100644 --- a/src/frontend/src/forms/PartForms.tsx +++ b/src/frontend/src/forms/PartForms.tsx @@ -3,6 +3,7 @@ import { IconPackages } from '@tabler/icons-react'; import { useMemo, useState } from 'react'; import { ApiFormFieldSet } from '../components/forms/fields/ApiFormField'; +import { useGlobalSettingsState } from '../states/SettingsState'; /** * Construct a set of fields for creating / editing a Part instance @@ -21,9 +22,19 @@ export function usePartFields({ }, name: {}, IPN: {}, - revision: {}, description: {}, - variant_of: {}, + revision: {}, + revision_of: { + filters: { + is_revision: false, + is_template: false + } + }, + variant_of: { + filters: { + is_template: true + } + }, keywords: {}, units: {}, link: {}, @@ -82,13 +93,22 @@ export function usePartFields({ }; } - // TODO: pop 'expiry' field if expiry not enabled - delete fields['default_expiry']; + const settings = useGlobalSettingsState.getState(); - // TODO: pop 'revision' field if PART_ENABLE_REVISION is False - delete fields['revision']; + if (settings.isSet('PART_REVISION_ASSEMBLY_ONLY')) { + fields.revision_of.filters['assembly'] = true; + } - // TODO: handle part duplications + // Pop 'revision' field if PART_ENABLE_REVISION is False + if (!settings.isSet('PART_ENABLE_REVISION')) { + delete fields['revision']; + delete fields['revision_of']; + } + + // Pop 'expiry' field if expiry not enabled + if (!settings.isSet('STOCK_ENABLE_EXPIRY')) { + delete fields['default_expiry']; + } return fields; }, [create]); diff --git a/src/frontend/src/functions/icons.tsx b/src/frontend/src/functions/icons.tsx index bafde65c76..587a244eb8 100644 --- a/src/frontend/src/functions/icons.tsx +++ b/src/frontend/src/functions/icons.tsx @@ -33,6 +33,7 @@ import { IconGitBranch, IconGridDots, IconHash, + IconHierarchy, IconInfoCircle, IconLayersLinked, IconLink, @@ -89,7 +90,8 @@ import React from 'react'; const icons = { name: IconPoint, description: IconInfoCircle, - variant_of: IconStatusChange, + variant_of: IconHierarchy, + revision_of: IconStatusChange, unallocated_stock: IconPackage, total_in_stock: IconPackages, minimum_stock: IconFlag, diff --git a/src/frontend/src/hooks/UseInstance.tsx b/src/frontend/src/hooks/UseInstance.tsx index e7c0c573b1..7a6ae1ebf8 100644 --- a/src/frontend/src/hooks/UseInstance.tsx +++ b/src/frontend/src/hooks/UseInstance.tsx @@ -85,7 +85,7 @@ export function useInstance({ }); }, refetchOnMount: refetchOnMount, - refetchOnWindowFocus: refetchOnWindowFocus, + refetchOnWindowFocus: refetchOnWindowFocus ?? false, refetchInterval: updateInterval }); diff --git a/src/frontend/src/pages/Index/Settings/SystemSettings.tsx b/src/frontend/src/pages/Index/Settings/SystemSettings.tsx index a9efa01aad..59bec1ab13 100644 --- a/src/frontend/src/pages/Index/Settings/SystemSettings.tsx +++ b/src/frontend/src/pages/Index/Settings/SystemSettings.tsx @@ -180,11 +180,12 @@ export default function SystemSettings() { content: ( @@ -467,22 +478,15 @@ export default function PartDetail() { /> - -
    -
    - {part.locked && ( - - - Locked - - - )} - {!part.active && ( - - - Inactive - - - )} - {part.template && ( - - )} - {part.assembly && ( - - )} - {part.component && ( - - )} - {part.trackable && ( - - )} - {part.purchaseable && ( - - )} - {part.saleable && ( - - )} - {part.virtual && ( - - -
    - {' '} - Virtual -
    -
    -
    - )} -
    -
    - - - - - -
    - - + + ) : ( + ); }, [part, instanceQuery]); @@ -655,6 +659,89 @@ export default function PartDetail() { ]; }, [id, part, user]); + // Fetch information on part revision + const partRevisionQuery = useQuery({ + refetchOnMount: true, + queryKey: [ + 'part_revisions', + part.pk, + part.revision_of, + part.revision_count + ], + queryFn: async () => { + if (!part.revision_of && !part.revision_count) { + return []; + } + + let revisions = []; + + // First, fetch information for the top-level part + if (part.revision_of) { + await api + .get(apiUrl(ApiEndpoints.part_list, part.revision_of)) + .then((response) => { + revisions.push(response.data); + }); + } else { + revisions.push(part); + } + + const url = apiUrl(ApiEndpoints.part_list); + + await api + .get(url, { + params: { + revision_of: part.revision_of || part.pk + } + }) + .then((response) => { + switch (response.status) { + case 200: + response.data.forEach((r: any) => { + revisions.push(r); + }); + break; + default: + break; + } + }) + .catch(() => {}); + + return revisions; + } + }); + + const partRevisionOptions: any[] = useMemo(() => { + if (partRevisionQuery.isFetching || !partRevisionQuery.data) { + return []; + } + + if (!part.revision_of && !part.revision_count) { + return []; + } + + let options: any[] = partRevisionQuery.data.map((revision: any) => { + return { + value: revision.pk, + label: revision.full_name, + part: revision + }; + }); + + // Add this part if not already available + if (!options.find((o) => o.value == part.pk)) { + options.push({ + value: part.pk, + label: part.full_name, + part: part + }); + } + + return options.sort((a, b) => { + return ('' + a.part.revision).localeCompare(b.part.revision); + }); + }, [part, partRevisionQuery.isFetching, partRevisionQuery.data]); + const breadcrumbs = useMemo( () => [ { name: t`Parts`, url: '/part' }, @@ -686,7 +773,7 @@ export default function PartDetail() { />, , @@ -705,7 +792,7 @@ export default function PartDetail() { , { + return ( + partRevisionOptions.length > 0 && + globalSettings.isSet('PART_ENABLE_REVISION') + ); + }, [partRevisionOptions, globalSettings]); + return ( <> {duplicatePart.modal} @@ -886,6 +988,40 @@ export default function PartDetail() { setTreeOpen(true); }} actions={partActions} + detail={ + enableRevisionSelection ? ( + + {t`Select Part Revision`} +