Initial commit from ZIP
This commit is contained in:
commit
378d4692a9
454 files changed
+40367
No files matched your search
@@ -0,0 +1,5 @@
|
||||
from .brief import Brief
|
||||
from .brief_item import BriefItem
|
||||
from .brief_item_photo import BriefItemPhoto
|
||||
from .brief_item_choice import BriefItemChoice
|
||||
from .category import Category
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
from itertools import product
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_fsm import FSMField, transition
|
||||
from rules.contrib.models import RulesModel
|
||||
|
||||
from outbo.apps.activity_log.enums import MessageType
|
||||
from outbo.apps.activity_log.models import ProductLogItem
|
||||
from outbo.apps.core.models import TimestampableDeletableMixin
|
||||
from outbo.apps.core.utils import get_current_date, is_empty_set
|
||||
from outbo.apps.final_photobriefing.models import FinalBrief
|
||||
from outbo.apps.photobriefing import rules
|
||||
from outbo.apps.photobriefing.enums import ChoiceRole
|
||||
|
||||
|
||||
class Brief(TimestampableDeletableMixin, RulesModel):
|
||||
class Meta:
|
||||
rules_permissions = {
|
||||
"add": rules.can_create_brief,
|
||||
"view": rules.can_read_brief,
|
||||
"change": rules.can_update_brief,
|
||||
"delete": rules.can_delete_brief,
|
||||
}
|
||||
|
||||
product = models.OneToOneField(
|
||||
verbose_name=_("product"),
|
||||
to="products.Product",
|
||||
on_delete=models.CASCADE,
|
||||
primary_key=True,
|
||||
editable=False,
|
||||
related_name="photo_brief",
|
||||
related_query_name="photo_brief",
|
||||
)
|
||||
|
||||
session_date = models.DateField(
|
||||
verbose_name=_("photo session date"),
|
||||
blank=False,
|
||||
null=False,
|
||||
default=get_current_date,
|
||||
)
|
||||
|
||||
concept_description = models.TextField(blank=True, null=False)
|
||||
|
||||
stage = FSMField(default="created", protected=True)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
result = super().save(*args, **kwargs)
|
||||
if self.product:
|
||||
self.product.save()
|
||||
return result
|
||||
|
||||
def acceptable_for_user(self, *, user):
|
||||
if user.is_observer or user.is_trader:
|
||||
return False
|
||||
return not user.is_agency and self.stage == "published"
|
||||
|
||||
def publishable_for_user(self, *, user):
|
||||
if user.is_observer or user.is_trader:
|
||||
return False
|
||||
all_categories = set(self.items.values_list("category", flat=True))
|
||||
if self.editable_for_user(user=user) and not is_empty_set(all_categories):
|
||||
return True
|
||||
return False
|
||||
|
||||
def completable_for_user(self, *, user):
|
||||
if user.is_observer or user.is_trader:
|
||||
return False
|
||||
if not user.is_agency or self.stage != "published":
|
||||
return False
|
||||
|
||||
roles = [ChoiceRole.SUPPLIER, ChoiceRole.CLIENT]
|
||||
all_categories = set(self.items.values_list("category", flat=True))
|
||||
if is_empty_set(all_categories):
|
||||
return False
|
||||
|
||||
for category, role in product(all_categories, roles):
|
||||
if not self.choices.filter(category_id=category, role=role).exists():
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def editable_for_user(self, *, user):
|
||||
if user.is_observer or user.is_trader:
|
||||
return False
|
||||
if not user.is_agency or not self.stage == "created":
|
||||
return False
|
||||
return self.product.stage.group in [2, 3]
|
||||
|
||||
@transition(field="stage", source="created", target="published")
|
||||
def publish_as_user(self, *, user):
|
||||
ProductLogItem.objects.create(
|
||||
product=self.product,
|
||||
created_by=user,
|
||||
message="Photobriefing published",
|
||||
message_type=MessageType.SUCCESS,
|
||||
)
|
||||
|
||||
@transition(field="stage", source="published", target="completed")
|
||||
def complete_as_user(self, *, user):
|
||||
FinalBrief.objects.create(brief=self)
|
||||
ProductLogItem.objects.create(
|
||||
product=self.product,
|
||||
created_by=user,
|
||||
message="Photobriefing completed",
|
||||
message_type=MessageType.SUCCESS,
|
||||
)
|
||||
@@ -0,0 +1,32 @@
|
||||
from django.db import models
|
||||
from rules.contrib.models import RulesModel
|
||||
|
||||
from outbo.apps.core.models import TimestampableDeletableMixin
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from outbo.apps.photobriefing import rules
|
||||
|
||||
|
||||
class BriefItem(TimestampableDeletableMixin, RulesModel):
|
||||
class Meta:
|
||||
rules_permissions = {
|
||||
"add": rules.can_create_brief_item,
|
||||
"view": rules.can_read_brief_item,
|
||||
"change": rules.can_update_brief_item,
|
||||
"delete": rules.can_delete_brief_item,
|
||||
}
|
||||
ordering = ["id"]
|
||||
|
||||
brief = models.ForeignKey(
|
||||
verbose_name=_("brief"),
|
||||
to="Brief",
|
||||
on_delete=models.CASCADE,
|
||||
related_name="items",
|
||||
related_query_name="item",
|
||||
)
|
||||
category = models.ForeignKey(
|
||||
verbose_name=_("category"), to="Category", on_delete=models.CASCADE
|
||||
)
|
||||
|
||||
title = models.CharField(max_length=100, blank=False, null=False)
|
||||
description = models.TextField(blank=False, null=False)
|
||||
@@ -0,0 +1,39 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rules.contrib.models import RulesModel
|
||||
|
||||
from outbo.apps.core.models import TimestampableDeletableMixin
|
||||
from outbo.apps.photobriefing.enums import ChoiceRole
|
||||
|
||||
|
||||
class BriefItemChoice(TimestampableDeletableMixin, RulesModel):
|
||||
class Meta:
|
||||
unique_together = (("brief", "category", "role"),)
|
||||
|
||||
brief = models.ForeignKey(
|
||||
verbose_name=_("brief"),
|
||||
to="Brief",
|
||||
on_delete=models.CASCADE,
|
||||
related_name="choices",
|
||||
related_query_name="choice",
|
||||
)
|
||||
category = models.ForeignKey(
|
||||
verbose_name=_("category"),
|
||||
to="Category",
|
||||
on_delete=models.CASCADE,
|
||||
related_name="choices+",
|
||||
related_query_name="choice",
|
||||
)
|
||||
role = models.CharField(
|
||||
max_length=30,
|
||||
choices=[(role, role.value) for role in ChoiceRole],
|
||||
default=ChoiceRole.INVALID,
|
||||
editable=False,
|
||||
)
|
||||
item = models.ForeignKey(
|
||||
verbose_name=_("item"),
|
||||
to="BriefItem",
|
||||
on_delete=models.CASCADE,
|
||||
related_name="choices",
|
||||
related_query_name="choice",
|
||||
)
|
||||
@@ -0,0 +1,40 @@
|
||||
import os
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rules import always_allow
|
||||
from rules.contrib.models import RulesModel
|
||||
|
||||
from outbo.apps.core.models import TimestampableDeletableMixin
|
||||
|
||||
|
||||
def filename(self, filename):
|
||||
return "/".join(
|
||||
(
|
||||
"projects",
|
||||
self.item.brief.product.project.slug[1:],
|
||||
"photobriefing",
|
||||
filename,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class BriefItemPhoto(TimestampableDeletableMixin, RulesModel):
|
||||
class Meta:
|
||||
rules_permissions = {
|
||||
"view": always_allow,
|
||||
}
|
||||
|
||||
item = models.ForeignKey(
|
||||
verbose_name=_("brief item"),
|
||||
to="BriefItem",
|
||||
on_delete=models.CASCADE,
|
||||
related_name="photos",
|
||||
related_query_name="photo",
|
||||
)
|
||||
|
||||
file = models.ImageField(verbose_name=_("file"), upload_to=filename)
|
||||
|
||||
@property
|
||||
def filename(self):
|
||||
return os.path.basename(self.file.name)
|
||||
@@ -0,0 +1,17 @@
|
||||
from django.db import models
|
||||
from rules.contrib.models import RulesModel
|
||||
|
||||
from outbo.apps.core.models import TimestampableDeletableMixin
|
||||
from django.utils.translation import gettext_lazy as _, pgettext
|
||||
|
||||
|
||||
class Category(TimestampableDeletableMixin, RulesModel):
|
||||
class Meta:
|
||||
verbose_name = _("category")
|
||||
verbose_name_plural = _("categories")
|
||||
|
||||
label = models.CharField(verbose_name=_("label"), max_length=30, primary_key=True)
|
||||
description = models.CharField(verbose_name=_("description"), max_length=30)
|
||||
|
||||
def __str__(self):
|
||||
return pgettext("photo_brief_categories", self.description)
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rules.contrib.models import RulesModel
|
||||
|
||||
from outbo.apps.core.models import TimestampableDeletableMixin
|
||||
from outbo.apps.final_photobriefing.enums import PhotoType
|
||||
|
||||
|
||||
class Photo(TimestampableDeletableMixin, RulesModel):
|
||||
brief = models.ForeignKey(
|
||||
verbose_name=_("photo brief"),
|
||||
to="Brief",
|
||||
on_delete=models.CASCADE,
|
||||
related_name="photos",
|
||||
related_query_name="photo",
|
||||
)
|
||||
|
||||
type = models.CharField(
|
||||
max_length=50,
|
||||
choices=((type, type.value) for type in PhotoType),
|
||||
default=PhotoType.INVALID,
|
||||
)
|
||||
|
||||
def filename(self, filename):
|
||||
return f"projects/{self.brief.product.project.slug[1:]}/photos/{filename}"
|
||||
|
||||
file = models.ImageField(verbose_name=_("file"), upload_to=filename)
|
||||
Reference in new issue
Block a user