147 lines
4.7 KiB
Python
Executable File
147 lines
4.7 KiB
Python
Executable File
from typing import TYPE_CHECKING
|
|
|
|
from django.db import models
|
|
from django.utils.translation import gettext_lazy as _
|
|
from rules.contrib.models import RulesModel
|
|
|
|
from outbo.apps.activity_log.enums import MessageType
|
|
from outbo.apps.activity_log.models import ProjectLogItem
|
|
from outbo.apps.core.models import TimestampableDeletableMixin, SoftDeletableManager
|
|
from outbo.apps.products.models import Product
|
|
from outbo.apps.projects import rules
|
|
from outbo.apps.projects.fields import SlugField
|
|
from outbo.apps.projects.models import ProjectNumber
|
|
|
|
if TYPE_CHECKING:
|
|
from outbo.apps.authentication.models import User
|
|
|
|
|
|
class ProjectManager(SoftDeletableManager):
|
|
def create(self, **kwargs):
|
|
products_amount = kwargs.pop("products_amount", None)
|
|
|
|
project: "Project" = super().create(**kwargs)
|
|
if products_amount is not None:
|
|
project.add_products(products_amount=products_amount)
|
|
project.save()
|
|
return project
|
|
|
|
|
|
class Project(TimestampableDeletableMixin, RulesModel):
|
|
objects = ProjectManager()
|
|
all_objects = ProjectManager(alive_only=False)
|
|
|
|
class Meta:
|
|
rules_permissions = {
|
|
"view": rules.can_read_project,
|
|
"add": rules.can_create_project,
|
|
"change": rules.can_update_project,
|
|
"delete": rules.can_delete_project,
|
|
}
|
|
ordering = ["-updated_at__date", "slug"]
|
|
|
|
def slugify(self):
|
|
brand_prefix = self.category.name[:2].upper()
|
|
category_prefix = self.brand.name[:2].upper()
|
|
|
|
number = ProjectNumber.objects.get_next_number(
|
|
prefix=f"{brand_prefix}{category_prefix}"
|
|
)
|
|
week_year = self.promo_date.strftime("%U%y")
|
|
return f"#{brand_prefix}{category_prefix}{number}-{week_year}"
|
|
|
|
slug = SlugField(
|
|
verbose_name=_("project identifier"), max_length=15, slugify=slugify
|
|
)
|
|
|
|
name = models.CharField(
|
|
verbose_name=_("name"), max_length=254, blank=False, null=False
|
|
)
|
|
description = models.TextField(
|
|
verbose_name=_("description"), blank=False, null=False
|
|
)
|
|
category = models.ForeignKey(
|
|
verbose_name=_("category"),
|
|
to="organizations.Category",
|
|
on_delete=models.CASCADE,
|
|
null=False,
|
|
)
|
|
brand = models.ForeignKey(
|
|
verbose_name=_("brand"),
|
|
to="organizations.Brand",
|
|
on_delete=models.CASCADE,
|
|
null=False,
|
|
)
|
|
printing_files_date = models.DateField(
|
|
verbose_name=_("printing files delivery date"), null=False
|
|
)
|
|
promo_date = models.DateField(verbose_name=_("promo date"), null=False)
|
|
|
|
# internal fields
|
|
|
|
published = models.BooleanField(
|
|
verbose_name=_("published"), blank=False, null=False, default=False
|
|
)
|
|
|
|
@property
|
|
def _max_product_stage_obj(self):
|
|
max_product_stage_obj = (
|
|
self.products.order_by("-stage__order").first()
|
|
)
|
|
if not max_product_stage_obj:
|
|
return None
|
|
return max_product_stage_obj
|
|
|
|
@property
|
|
def max_product_stage(self):
|
|
return self._max_product_stage_obj.stage.id
|
|
|
|
@property
|
|
def max_product_stage_description(self):
|
|
return self._max_product_stage_obj.stage.description
|
|
|
|
def __str__(self):
|
|
if self.slug:
|
|
return f"[{self.slug}] {self.name}"
|
|
else:
|
|
return self.name
|
|
|
|
def publishable_for_user(self, *, user: "User"):
|
|
if user.is_observer or user.is_trader:
|
|
return False
|
|
return not self.published and all(
|
|
[
|
|
product.has_brief_publishable_for_user(user=user)
|
|
for product in self.products.all()
|
|
]
|
|
)
|
|
|
|
def save(self, *args, **kwargs):
|
|
products_amount = kwargs.pop("products_amount", None)
|
|
super().save(*args, **kwargs)
|
|
if products_amount is not None:
|
|
self.add_products(products_amount=products_amount)
|
|
|
|
def add_products(self, *, products_amount):
|
|
[Product.objects.create(project=self) for _ in range(products_amount)]
|
|
self.save()
|
|
|
|
def publish_as_user(self, *, user: "User"):
|
|
self.published = True
|
|
for product in self.products.all():
|
|
product.send_action_emails_for_users_passing_test(
|
|
test=lambda u: u in [m.user for m in self.members.all()]
|
|
and u.is_agency,
|
|
action_url="https://outbo.pl/projects/{id}/products/{pid}",
|
|
)
|
|
product.publish_brief_as_user(user=user)
|
|
product.save()
|
|
|
|
ProjectLogItem.objects.create(
|
|
project=self,
|
|
created_by=user,
|
|
message="Project published",
|
|
message_type=MessageType.SUCCESS,
|
|
)
|
|
self.save()
|