feature:warehouse

This commit is contained in:
hungdztrau123 2024-05-15 15:46:12 +07:00
parent 2f20dac956
commit c2eebe808b
6 changed files with 125 additions and 0 deletions

View File

@ -19,6 +19,7 @@ from documents.models import Log
from documents.models import ShareLink from documents.models import ShareLink
from documents.models import StoragePath from documents.models import StoragePath
from documents.models import Tag from documents.models import Tag
from documents.models import Warehouse
CHAR_KWARGS = ["istartswith", "iendswith", "icontains", "iexact"] CHAR_KWARGS = ["istartswith", "iendswith", "icontains", "iexact"]
ID_KWARGS = ["in", "exact"] ID_KWARGS = ["in", "exact"]
@ -257,3 +258,16 @@ class ObjectOwnedOrGrantedPermissionsFilter(ObjectPermissionsFilter):
objects_owned = queryset.filter(owner=request.user) objects_owned = queryset.filter(owner=request.user)
objects_unowned = queryset.filter(owner__isnull=True) objects_unowned = queryset.filter(owner__isnull=True)
return objects_with_perms | objects_owned | objects_unowned return objects_with_perms | objects_owned | objects_unowned
class WarehouseFilterSet(FilterSet):
class Meta:
model = Warehouse
fields = {
"id": ID_KWARGS,
"name": CHAR_KWARGS,
"type": CHAR_KWARGS,
"parent_warehouse": ID_KWARGS,
}

View File

@ -0,0 +1,30 @@
# Generated by Django 4.2.11 on 2024-05-15 04:18
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('documents', '1046_workflowaction_remove_all_correspondents_and_more'),
]
operations = [
migrations.CreateModel(
name='Warehouse',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=256, unique=True, verbose_name='name')),
('type', models.CharField(blank=True, choices=[(1, 'Warehouse'), (2, 'Shelf'), (3, 'Boxcase')], default=1, max_length=20, null=True)),
('owner', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='owner')),
('parent_warehouse', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='parent_warehouses', to='documents.warehouse')),
],
options={
'verbose_name': 'warehouse',
'verbose_name_plural': 'warehouses',
},
),
]

View File

@ -1237,3 +1237,30 @@ class Workflow(models.Model):
def __str__(self): def __str__(self):
return f"Workflow: {self.name}" return f"Workflow: {self.name}"
class Warehouse(ModelWithOwner):
WAREHOUSE = "Warehouse"
SHELF = "Shelf"
BOXCASE = "Boxcase"
TYPE_WAREHOUSE = (
(WAREHOUSE, _("Warehouse")),
(SHELF, _("Shelf")),
(BOXCASE, _("Boxcase")),
)
name = models.CharField(_("name"), max_length=256, unique=True)
type = models.CharField(max_length=20, null=True, blank=True,
choices=TYPE_WAREHOUSE,
default=WAREHOUSE,)
parent_warehouse = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name="parent_warehouses" )
class Meta:
verbose_name = _("warehouse")
verbose_name_plural = _("warehouses")
def __str__(self):
return self.name

View File

@ -45,6 +45,7 @@ from documents.models import UiSettings
from documents.models import Workflow from documents.models import Workflow
from documents.models import WorkflowAction from documents.models import WorkflowAction
from documents.models import WorkflowTrigger from documents.models import WorkflowTrigger
from documents.models import Warehouse
from documents.parsers import is_mime_type_supported from documents.parsers import is_mime_type_supported
from documents.permissions import get_groups_with_only_permission from documents.permissions import get_groups_with_only_permission
from documents.permissions import set_permissions_for_object from documents.permissions import set_permissions_for_object
@ -1384,6 +1385,7 @@ class BulkEditObjectsSerializer(SerializerWithPerms, SetPermissionsMixin):
"correspondents", "correspondents",
"document_types", "document_types",
"storage_paths", "storage_paths",
"warehouses",
], ],
label="Object Type", label="Object Type",
write_only=True, write_only=True,
@ -1428,6 +1430,8 @@ class BulkEditObjectsSerializer(SerializerWithPerms, SetPermissionsMixin):
object_class = DocumentType object_class = DocumentType
elif object_type == "storage_paths": elif object_type == "storage_paths":
object_class = StoragePath object_class = StoragePath
elif object_type == "warehouses":
object_class = Warehouse
return object_class return object_class
def _validate_objects(self, objects, object_type): def _validate_objects(self, objects, object_type):
@ -1740,3 +1744,22 @@ class WorkflowSerializer(serializers.ModelSerializer):
self.prune_triggers_and_actions() self.prune_triggers_and_actions()
return instance return instance
class WarehouseSerializer(MatchingModelSerializer, OwnedObjectSerializer):
parent_warehouse_reference = serializers.SerializerMethodField()
class Meta:
model = Warehouse
fields = '__all__'
def get_parent_warehouse_reference(self, obj):
if obj.parent_warehouse:
return WarehouseSerializer(obj.parent_warehouse).data
return None

