mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-15 11:35:41 +00:00
Merge remote-tracking branch 'upstream/master' into pui-feature-plugin
This commit is contained in:
@ -173,9 +173,9 @@ idna==3.7 \
|
|||||||
# anyio
|
# anyio
|
||||||
# httpx
|
# httpx
|
||||||
# requests
|
# requests
|
||||||
importlib-metadata==8.4.0 \
|
importlib-metadata==8.5.0 \
|
||||||
--hash=sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1 \
|
--hash=sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b \
|
||||||
--hash=sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5
|
--hash=sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7
|
||||||
# via
|
# via
|
||||||
# markdown
|
# markdown
|
||||||
# mkdocs
|
# mkdocs
|
||||||
@ -301,17 +301,17 @@ mkdocs-get-deps==0.2.0 \
|
|||||||
--hash=sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c \
|
--hash=sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c \
|
||||||
--hash=sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134
|
--hash=sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134
|
||||||
# via mkdocs
|
# via mkdocs
|
||||||
mkdocs-git-revision-date-localized-plugin==1.2.8 \
|
mkdocs-git-revision-date-localized-plugin==1.2.9 \
|
||||||
--hash=sha256:6e09c308bb27bcf36b211d17b74152ecc2837cdfc351237f70cffc723ef0fd99 \
|
--hash=sha256:dea5c8067c23df30275702a1708885500fadf0abfb595b60e698bffc79c7a423 \
|
||||||
--hash=sha256:c7ec3b1481ca23134269e84927bd8a5dc1aa359c0e515b832dbd5d25019b5748
|
--hash=sha256:df9a50873fba3a42ce9123885f8c53d589e90ef6c2443fe3280ef1e8d33c8f65
|
||||||
# via -r docs/requirements.in
|
# via -r docs/requirements.in
|
||||||
mkdocs-include-markdown-plugin==6.2.2 \
|
mkdocs-include-markdown-plugin==6.2.2 \
|
||||||
--hash=sha256:d293950f6499d2944291ca7b9bc4a60e652bbfd3e3a42b564f6cceee268694e7 \
|
--hash=sha256:d293950f6499d2944291ca7b9bc4a60e652bbfd3e3a42b564f6cceee268694e7 \
|
||||||
--hash=sha256:f2bd5026650492a581d2fd44be6c22f90391910d76582b96a34c264f2d17875d
|
--hash=sha256:f2bd5026650492a581d2fd44be6c22f90391910d76582b96a34c264f2d17875d
|
||||||
# via -r docs/requirements.in
|
# via -r docs/requirements.in
|
||||||
mkdocs-macros-plugin==1.0.5 \
|
mkdocs-macros-plugin==1.2.0 \
|
||||||
--hash=sha256:f60e26f711f5a830ddf1e7980865bf5c0f1180db56109803cdd280073c1a050a \
|
--hash=sha256:3e442f8f37aa69710a69b5389e6b6cd0f54f4fcaee354aa57a61735ba8f97d27 \
|
||||||
--hash=sha256:fe348d75f01c911f362b6d998c57b3d85b505876dde69db924f2c512c395c328
|
--hash=sha256:7603b85cb336d669e29a8a9cc3af8b90767ffdf6021b3e023d5ec2e0a1f927a7
|
||||||
# via -r docs/requirements.in
|
# via -r docs/requirements.in
|
||||||
mkdocs-material==9.5.34 \
|
mkdocs-material==9.5.34 \
|
||||||
--hash=sha256:1e60ddf716cfb5679dfd65900b8a25d277064ed82d9a53cd5190e3f894df7840 \
|
--hash=sha256:1e60ddf716cfb5679dfd65900b8a25d277064ed82d9a53cd5190e3f894df7840 \
|
||||||
@ -342,7 +342,9 @@ neoteroi-mkdocs==1.1.0 \
|
|||||||
packaging==24.0 \
|
packaging==24.0 \
|
||||||
--hash=sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5 \
|
--hash=sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5 \
|
||||||
--hash=sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9
|
--hash=sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9
|
||||||
# via mkdocs
|
# via
|
||||||
|
# mkdocs
|
||||||
|
# mkdocs-macros-plugin
|
||||||
paginate==0.5.6 \
|
paginate==0.5.6 \
|
||||||
--hash=sha256:5e6007b6a9398177a7e1648d04fdd9f8c9766a1a945bceac82f1929e8c78af2d
|
--hash=sha256:5e6007b6a9398177a7e1648d04fdd9f8c9766a1a945bceac82f1929e8c78af2d
|
||||||
# via mkdocs-material
|
# via mkdocs-material
|
||||||
@ -443,86 +445,101 @@ pyyaml-env-tag==0.1 \
|
|||||||
--hash=sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb \
|
--hash=sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb \
|
||||||
--hash=sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069
|
--hash=sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069
|
||||||
# via mkdocs
|
# via mkdocs
|
||||||
regex==2024.7.24 \
|
regex==2024.9.11 \
|
||||||
--hash=sha256:01b689e887f612610c869421241e075c02f2e3d1ae93a037cb14f88ab6a8934c \
|
--hash=sha256:01c2acb51f8a7d6494c8c5eafe3d8e06d76563d8a8a4643b37e9b2dd8a2ff623 \
|
||||||
--hash=sha256:04ce29e2c5fedf296b1a1b0acc1724ba93a36fb14031f3abfb7abda2806c1535 \
|
--hash=sha256:02087ea0a03b4af1ed6ebab2c54d7118127fee8d71b26398e8e4b05b78963199 \
|
||||||
--hash=sha256:0ffe3f9d430cd37d8fa5632ff6fb36d5b24818c5c986893063b4e5bdb84cdf24 \
|
--hash=sha256:040562757795eeea356394a7fb13076ad4f99d3c62ab0f8bdfb21f99a1f85664 \
|
||||||
--hash=sha256:18300a1d78cf1290fa583cd8b7cde26ecb73e9f5916690cf9d42de569c89b1ce \
|
--hash=sha256:042c55879cfeb21a8adacc84ea347721d3d83a159da6acdf1116859e2427c43f \
|
||||||
--hash=sha256:185e029368d6f89f36e526764cf12bf8d6f0e3a2a7737da625a76f594bdfcbfc \
|
--hash=sha256:079400a8269544b955ffa9e31f186f01d96829110a3bf79dc338e9910f794fca \
|
||||||
--hash=sha256:19c65b00d42804e3fbea9708f0937d157e53429a39b7c61253ff15670ff62cb5 \
|
--hash=sha256:07f45f287469039ffc2c53caf6803cd506eb5f5f637f1d4acb37a738f71dd066 \
|
||||||
--hash=sha256:228b0d3f567fafa0633aee87f08b9276c7062da9616931382993c03808bb68ce \
|
--hash=sha256:09d77559e80dcc9d24570da3745ab859a9cf91953062e4ab126ba9d5993688ca \
|
||||||
--hash=sha256:23acc72f0f4e1a9e6e9843d6328177ae3074b4182167e34119ec7233dfeccf53 \
|
--hash=sha256:0cbff728659ce4bbf4c30b2a1be040faafaa9eca6ecde40aaff86f7889f4ab39 \
|
||||||
--hash=sha256:25419b70ba00a16abc90ee5fce061228206173231f004437730b67ac77323f0d \
|
--hash=sha256:0e12c481ad92d129c78f13a2a3662317e46ee7ef96c94fd332e1c29131875b7d \
|
||||||
--hash=sha256:2dfbb8baf8ba2c2b9aa2807f44ed272f0913eeeba002478c4577b8d29cde215c \
|
--hash=sha256:0ea51dcc0835eea2ea31d66456210a4e01a076d820e9039b04ae8d17ac11dee6 \
|
||||||
--hash=sha256:2f1baff13cc2521bea83ab2528e7a80cbe0ebb2c6f0bfad15be7da3aed443908 \
|
--hash=sha256:0ffbcf9221e04502fc35e54d1ce9567541979c3fdfb93d2c554f0ca583a19b35 \
|
||||||
--hash=sha256:33e2614a7ce627f0cdf2ad104797d1f68342d967de3695678c0cb84f530709f8 \
|
--hash=sha256:1494fa8725c285a81d01dc8c06b55287a1ee5e0e382d8413adc0a9197aac6408 \
|
||||||
--hash=sha256:3426de3b91d1bc73249042742f45c2148803c111d1175b283270177fdf669024 \
|
--hash=sha256:16e13a7929791ac1216afde26f712802e3df7bf0360b32e4914dca3ab8baeea5 \
|
||||||
--hash=sha256:382281306e3adaaa7b8b9ebbb3ffb43358a7bbf585fa93821300a418bb975281 \
|
--hash=sha256:18406efb2f5a0e57e3a5881cd9354c1512d3bb4f5c45d96d110a66114d84d23a \
|
||||||
--hash=sha256:3d974d24edb231446f708c455fd08f94c41c1ff4f04bcf06e5f36df5ef50b95a \
|
--hash=sha256:18e707ce6c92d7282dfce370cd205098384b8ee21544e7cb29b8aab955b66fa9 \
|
||||||
--hash=sha256:3f3b6ca8eae6d6c75a6cff525c8530c60e909a71a15e1b731723233331de4169 \
|
--hash=sha256:220e92a30b426daf23bb67a7962900ed4613589bab80382be09b48896d211e92 \
|
||||||
--hash=sha256:3fac296f99283ac232d8125be932c5cd7644084a30748fda013028c815ba3364 \
|
--hash=sha256:23b30c62d0f16827f2ae9f2bb87619bc4fba2044911e2e6c2eb1af0161cdb766 \
|
||||||
--hash=sha256:416c0e4f56308f34cdb18c3f59849479dde5b19febdcd6e6fa4d04b6c31c9faa \
|
--hash=sha256:23f9985c8784e544d53fc2930fc1ac1a7319f5d5332d228437acc9f418f2f168 \
|
||||||
--hash=sha256:438d9f0f4bc64e8dea78274caa5af971ceff0f8771e1a2333620969936ba10be \
|
--hash=sha256:297f54910247508e6e5cae669f2bc308985c60540a4edd1c77203ef19bfa63ca \
|
||||||
--hash=sha256:43affe33137fcd679bdae93fb25924979517e011f9dea99163f80b82eadc7e53 \
|
--hash=sha256:2b08fce89fbd45664d3df6ad93e554b6c16933ffa9d55cb7e01182baaf971508 \
|
||||||
--hash=sha256:44fc61b99035fd9b3b9453f1713234e5a7c92a04f3577252b45feefe1b327759 \
|
--hash=sha256:2cce2449e5927a0bf084d346da6cd5eb016b2beca10d0013ab50e3c226ffc0df \
|
||||||
--hash=sha256:45104baae8b9f67569f0f1dca5e1f1ed77a54ae1cd8b0b07aba89272710db61e \
|
--hash=sha256:313ea15e5ff2a8cbbad96ccef6be638393041b0a7863183c2d31e0c6116688cf \
|
||||||
--hash=sha256:4fdd1384619f406ad9037fe6b6eaa3de2749e2e12084abc80169e8e075377d3b \
|
--hash=sha256:323c1f04be6b2968944d730e5c2091c8c89767903ecaa135203eec4565ed2b2b \
|
||||||
--hash=sha256:538d30cd96ed7d1416d3956f94d54e426a8daf7c14527f6e0d6d425fcb4cca52 \
|
--hash=sha256:35f4a6f96aa6cb3f2f7247027b07b15a374f0d5b912c0001418d1d55024d5cb4 \
|
||||||
--hash=sha256:558a57cfc32adcf19d3f791f62b5ff564922942e389e3cfdb538a23d65a6b610 \
|
--hash=sha256:3b37fa423beefa44919e009745ccbf353d8c981516e807995b2bd11c2c77d268 \
|
||||||
--hash=sha256:5eefee9bfe23f6df09ffb6dfb23809f4d74a78acef004aa904dc7c88b9944b05 \
|
--hash=sha256:3ce4f1185db3fbde8ed8aa223fc9620f276c58de8b0d4f8cc86fd1360829edb6 \
|
||||||
--hash=sha256:64bd50cf16bcc54b274e20235bf8edbb64184a30e1e53873ff8d444e7ac656b2 \
|
--hash=sha256:46989629904bad940bbec2106528140a218b4a36bb3042d8406980be1941429c \
|
||||||
--hash=sha256:65fd3d2e228cae024c411c5ccdffae4c315271eee4a8b839291f84f796b34eca \
|
--hash=sha256:4838e24ee015101d9f901988001038f7f0d90dc0c3b115541a1365fb439add62 \
|
||||||
--hash=sha256:66b4c0731a5c81921e938dcf1a88e978264e26e6ac4ec96a4d21ae0354581ae0 \
|
--hash=sha256:49b0e06786ea663f933f3710a51e9385ce0cba0ea56b67107fd841a55d56a231 \
|
||||||
--hash=sha256:68a8f8c046c6466ac61a36b65bb2395c74451df2ffb8458492ef49900efed293 \
|
--hash=sha256:4db21ece84dfeefc5d8a3863f101995de646c6cb0536952c321a2650aa202c36 \
|
||||||
--hash=sha256:6a1141a1dcc32904c47f6846b040275c6e5de0bf73f17d7a409035d55b76f289 \
|
--hash=sha256:54c4a097b8bc5bb0dfc83ae498061d53ad7b5762e00f4adaa23bee22b012e6ba \
|
||||||
--hash=sha256:6b9fc7e9cc983e75e2518496ba1afc524227c163e43d706688a6bb9eca41617e \
|
--hash=sha256:54d9ff35d4515debf14bc27f1e3b38bfc453eff3220f5bce159642fa762fe5d4 \
|
||||||
--hash=sha256:6f51f9556785e5a203713f5efd9c085b4a45aecd2a42573e2b5041881b588d1f \
|
--hash=sha256:55b96e7ce3a69a8449a66984c268062fbaa0d8ae437b285428e12797baefce7e \
|
||||||
--hash=sha256:7214477bf9bd195894cf24005b1e7b496f46833337b5dedb7b2a6e33f66d962c \
|
--hash=sha256:57fdd2e0b2694ce6fc2e5ccf189789c3e2962916fb38779d3e3521ff8fe7a822 \
|
||||||
--hash=sha256:731fcd76bbdbf225e2eb85b7c38da9633ad3073822f5ab32379381e8c3c12e94 \
|
--hash=sha256:587d4af3979376652010e400accc30404e6c16b7df574048ab1f581af82065e4 \
|
||||||
--hash=sha256:74007a5b25b7a678459f06559504f1eec2f0f17bca218c9d56f6a0a12bfffdad \
|
--hash=sha256:5b513b6997a0b2f10e4fd3a1313568e373926e8c252bd76c960f96fd039cd28d \
|
||||||
--hash=sha256:7a5486ca56c8869070a966321d5ab416ff0f83f30e0e2da1ab48815c8d165d46 \
|
--hash=sha256:5ddcd9a179c0a6fa8add279a4444015acddcd7f232a49071ae57fa6e278f1f71 \
|
||||||
--hash=sha256:7c479f5ae937ec9985ecaf42e2e10631551d909f203e31308c12d703922742f9 \
|
--hash=sha256:6113c008a7780792efc80f9dfe10ba0cd043cbf8dc9a76ef757850f51b4edc50 \
|
||||||
--hash=sha256:7df9ea48641da022c2a3c9c641650cd09f0cd15e8908bf931ad538f5ca7919c9 \
|
--hash=sha256:635a1d96665f84b292e401c3d62775851aedc31d4f8784117b3c68c4fcd4118d \
|
||||||
--hash=sha256:7e37e809b9303ec3a179085415cb5f418ecf65ec98cdfe34f6a078b46ef823ee \
|
--hash=sha256:64ce2799bd75039b480cc0360907c4fb2f50022f030bf9e7a8705b636e408fad \
|
||||||
--hash=sha256:80c811cfcb5c331237d9bad3bea2c391114588cf4131707e84d9493064d267f9 \
|
--hash=sha256:69dee6a020693d12a3cf892aba4808fe168d2a4cef368eb9bf74f5398bfd4ee8 \
|
||||||
--hash=sha256:836d3cc225b3e8a943d0b02633fb2f28a66e281290302a79df0e1eaa984ff7c1 \
|
--hash=sha256:6a2644a93da36c784e546de579ec1806bfd2763ef47babc1b03d765fe560c9f8 \
|
||||||
--hash=sha256:84c312cdf839e8b579f504afcd7b65f35d60b6285d892b19adea16355e8343c9 \
|
--hash=sha256:6b41e1adc61fa347662b09398e31ad446afadff932a24807d3ceb955ed865cc8 \
|
||||||
--hash=sha256:86b17ba823ea76256b1885652e3a141a99a5c4422f4a869189db328321b73799 \
|
--hash=sha256:6c188c307e8433bcb63dc1915022deb553b4203a70722fc542c363bf120a01fd \
|
||||||
--hash=sha256:871e3ab2838fbcb4e0865a6e01233975df3a15e6fce93b6f99d75cacbd9862d1 \
|
--hash=sha256:6edd623bae6a737f10ce853ea076f56f507fd7726bee96a41ee3d68d347e4d16 \
|
||||||
--hash=sha256:88ecc3afd7e776967fa16c80f974cb79399ee8dc6c96423321d6f7d4b881c92b \
|
--hash=sha256:73d6d2f64f4d894c96626a75578b0bf7d9e56dcda8c3d037a2118fdfe9b1c664 \
|
||||||
--hash=sha256:8bc593dcce679206b60a538c302d03c29b18e3d862609317cb560e18b66d10cf \
|
--hash=sha256:7a22ccefd4db3f12b526eccb129390942fe874a3a9fdbdd24cf55773a1faab1a \
|
||||||
--hash=sha256:8fd5afd101dcf86a270d254364e0e8dddedebe6bd1ab9d5f732f274fa00499a5 \
|
--hash=sha256:7fb89ee5d106e4a7a51bce305ac4efb981536301895f7bdcf93ec92ae0d91c7f \
|
||||||
--hash=sha256:945352286a541406f99b2655c973852da7911b3f4264e010218bbc1cc73168f2 \
|
--hash=sha256:846bc79ee753acf93aef4184c040d709940c9d001029ceb7b7a52747b80ed2dd \
|
||||||
--hash=sha256:973335b1624859cb0e52f96062a28aa18f3a5fc77a96e4a3d6d76e29811a0e6e \
|
--hash=sha256:85ab7824093d8f10d44330fe1e6493f756f252d145323dd17ab6b48733ff6c0a \
|
||||||
--hash=sha256:994448ee01864501912abf2bad9203bffc34158e80fe8bfb5b031f4f8e16da51 \
|
--hash=sha256:8dee5b4810a89447151999428fe096977346cf2f29f4d5e29609d2e19e0199c9 \
|
||||||
--hash=sha256:9cfd009eed1a46b27c14039ad5bbc5e71b6367c5b2e6d5f5da0ea91600817506 \
|
--hash=sha256:8e5fb5f77c8745a60105403a774fe2c1759b71d3e7b4ca237a5e67ad066c7199 \
|
||||||
--hash=sha256:a2ec4419a3fe6cf8a4795752596dfe0adb4aea40d3683a132bae9c30b81e8d73 \
|
--hash=sha256:98eeee2f2e63edae2181c886d7911ce502e1292794f4c5ee71e60e23e8d26b5d \
|
||||||
--hash=sha256:a4997716674d36a82eab3e86f8fa77080a5d8d96a389a61ea1d0e3a94a582cf7 \
|
--hash=sha256:9d4a76b96f398697fe01117093613166e6aa8195d63f1b4ec3f21ab637632963 \
|
||||||
--hash=sha256:a512eed9dfd4117110b1881ba9a59b31433caed0c4101b361f768e7bcbaf93c5 \
|
--hash=sha256:9e8719792ca63c6b8340380352c24dcb8cd7ec49dae36e963742a275dfae6009 \
|
||||||
--hash=sha256:a82465ebbc9b1c5c50738536fdfa7cab639a261a99b469c9d4c7dcbb2b3f1e57 \
|
--hash=sha256:a0b2b80321c2ed3fcf0385ec9e51a12253c50f146fddb2abbb10f033fe3d049a \
|
||||||
--hash=sha256:ae2757ace61bc4061b69af19e4689fa4416e1a04840f33b441034202b5cd02d4 \
|
--hash=sha256:a4cc92bb6db56ab0c1cbd17294e14f5e9224f0cc6521167ef388332604e92679 \
|
||||||
--hash=sha256:b16582783f44fbca6fcf46f61347340c787d7530d88b4d590a397a47583f31dd \
|
--hash=sha256:a738b937d512b30bf75995c0159c0ddf9eec0775c9d72ac0202076c72f24aa96 \
|
||||||
--hash=sha256:ba2537ef2163db9e6ccdbeb6f6424282ae4dea43177402152c67ef869cf3978b \
|
--hash=sha256:a8f877c89719d759e52783f7fe6e1c67121076b87b40542966c02de5503ace42 \
|
||||||
--hash=sha256:bf7a89eef64b5455835f5ed30254ec19bf41f7541cd94f266ab7cbd463f00c41 \
|
--hash=sha256:a906ed5e47a0ce5f04b2c981af1c9acf9e8696066900bf03b9d7879a6f679fc8 \
|
||||||
--hash=sha256:c0abb5e4e8ce71a61d9446040c1e86d4e6d23f9097275c5bd49ed978755ff0fe \
|
--hash=sha256:ae2941333154baff9838e88aa71c1d84f4438189ecc6021a12c7573728b5838e \
|
||||||
--hash=sha256:c414cbda77dbf13c3bc88b073a1a9f375c7b0cb5e115e15d4b73ec3a2fbc6f59 \
|
--hash=sha256:b0d0a6c64fcc4ef9c69bd5b3b3626cc3776520a1637d8abaa62b9edc147a58f7 \
|
||||||
--hash=sha256:c51edc3541e11fbe83f0c4d9412ef6c79f664a3745fab261457e84465ec9d5a8 \
|
--hash=sha256:b5b029322e6e7b94fff16cd120ab35a253236a5f99a79fb04fda7ae71ca20ae8 \
|
||||||
--hash=sha256:c5e69fd3eb0b409432b537fe3c6f44ac089c458ab6b78dcec14478422879ec5f \
|
--hash=sha256:b7aaa315101c6567a9a45d2839322c51c8d6e81f67683d529512f5bcfb99c802 \
|
||||||
--hash=sha256:c918b7a1e26b4ab40409820ddccc5d49871a82329640f5005f73572d5eaa9b5e \
|
--hash=sha256:be1c8ed48c4c4065ecb19d882a0ce1afe0745dfad8ce48c49586b90a55f02366 \
|
||||||
--hash=sha256:c9bb87fdf2ab2370f21e4d5636e5317775e5d51ff32ebff2cf389f71b9b13750 \
|
--hash=sha256:c0256beda696edcf7d97ef16b2a33a8e5a875affd6fa6567b54f7c577b30a137 \
|
||||||
--hash=sha256:ca5b2028c2f7af4e13fb9fc29b28d0ce767c38c7facdf64f6c2cd040413055f1 \
|
--hash=sha256:c157bb447303070f256e084668b702073db99bbb61d44f85d811025fcf38f784 \
|
||||||
--hash=sha256:d0a07763776188b4db4c9c7fb1b8c494049f84659bb387b71c73bbc07f189e96 \
|
--hash=sha256:c57d08ad67aba97af57a7263c2d9006d5c404d721c5f7542f077f109ec2a4a29 \
|
||||||
--hash=sha256:d33a0021893ede5969876052796165bab6006559ab845fd7b515a30abdd990dc \
|
--hash=sha256:c69ada171c2d0e97a4b5aa78fbb835e0ffbb6b13fc5da968c09811346564f0d3 \
|
||||||
--hash=sha256:d55588cba7553f0b6ec33130bc3e114b355570b45785cebdc9daed8c637dd440 \
|
--hash=sha256:c94bb0a9f1db10a1d16c00880bdebd5f9faf267273b8f5bd1878126e0fbde771 \
|
||||||
--hash=sha256:dac8e84fff5d27420f3c1e879ce9929108e873667ec87e0c8eeb413a5311adfe \
|
--hash=sha256:cb130fccd1a37ed894824b8c046321540263013da72745d755f2d35114b81a60 \
|
||||||
--hash=sha256:eaef80eac3b4cfbdd6de53c6e108b4c534c21ae055d1dbea2de6b3b8ff3def38 \
|
--hash=sha256:ced479f601cd2f8ca1fd7b23925a7e0ad512a56d6e9476f79b8f381d9d37090a \
|
||||||
--hash=sha256:eb462f0e346fcf41a901a126b50f8781e9a474d3927930f3490f38a6e73b6950 \
|
--hash=sha256:d05ac6fa06959c4172eccd99a222e1fbf17b5670c4d596cb1e5cde99600674c4 \
|
||||||
--hash=sha256:eb563dd3aea54c797adf513eeec819c4213d7dbfc311874eb4fd28d10f2ff0f2 \
|
--hash=sha256:d552c78411f60b1fdaafd117a1fca2f02e562e309223b9d44b7de8be451ec5e0 \
|
||||||
--hash=sha256:f273674b445bcb6e4409bf8d1be67bc4b58e8b46fd0d560055d515b8830063cd \
|
--hash=sha256:dd4490a33eb909ef5078ab20f5f000087afa2a4daa27b4c072ccb3cb3050ad84 \
|
||||||
--hash=sha256:f6442f0f0ff81775eaa5b05af8a0ffa1dda36e9cf6ec1e0d3d245e8564b684ce \
|
--hash=sha256:df5cbb1fbc74a8305b6065d4ade43b993be03dbe0f8b30032cced0d7740994bd \
|
||||||
--hash=sha256:fb168b5924bef397b5ba13aabd8cf5df7d3d93f10218d7b925e360d436863f66 \
|
--hash=sha256:e28f9faeb14b6f23ac55bfbbfd3643f5c7c18ede093977f1df249f73fd22c7b1 \
|
||||||
--hash=sha256:fbf8c2f00904eaf63ff37718eb13acf8e178cb940520e47b2f05027f5bb34ce3 \
|
--hash=sha256:e464b467f1588e2c42d26814231edecbcfe77f5ac414d92cbf4e7b55b2c2a776 \
|
||||||
--hash=sha256:fe4ebef608553aff8deb845c7f4f1d0740ff76fa672c011cc0bacb2a00fbde86
|
--hash=sha256:e4c22e1ac1f1ec1e09f72e6c44d8f2244173db7eb9629cc3a346a8d7ccc31142 \
|
||||||
|
--hash=sha256:e53b5fbab5d675aec9f0c501274c467c0f9a5d23696cfc94247e1fb56501ed89 \
|
||||||
|
--hash=sha256:e93f1c331ca8e86fe877a48ad64e77882c0c4da0097f2212873a69bbfea95d0c \
|
||||||
|
--hash=sha256:e997fd30430c57138adc06bba4c7c2968fb13d101e57dd5bb9355bf8ce3fa7e8 \
|
||||||
|
--hash=sha256:e9a091b0550b3b0207784a7d6d0f1a00d1d1c8a11699c1a4d93db3fbefc3ad35 \
|
||||||
|
--hash=sha256:eab4bb380f15e189d1313195b062a6aa908f5bd687a0ceccd47c8211e9cf0d4a \
|
||||||
|
--hash=sha256:eb1ae19e64c14c7ec1995f40bd932448713d3c73509e82d8cd7744dc00e29e86 \
|
||||||
|
--hash=sha256:ecea58b43a67b1b79805f1a0255730edaf5191ecef84dbc4cc85eb30bc8b63b9 \
|
||||||
|
--hash=sha256:ee439691d8c23e76f9802c42a95cfeebf9d47cf4ffd06f18489122dbb0a7ad64 \
|
||||||
|
--hash=sha256:eee9130eaad130649fd73e5cd92f60e55708952260ede70da64de420cdcad554 \
|
||||||
|
--hash=sha256:f47cd43a5bfa48f86925fe26fbdd0a488ff15b62468abb5d2a1e092a4fb10e85 \
|
||||||
|
--hash=sha256:f6fff13ef6b5f29221d6904aa816c34701462956aa72a77f1f151a8ec4f56aeb \
|
||||||
|
--hash=sha256:f745ec09bc1b0bd15cfc73df6fa4f726dcc26bb16c23a03f9e3367d357eeedd0 \
|
||||||
|
--hash=sha256:f8404bf61298bb6f8224bb9176c1424548ee1181130818fcd2cbffddc768bed8 \
|
||||||
|
--hash=sha256:f9268774428ec173654985ce55fc6caf4c6d11ade0f6f914d48ef4719eb05ebb \
|
||||||
|
--hash=sha256:faa3c142464efec496967359ca99696c896c591c56c53506bac1ad465f66e919
|
||||||
# via mkdocs-material
|
# via mkdocs-material
|
||||||
requests==2.32.3 \
|
requests==2.32.3 \
|
||||||
--hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \
|
--hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \
|
||||||
@ -595,7 +612,7 @@ wcmatch==8.5.2 \
|
|||||||
--hash=sha256:17d3ad3758f9d0b5b4dedc770b65420d4dac62e680229c287bf24c9db856a478 \
|
--hash=sha256:17d3ad3758f9d0b5b4dedc770b65420d4dac62e680229c287bf24c9db856a478 \
|
||||||
--hash=sha256:a70222b86dea82fb382dd87b73278c10756c138bd6f8f714e2183128887b9eb2
|
--hash=sha256:a70222b86dea82fb382dd87b73278c10756c138bd6f8f714e2183128887b9eb2
|
||||||
# via mkdocs-include-markdown-plugin
|
# via mkdocs-include-markdown-plugin
|
||||||
zipp==3.20.1 \
|
zipp==3.20.2 \
|
||||||
--hash=sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064 \
|
--hash=sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350 \
|
||||||
--hash=sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b
|
--hash=sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29
|
||||||
# via importlib-metadata
|
# via importlib-metadata
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
"""InvenTree API version information."""
|
"""InvenTree API version information."""
|
||||||
|
|
||||||
# InvenTree API version
|
# InvenTree API version
|
||||||
INVENTREE_API_VERSION = 255
|
INVENTREE_API_VERSION = 256
|
||||||
|
|
||||||
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
||||||
|
|
||||||
|
|
||||||
INVENTREE_API_TEXT = """
|
INVENTREE_API_TEXT = """
|
||||||
|
|
||||||
v255 - 2024-09-18 : https://github.com/inventree/InvenTree/pull/8137
|
v256 - 2024-09-18 : https://github.com/inventree/InvenTree/pull/8137
|
||||||
- Implements new API endpoints for enabling custom UI features via plugins
|
- Implements new API endpoints for enabling custom UI features via plugins
|
||||||
|
|
||||||
|
v255 - 2024-09-19 : https://github.com/inventree/InvenTree/pull/8145
|
||||||
|
- Enables copying line items when duplicating an order
|
||||||
|
|
||||||
v254 - 2024-09-14 : https://github.com/inventree/InvenTree/pull/7470
|
v254 - 2024-09-14 : https://github.com/inventree/InvenTree/pull/7470
|
||||||
- Implements new API endpoints for enabling custom UI functionality via plugins
|
- Implements new API endpoints for enabling custom UI functionality via plugins
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ from typing import cast
|
|||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import authenticate, login
|
from django.contrib.auth import authenticate, login
|
||||||
from django.db import transaction
|
|
||||||
from django.db.models import F, Q
|
from django.db.models import F, Q
|
||||||
from django.http.response import JsonResponse
|
from django.http.response import JsonResponse
|
||||||
from django.urls import include, path, re_path
|
from django.urls import include, path, re_path
|
||||||
@ -14,7 +13,6 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from django_filters import rest_framework as rest_filters
|
from django_filters import rest_framework as rest_filters
|
||||||
from django_ical.views import ICalFeed
|
from django_ical.views import ICalFeed
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.exceptions import ValidationError
|
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
import common.models
|
import common.models
|
||||||
@ -214,54 +212,6 @@ class PurchaseOrderList(PurchaseOrderMixin, DataExportViewMixin, ListCreateAPI):
|
|||||||
|
|
||||||
filterset_class = PurchaseOrderFilter
|
filterset_class = PurchaseOrderFilter
|
||||||
|
|
||||||
def create(self, request, *args, **kwargs):
|
|
||||||
"""Save user information on create."""
|
|
||||||
data = self.clean_data(request.data)
|
|
||||||
|
|
||||||
duplicate_order = data.pop('duplicate_order', None)
|
|
||||||
duplicate_line_items = str2bool(data.pop('duplicate_line_items', False))
|
|
||||||
duplicate_extra_lines = str2bool(data.pop('duplicate_extra_lines', False))
|
|
||||||
|
|
||||||
if duplicate_order is not None:
|
|
||||||
try:
|
|
||||||
duplicate_order = models.PurchaseOrder.objects.get(pk=duplicate_order)
|
|
||||||
except (ValueError, models.PurchaseOrder.DoesNotExist):
|
|
||||||
raise ValidationError({
|
|
||||||
'duplicate_order': [_('No matching purchase order found')]
|
|
||||||
})
|
|
||||||
|
|
||||||
serializer = self.get_serializer(data=data)
|
|
||||||
serializer.is_valid(raise_exception=True)
|
|
||||||
|
|
||||||
with transaction.atomic():
|
|
||||||
order = serializer.save()
|
|
||||||
order.created_by = request.user
|
|
||||||
order.save()
|
|
||||||
|
|
||||||
# Duplicate line items from other order if required
|
|
||||||
if duplicate_order is not None:
|
|
||||||
if duplicate_line_items:
|
|
||||||
for line in duplicate_order.lines.all():
|
|
||||||
# Copy the line across to the new order
|
|
||||||
line.pk = None
|
|
||||||
line.order = order
|
|
||||||
line.received = 0
|
|
||||||
|
|
||||||
line.save()
|
|
||||||
|
|
||||||
if duplicate_extra_lines:
|
|
||||||
for line in duplicate_order.extra_lines.all():
|
|
||||||
# Copy the line across to the new order
|
|
||||||
line.pk = None
|
|
||||||
line.order = order
|
|
||||||
|
|
||||||
line.save()
|
|
||||||
|
|
||||||
headers = self.get_success_headers(serializer.data)
|
|
||||||
return Response(
|
|
||||||
serializer.data, status=status.HTTP_201_CREATED, headers=headers
|
|
||||||
)
|
|
||||||
|
|
||||||
def filter_queryset(self, queryset):
|
def filter_queryset(self, queryset):
|
||||||
"""Custom queryset filtering."""
|
"""Custom queryset filtering."""
|
||||||
# Perform basic filtering
|
# Perform basic filtering
|
||||||
|
@ -247,6 +247,16 @@ class Order(
|
|||||||
'contact': _('Contact does not match selected company')
|
'contact': _('Contact does not match selected company')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def clean_line_item(self, line):
|
||||||
|
"""Clean a line item for this order.
|
||||||
|
|
||||||
|
Used when duplicating an existing line item,
|
||||||
|
to ensure it is 'fresh'.
|
||||||
|
"""
|
||||||
|
line.pk = None
|
||||||
|
line.target_date = None
|
||||||
|
line.order = self
|
||||||
|
|
||||||
def report_context(self):
|
def report_context(self):
|
||||||
"""Generate context data for the reporting interface."""
|
"""Generate context data for the reporting interface."""
|
||||||
return {
|
return {
|
||||||
@ -379,6 +389,11 @@ class PurchaseOrder(TotalPriceMixin, Order):
|
|||||||
|
|
||||||
verbose_name = _('Purchase Order')
|
verbose_name = _('Purchase Order')
|
||||||
|
|
||||||
|
def clean_line_item(self, line):
|
||||||
|
"""Clean a line item for this PurchaseOrder."""
|
||||||
|
super().clean_line_item(line)
|
||||||
|
line.received = 0
|
||||||
|
|
||||||
def report_context(self):
|
def report_context(self):
|
||||||
"""Return report context data for this PurchaseOrder."""
|
"""Return report context data for this PurchaseOrder."""
|
||||||
return {**super().report_context(), 'supplier': self.supplier}
|
return {**super().report_context(), 'supplier': self.supplier}
|
||||||
@ -892,6 +907,11 @@ class SalesOrder(TotalPriceMixin, Order):
|
|||||||
|
|
||||||
verbose_name = _('Sales Order')
|
verbose_name = _('Sales Order')
|
||||||
|
|
||||||
|
def clean_line_item(self, line):
|
||||||
|
"""Clean a line item for this SalesOrder."""
|
||||||
|
super().clean_line_item(line)
|
||||||
|
line.shipped = 0
|
||||||
|
|
||||||
def report_context(self):
|
def report_context(self):
|
||||||
"""Generate report context data for this SalesOrder."""
|
"""Generate report context data for this SalesOrder."""
|
||||||
return {**super().report_context(), 'customer': self.customer}
|
return {**super().report_context(), 'customer': self.customer}
|
||||||
@ -2083,6 +2103,12 @@ class ReturnOrder(TotalPriceMixin, Order):
|
|||||||
|
|
||||||
verbose_name = _('Return Order')
|
verbose_name = _('Return Order')
|
||||||
|
|
||||||
|
def clean_line_item(self, line):
|
||||||
|
"""Clean a line item for this ReturnOrder."""
|
||||||
|
super().clean_line_item(line)
|
||||||
|
line.received_date = None
|
||||||
|
line.outcome = ReturnOrderLineStatus.PENDING.value
|
||||||
|
|
||||||
def report_context(self):
|
def report_context(self):
|
||||||
"""Generate report context data for this ReturnOrder."""
|
"""Generate report context data for this ReturnOrder."""
|
||||||
return {**super().report_context(), 'customer': self.customer}
|
return {**super().report_context(), 'customer': self.customer}
|
||||||
|
@ -74,10 +74,39 @@ class TotalPriceMixin(serializers.Serializer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DuplicateOrderSerializer(serializers.Serializer):
|
||||||
|
"""Serializer for specifying options when duplicating an order."""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Metaclass options."""
|
||||||
|
|
||||||
|
fields = ['order_id', 'copy_lines', 'copy_extra_lines']
|
||||||
|
|
||||||
|
order_id = serializers.IntegerField(
|
||||||
|
required=True, label=_('Order ID'), help_text=_('ID of the order to duplicate')
|
||||||
|
)
|
||||||
|
|
||||||
|
copy_lines = serializers.BooleanField(
|
||||||
|
required=False,
|
||||||
|
default=True,
|
||||||
|
label=_('Copy Lines'),
|
||||||
|
help_text=_('Copy line items from the original order'),
|
||||||
|
)
|
||||||
|
|
||||||
|
copy_extra_lines = serializers.BooleanField(
|
||||||
|
required=False,
|
||||||
|
default=True,
|
||||||
|
label=_('Copy Extra Lines'),
|
||||||
|
help_text=_('Copy extra line items from the original order'),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class AbstractOrderSerializer(DataImportExportSerializerMixin, serializers.Serializer):
|
class AbstractOrderSerializer(DataImportExportSerializerMixin, serializers.Serializer):
|
||||||
"""Abstract serializer class which provides fields common to all order types."""
|
"""Abstract serializer class which provides fields common to all order types."""
|
||||||
|
|
||||||
export_exclude_fields = ['notes']
|
export_exclude_fields = ['notes', 'duplicate']
|
||||||
|
|
||||||
|
import_exclude_fields = ['notes', 'duplicate']
|
||||||
|
|
||||||
# Number of line items in this order
|
# Number of line items in this order
|
||||||
line_items = serializers.IntegerField(read_only=True, label=_('Line Items'))
|
line_items = serializers.IntegerField(read_only=True, label=_('Line Items'))
|
||||||
@ -127,6 +156,13 @@ class AbstractOrderSerializer(DataImportExportSerializerMixin, serializers.Seria
|
|||||||
required=False, allow_null=True, label=_('Creation Date')
|
required=False, allow_null=True, label=_('Creation Date')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
duplicate = DuplicateOrderSerializer(
|
||||||
|
label=_('Duplicate Order'),
|
||||||
|
help_text=_('Specify options for duplicating this order'),
|
||||||
|
required=False,
|
||||||
|
write_only=True,
|
||||||
|
)
|
||||||
|
|
||||||
def validate_reference(self, reference):
|
def validate_reference(self, reference):
|
||||||
"""Custom validation for the reference field."""
|
"""Custom validation for the reference field."""
|
||||||
self.Meta.model.validate_reference_field(reference)
|
self.Meta.model.validate_reference_field(reference)
|
||||||
@ -166,9 +202,49 @@ class AbstractOrderSerializer(DataImportExportSerializerMixin, serializers.Seria
|
|||||||
'notes',
|
'notes',
|
||||||
'barcode_hash',
|
'barcode_hash',
|
||||||
'overdue',
|
'overdue',
|
||||||
|
'duplicate',
|
||||||
*extra_fields,
|
*extra_fields,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def clean_line_item(self, line):
|
||||||
|
"""Clean a line item object (when duplicating)."""
|
||||||
|
line.pk = None
|
||||||
|
line.order = self
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def create(self, validated_data):
|
||||||
|
"""Create a new order object.
|
||||||
|
|
||||||
|
Optionally, copy line items from an existing order.
|
||||||
|
"""
|
||||||
|
duplicate = validated_data.pop('duplicate', None)
|
||||||
|
|
||||||
|
instance = super().create(validated_data)
|
||||||
|
|
||||||
|
if duplicate:
|
||||||
|
order_id = duplicate.get('order_id', None)
|
||||||
|
copy_lines = duplicate.get('copy_lines', True)
|
||||||
|
copy_extra_lines = duplicate.get('copy_extra_lines', True)
|
||||||
|
|
||||||
|
try:
|
||||||
|
copy_from = instance.__class__.objects.get(pk=order_id)
|
||||||
|
except Exception:
|
||||||
|
# If the order ID is invalid, raise a validation error
|
||||||
|
raise ValidationError(_('Invalid order ID'))
|
||||||
|
|
||||||
|
if copy_lines:
|
||||||
|
for line in copy_from.lines.all():
|
||||||
|
instance.clean_line_item(line)
|
||||||
|
line.save()
|
||||||
|
|
||||||
|
if copy_extra_lines:
|
||||||
|
for line in copy_from.extra_lines.all():
|
||||||
|
line.pk = None
|
||||||
|
line.order = instance
|
||||||
|
line.save()
|
||||||
|
|
||||||
|
return instance
|
||||||
|
|
||||||
|
|
||||||
class AbstractLineItemSerializer:
|
class AbstractLineItemSerializer:
|
||||||
"""Abstract serializer for LineItem object."""
|
"""Abstract serializer for LineItem object."""
|
||||||
@ -259,6 +335,12 @@ class PurchaseOrderSerializer(
|
|||||||
if supplier_detail is not True:
|
if supplier_detail is not True:
|
||||||
self.fields.pop('supplier_detail', None)
|
self.fields.pop('supplier_detail', None)
|
||||||
|
|
||||||
|
def skip_create_fields(self):
|
||||||
|
"""Skip these fields when instantiating a new object."""
|
||||||
|
fields = super().skip_create_fields()
|
||||||
|
|
||||||
|
return [*fields, 'duplicate']
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def annotate_queryset(queryset):
|
def annotate_queryset(queryset):
|
||||||
"""Add extra information to the queryset.
|
"""Add extra information to the queryset.
|
||||||
@ -900,6 +982,12 @@ class SalesOrderSerializer(
|
|||||||
if customer_detail is not True:
|
if customer_detail is not True:
|
||||||
self.fields.pop('customer_detail', None)
|
self.fields.pop('customer_detail', None)
|
||||||
|
|
||||||
|
def skip_create_fields(self):
|
||||||
|
"""Skip these fields when instantiating a new object."""
|
||||||
|
fields = super().skip_create_fields()
|
||||||
|
|
||||||
|
return [*fields, 'duplicate']
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def annotate_queryset(queryset):
|
def annotate_queryset(queryset):
|
||||||
"""Add extra information to the queryset.
|
"""Add extra information to the queryset.
|
||||||
@ -1692,6 +1780,12 @@ class ReturnOrderSerializer(
|
|||||||
if customer_detail is not True:
|
if customer_detail is not True:
|
||||||
self.fields.pop('customer_detail', None)
|
self.fields.pop('customer_detail', None)
|
||||||
|
|
||||||
|
def skip_create_fields(self):
|
||||||
|
"""Skip these fields when instantiating a new object."""
|
||||||
|
fields = super().skip_create_fields()
|
||||||
|
|
||||||
|
return [*fields, 'duplicate']
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def annotate_queryset(queryset):
|
def annotate_queryset(queryset):
|
||||||
"""Custom annotation for the serializer queryset."""
|
"""Custom annotation for the serializer queryset."""
|
||||||
|
@ -439,18 +439,22 @@ class PurchaseOrderTest(OrderTest):
|
|||||||
del data['reference']
|
del data['reference']
|
||||||
|
|
||||||
# Duplicate with non-existent PK to provoke error
|
# Duplicate with non-existent PK to provoke error
|
||||||
data['duplicate_order'] = 10000001
|
data['duplicate'] = {
|
||||||
data['duplicate_line_items'] = True
|
'order_id': 10000001,
|
||||||
data['duplicate_extra_lines'] = False
|
'copy_lines': True,
|
||||||
|
'copy_extra_lines': False,
|
||||||
|
}
|
||||||
|
|
||||||
data['reference'] = 'PO-9999'
|
data['reference'] = 'PO-9999'
|
||||||
|
|
||||||
# Duplicate via the API
|
# Duplicate via the API
|
||||||
response = self.post(reverse('api-po-list'), data, expected_code=400)
|
response = self.post(reverse('api-po-list'), data, expected_code=400)
|
||||||
|
|
||||||
data['duplicate_order'] = 1
|
data['duplicate'] = {
|
||||||
data['duplicate_line_items'] = True
|
'order_id': 1,
|
||||||
data['duplicate_extra_lines'] = False
|
'copy_lines': True,
|
||||||
|
'copy_extra_lines': False,
|
||||||
|
}
|
||||||
|
|
||||||
data['reference'] = 'PO-9999'
|
data['reference'] = 'PO-9999'
|
||||||
|
|
||||||
@ -466,8 +470,12 @@ class PurchaseOrderTest(OrderTest):
|
|||||||
self.assertEqual(po_dup.lines.count(), po.lines.count())
|
self.assertEqual(po_dup.lines.count(), po.lines.count())
|
||||||
|
|
||||||
data['reference'] = 'PO-9998'
|
data['reference'] = 'PO-9998'
|
||||||
data['duplicate_line_items'] = False
|
|
||||||
data['duplicate_extra_lines'] = True
|
data['duplicate'] = {
|
||||||
|
'order_id': 1,
|
||||||
|
'copy_lines': False,
|
||||||
|
'copy_extra_lines': True,
|
||||||
|
}
|
||||||
|
|
||||||
response = self.post(reverse('api-po-list'), data, expected_code=201)
|
response = self.post(reverse('api-po-list'), data, expected_code=201)
|
||||||
|
|
||||||
|
@ -98,7 +98,8 @@ function purchaseOrderFields(options={}) {
|
|||||||
|
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
disabled: !!options.duplicate_order,
|
||||||
},
|
},
|
||||||
supplier_reference: {},
|
supplier_reference: {},
|
||||||
project_code: {
|
project_code: {
|
||||||
@ -155,35 +156,13 @@ function purchaseOrderFields(options={}) {
|
|||||||
|
|
||||||
// Add fields for order duplication (only if required)
|
// Add fields for order duplication (only if required)
|
||||||
if (options.duplicate_order) {
|
if (options.duplicate_order) {
|
||||||
fields.duplicate_order = {
|
fields.duplicate__order_id = {
|
||||||
value: options.duplicate_order,
|
value: options.duplicate_order,
|
||||||
group: 'duplicate',
|
hidden: true,
|
||||||
required: 'true',
|
|
||||||
type: 'related field',
|
|
||||||
model: 'purchaseorder',
|
|
||||||
filters: {
|
|
||||||
supplier_detail: true,
|
|
||||||
},
|
|
||||||
api_url: '{% url "api-po-list" %}',
|
|
||||||
label: '{% trans "Purchase Order" %}',
|
|
||||||
help_text: '{% trans "Select purchase order to duplicate" %}',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fields.duplicate_line_items = {
|
fields.duplicate__copy_lines = {};
|
||||||
value: true,
|
fields.duplicate__copy_extra_lines = {};
|
||||||
group: 'duplicate',
|
|
||||||
type: 'boolean',
|
|
||||||
label: '{% trans "Duplicate Line Items" %}',
|
|
||||||
help_text: '{% trans "Duplicate all line items from the selected order" %}',
|
|
||||||
};
|
|
||||||
|
|
||||||
fields.duplicate_extra_lines = {
|
|
||||||
value: true,
|
|
||||||
group: 'duplicate',
|
|
||||||
type: 'boolean',
|
|
||||||
label: '{% trans "Duplicate Extra Lines" %}',
|
|
||||||
help_text: '{% trans "Duplicate extra line items from the selected order" %}',
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!global_settings.PROJECT_CODES_ENABLED) {
|
if (!global_settings.PROJECT_CODES_ENABLED) {
|
||||||
|
@ -138,14 +138,19 @@ export function usePurchaseOrderLineItemFields({
|
|||||||
/**
|
/**
|
||||||
* Construct a set of fields for creating / editing a PurchaseOrder instance
|
* Construct a set of fields for creating / editing a PurchaseOrder instance
|
||||||
*/
|
*/
|
||||||
export function usePurchaseOrderFields(): ApiFormFieldSet {
|
export function usePurchaseOrderFields({
|
||||||
|
duplicateOrderId
|
||||||
|
}: {
|
||||||
|
duplicateOrderId?: number;
|
||||||
|
}): ApiFormFieldSet {
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
return {
|
let fields: ApiFormFieldSet = {
|
||||||
reference: {
|
reference: {
|
||||||
icon: <IconHash />
|
icon: <IconHash />
|
||||||
},
|
},
|
||||||
description: {},
|
description: {},
|
||||||
supplier: {
|
supplier: {
|
||||||
|
disabled: duplicateOrderId !== undefined,
|
||||||
filters: {
|
filters: {
|
||||||
is_supplier: true,
|
is_supplier: true,
|
||||||
active: true
|
active: true
|
||||||
@ -187,7 +192,23 @@ export function usePurchaseOrderFields(): ApiFormFieldSet {
|
|||||||
icon: <IconUsers />
|
icon: <IconUsers />
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, []);
|
|
||||||
|
// Order duplication fields
|
||||||
|
if (!!duplicateOrderId) {
|
||||||
|
fields.duplicate = {
|
||||||
|
children: {
|
||||||
|
order_id: {
|
||||||
|
hidden: true,
|
||||||
|
value: duplicateOrderId
|
||||||
|
},
|
||||||
|
copy_lines: {},
|
||||||
|
copy_extra_lines: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}, [duplicateOrderId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,16 +1,88 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { Flex, Table } from '@mantine/core';
|
import { Flex, Table } from '@mantine/core';
|
||||||
import { IconUsers } from '@tabler/icons-react';
|
import { IconAddressBook, IconUser, IconUsers } from '@tabler/icons-react';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
import RemoveRowButton from '../components/buttons/RemoveRowButton';
|
import RemoveRowButton from '../components/buttons/RemoveRowButton';
|
||||||
import { ApiFormFieldSet } from '../components/forms/fields/ApiFormField';
|
import {
|
||||||
|
ApiFormAdjustFilterType,
|
||||||
|
ApiFormFieldSet
|
||||||
|
} from '../components/forms/fields/ApiFormField';
|
||||||
import { TableFieldRowProps } from '../components/forms/fields/TableField';
|
import { TableFieldRowProps } from '../components/forms/fields/TableField';
|
||||||
import { Thumbnail } from '../components/images/Thumbnail';
|
import { Thumbnail } from '../components/images/Thumbnail';
|
||||||
import { ApiEndpoints } from '../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../enums/ApiEndpoints';
|
||||||
import { useCreateApiFormModal } from '../hooks/UseForm';
|
import { useCreateApiFormModal } from '../hooks/UseForm';
|
||||||
import { apiUrl } from '../states/ApiState';
|
import { apiUrl } from '../states/ApiState';
|
||||||
|
|
||||||
|
export function useReturnOrderFields({
|
||||||
|
duplicateOrderId
|
||||||
|
}: {
|
||||||
|
duplicateOrderId?: number;
|
||||||
|
}): ApiFormFieldSet {
|
||||||
|
return useMemo(() => {
|
||||||
|
let fields: ApiFormFieldSet = {
|
||||||
|
reference: {},
|
||||||
|
description: {},
|
||||||
|
customer: {
|
||||||
|
disabled: duplicateOrderId != undefined,
|
||||||
|
filters: {
|
||||||
|
is_customer: true,
|
||||||
|
active: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
customer_reference: {},
|
||||||
|
project_code: {},
|
||||||
|
order_currency: {},
|
||||||
|
target_date: {},
|
||||||
|
link: {},
|
||||||
|
contact: {
|
||||||
|
icon: <IconUser />,
|
||||||
|
adjustFilters: (value: ApiFormAdjustFilterType) => {
|
||||||
|
return {
|
||||||
|
...value.filters,
|
||||||
|
company: value.data.customer
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
address: {
|
||||||
|
icon: <IconAddressBook />,
|
||||||
|
adjustFilters: (value: ApiFormAdjustFilterType) => {
|
||||||
|
return {
|
||||||
|
...value.filters,
|
||||||
|
company: value.data.customer
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
responsible: {
|
||||||
|
filters: {
|
||||||
|
is_active: true
|
||||||
|
},
|
||||||
|
icon: <IconUsers />
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Order duplication fields
|
||||||
|
if (!!duplicateOrderId) {
|
||||||
|
fields.duplicate = {
|
||||||
|
children: {
|
||||||
|
order_id: {
|
||||||
|
hidden: true,
|
||||||
|
value: duplicateOrderId
|
||||||
|
},
|
||||||
|
copy_lines: {
|
||||||
|
// Cannot duplicate lines from a return order!
|
||||||
|
value: false,
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
|
copy_extra_lines: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}, [duplicateOrderId]);
|
||||||
|
}
|
||||||
|
|
||||||
export function useReturnOrderLineItemFields({
|
export function useReturnOrderLineItemFields({
|
||||||
orderId,
|
orderId,
|
||||||
customerId,
|
customerId,
|
||||||
|
@ -6,12 +6,17 @@ import {
|
|||||||
ApiFormFieldSet
|
ApiFormFieldSet
|
||||||
} from '../components/forms/fields/ApiFormField';
|
} from '../components/forms/fields/ApiFormField';
|
||||||
|
|
||||||
export function useSalesOrderFields(): ApiFormFieldSet {
|
export function useSalesOrderFields({
|
||||||
|
duplicateOrderId
|
||||||
|
}: {
|
||||||
|
duplicateOrderId?: number;
|
||||||
|
}): ApiFormFieldSet {
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
return {
|
let fields: ApiFormFieldSet = {
|
||||||
reference: {},
|
reference: {},
|
||||||
description: {},
|
description: {},
|
||||||
customer: {
|
customer: {
|
||||||
|
disabled: duplicateOrderId != undefined,
|
||||||
filters: {
|
filters: {
|
||||||
is_customer: true,
|
is_customer: true,
|
||||||
active: true
|
active: true
|
||||||
@ -44,7 +49,23 @@ export function useSalesOrderFields(): ApiFormFieldSet {
|
|||||||
icon: <IconUsers />
|
icon: <IconUsers />
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, []);
|
|
||||||
|
// Order duplication fields
|
||||||
|
if (!!duplicateOrderId) {
|
||||||
|
fields.duplicate = {
|
||||||
|
children: {
|
||||||
|
order_id: {
|
||||||
|
hidden: true,
|
||||||
|
value: duplicateOrderId
|
||||||
|
},
|
||||||
|
copy_lines: {},
|
||||||
|
copy_extra_lines: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}, [duplicateOrderId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useSalesOrderLineItemFields({
|
export function useSalesOrderLineItemFields({
|
||||||
@ -125,47 +146,3 @@ export function useSalesOrderShipmentFields(): ApiFormFieldSet {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useReturnOrderFields(): ApiFormFieldSet {
|
|
||||||
return useMemo(() => {
|
|
||||||
return {
|
|
||||||
reference: {},
|
|
||||||
description: {},
|
|
||||||
customer: {
|
|
||||||
filters: {
|
|
||||||
is_customer: true,
|
|
||||||
active: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
customer_reference: {},
|
|
||||||
project_code: {},
|
|
||||||
order_currency: {},
|
|
||||||
target_date: {},
|
|
||||||
link: {},
|
|
||||||
contact: {
|
|
||||||
icon: <IconUser />,
|
|
||||||
adjustFilters: (value: ApiFormAdjustFilterType) => {
|
|
||||||
return {
|
|
||||||
...value.filters,
|
|
||||||
company: value.data.customer
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
address: {
|
|
||||||
icon: <IconAddressBook />,
|
|
||||||
adjustFilters: (value: ApiFormAdjustFilterType) => {
|
|
||||||
return {
|
|
||||||
...value.filters,
|
|
||||||
company: value.data.customer
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
responsible: {
|
|
||||||
filters: {
|
|
||||||
is_active: true
|
|
||||||
},
|
|
||||||
icon: <IconUsers />
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
}
|
|
||||||
|
@ -81,7 +81,11 @@ export default function PurchaseOrderDetail() {
|
|||||||
);
|
);
|
||||||
}, [order, globalSettings]);
|
}, [order, globalSettings]);
|
||||||
|
|
||||||
const purchaseOrderFields = usePurchaseOrderFields();
|
const purchaseOrderFields = usePurchaseOrderFields({});
|
||||||
|
|
||||||
|
const duplicatePurchaseOrderFields = usePurchaseOrderFields({
|
||||||
|
duplicateOrderId: order.pk
|
||||||
|
});
|
||||||
|
|
||||||
const editPurchaseOrder = useEditApiFormModal({
|
const editPurchaseOrder = useEditApiFormModal({
|
||||||
url: ApiEndpoints.purchase_order_list,
|
url: ApiEndpoints.purchase_order_list,
|
||||||
@ -96,7 +100,7 @@ export default function PurchaseOrderDetail() {
|
|||||||
const duplicatePurchaseOrder = useCreateApiFormModal({
|
const duplicatePurchaseOrder = useCreateApiFormModal({
|
||||||
url: ApiEndpoints.purchase_order_list,
|
url: ApiEndpoints.purchase_order_list,
|
||||||
title: t`Add Purchase Order`,
|
title: t`Add Purchase Order`,
|
||||||
fields: purchaseOrderFields,
|
fields: duplicatePurchaseOrderFields,
|
||||||
initialData: {
|
initialData: {
|
||||||
...order,
|
...order,
|
||||||
reference: undefined
|
reference: undefined
|
||||||
|
@ -34,7 +34,7 @@ import { formatCurrency } from '../../defaults/formatters';
|
|||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { UserRoles } from '../../enums/Roles';
|
import { UserRoles } from '../../enums/Roles';
|
||||||
import { useReturnOrderFields } from '../../forms/SalesOrderForms';
|
import { useReturnOrderFields } from '../../forms/ReturnOrderForms';
|
||||||
import {
|
import {
|
||||||
useCreateApiFormModal,
|
useCreateApiFormModal,
|
||||||
useEditApiFormModal
|
useEditApiFormModal
|
||||||
@ -304,7 +304,11 @@ export default function ReturnOrderDetail() {
|
|||||||
];
|
];
|
||||||
}, [order, instanceQuery]);
|
}, [order, instanceQuery]);
|
||||||
|
|
||||||
const returnOrderFields = useReturnOrderFields();
|
const returnOrderFields = useReturnOrderFields({});
|
||||||
|
|
||||||
|
const duplicateReturnOrderFields = useReturnOrderFields({
|
||||||
|
duplicateOrderId: order.pk
|
||||||
|
});
|
||||||
|
|
||||||
const editReturnOrder = useEditApiFormModal({
|
const editReturnOrder = useEditApiFormModal({
|
||||||
url: ApiEndpoints.return_order_list,
|
url: ApiEndpoints.return_order_list,
|
||||||
@ -319,7 +323,7 @@ export default function ReturnOrderDetail() {
|
|||||||
const duplicateReturnOrder = useCreateApiFormModal({
|
const duplicateReturnOrder = useCreateApiFormModal({
|
||||||
url: ApiEndpoints.return_order_list,
|
url: ApiEndpoints.return_order_list,
|
||||||
title: t`Add Return Order`,
|
title: t`Add Return Order`,
|
||||||
fields: returnOrderFields,
|
fields: duplicateReturnOrderFields,
|
||||||
initialData: {
|
initialData: {
|
||||||
...order,
|
...order,
|
||||||
reference: undefined
|
reference: undefined
|
||||||
|
@ -231,7 +231,7 @@ export default function SalesOrderDetail() {
|
|||||||
|
|
||||||
const soStatus = useStatusCodes({ modelType: ModelType.salesorder });
|
const soStatus = useStatusCodes({ modelType: ModelType.salesorder });
|
||||||
|
|
||||||
const salesOrderFields = useSalesOrderFields();
|
const salesOrderFields = useSalesOrderFields({});
|
||||||
|
|
||||||
const editSalesOrder = useEditApiFormModal({
|
const editSalesOrder = useEditApiFormModal({
|
||||||
url: ApiEndpoints.sales_order_list,
|
url: ApiEndpoints.sales_order_list,
|
||||||
@ -243,10 +243,14 @@ export default function SalesOrderDetail() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const duplicateOrderFields = useSalesOrderFields({
|
||||||
|
duplicateOrderId: order.pk
|
||||||
|
});
|
||||||
|
|
||||||
const duplicateSalesOrder = useCreateApiFormModal({
|
const duplicateSalesOrder = useCreateApiFormModal({
|
||||||
url: ApiEndpoints.sales_order_list,
|
url: ApiEndpoints.sales_order_list,
|
||||||
title: t`Add Sales Order`,
|
title: t`Add Sales Order`,
|
||||||
fields: salesOrderFields,
|
fields: duplicateOrderFields,
|
||||||
initialData: {
|
initialData: {
|
||||||
...order,
|
...order,
|
||||||
reference: undefined
|
reference: undefined
|
||||||
|
@ -121,7 +121,7 @@ export function PurchaseOrderTable({
|
|||||||
];
|
];
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const purchaseOrderFields = usePurchaseOrderFields();
|
const purchaseOrderFields = usePurchaseOrderFields({});
|
||||||
|
|
||||||
const newPurchaseOrder = useCreateApiFormModal({
|
const newPurchaseOrder = useCreateApiFormModal({
|
||||||
url: ApiEndpoints.purchase_order_list,
|
url: ApiEndpoints.purchase_order_list,
|
||||||
|
@ -7,7 +7,7 @@ import { formatCurrency } from '../../defaults/formatters';
|
|||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { UserRoles } from '../../enums/Roles';
|
import { UserRoles } from '../../enums/Roles';
|
||||||
import { useReturnOrderFields } from '../../forms/SalesOrderForms';
|
import { useReturnOrderFields } from '../../forms/ReturnOrderForms';
|
||||||
import { useOwnerFilters, useProjectCodeFilters } from '../../hooks/UseFilter';
|
import { useOwnerFilters, useProjectCodeFilters } from '../../hooks/UseFilter';
|
||||||
import { useCreateApiFormModal } from '../../hooks/UseForm';
|
import { useCreateApiFormModal } from '../../hooks/UseForm';
|
||||||
import { useTable } from '../../hooks/UseTable';
|
import { useTable } from '../../hooks/UseTable';
|
||||||
@ -112,7 +112,7 @@ export function ReturnOrderTable({ params }: Readonly<{ params?: any }>) {
|
|||||||
];
|
];
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const returnOrderFields = useReturnOrderFields();
|
const returnOrderFields = useReturnOrderFields({});
|
||||||
|
|
||||||
const newReturnOrder = useCreateApiFormModal({
|
const newReturnOrder = useCreateApiFormModal({
|
||||||
url: ApiEndpoints.return_order_list,
|
url: ApiEndpoints.return_order_list,
|
||||||
|
@ -77,7 +77,7 @@ export function SalesOrderTable({
|
|||||||
];
|
];
|
||||||
}, [projectCodeFilters.choices, responsibleFilters.choices]);
|
}, [projectCodeFilters.choices, responsibleFilters.choices]);
|
||||||
|
|
||||||
const salesOrderFields = useSalesOrderFields();
|
const salesOrderFields = useSalesOrderFields({});
|
||||||
|
|
||||||
const newSalesOrder = useCreateApiFormModal({
|
const newSalesOrder = useCreateApiFormModal({
|
||||||
url: ApiEndpoints.sales_order_list,
|
url: ApiEndpoints.sales_order_list,
|
||||||
|
Reference in New Issue
Block a user