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 StoragePath
from documents.models import Tag
from documents.models import Warehouse
CHAR_KWARGS = ["istartswith", "iendswith", "icontains", "iexact"]
ID_KWARGS = ["in", "exact"]
@ -257,3 +258,16 @@ class ObjectOwnedOrGrantedPermissionsFilter(ObjectPermissionsFilter):
objects_owned = queryset.filter(owner=request.user)
objects_unowned = queryset.filter(owner__isnull=True)
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):
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 WorkflowAction
from documents.models import WorkflowTrigger
from documents.models import Warehouse
from documents.parsers import is_mime_type_supported
from documents.permissions import get_groups_with_only_permission
from documents.permissions import set_permissions_for_object
@ -1384,6 +1385,7 @@ class BulkEditObjectsSerializer(SerializerWithPerms, SetPermissionsMixin):
"correspondents",
"document_types",
"storage_paths",
"warehouses",
],
label="Object Type",
write_only=True,
@ -1428,6 +1430,8 @@ class BulkEditObjectsSerializer(SerializerWithPerms, SetPermissionsMixin):
object_class = DocumentType
elif object_type == "storage_paths":
object_class = StoragePath
elif object_type == "warehouses":
object_class = Warehouse
return object_class
def _validate_objects(self, objects, object_type):
@ -1740,3 +1744,22 @@ class WorkflowSerializer(serializers.ModelSerializer):
self.prune_triggers_and_actions()
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 StoragePathFilterSet
from documents.filters import TagFilterSet
from documents.filters import WarehouseFilterSet
from documents.matching import match_correspondents
from documents.matching import match_document_types
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 WorkflowAction
from documents.models import WorkflowTrigger
from documents.models import Warehouse
from documents.parsers import get_parser_class_for_mime_type
from documents.parsers import parse_date_generator
from documents.permissions import PaperlessAdminPermissions
@ -144,6 +148,8 @@ from documents.serialisers import UiSettingsViewSerializer
from documents.serialisers import WorkflowActionSerializer
from documents.serialisers import WorkflowSerializer
from documents.serialisers import WorkflowTriggerSerializer
from documents.serialisers import WarehouseSerializer
from documents.signals import document_updated
from documents.tasks import consume_file
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 WorkflowTriggerViewSet
from documents.views import WorkflowViewSet
from documents.views import WarehouseViewSet
from paperless.consumers import StatusConsumer
from paperless.views import ApplicationConfigurationViewSet
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 MailRuleViewSet
api_router = DefaultRouter()
api_router.register(r"correspondents", CorrespondentViewSet)
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"custom_fields", CustomFieldViewSet)
api_router.register(r"config", ApplicationConfigurationViewSet)
api_router.register(r"warehouses", WarehouseViewSet)
urlpatterns = [
re_path(
r"^api/",
include(