View File

@ -99,6 +99,8 @@ from documents.filters import ObjectOwnedOrGrantedPermissionsFilter
from documents.filters import ShareLinkFilterSet from documents.filters import ShareLinkFilterSet
from documents.filters import StoragePathFilterSet from documents.filters import StoragePathFilterSet
from documents.filters import TagFilterSet from documents.filters import TagFilterSet
from documents.filters import WarehouseFilterSet
from documents.matching import match_correspondents from documents.matching import match_correspondents
from documents.matching import match_document_types from documents.matching import match_document_types
from documents.matching import match_storage_paths from documents.matching import match_storage_paths
@ -117,6 +119,8 @@ from documents.models import UiSettings
from documents.models import Workflow from documents.models import Workflow
from documents.models import WorkflowAction from documents.models import WorkflowAction
from documents.models import WorkflowTrigger from documents.models import WorkflowTrigger
from documents.models import Warehouse
from documents.parsers import get_parser_class_for_mime_type from documents.parsers import get_parser_class_for_mime_type
from documents.parsers import parse_date_generator from documents.parsers import parse_date_generator
from documents.permissions import PaperlessAdminPermissions from documents.permissions import PaperlessAdminPermissions
@ -144,6 +148,8 @@ from documents.serialisers import UiSettingsViewSerializer
from documents.serialisers import WorkflowActionSerializer from documents.serialisers import WorkflowActionSerializer
from documents.serialisers import WorkflowSerializer from documents.serialisers import WorkflowSerializer
from documents.serialisers import WorkflowTriggerSerializer from documents.serialisers import WorkflowTriggerSerializer
from documents.serialisers import WarehouseSerializer
from documents.signals import document_updated from documents.signals import document_updated
from documents.tasks import consume_file from documents.tasks import consume_file
from paperless import version from paperless import version
@ -1749,3 +1755,24 @@ class SystemStatusView(PassUserMixin):
}, },
}, },
) )
class WarehouseViewSet(ModelViewSet):
model = Warehouse
queryset = Warehouse.objects.select_related("owner").order_by(
Lower("name"),
)
serializer_class = WarehouseSerializer
pagination_class = StandardPagination
permission_classes = (IsAuthenticated, PaperlessObjectPermissions)
filter_backends = (
DjangoFilterBackend,
OrderingFilter,
ObjectOwnedOrGrantedPermissionsFilter,
)
filterset_class = WarehouseFilterSet
ordering_fields = ("name", "type", "parent_warehouse")

View File

@ -40,6 +40,7 @@ from documents.views import UnifiedSearchViewSet
from documents.views import WorkflowActionViewSet from documents.views import WorkflowActionViewSet
from documents.views import WorkflowTriggerViewSet from documents.views import WorkflowTriggerViewSet
from documents.views import WorkflowViewSet from documents.views import WorkflowViewSet
from documents.views import WarehouseViewSet
from paperless.consumers import StatusConsumer from paperless.consumers import StatusConsumer
from paperless.views import ApplicationConfigurationViewSet from paperless.views import ApplicationConfigurationViewSet
from paperless.views import DisconnectSocialAccountView from paperless.views import DisconnectSocialAccountView
@ -53,6 +54,7 @@ from paperless_mail.views import MailAccountTestView
from paperless_mail.views import MailAccountViewSet from paperless_mail.views import MailAccountViewSet
from paperless_mail.views import MailRuleViewSet from paperless_mail.views import MailRuleViewSet
api_router = DefaultRouter() api_router = DefaultRouter()
api_router.register(r"correspondents", CorrespondentViewSet) api_router.register(r"correspondents", CorrespondentViewSet)
api_router.register(r"document_types", DocumentTypeViewSet) api_router.register(r"document_types", DocumentTypeViewSet)
@ -72,9 +74,11 @@ api_router.register(r"workflow_actions", WorkflowActionViewSet)
api_router.register(r"workflows", WorkflowViewSet) api_router.register(r"workflows", WorkflowViewSet)
api_router.register(r"custom_fields", CustomFieldViewSet) api_router.register(r"custom_fields", CustomFieldViewSet)
api_router.register(r"config", ApplicationConfigurationViewSet) api_router.register(r"config", ApplicationConfigurationViewSet)
api_router.register(r"warehouses", WarehouseViewSet)
urlpatterns = [ urlpatterns = [
re_path( re_path(
r"^api/", r"^api/",
include( include(