Compare commits
2 Commits
feature-ma
...
feature-sw
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d5a743600 | ||
|
|
3656c36965 |
@@ -123,13 +123,13 @@ RUN set -eux \
|
||||
WORKDIR /usr/src/paperless/src/docker/
|
||||
|
||||
COPY [ \
|
||||
"docker/rootfs/etc/ImageMagick-6/paperless-policy.xml", \
|
||||
"docker/imagemagick-policy.xml", \
|
||||
"./" \
|
||||
]
|
||||
|
||||
RUN set -eux \
|
||||
&& echo "Configuring ImageMagick" \
|
||||
&& mv paperless-policy.xml /etc/ImageMagick-6/policy.xml
|
||||
&& mv imagemagick-policy.xml /etc/ImageMagick-6/policy.xml
|
||||
|
||||
# Packages needed only for building a few quick Python
|
||||
# dependencies
|
||||
|
||||
@@ -65,7 +65,7 @@ services:
|
||||
command: /bin/sh -c "chown -R paperless:paperless /usr/src/paperless/paperless-ngx/src/documents/static/frontend && chown -R paperless:paperless /usr/src/paperless/paperless-ngx/.ruff_cache && while sleep 1000; do :; done"
|
||||
|
||||
gotenberg:
|
||||
image: docker.io/gotenberg/gotenberg:8.17
|
||||
image: docker.io/gotenberg/gotenberg:7.10
|
||||
restart: unless-stopped
|
||||
|
||||
# The Gotenberg Chromium route is used to convert .eml files. We do not
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
services:
|
||||
gotenberg:
|
||||
image: docker.io/gotenberg/gotenberg:8.17
|
||||
image: docker.io/gotenberg/gotenberg:8.7
|
||||
hostname: gotenberg
|
||||
container_name: gotenberg
|
||||
network_mode: host
|
||||
|
||||
@@ -77,7 +77,7 @@ services:
|
||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||
|
||||
gotenberg:
|
||||
image: docker.io/gotenberg/gotenberg:8.17
|
||||
image: docker.io/gotenberg/gotenberg:8.7
|
||||
restart: unless-stopped
|
||||
# The gotenberg chromium route is used to convert .eml files. We do not
|
||||
# want to allow external content like tracking pixels or even javascript.
|
||||
|
||||
@@ -71,7 +71,7 @@ services:
|
||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||
|
||||
gotenberg:
|
||||
image: docker.io/gotenberg/gotenberg:8.17
|
||||
image: docker.io/gotenberg/gotenberg:8.7
|
||||
restart: unless-stopped
|
||||
|
||||
# The gotenberg chromium route is used to convert .eml files. We do not
|
||||
|
||||
@@ -59,7 +59,7 @@ services:
|
||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||
|
||||
gotenberg:
|
||||
image: docker.io/gotenberg/gotenberg:8.17
|
||||
image: docker.io/gotenberg/gotenberg:8.7
|
||||
restart: unless-stopped
|
||||
|
||||
# The gotenberg chromium route is used to convert .eml files. We do not
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
#!/command/with-contenv /usr/bin/bash
|
||||
# shellcheck shell=bash
|
||||
|
||||
cd ${PAPERLESS_SRC_DIR}
|
||||
|
||||
if [[ -n "${PAPERLESS_CONSUMER_DISABLE}" ]]; then
|
||||
echo "[svc-consumer] Consumer is disabled, exiting"
|
||||
# https://skarnet.org/software/s6/s6-svc.html
|
||||
s6-svc -Od .
|
||||
|
||||
if [[ -n "${USER_IS_NON_ROOT}" ]]; then
|
||||
exec python3 manage.py document_consumer
|
||||
else
|
||||
cd ${PAPERLESS_SRC_DIR}
|
||||
|
||||
if [[ -n "${USER_IS_NON_ROOT}" ]]; then
|
||||
exec python3 manage.py document_consumer
|
||||
else
|
||||
exec s6-setuidgid paperless python3 manage.py document_consumer
|
||||
fi
|
||||
exec s6-setuidgid paperless python3 manage.py document_consumer
|
||||
fi
|
||||
|
||||
@@ -1030,11 +1030,6 @@ be used with caution!
|
||||
|
||||
## Document Consumption {#consume_config}
|
||||
|
||||
#### [`PAPERLESS_CONSUMER_DISABLE=<bool>`](#PAPERLESS_CONSUMER_DISABLE) {#PAPERLESS_CONSUMER_DISABLE}
|
||||
|
||||
: Completely disable the directory-based consumer in docker. If you don't plan to consume documents
|
||||
via the consumption directory, you can disable the consumer to save resources.
|
||||
|
||||
#### [`PAPERLESS_CONSUMER_DELETE_DUPLICATES=<bool>`](#PAPERLESS_CONSUMER_DELETE_DUPLICATES) {#PAPERLESS_CONSUMER_DELETE_DUPLICATES}
|
||||
|
||||
: When the consumer detects a duplicate document, it will not touch
|
||||
|
||||
@@ -714,8 +714,6 @@ the Pi and configuring some options in paperless can help improve
|
||||
performance immensely:
|
||||
|
||||
- Stick with SQLite to save some resources.
|
||||
- If you do not need the filesystem-based consumer, consider disabling it
|
||||
entirely by setting [`PAPERLESS_CONSUMER_DISABLE`](configuration.md#PAPERLESS_CONSUMER_DISABLE) to `true`.
|
||||
- Consider setting [`PAPERLESS_OCR_PAGES`](configuration.md#PAPERLESS_OCR_PAGES) to 1, so that paperless will
|
||||
only OCR the first page of your documents. In most cases, this page
|
||||
contains enough information to be able to find it.
|
||||
|
||||
@@ -569,7 +569,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">81</context>
|
||||
<context context-type="linenumber">76</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.html</context>
|
||||
@@ -1453,7 +1453,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">80</context>
|
||||
<context context-type="linenumber">75</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/storage-path-edit-dialog/storage-path-edit-dialog.component.html</context>
|
||||
@@ -1736,7 +1736,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||
<context context-type="linenumber">87</context>
|
||||
<context context-type="linenumber">83</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
|
||||
@@ -3543,7 +3543,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||
<context context-type="linenumber">83</context>
|
||||
<context context-type="linenumber">79</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
|
||||
@@ -3890,11 +3890,18 @@
|
||||
<context context-type="linenumber">113</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="220550782947016929" datatype="html">
|
||||
<source>Order</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">19</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4816216590591222133" datatype="html">
|
||||
<source>Enabled</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">19</context>
|
||||
<context context-type="linenumber">22</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
@@ -3909,176 +3916,155 @@
|
||||
<context context-type="linenumber">41</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="220550782947016929" datatype="html">
|
||||
<source>Order</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">24</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1504364192557145528" datatype="html">
|
||||
<source>Stop further processing</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">27</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6164556674897067551" datatype="html">
|
||||
<source>Stop processing further rules if this rule queues any document(s).</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">27</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4348351765075925931" datatype="html">
|
||||
<source>Paperless will only process mails that match <x id="START_EMPHASISED_TEXT" ctype="x-em" equiv-text="<em>"/>all<x id="CLOSE_EMPHASISED_TEXT" ctype="x-em" equiv-text="</em>"/> of the criteria specified below.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">32</context>
|
||||
<context context-type="linenumber">27</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7046259383943324039" datatype="html">
|
||||
<source>Folder</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">34</context>
|
||||
<context context-type="linenumber">29</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1391527525114848695" datatype="html">
|
||||
<source>Subfolders must be separated by a delimiter, often a dot ('.') or slash ('/'), but it varies by mail server.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">34</context>
|
||||
<context context-type="linenumber">29</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="101686279614365671" datatype="html">
|
||||
<source>Maximum age (days)</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">35</context>
|
||||
<context context-type="linenumber">30</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6925928412364847639" datatype="html">
|
||||
<source>Filter from</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">38</context>
|
||||
<context context-type="linenumber">33</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8977094263269822022" datatype="html">
|
||||
<source>Filter to</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">39</context>
|
||||
<context context-type="linenumber">34</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8497813481090627874" datatype="html">
|
||||
<source>Filter subject</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">40</context>
|
||||
<context context-type="linenumber">35</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7314357616097563149" datatype="html">
|
||||
<source>Filter body</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">41</context>
|
||||
<context context-type="linenumber">36</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="559099472394646919" datatype="html">
|
||||
<source>Consumption scope</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">47</context>
|
||||
<context context-type="linenumber">42</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="56643687972548912" datatype="html">
|
||||
<source>See docs for .eml processing requirements</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">47</context>
|
||||
<context context-type="linenumber">42</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7093509971705471817" datatype="html">
|
||||
<source>Attachment type</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">48</context>
|
||||
<context context-type="linenumber">43</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3842519365862452117" datatype="html">
|
||||
<source>PDF layout</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">49</context>
|
||||
<context context-type="linenumber">44</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2873939123535615966" datatype="html">
|
||||
<source>Include only files matching</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">52</context>
|
||||
<context context-type="linenumber">47</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7233407036155150477" datatype="html">
|
||||
<source>Optional. Wildcards e.g. *.pdf or *invoice* allowed. Can be comma-separated list. Case insensitive.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">52</context>
|
||||
<context context-type="linenumber">47</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">53</context>
|
||||
<context context-type="linenumber">48</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1546332577833742677" datatype="html">
|
||||
<source>Exclude files matching</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">53</context>
|
||||
<context context-type="linenumber">48</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="9216117865911519658" datatype="html">
|
||||
<source>Action</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">59</context>
|
||||
<context context-type="linenumber">54</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7841986067387421166" datatype="html">
|
||||
<source>Only performed if the mail is processed.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">59</context>
|
||||
<context context-type="linenumber">54</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1261794314435932203" datatype="html">
|
||||
<source>Action parameter</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">61</context>
|
||||
<context context-type="linenumber">56</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6093797930511670257" datatype="html">
|
||||
<source>Assign title from</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">63</context>
|
||||
<context context-type="linenumber">58</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5232720756589450549" datatype="html">
|
||||
<source>Assign owner from rule</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">64</context>
|
||||
<context context-type="linenumber">59</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6695990587380209737" datatype="html">
|
||||
<source>Assign document type</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">68</context>
|
||||
<context context-type="linenumber">63</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
@@ -4089,14 +4075,14 @@
|
||||
<source>Assign correspondent from</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">69</context>
|
||||
<context context-type="linenumber">64</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4875491778188965469" datatype="html">
|
||||
<source>Assign correspondent</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">71</context>
|
||||
<context context-type="linenumber">66</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
@@ -4107,7 +4093,7 @@
|
||||
<source>Error</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component.html</context>
|
||||
<context context-type="linenumber">78</context>
|
||||
<context context-type="linenumber">73</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html</context>
|
||||
@@ -4398,7 +4384,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||
<context context-type="linenumber">129</context>
|
||||
<context context-type="linenumber">125</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/profile-edit-dialog/profile-edit-dialog.component.html</context>
|
||||
@@ -4998,18 +4984,11 @@
|
||||
<context context-type="linenumber">72</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="235571817610183244" datatype="html">
|
||||
<source>Web UI</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||
<context context-type="linenumber">76</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3553216189604488439" datatype="html">
|
||||
<source>Modified</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||
<context context-type="linenumber">91</context>
|
||||
<context context-type="linenumber">87</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/document.ts</context>
|
||||
@@ -5020,70 +4999,70 @@
|
||||
<source>Custom Field</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||
<context context-type="linenumber">95</context>
|
||||
<context context-type="linenumber">91</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8696908693776094667" datatype="html">
|
||||
<source>Consumption Started</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||
<context context-type="linenumber">102</context>
|
||||
<context context-type="linenumber">98</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7858311467093621703" datatype="html">
|
||||
<source>Document Added</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||
<context context-type="linenumber">106</context>
|
||||
<context context-type="linenumber">102</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7955486237346046731" datatype="html">
|
||||
<source>Document Updated</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||
<context context-type="linenumber">110</context>
|
||||
<context context-type="linenumber">106</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="9172233176401579786" datatype="html">
|
||||
<source>Scheduled</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||
<context context-type="linenumber">114</context>
|
||||
<context context-type="linenumber">110</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5502398334173581061" datatype="html">
|
||||
<source>Assignment</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||
<context context-type="linenumber">121</context>
|
||||
<context context-type="linenumber">117</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6234812824772766804" datatype="html">
|
||||
<source>Removal</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||
<context context-type="linenumber">125</context>
|
||||
<context context-type="linenumber">121</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4206419737792796794" datatype="html">
|
||||
<source>Webhook</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||
<context context-type="linenumber">133</context>
|
||||
<context context-type="linenumber">129</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3138206142174978019" datatype="html">
|
||||
<source>Create new workflow</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||
<context context-type="linenumber">229</context>
|
||||
<context context-type="linenumber">225</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5996779210524133604" datatype="html">
|
||||
<source>Edit workflow</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts</context>
|
||||
<context context-type="linenumber">233</context>
|
||||
<context context-type="linenumber">229</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7376342558017986274" datatype="html">
|
||||
@@ -9747,28 +9726,28 @@
|
||||
<source>Connecting...</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/services/upload-documents.service.ts</context>
|
||||
<context context-type="linenumber">43</context>
|
||||
<context context-type="linenumber">42</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1245343823699368872" datatype="html">
|
||||
<source>Uploading...</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/services/upload-documents.service.ts</context>
|
||||
<context context-type="linenumber">55</context>
|
||||
<context context-type="linenumber">54</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7446520539098045935" datatype="html">
|
||||
<source>Upload complete, waiting...</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/services/upload-documents.service.ts</context>
|
||||
<context context-type="linenumber">58</context>
|
||||
<context context-type="linenumber">57</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1405142710727603568" datatype="html">
|
||||
<source>HTTP error: <x id="PH" equiv-text="error.status"/> <x id="PH_1" equiv-text="error.statusText"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/services/upload-documents.service.ts</context>
|
||||
<context context-type="linenumber">71</context>
|
||||
<context context-type="linenumber">70</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2119857572761283468" datatype="html">
|
||||
|
||||
@@ -84,7 +84,7 @@ export class SplitConfirmDialogComponent
|
||||
addSplit() {
|
||||
if (this.page === this.totalPages) return
|
||||
this.pages.add(this.page)
|
||||
this.pages = new Set(Array.from(this.pages).sort((a, b) => a - b))
|
||||
this.pages = new Set(Array.from(this.pages).sort())
|
||||
this.confirmButtonEnabled = this.pages.size > 0
|
||||
}
|
||||
|
||||
|
||||
@@ -9,24 +9,19 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-4">
|
||||
<pngx-input-text [horizontal]="true" i18n-title title="Name" formControlName="name" [error]="error?.name" autocomplete="off"></pngx-input-text>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-3">
|
||||
<pngx-input-select [horizontal]="true" i18n-title title="Account" [items]="accounts" formControlName="account"></pngx-input-select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<pngx-input-number [horizontal]="true" i18n-title title="Order" formControlName="order" [showAdd]="false" [error]="error?.order"></pngx-input-number>
|
||||
</div>
|
||||
<div class="col-md-2 pt-2">
|
||||
<pngx-input-switch [horizontal]="true" i18n-title title="Enabled" formControlName="enabled"></pngx-input-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<pngx-input-number [horizontal]="true" i18n-title title="Order" formControlName="order" [showAdd]="false" [error]="error?.order"></pngx-input-number>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<pngx-input-switch [horizontal]="true" i18n-title title="Stop further processing" formControlName="stop_processing" i18n-hint hint="Stop processing further rules if this rule queues any document(s)."></pngx-input-switch>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="mt-0"/>
|
||||
<div class="row">
|
||||
<p class="small" i18n>Paperless will only process mails that match <em>all</em> of the criteria specified below.</p>
|
||||
|
||||
@@ -221,7 +221,6 @@ export class MailRuleEditDialogComponent extends EditDialogComponent<MailRule> {
|
||||
),
|
||||
assign_correspondent: new FormControl(null),
|
||||
assign_owner_from_rule: new FormControl(true),
|
||||
stop_processing: new FormControl(false),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,4 @@ export interface MailRule extends ObjectWithPermissions {
|
||||
assign_correspondent?: number // PaperlessCorrespondent.id
|
||||
|
||||
assign_owner_from_rule: boolean
|
||||
|
||||
stop_processing: boolean
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ const mail_rules = [
|
||||
action: MailAction.MarkRead,
|
||||
assign_title_from: MailMetadataTitleOption.FromSubject,
|
||||
assign_owner_from_rule: true,
|
||||
stop_processing: false,
|
||||
},
|
||||
{
|
||||
name: 'Mail Rule 2',
|
||||
@@ -53,7 +52,6 @@ const mail_rules = [
|
||||
action: MailAction.Delete,
|
||||
assign_title_from: MailMetadataTitleOption.FromSubject,
|
||||
assign_owner_from_rule: true,
|
||||
stop_processing: false,
|
||||
},
|
||||
{
|
||||
name: 'Mail Rule 3',
|
||||
@@ -73,7 +71,6 @@ const mail_rules = [
|
||||
action: MailAction.Flag,
|
||||
assign_title_from: MailMetadataTitleOption.FromSubject,
|
||||
assign_owner_from_rule: false,
|
||||
stop_processing: false,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import logging
|
||||
import multiprocessing
|
||||
|
||||
import tqdm
|
||||
from django import db
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand
|
||||
from rich.progress import track
|
||||
|
||||
from documents.management.commands.mixins import MultiProcessMixin
|
||||
from documents.management.commands.mixins import ProgressBarMixin
|
||||
@@ -81,7 +81,7 @@ class Command(MultiProcessMixin, ProgressBarMixin, BaseCommand):
|
||||
else: # pragma: no cover
|
||||
with multiprocessing.Pool(self.process_count) as pool:
|
||||
list(
|
||||
tqdm.tqdm(
|
||||
track(
|
||||
pool.imap_unordered(
|
||||
update_document_content_maybe_archive_file,
|
||||
document_ids,
|
||||
|
||||
@@ -7,7 +7,6 @@ import time
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import tqdm
|
||||
from allauth.mfa.models import Authenticator
|
||||
from allauth.socialaccount.models import SocialAccount
|
||||
from allauth.socialaccount.models import SocialApp
|
||||
@@ -25,6 +24,11 @@ from django.utils import timezone
|
||||
from filelock import FileLock
|
||||
from guardian.models import GroupObjectPermission
|
||||
from guardian.models import UserObjectPermission
|
||||
from rich.progress import BarColumn
|
||||
from rich.progress import MofNCompleteColumn
|
||||
from rich.progress import Progress
|
||||
from rich.progress import TaskProgressColumn
|
||||
from rich.progress import TextColumn
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from django.db.models import QuerySet
|
||||
@@ -229,8 +233,17 @@ class Command(CryptMixin, BaseCommand):
|
||||
|
||||
try:
|
||||
# Prevent any ongoing changes in the documents
|
||||
with FileLock(settings.MEDIA_LOCK):
|
||||
self.dump()
|
||||
with (
|
||||
FileLock(settings.MEDIA_LOCK),
|
||||
Progress(
|
||||
TextColumn("[progress.description]{task.description}"),
|
||||
BarColumn(),
|
||||
TaskProgressColumn(),
|
||||
MofNCompleteColumn(),
|
||||
disable=self.no_progress_bar,
|
||||
) as progress,
|
||||
):
|
||||
self.dump(progress)
|
||||
|
||||
# We've written everything to the temporary directory in this case,
|
||||
# now make an archive in the original target, with all files stored
|
||||
@@ -249,7 +262,7 @@ class Command(CryptMixin, BaseCommand):
|
||||
if self.zip_export and temp_dir is not None:
|
||||
temp_dir.cleanup()
|
||||
|
||||
def dump(self):
|
||||
def dump(self, progress: Progress):
|
||||
# 1. Take a snapshot of what files exist in the current export folder
|
||||
for x in self.target.glob("**/*"):
|
||||
if x.is_file():
|
||||
@@ -297,11 +310,17 @@ class Command(CryptMixin, BaseCommand):
|
||||
with transaction.atomic():
|
||||
manifest_dict = {}
|
||||
|
||||
serialize_task = progress.add_task(
|
||||
"Serializing database",
|
||||
total=len(manifest_key_to_object_query),
|
||||
)
|
||||
|
||||
# Build an overall manifest
|
||||
for key, object_query in manifest_key_to_object_query.items():
|
||||
manifest_dict[key] = json.loads(
|
||||
serializers.serialize("json", object_query),
|
||||
)
|
||||
progress.advance(serialize_task)
|
||||
|
||||
self.encrypt_secret_fields(manifest_dict)
|
||||
|
||||
@@ -313,12 +332,10 @@ class Command(CryptMixin, BaseCommand):
|
||||
}
|
||||
document_manifest = manifest_dict["documents"]
|
||||
|
||||
copy_task = progress.add_task("Copying files", total=len(document_manifest))
|
||||
|
||||
# 3. Export files from each document
|
||||
for index, document_dict in tqdm.tqdm(
|
||||
enumerate(document_manifest),
|
||||
total=len(document_manifest),
|
||||
disable=self.no_progress_bar,
|
||||
):
|
||||
for index, document_dict in enumerate(document_manifest):
|
||||
# 3.1. store files unencrypted
|
||||
document_dict["fields"]["storage_type"] = Document.STORAGE_TYPE_UNENCRYPTED
|
||||
|
||||
@@ -365,6 +382,7 @@ class Command(CryptMixin, BaseCommand):
|
||||
content,
|
||||
manifest_name,
|
||||
)
|
||||
progress.advance(copy_task)
|
||||
|
||||
# These were exported already
|
||||
if self.split_manifest:
|
||||
|
||||
@@ -3,9 +3,9 @@ import multiprocessing
|
||||
from typing import Final
|
||||
|
||||
import rapidfuzz
|
||||
import tqdm
|
||||
from django.core.management import BaseCommand
|
||||
from django.core.management import CommandError
|
||||
from rich.progress import track
|
||||
|
||||
from documents.management.commands.mixins import MultiProcessMixin
|
||||
from documents.management.commands.mixins import ProgressBarMixin
|
||||
@@ -105,12 +105,12 @@ class Command(MultiProcessMixin, ProgressBarMixin, BaseCommand):
|
||||
# Don't spin up a pool of 1 process
|
||||
if self.process_count == 1:
|
||||
results = []
|
||||
for work in tqdm.tqdm(work_pkgs, disable=self.no_progress_bar):
|
||||
for work in track(work_pkgs, disable=self.no_progress_bar):
|
||||
results.append(_process_and_match(work))
|
||||
else: # pragma: no cover
|
||||
with multiprocessing.Pool(processes=self.process_count) as pool:
|
||||
results = list(
|
||||
tqdm.tqdm(
|
||||
track(
|
||||
pool.imap_unordered(_process_and_match, work_pkgs),
|
||||
total=len(work_pkgs),
|
||||
disable=self.no_progress_bar,
|
||||
|
||||
@@ -5,7 +5,6 @@ from collections.abc import Generator
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
|
||||
import tqdm
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.auth.models import User
|
||||
@@ -20,6 +19,7 @@ from django.db import transaction
|
||||
from django.db.models.signals import m2m_changed
|
||||
from django.db.models.signals import post_save
|
||||
from filelock import FileLock
|
||||
from rich.progress import Progress
|
||||
|
||||
from documents.file_handling import create_source_path_directory
|
||||
from documents.management.commands.mixins import CryptMixin
|
||||
@@ -138,7 +138,7 @@ class Command(CryptMixin, BaseCommand):
|
||||
pre_check_maybe_not_empty()
|
||||
pre_check_manifest_exists()
|
||||
|
||||
def load_manifest_files(self) -> None:
|
||||
def load_manifest_files(self, progress: Progress) -> None:
|
||||
"""
|
||||
Loads manifest data from the various JSON files for parsing and loading the database
|
||||
"""
|
||||
@@ -148,10 +148,15 @@ class Command(CryptMixin, BaseCommand):
|
||||
self.manifest = json.load(infile)
|
||||
self.manifest_paths.append(main_manifest_path)
|
||||
|
||||
split_manifest_task = progress.add_task("Parsing split manifests")
|
||||
|
||||
for file in Path(self.source).glob("**/*-manifest.json"):
|
||||
progress.update(split_manifest_task, visible=True)
|
||||
with file.open() as infile:
|
||||
self.manifest += json.load(infile)
|
||||
self.manifest_paths.append(file)
|
||||
progress.advance(split_manifest_task)
|
||||
progress.update(split_manifest_task, total=1, completed=1)
|
||||
|
||||
def load_metadata(self) -> None:
|
||||
"""
|
||||
@@ -191,7 +196,7 @@ class Command(CryptMixin, BaseCommand):
|
||||
),
|
||||
)
|
||||
|
||||
def load_data_to_database(self) -> None:
|
||||
def load_data_to_database(self, progress: Progress) -> None:
|
||||
"""
|
||||
As the name implies, loads data from the JSON file(s) into the database
|
||||
"""
|
||||
@@ -201,7 +206,7 @@ class Command(CryptMixin, BaseCommand):
|
||||
ContentType.objects.all().delete()
|
||||
Permission.objects.all().delete()
|
||||
for manifest_path in self.manifest_paths:
|
||||
call_command("loaddata", manifest_path)
|
||||
call_command("loaddata", "-v", "0", manifest_path)
|
||||
except (FieldDoesNotExist, DeserializationError, IntegrityError) as e:
|
||||
self.stdout.write(self.style.ERROR("Database import failed"))
|
||||
if (
|
||||
@@ -234,55 +239,56 @@ class Command(CryptMixin, BaseCommand):
|
||||
self.manifest_paths = []
|
||||
self.manifest = []
|
||||
|
||||
self.pre_check()
|
||||
with Progress(disable=self.no_progress_bar) as progress:
|
||||
self.pre_check()
|
||||
|
||||
self.load_metadata()
|
||||
self.load_metadata()
|
||||
|
||||
self.load_manifest_files()
|
||||
self.load_manifest_files(progress)
|
||||
|
||||
self.check_manifest_validity()
|
||||
self.check_manifest_validity(progress)
|
||||
|
||||
self.decrypt_secret_fields()
|
||||
self.decrypt_secret_fields()
|
||||
|
||||
# see /src/documents/signals/handlers.py
|
||||
with (
|
||||
disable_signal(
|
||||
post_save,
|
||||
receiver=update_filename_and_move_files,
|
||||
sender=Document,
|
||||
),
|
||||
disable_signal(
|
||||
m2m_changed,
|
||||
receiver=update_filename_and_move_files,
|
||||
sender=Document.tags.through,
|
||||
),
|
||||
disable_signal(
|
||||
post_save,
|
||||
receiver=update_filename_and_move_files,
|
||||
sender=CustomFieldInstance,
|
||||
),
|
||||
disable_signal(
|
||||
post_save,
|
||||
receiver=check_paths_and_prune_custom_fields,
|
||||
sender=CustomField,
|
||||
),
|
||||
):
|
||||
if settings.AUDIT_LOG_ENABLED:
|
||||
auditlog.unregister(Document)
|
||||
auditlog.unregister(Correspondent)
|
||||
auditlog.unregister(Tag)
|
||||
auditlog.unregister(DocumentType)
|
||||
auditlog.unregister(Note)
|
||||
auditlog.unregister(CustomField)
|
||||
auditlog.unregister(CustomFieldInstance)
|
||||
# see /src/documents/signals/handlers.py
|
||||
with (
|
||||
disable_signal(
|
||||
post_save,
|
||||
receiver=update_filename_and_move_files,
|
||||
sender=Document,
|
||||
),
|
||||
disable_signal(
|
||||
m2m_changed,
|
||||
receiver=update_filename_and_move_files,
|
||||
sender=Document.tags.through,
|
||||
),
|
||||
disable_signal(
|
||||
post_save,
|
||||
receiver=update_filename_and_move_files,
|
||||
sender=CustomFieldInstance,
|
||||
),
|
||||
disable_signal(
|
||||
post_save,
|
||||
receiver=check_paths_and_prune_custom_fields,
|
||||
sender=CustomField,
|
||||
),
|
||||
):
|
||||
if settings.AUDIT_LOG_ENABLED:
|
||||
auditlog.unregister(Document)
|
||||
auditlog.unregister(Correspondent)
|
||||
auditlog.unregister(Tag)
|
||||
auditlog.unregister(DocumentType)
|
||||
auditlog.unregister(Note)
|
||||
auditlog.unregister(CustomField)
|
||||
auditlog.unregister(CustomFieldInstance)
|
||||
|
||||
# Fill up the database with whatever is in the manifest
|
||||
self.load_data_to_database()
|
||||
# Fill up the database with whatever is in the manifest
|
||||
self.load_data_to_database(progress)
|
||||
|
||||
if not self.data_only:
|
||||
self._import_files_from_manifest()
|
||||
else:
|
||||
self.stdout.write(self.style.NOTICE("Data only import completed"))
|
||||
if not self.data_only:
|
||||
self._import_files_from_manifest(progress)
|
||||
else:
|
||||
self.stdout.write(self.style.NOTICE("Data only import completed"))
|
||||
|
||||
self.stdout.write("Updating search index...")
|
||||
call_command(
|
||||
@@ -291,7 +297,7 @@ class Command(CryptMixin, BaseCommand):
|
||||
no_progress_bar=self.no_progress_bar,
|
||||
)
|
||||
|
||||
def check_manifest_validity(self) -> None:
|
||||
def check_manifest_validity(self, progress: Progress) -> None:
|
||||
"""
|
||||
Attempts to verify the manifest is valid. Namely checking the files
|
||||
referred to exist and the files can be read from
|
||||
@@ -335,45 +341,56 @@ class Command(CryptMixin, BaseCommand):
|
||||
f"Failed to read from archive file {doc_archive_path}",
|
||||
) from e
|
||||
|
||||
self.stdout.write("Checking the manifest")
|
||||
manifest_valid_task = progress.add_task(
|
||||
"Checking validity",
|
||||
total=None,
|
||||
visible=not self.data_only,
|
||||
)
|
||||
|
||||
# self.stdout.write("Checking the manifest")
|
||||
for record in self.manifest:
|
||||
# Only check if the document files exist if this is not data only
|
||||
# We don't care about documents for a data only import
|
||||
if not self.data_only and record["model"] == "documents.document":
|
||||
check_document_validity(record)
|
||||
progress.advance(manifest_valid_task)
|
||||
progress.update(manifest_valid_task, total=1, completed=1)
|
||||
|
||||
def _import_files_from_manifest(self) -> None:
|
||||
def _import_files_from_manifest(self, progress: Progress) -> None:
|
||||
settings.ORIGINALS_DIR.mkdir(parents=True, exist_ok=True)
|
||||
settings.THUMBNAIL_DIR.mkdir(parents=True, exist_ok=True)
|
||||
settings.ARCHIVE_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
self.stdout.write("Copy files into paperless...")
|
||||
# self.stdout.write("Copy files into paperless...")
|
||||
|
||||
manifest_documents = list(
|
||||
filter(lambda r: r["model"] == "documents.document", self.manifest),
|
||||
)
|
||||
copy_file_task = progress.add_task(
|
||||
"Copying files",
|
||||
total=len(manifest_documents),
|
||||
)
|
||||
with FileLock(settings.MEDIA_LOCK):
|
||||
for record in manifest_documents:
|
||||
document = Document.objects.get(pk=record["pk"])
|
||||
|
||||
for record in tqdm.tqdm(manifest_documents, disable=self.no_progress_bar):
|
||||
document = Document.objects.get(pk=record["pk"])
|
||||
doc_file = record[EXPORTER_FILE_NAME]
|
||||
document_path = self.source / doc_file
|
||||
|
||||
doc_file = record[EXPORTER_FILE_NAME]
|
||||
document_path = self.source / doc_file
|
||||
if EXPORTER_THUMBNAIL_NAME in record:
|
||||
thumb_file = record[EXPORTER_THUMBNAIL_NAME]
|
||||
thumbnail_path = (self.source / thumb_file).resolve()
|
||||
else:
|
||||
thumbnail_path = None
|
||||
|
||||
if EXPORTER_THUMBNAIL_NAME in record:
|
||||
thumb_file = record[EXPORTER_THUMBNAIL_NAME]
|
||||
thumbnail_path = (self.source / thumb_file).resolve()
|
||||
else:
|
||||
thumbnail_path = None
|
||||
if EXPORTER_ARCHIVE_NAME in record:
|
||||
archive_file = record[EXPORTER_ARCHIVE_NAME]
|
||||
archive_path = self.source / archive_file
|
||||
else:
|
||||
archive_path = None
|
||||
|
||||
if EXPORTER_ARCHIVE_NAME in record:
|
||||
archive_file = record[EXPORTER_ARCHIVE_NAME]
|
||||
archive_path = self.source / archive_file
|
||||
else:
|
||||
archive_path = None
|
||||
document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED
|
||||
|
||||
document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED
|
||||
|
||||
with FileLock(settings.MEDIA_LOCK):
|
||||
if Path(document.source_path).is_file():
|
||||
raise FileExistsError(document.source_path)
|
||||
|
||||
@@ -406,7 +423,8 @@ class Command(CryptMixin, BaseCommand):
|
||||
# archived files
|
||||
copy_file_with_basic_stats(archive_path, document.archive_path)
|
||||
|
||||
document.save()
|
||||
document.save()
|
||||
progress.advance(copy_file_task)
|
||||
|
||||
def decrypt_secret_fields(self) -> None:
|
||||
"""
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import logging
|
||||
|
||||
import tqdm
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db.models.signals import post_save
|
||||
from rich.progress import track
|
||||
|
||||
from documents.management.commands.mixins import ProgressBarMixin
|
||||
from documents.models import Document
|
||||
@@ -17,9 +17,10 @@ class Command(ProgressBarMixin, BaseCommand):
|
||||
def handle(self, *args, **options):
|
||||
self.handle_progress_bar_mixin(**options)
|
||||
logging.getLogger().handlers[0].level = logging.ERROR
|
||||
|
||||
for document in tqdm.tqdm(
|
||||
Document.objects.all(),
|
||||
qs = Document.objects.all()
|
||||
for document in track(
|
||||
qs,
|
||||
total=qs.count(),
|
||||
disable=self.no_progress_bar,
|
||||
):
|
||||
post_save.send(Document, instance=document, created=False)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import logging
|
||||
|
||||
import tqdm
|
||||
from django.core.management.base import BaseCommand
|
||||
from rich.progress import track
|
||||
|
||||
from documents.classifier import load_classifier
|
||||
from documents.management.commands.mixins import ProgressBarMixin
|
||||
@@ -84,7 +84,11 @@ class Command(ProgressBarMixin, BaseCommand):
|
||||
|
||||
classifier = load_classifier()
|
||||
|
||||
for document in tqdm.tqdm(documents, disable=self.no_progress_bar):
|
||||
for document in track(
|
||||
documents,
|
||||
total=documents.count(),
|
||||
disable=self.no_progress_bar,
|
||||
):
|
||||
if options["correspondent"]:
|
||||
set_correspondent(
|
||||
sender=None,
|
||||
|
||||
@@ -2,9 +2,9 @@ import logging
|
||||
import multiprocessing
|
||||
import shutil
|
||||
|
||||
import tqdm
|
||||
from django import db
|
||||
from django.core.management.base import BaseCommand
|
||||
from rich.progress import track
|
||||
|
||||
from documents.management.commands.mixins import MultiProcessMixin
|
||||
from documents.management.commands.mixins import ProgressBarMixin
|
||||
@@ -76,7 +76,7 @@ class Command(MultiProcessMixin, ProgressBarMixin, BaseCommand):
|
||||
else: # pragma: no cover
|
||||
with multiprocessing.Pool(processes=self.process_count) as pool:
|
||||
list(
|
||||
tqdm.tqdm(
|
||||
track(
|
||||
pool.imap_unordered(_process_document, ids),
|
||||
total=len(ids),
|
||||
disable=self.no_progress_bar,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from auditlog.models import LogEntry
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db import transaction
|
||||
from tqdm import tqdm
|
||||
from rich.progress import track
|
||||
|
||||
from documents.management.commands.mixins import ProgressBarMixin
|
||||
|
||||
@@ -19,7 +19,10 @@ class Command(BaseCommand, ProgressBarMixin):
|
||||
def handle(self, **options):
|
||||
self.handle_progress_bar_mixin(**options)
|
||||
with transaction.atomic():
|
||||
for log_entry in tqdm(LogEntry.objects.all(), disable=self.no_progress_bar):
|
||||
for log_entry in track(
|
||||
LogEntry.objects.all(),
|
||||
disable=self.no_progress_bar,
|
||||
):
|
||||
model_class = log_entry.content_type.model_class()
|
||||
# use global_objects for SoftDeleteModel
|
||||
objects = (
|
||||
@@ -32,7 +35,7 @@ class Command(BaseCommand, ProgressBarMixin):
|
||||
and not objects.filter(pk=log_entry.object_id).exists()
|
||||
):
|
||||
log_entry.delete()
|
||||
tqdm.write(
|
||||
self.stdout.write(
|
||||
self.style.NOTICE(
|
||||
f"Deleted audit log entry for {model_class.__name__} #{log_entry.object_id}",
|
||||
),
|
||||
|
||||
@@ -5,7 +5,7 @@ from pathlib import Path
|
||||
from typing import Final
|
||||
|
||||
from django.conf import settings
|
||||
from tqdm import tqdm
|
||||
from rich.progress import track
|
||||
|
||||
from documents.models import Document
|
||||
|
||||
@@ -68,7 +68,9 @@ def check_sanity(*, progress=False) -> SanityCheckMessages:
|
||||
if lockfile in present_files:
|
||||
present_files.remove(lockfile)
|
||||
|
||||
for doc in tqdm(Document.global_objects.all(), disable=not progress):
|
||||
qs = Document.global_objects.all()
|
||||
|
||||
for doc in track(qs, total=qs.count(), disable=not progress):
|
||||
# Check sanity of the thumbnail
|
||||
thumbnail_path: Final[Path] = Path(doc.thumbnail_path).resolve()
|
||||
if not thumbnail_path.exists() or not thumbnail_path.is_file():
|
||||
|
||||
@@ -6,7 +6,6 @@ from datetime import timedelta
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
import tqdm
|
||||
from celery import Task
|
||||
from celery import shared_task
|
||||
from django.conf import settings
|
||||
@@ -16,6 +15,7 @@ from django.db import transaction
|
||||
from django.db.models.signals import post_save
|
||||
from django.utils import timezone
|
||||
from filelock import FileLock
|
||||
from rich.progress import track
|
||||
from whoosh.writing import AsyncWriter
|
||||
|
||||
from documents import index
|
||||
@@ -69,7 +69,12 @@ def index_reindex(*, progress_bar_disable=False):
|
||||
ix = index.open_index(recreate=True)
|
||||
|
||||
with AsyncWriter(ix) as writer:
|
||||
for document in tqdm.tqdm(documents, disable=progress_bar_disable):
|
||||
for document in track(
|
||||
documents,
|
||||
total=documents.count(),
|
||||
description="Indexing...",
|
||||
disable=progress_bar_disable,
|
||||
):
|
||||
index.update_document(writer, document)
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ from django.contrib.auth.models import User
|
||||
from django.core.management import call_command
|
||||
from django.core.management.base import CommandError
|
||||
from django.test import TestCase
|
||||
from rich.progress import Progress
|
||||
|
||||
from documents.management.commands.document_importer import Command
|
||||
from documents.models import Document
|
||||
@@ -126,15 +127,21 @@ class TestCommandImport(
|
||||
},
|
||||
]
|
||||
cmd.data_only = False
|
||||
with self.assertRaises(CommandError) as cm:
|
||||
cmd.check_manifest_validity()
|
||||
with (
|
||||
self.assertRaises(CommandError) as cm,
|
||||
Progress(disable=True) as progress,
|
||||
):
|
||||
cmd.check_manifest_validity(progress)
|
||||
self.assertInt("Failed to read from original file", str(cm.exception))
|
||||
|
||||
original_path.chmod(0o444)
|
||||
archive_path.chmod(0o222)
|
||||
|
||||
with self.assertRaises(CommandError) as cm:
|
||||
cmd.check_manifest_validity()
|
||||
with (
|
||||
self.assertRaises(CommandError) as cm,
|
||||
Progress(disable=True) as progress,
|
||||
):
|
||||
cmd.check_manifest_validity(progress)
|
||||
self.assertInt("Failed to read from archive file", str(cm.exception))
|
||||
|
||||
def test_import_source_not_existing(self):
|
||||
|
||||
@@ -8,7 +8,7 @@ class TestMigrateWorkflow(TestMigrations):
|
||||
dependencies = (
|
||||
(
|
||||
"paperless_mail",
|
||||
"0030_mailrule_stop_processing",
|
||||
"0029_mailrule_pdf_layout",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: paperless-ngx\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-02-24 09:00-0800\n"
|
||||
"POT-Creation-Date: 2025-02-11 18:43-0800\n"
|
||||
"PO-Revision-Date: 2022-02-17 04:17\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: English\n"
|
||||
@@ -89,20 +89,20 @@ msgstr ""
|
||||
msgid "Automatic"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:67 documents/models.py:433 documents/models.py:1502
|
||||
#: documents/models.py:67 documents/models.py:433 documents/models.py:1498
|
||||
#: paperless_mail/models.py:23 paperless_mail/models.py:143
|
||||
msgid "name"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:69 documents/models.py:1086
|
||||
#: documents/models.py:69 documents/models.py:1085
|
||||
msgid "match"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:72 documents/models.py:1089
|
||||
#: documents/models.py:72 documents/models.py:1088
|
||||
msgid "matching algorithm"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:77 documents/models.py:1094
|
||||
#: documents/models.py:77 documents/models.py:1093
|
||||
msgid "is insensitive"
|
||||
msgstr ""
|
||||
|
||||
@@ -256,7 +256,7 @@ msgid "The position of this document in your physical document archive."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:295 documents/models.py:737 documents/models.py:791
|
||||
#: documents/models.py:1545
|
||||
#: documents/models.py:1541
|
||||
msgid "document"
|
||||
msgstr ""
|
||||
|
||||
@@ -276,7 +276,7 @@ msgstr ""
|
||||
msgid "warning"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:387 paperless_mail/models.py:371
|
||||
#: documents/models.py:387 paperless_mail/models.py:363
|
||||
msgid "error"
|
||||
msgstr ""
|
||||
|
||||
@@ -320,11 +320,11 @@ msgstr ""
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:420 documents/models.py:1038
|
||||
#: documents/models.py:420 documents/models.py:1037
|
||||
msgid "Created"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:421 documents/models.py:1037
|
||||
#: documents/models.py:421 documents/models.py:1036
|
||||
msgid "Added"
|
||||
msgstr ""
|
||||
|
||||
@@ -812,381 +812,377 @@ msgstr ""
|
||||
msgid "Mail Fetch"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1034
|
||||
msgid "Web UI"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1039
|
||||
#: documents/models.py:1038
|
||||
msgid "Modified"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1040
|
||||
#: documents/models.py:1039
|
||||
msgid "Custom Field"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1043
|
||||
#: documents/models.py:1042
|
||||
msgid "Workflow Trigger Type"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1055
|
||||
#: documents/models.py:1054
|
||||
msgid "filter path"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1060
|
||||
#: documents/models.py:1059
|
||||
msgid ""
|
||||
"Only consume documents with a path that matches this if specified. Wildcards "
|
||||
"specified as * are allowed. Case insensitive."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1067
|
||||
#: documents/models.py:1066
|
||||
msgid "filter filename"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1072 paperless_mail/models.py:200
|
||||
#: documents/models.py:1071 paperless_mail/models.py:200
|
||||
msgid ""
|
||||
"Only consume documents which entirely match this filename if specified. "
|
||||
"Wildcards such as *.pdf or *invoice* are allowed. Case insensitive."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1083
|
||||
#: documents/models.py:1082
|
||||
msgid "filter documents from this mail rule"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1099
|
||||
#: documents/models.py:1098
|
||||
msgid "has these tag(s)"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1107
|
||||
#: documents/models.py:1106
|
||||
msgid "has this document type"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1115
|
||||
#: documents/models.py:1114
|
||||
msgid "has this correspondent"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1119
|
||||
#: documents/models.py:1118
|
||||
msgid "schedule offset days"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1122
|
||||
#: documents/models.py:1121
|
||||
msgid "The number of days to offset the schedule trigger by."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1127
|
||||
#: documents/models.py:1126
|
||||
msgid "schedule is recurring"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1130
|
||||
#: documents/models.py:1129
|
||||
msgid "If the schedule should be recurring."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1135
|
||||
#: documents/models.py:1134
|
||||
msgid "schedule recurring delay in days"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1139
|
||||
#: documents/models.py:1138
|
||||
msgid "The number of days between recurring schedule triggers."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1144
|
||||
#: documents/models.py:1143
|
||||
msgid "schedule date field"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1149
|
||||
#: documents/models.py:1148
|
||||
msgid "The field to check for a schedule trigger."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1158
|
||||
#: documents/models.py:1157
|
||||
msgid "schedule date custom field"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1162
|
||||
#: documents/models.py:1161
|
||||
msgid "workflow trigger"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1163
|
||||
#: documents/models.py:1162
|
||||
msgid "workflow triggers"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1171
|
||||
#: documents/models.py:1170
|
||||
msgid "email subject"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1175
|
||||
#: documents/models.py:1174
|
||||
msgid ""
|
||||
"The subject of the email, can include some placeholders, see documentation."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1181
|
||||
#: documents/models.py:1180
|
||||
msgid "email body"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1184
|
||||
#: documents/models.py:1183
|
||||
msgid ""
|
||||
"The body (message) of the email, can include some placeholders, see "
|
||||
"documentation."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1190
|
||||
#: documents/models.py:1189
|
||||
msgid "emails to"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1193
|
||||
#: documents/models.py:1192
|
||||
msgid "The destination email addresses, comma separated."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1199
|
||||
#: documents/models.py:1198
|
||||
msgid "include document in email"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1210
|
||||
#: documents/models.py:1207
|
||||
msgid "webhook url"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1213
|
||||
#: documents/models.py:1209
|
||||
msgid "The destination URL for the notification."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1218
|
||||
#: documents/models.py:1214
|
||||
msgid "use parameters"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1223
|
||||
#: documents/models.py:1219
|
||||
msgid "send as JSON"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1227
|
||||
#: documents/models.py:1223
|
||||
msgid "webhook parameters"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1230
|
||||
#: documents/models.py:1226
|
||||
msgid "The parameters to send with the webhook URL if body not used."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1234
|
||||
#: documents/models.py:1230
|
||||
msgid "webhook body"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1237
|
||||
#: documents/models.py:1233
|
||||
msgid "The body to send with the webhook URL if parameters not used."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1241
|
||||
#: documents/models.py:1237
|
||||
msgid "webhook headers"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1244
|
||||
#: documents/models.py:1240
|
||||
msgid "The headers to send with the webhook URL."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1249
|
||||
#: documents/models.py:1245
|
||||
msgid "include document in webhook"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1260
|
||||
#: documents/models.py:1256
|
||||
msgid "Assignment"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1264
|
||||
#: documents/models.py:1260
|
||||
msgid "Removal"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1268 documents/templates/account/password_reset.html:15
|
||||
#: documents/models.py:1264 documents/templates/account/password_reset.html:15
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1272
|
||||
#: documents/models.py:1268
|
||||
msgid "Webhook"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1276
|
||||
#: documents/models.py:1272
|
||||
msgid "Workflow Action Type"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1282
|
||||
#: documents/models.py:1278
|
||||
msgid "assign title"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1287
|
||||
#: documents/models.py:1283
|
||||
msgid ""
|
||||
"Assign a document title, can include some placeholders, see documentation."
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1296 paperless_mail/models.py:274
|
||||
#: documents/models.py:1292 paperless_mail/models.py:274
|
||||
msgid "assign this tag"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1305 paperless_mail/models.py:282
|
||||
#: documents/models.py:1301 paperless_mail/models.py:282
|
||||
msgid "assign this document type"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1314 paperless_mail/models.py:296
|
||||
#: documents/models.py:1310 paperless_mail/models.py:296
|
||||
msgid "assign this correspondent"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1323
|
||||
#: documents/models.py:1319
|
||||
msgid "assign this storage path"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1332
|
||||
#: documents/models.py:1328
|
||||
msgid "assign this owner"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1339
|
||||
#: documents/models.py:1335
|
||||
msgid "grant view permissions to these users"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1346
|
||||
#: documents/models.py:1342
|
||||
msgid "grant view permissions to these groups"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1353
|
||||
#: documents/models.py:1349
|
||||
msgid "grant change permissions to these users"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1360
|
||||
#: documents/models.py:1356
|
||||
msgid "grant change permissions to these groups"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1367
|
||||
#: documents/models.py:1363
|
||||
msgid "assign these custom fields"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1374
|
||||
#: documents/models.py:1370
|
||||
msgid "remove these tag(s)"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1379
|
||||
#: documents/models.py:1375
|
||||
msgid "remove all tags"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1386
|
||||
#: documents/models.py:1382
|
||||
msgid "remove these document type(s)"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1391
|
||||
#: documents/models.py:1387
|
||||
msgid "remove all document types"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1398
|
||||
#: documents/models.py:1394
|
||||
msgid "remove these correspondent(s)"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1403
|
||||
#: documents/models.py:1399
|
||||
msgid "remove all correspondents"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1410
|
||||
#: documents/models.py:1406
|
||||
msgid "remove these storage path(s)"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1415
|
||||
#: documents/models.py:1411
|
||||
msgid "remove all storage paths"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1422
|
||||
#: documents/models.py:1418
|
||||
msgid "remove these owner(s)"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1427
|
||||
#: documents/models.py:1423
|
||||
msgid "remove all owners"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1434
|
||||
#: documents/models.py:1430
|
||||
msgid "remove view permissions for these users"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1441
|
||||
#: documents/models.py:1437
|
||||
msgid "remove view permissions for these groups"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1448
|
||||
#: documents/models.py:1444
|
||||
msgid "remove change permissions for these users"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1455
|
||||
#: documents/models.py:1451
|
||||
msgid "remove change permissions for these groups"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1460
|
||||
#: documents/models.py:1456
|
||||
msgid "remove all permissions"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1467
|
||||
#: documents/models.py:1463
|
||||
msgid "remove these custom fields"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1472
|
||||
#: documents/models.py:1468
|
||||
msgid "remove all custom fields"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1481
|
||||
#: documents/models.py:1477
|
||||
msgid "email"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1490
|
||||
#: documents/models.py:1486
|
||||
msgid "webhook"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1494
|
||||
#: documents/models.py:1490
|
||||
msgid "workflow action"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1495
|
||||
#: documents/models.py:1491
|
||||
msgid "workflow actions"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1504 paperless_mail/models.py:145
|
||||
#: documents/models.py:1500 paperless_mail/models.py:145
|
||||
msgid "order"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1510
|
||||
#: documents/models.py:1506
|
||||
msgid "triggers"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1517
|
||||
#: documents/models.py:1513
|
||||
msgid "actions"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1520 paperless_mail/models.py:154
|
||||
#: documents/models.py:1516 paperless_mail/models.py:154
|
||||
msgid "enabled"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1531
|
||||
#: documents/models.py:1527
|
||||
msgid "workflow"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1535
|
||||
#: documents/models.py:1531
|
||||
msgid "workflow trigger type"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1549
|
||||
#: documents/models.py:1545
|
||||
msgid "date run"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1555
|
||||
#: documents/models.py:1551
|
||||
msgid "workflow run"
|
||||
msgstr ""
|
||||
|
||||
#: documents/models.py:1556
|
||||
#: documents/models.py:1552
|
||||
msgid "workflow runs"
|
||||
msgstr ""
|
||||
|
||||
#: documents/serialisers.py:128
|
||||
#: documents/serialisers.py:127
|
||||
#, python-format
|
||||
msgid "Invalid regular expression: %(error)s"
|
||||
msgstr ""
|
||||
|
||||
#: documents/serialisers.py:554
|
||||
#: documents/serialisers.py:553
|
||||
msgid "Invalid color."
|
||||
msgstr ""
|
||||
|
||||
#: documents/serialisers.py:1570
|
||||
#: documents/serialisers.py:1554
|
||||
#, python-format
|
||||
msgid "File type %(type)s not supported"
|
||||
msgstr ""
|
||||
|
||||
#: documents/serialisers.py:1659
|
||||
#: documents/serialisers.py:1643
|
||||
msgid "Invalid variable detected."
|
||||
msgstr ""
|
||||
|
||||
@@ -1406,23 +1402,17 @@ msgstr ""
|
||||
msgid "As a final step, please complete the following form:"
|
||||
msgstr ""
|
||||
|
||||
#: documents/validators.py:24
|
||||
#: documents/validators.py:17
|
||||
#, python-brace-format
|
||||
msgid "Unable to parse URI {value}, missing scheme"
|
||||
msgstr ""
|
||||
|
||||
#: documents/validators.py:29
|
||||
#: documents/validators.py:22
|
||||
#, python-brace-format
|
||||
msgid "Unable to parse URI {value}, missing net location or path"
|
||||
msgstr ""
|
||||
|
||||
#: documents/validators.py:36
|
||||
msgid ""
|
||||
"URI scheme '{parts.scheme}' is not allowed. Allowed schemes: {', '."
|
||||
"join(allowed_schemes)}"
|
||||
msgstr ""
|
||||
|
||||
#: documents/validators.py:45
|
||||
#: documents/validators.py:27
|
||||
#, python-brace-format
|
||||
msgid "Unable to parse URI {value}"
|
||||
msgstr ""
|
||||
@@ -1711,7 +1701,7 @@ msgstr ""
|
||||
msgid "Chinese Traditional"
|
||||
msgstr ""
|
||||
|
||||
#: paperless/urls.py:369
|
||||
#: paperless/urls.py:364
|
||||
msgid "Paperless-ngx administration"
|
||||
msgstr ""
|
||||
|
||||
@@ -1943,7 +1933,7 @@ msgstr ""
|
||||
msgid "account"
|
||||
msgstr ""
|
||||
|
||||
#: paperless_mail/models.py:157 paperless_mail/models.py:326
|
||||
#: paperless_mail/models.py:157 paperless_mail/models.py:318
|
||||
msgid "folder"
|
||||
msgstr ""
|
||||
|
||||
@@ -2035,32 +2025,22 @@ msgstr ""
|
||||
msgid "Assign the rule owner to documents"
|
||||
msgstr ""
|
||||
|
||||
#: paperless_mail/models.py:305
|
||||
msgid "Stop processing further rules"
|
||||
msgstr ""
|
||||
|
||||
#: paperless_mail/models.py:308
|
||||
msgid ""
|
||||
"If True, no further rules will be processed after this one if any document "
|
||||
"is queued."
|
||||
msgstr ""
|
||||
|
||||
#: paperless_mail/models.py:334
|
||||
#: paperless_mail/models.py:326
|
||||
msgid "uid"
|
||||
msgstr ""
|
||||
|
||||
#: paperless_mail/models.py:342
|
||||
#: paperless_mail/models.py:334
|
||||
msgid "subject"
|
||||
msgstr ""
|
||||
|
||||
#: paperless_mail/models.py:350
|
||||
#: paperless_mail/models.py:342
|
||||
msgid "received"
|
||||
msgstr ""
|
||||
|
||||
#: paperless_mail/models.py:357
|
||||
#: paperless_mail/models.py:349
|
||||
msgid "processed"
|
||||
msgstr ""
|
||||
|
||||
#: paperless_mail/models.py:363
|
||||
#: paperless_mail/models.py:355
|
||||
msgid "status"
|
||||
msgstr ""
|
||||
|
||||
@@ -571,11 +571,6 @@ class MailAccountHandler(LoggingMixin):
|
||||
rule,
|
||||
supports_gmail_labels=supports_gmail_labels,
|
||||
)
|
||||
if total_processed_files > 0 and rule.stop_processing:
|
||||
self.log.debug(
|
||||
f"Rule {rule}: Stopping processing rules due to stop_processing flag",
|
||||
)
|
||||
break
|
||||
except Exception as e:
|
||||
self.log.exception(
|
||||
f"Rule {rule}: Error while processing rule: {e}",
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
# Generated by Django 5.1.6 on 2025-02-24 16:07
|
||||
|
||||
from django.db import migrations
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("paperless_mail", "0029_mailrule_pdf_layout"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="mailrule",
|
||||
name="stop_processing",
|
||||
field=models.BooleanField(
|
||||
default=False,
|
||||
help_text="If True, no further rules will be processed after this one if any document is consumed.",
|
||||
verbose_name="Stop processing further rules",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -301,14 +301,6 @@ class MailRule(document_models.ModelWithOwner):
|
||||
default=True,
|
||||
)
|
||||
|
||||
stop_processing = models.BooleanField(
|
||||
_("Stop processing further rules"),
|
||||
default=False,
|
||||
help_text=_(
|
||||
"If True, no further rules will be processed after this one if any document is queued.",
|
||||
),
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.account.name}.{self.name}"
|
||||
|
||||
|
||||
@@ -101,7 +101,6 @@ class MailRuleSerializer(OwnedObjectSerializer):
|
||||
"user_can_change",
|
||||
"permissions",
|
||||
"set_permissions",
|
||||
"stop_processing",
|
||||
]
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
|
||||
@@ -1671,39 +1671,6 @@ class TestTasks(TestCase):
|
||||
result = tasks.process_mail_accounts(account_ids=[account_b.id])
|
||||
self.assertIn("No new", result)
|
||||
|
||||
@mock.patch("paperless_mail.tasks.MailAccountHandler.handle_mail_account")
|
||||
def test_rule_with_stop_processing(self, m):
|
||||
"""
|
||||
GIVEN:
|
||||
- Mail account with a rule with stop_processing=True
|
||||
WHEN:
|
||||
- Mail account is processed
|
||||
THEN:
|
||||
- Should only process the first rule
|
||||
"""
|
||||
m.side_effect = lambda account: 6
|
||||
|
||||
account = MailAccount.objects.create(
|
||||
name="A",
|
||||
imap_server="A",
|
||||
username="A",
|
||||
password="A",
|
||||
)
|
||||
MailRule.objects.create(
|
||||
name="A",
|
||||
account=account,
|
||||
stop_processing=True,
|
||||
)
|
||||
MailRule.objects.create(
|
||||
name="B",
|
||||
account=account,
|
||||
)
|
||||
|
||||
result = tasks.process_mail_accounts()
|
||||
|
||||
self.assertEqual(m.call_count, 1)
|
||||
self.assertIn("Added 6", result)
|
||||
|
||||
|
||||
class TestMailAccountTestView(APITestCase):
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user