Compare commits

...

4 commits

Author SHA1 Message Date
8d830bda64 added readme for shipment features
All checks were successful
/ test (push) Successful in 2m19s
2025-03-15 22:55:51 +01:00
67075c25b7 created model for shipments 2025-03-15 22:38:56 +01:00
40eae9187b created missing migration 2025-03-15 22:38:42 +01:00
04f42a8747 added test containers and items to testdata 2025-03-15 21:59:22 +01:00
9 changed files with 106 additions and 1 deletions

View file

@ -70,6 +70,7 @@ INSTALLED_APPS = [
'inventory', 'inventory',
'mail', 'mail',
'notify_sessions', 'notify_sessions',
'shipments'
] ]
REST_FRAMEWORK = { REST_FRAMEWORK = {

18
core/shipments/README.md Normal file
View file

@ -0,0 +1,18 @@
# Shipment Management
## Functional Description
This module handles shipments that are processed by the lost&found team.
**Feature List**
- Shipment can contain *n* (often one, but a lostee can also be sent multiple items) items
- Shipment is linked to *n* tickets (for informative purposes)
- Shipment holds the address of the parcel
- Shipment holds the dhl voucher used
- On creation of a shipment, the agent can activate the features "adress retrieval", "item validation" and/or tracking
- **address retrieval**: the lostee recieves a email with publicly accessible link, on this page the user can enter his address.
- address sanitation
- address validation
- automatic state change after successful address entry (-> waiting for shipping)
- **item validation**: the lostee recieves a email with publicly accessible link, on this page the user see the images and confirm the items
- automatic state change after confirmation
- **tracking**: the lostee recieves a email with publicly accessible link, on this page the user can enter his address
- Returning parcels could be managed to (e.g. if a shipment is marked as returned, the items will be *unfound* again)

View file

0
core/shipments/api_v2.py Normal file
View file

View file

@ -0,0 +1,37 @@
# Generated by Django 4.2.7 on 2025-03-15 21:37
from django.db import migrations, models
import django.db.models.manager
import uuid
class Migration(migrations.Migration):
initial = True
dependencies = [
('inventory', '0007_rename_container_item_container_old_itemplacement_and_more'),
('tickets', '0013_alter_statechange_state'),
]
operations = [
migrations.CreateModel(
name='Shipment',
fields=[
('is_deleted', models.BooleanField(default=False)),
('deleted_at', models.DateTimeField(blank=True, null=True)),
('id', models.AutoField(primary_key=True, serialize=False)),
('public_secret', models.UUIDField(default=uuid.uuid4)),
('created_at', models.DateTimeField(auto_now_add=True, null=True)),
('updated_at', models.DateTimeField(blank=True, null=True)),
('related_items', models.ManyToManyField(to='inventory.item')),
('related_tickets', models.ManyToManyField(to='tickets.issuethread')),
],
options={
'abstract': False,
},
managers=[
('all_objects', django.db.models.manager.Manager()),
],
),
]

View file

21
core/shipments/models.py Normal file
View file

@ -0,0 +1,21 @@
import uuid
from django.db import models
from django_softdelete.models import SoftDeleteModel, SoftDeleteManager
from inventory.models import Item
from tickets.models import IssueThread
class Shipment(SoftDeleteModel):
id = models.AutoField(primary_key=True)
public_secret = models.UUIDField(default = uuid.uuid4)
related_items = models.ManyToManyField(Item)
related_tickets = models.ManyToManyField(IssueThread)
created_at = models.DateTimeField(null=True, auto_now_add=True)
updated_at = models.DateTimeField(blank=True, null=True)
all_objects = models.Manager()
def __str__(self):
return '[' + str(self.id) + ']' + self.description

View file

@ -0,0 +1,18 @@
# Generated by Django 4.2.7 on 2025-03-15 21:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tickets', '0012_remove_issuethread_related_items_and_more'),
]
operations = [
migrations.AlterField(
model_name='statechange',
name='state',
field=models.CharField(choices=[('pending_new', 'New'), ('pending_open', 'Open'), ('pending_shipping', 'Needs to be shipped'), ('pending_physical_confirmation', 'Needs to be confirmed physically'), ('pending_return', 'Needs to be returned'), ('pending_postponed', 'Postponed'), ('pending_suspected_spam', 'Suspected Spam'), ('waiting_details', 'Waiting for details'), ('waiting_pre_shipping', 'Waiting for Address/Shipping Info'), ('closed_returned', 'Closed: Returned'), ('closed_shipped', 'Closed: Shipped'), ('closed_not_found', 'Closed: Not found'), ('closed_not_our_problem', 'Closed: Not our problem'), ('closed_duplicate', 'Closed: Duplicate'), ('closed_timeout', 'Closed: Timeout'), ('closed_spam', 'Closed: Spam'), ('closed_nothing_missing', 'Closed: Nothing missing'), ('closed_wtf', 'Closed: WTF'), ('found_open', 'Item Found and stored externally'), ('found_closed', 'Item Found and stored externally and closed')], default='pending_new', max_length=255),
),
]

View file

@ -3,7 +3,7 @@ import os
def setup(): def setup():
from authentication.models import ExtendedUser, EventPermission from authentication.models import ExtendedUser, EventPermission
from inventory.models import Event from inventory.models import Event, Container, Item
from django.contrib.auth.models import Permission, Group from django.contrib.auth.models import Permission, Group
permissions = ['add_item', 'view_item', 'view_file', 'delete_item', 'change_item'] permissions = ['add_item', 'view_item', 'view_file', 'delete_item', 'change_item']
if not ExtendedUser.objects.filter(username='admin').exists(): if not ExtendedUser.objects.filter(username='admin').exists():
@ -38,6 +38,16 @@ def setup():
start='2024-12-18 00:00:00.000000', end='2024-12-27 00:00:00.000000', start='2024-12-18 00:00:00.000000', end='2024-12-27 00:00:00.000000',
pre_start='2024-12-31 00:00:00.000000', post_end='2025-01-04 00:00:00.000000')[ pre_start='2024-12-31 00:00:00.000000', post_end='2025-01-04 00:00:00.000000')[
0] 0]
container1 ,_= Container.objects.get_or_create(id=1, name='Box1')
container2 ,_= Container.objects.get_or_create(id=2, name='Box2')
testitem1 ,_= Item.objects.get_or_create(id=1, event=event1, description="Test item 1",uid_deprecated=111)
testitem1.container = container1
testitem2 ,_= Item.objects.get_or_create(id=2, event=event2, description="Test item 2",uid_deprecated=112)
testitem2.container = container1
testitem3 ,_= Item.objects.get_or_create(id=3, event=event2, description="Test item 3",uid_deprecated=113)
testitem3.container = container2
# for permission in permissions: # for permission in permissions:
# EventPermission.objects.create(event=event_37c3, user=foo, # EventPermission.objects.create(event=event_37c3, user=foo,