Initial commit from ZIP
This commit is contained in:
commit
378d4692a9
454 files changed
+40367
No files matched your search
+11
@@ -0,0 +1,11 @@
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class OrganizationsAppConfig(AppConfig):
|
||||
name = "outbo.apps.organizations"
|
||||
label = "organizations"
|
||||
verbose_name = _("Organizations")
|
||||
|
||||
|
||||
default_app_config = "outbo.apps.organizations.OrganizationsAppConfig"
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
from django.contrib import admin
|
||||
from polymorphic.admin import (
|
||||
PolymorphicChildModelAdmin,
|
||||
PolymorphicChildModelFilter,
|
||||
)
|
||||
|
||||
from outbo.apps.core.admin import PolymorphicParentModelAdmin
|
||||
from outbo.apps.organizations.models import (
|
||||
Organization,
|
||||
AgencyOrganization,
|
||||
ClientOrganization,
|
||||
SupplierOrganization,
|
||||
Brand,
|
||||
Category,
|
||||
)
|
||||
|
||||
|
||||
class _OrganizationChildAdmin(PolymorphicChildModelAdmin):
|
||||
base_model = Organization
|
||||
|
||||
|
||||
@admin.register(AgencyOrganization)
|
||||
class AgencyOrganizationAdmin(_OrganizationChildAdmin):
|
||||
base_model = AgencyOrganization
|
||||
|
||||
|
||||
@admin.register(ClientOrganization)
|
||||
class ClientOrganizationAdmin(_OrganizationChildAdmin):
|
||||
base_model = ClientOrganization
|
||||
search_fields = ["name"]
|
||||
|
||||
|
||||
@admin.register(SupplierOrganization)
|
||||
class SupplierOrganizationAdmin(_OrganizationChildAdmin):
|
||||
base_model = SupplierOrganization
|
||||
search_fields = ["name"]
|
||||
|
||||
|
||||
@admin.register(Organization)
|
||||
class OrganizationAdmin(PolymorphicParentModelAdmin):
|
||||
base_model = Organization
|
||||
child_models = (AgencyOrganization, ClientOrganization, SupplierOrganization)
|
||||
list_filter = (PolymorphicChildModelFilter,)
|
||||
search_fields = ["name"]
|
||||
|
||||
|
||||
@admin.register(Brand)
|
||||
class BrandAdmin(admin.ModelAdmin):
|
||||
autocomplete_fields = ["client", "suppliers", "categories"]
|
||||
|
||||
|
||||
@admin.register(Category)
|
||||
class CategoryAdmin(admin.ModelAdmin):
|
||||
search_fields = ["name"]
|
||||
|
||||
|
||||
# NOTE: https://stackoverflow.com/questions/9879687/adding-a-manytomanywidget-to-the-reverse-of-a-manytomanyfield-in-the-django-admi/13189954
|
||||
@@ -0,0 +1,220 @@
|
||||
# Generated by Django 2.2.7 on 2019-11-29 08:57
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import outbo.apps.core.fields
|
||||
import rules.contrib.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
("contenttypes", "0002_remove_content_type_name"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Category",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_at",
|
||||
outbo.apps.core.fields.CreationDateTimeField(
|
||||
auto_now_add=True, verbose_name="Created at"
|
||||
),
|
||||
),
|
||||
(
|
||||
"updated_at",
|
||||
outbo.apps.core.fields.ModificationDateTimeField(
|
||||
auto_now=True, verbose_name="Updated at"
|
||||
),
|
||||
),
|
||||
(
|
||||
"deleted_at",
|
||||
outbo.apps.core.fields.RemovalDateTimeField(
|
||||
blank=True, editable=False, null=True, verbose_name="Deleted at"
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=254, verbose_name="name")),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "category",
|
||||
"verbose_name_plural": "categories",
|
||||
"ordering": ["name"],
|
||||
},
|
||||
bases=(rules.contrib.models.RulesModelMixin, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Organization",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_at",
|
||||
outbo.apps.core.fields.CreationDateTimeField(
|
||||
auto_now_add=True, verbose_name="Created at"
|
||||
),
|
||||
),
|
||||
(
|
||||
"updated_at",
|
||||
outbo.apps.core.fields.ModificationDateTimeField(
|
||||
auto_now=True, verbose_name="Updated at"
|
||||
),
|
||||
),
|
||||
(
|
||||
"deleted_at",
|
||||
outbo.apps.core.fields.RemovalDateTimeField(
|
||||
blank=True, editable=False, null=True, verbose_name="Deleted at"
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=100)),
|
||||
(
|
||||
"polymorphic_ctype",
|
||||
models.ForeignKey(
|
||||
editable=False,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="polymorphic_organizations.organization_set+",
|
||||
to="contenttypes.ContentType",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={"abstract": False,},
|
||||
bases=(rules.contrib.models.RulesModelMixin, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="AgencyOrganization",
|
||||
fields=[
|
||||
(
|
||||
"organization_ptr",
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="organizations.Organization",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={"verbose_name": "agency", "verbose_name_plural": "agencies",},
|
||||
bases=("organizations.organization",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="ClientOrganization",
|
||||
fields=[
|
||||
(
|
||||
"organization_ptr",
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="organizations.Organization",
|
||||
),
|
||||
),
|
||||
("uses_simple_project_flow", models.BooleanField(default=False)),
|
||||
],
|
||||
options={"verbose_name": "client", "verbose_name_plural": "clients",},
|
||||
bases=("organizations.organization",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="SupplierOrganization",
|
||||
fields=[
|
||||
(
|
||||
"organization_ptr",
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="organizations.Organization",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={"verbose_name": "supplier", "verbose_name_plural": "suppliers",},
|
||||
bases=("organizations.organization",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Brand",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"created_at",
|
||||
outbo.apps.core.fields.CreationDateTimeField(
|
||||
auto_now_add=True, verbose_name="Created at"
|
||||
),
|
||||
),
|
||||
(
|
||||
"updated_at",
|
||||
outbo.apps.core.fields.ModificationDateTimeField(
|
||||
auto_now=True, verbose_name="Updated at"
|
||||
),
|
||||
),
|
||||
(
|
||||
"deleted_at",
|
||||
outbo.apps.core.fields.RemovalDateTimeField(
|
||||
blank=True, editable=False, null=True, verbose_name="Deleted at"
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=50, verbose_name="name")),
|
||||
(
|
||||
"categories",
|
||||
models.ManyToManyField(
|
||||
related_name="brands",
|
||||
related_query_name="brand",
|
||||
to="organizations.Category",
|
||||
verbose_name="categories",
|
||||
),
|
||||
),
|
||||
(
|
||||
"client",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="brands",
|
||||
related_query_name="brand",
|
||||
to="organizations.ClientOrganization",
|
||||
verbose_name="client",
|
||||
),
|
||||
),
|
||||
(
|
||||
"suppliers",
|
||||
models.ManyToManyField(
|
||||
related_name="brands",
|
||||
related_query_name="brand",
|
||||
to="organizations.SupplierOrganization",
|
||||
verbose_name="suppliers",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={"verbose_name": "brand", "verbose_name_plural": "brands",},
|
||||
bases=(rules.contrib.models.RulesModelMixin, models.Model),
|
||||
),
|
||||
]
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
# Generated by Django 2.2.10 on 2020-05-25 08:25
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("organizations", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="brand",
|
||||
name="client",
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="brands",
|
||||
related_query_name="brand",
|
||||
to="organizations.ClientOrganization",
|
||||
verbose_name="client",
|
||||
),
|
||||
),
|
||||
]
|
||||
Whitespace-only changes.
@@ -0,0 +1,8 @@
|
||||
from .organization import (
|
||||
Organization,
|
||||
AgencyOrganization,
|
||||
ClientOrganization,
|
||||
SupplierOrganization,
|
||||
)
|
||||
from .brand import Brand
|
||||
from .category import Category
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.db import models
|
||||
from rules.contrib.models import RulesModel
|
||||
|
||||
from outbo.apps.core.models import TimestampableDeletableMixin
|
||||
from outbo.apps.organizations import rules
|
||||
|
||||
|
||||
class Brand(TimestampableDeletableMixin, RulesModel):
|
||||
class Meta:
|
||||
verbose_name = _("brand")
|
||||
verbose_name_plural = _("brands")
|
||||
rules_permissions = {"read": rules.can_read_brand}
|
||||
|
||||
name = models.CharField(verbose_name=_("name"), max_length=50)
|
||||
client = models.ForeignKey(
|
||||
verbose_name=_("client"),
|
||||
to="ClientOrganization",
|
||||
on_delete=models.CASCADE,
|
||||
related_name="brands",
|
||||
related_query_name="brand",
|
||||
null=False,
|
||||
)
|
||||
suppliers = models.ManyToManyField(
|
||||
verbose_name=_("suppliers"),
|
||||
to="SupplierOrganization",
|
||||
related_name="brands",
|
||||
related_query_name="brand",
|
||||
)
|
||||
categories = models.ManyToManyField(
|
||||
verbose_name=_("categories"),
|
||||
to="Category",
|
||||
related_name="brands",
|
||||
related_query_name="brand",
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
@@ -0,0 +1,17 @@
|
||||
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
|
||||
|
||||
|
||||
class Category(TimestampableDeletableMixin, RulesModel):
|
||||
class Meta:
|
||||
verbose_name = _("category")
|
||||
verbose_name_plural = _("categories")
|
||||
ordering = ["name"]
|
||||
|
||||
name = models.CharField(verbose_name=_("name"), max_length=254)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
@@ -0,0 +1,50 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.db import models
|
||||
|
||||
from outbo.apps.core.models import (
|
||||
RulesPolymorphicModel,
|
||||
TimestampableDeletableMixin,
|
||||
SoftDeletablePolymorphicManager,
|
||||
)
|
||||
|
||||
|
||||
class Organization(TimestampableDeletableMixin, RulesPolymorphicModel):
|
||||
objects = SoftDeletablePolymorphicManager()
|
||||
all_objects = SoftDeletablePolymorphicManager(alive_only=False)
|
||||
|
||||
name = models.CharField(max_length=100)
|
||||
|
||||
def __str__(self):
|
||||
return f"[{str(self.polymorphic_ctype).title()}] {self.name}"
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self.polymorphic_ctype
|
||||
|
||||
@type.setter
|
||||
def type(self, value):
|
||||
self.polymorphic_ctype = value
|
||||
|
||||
@type.deleter
|
||||
def type(self):
|
||||
del self.polymorphic_ctype
|
||||
|
||||
|
||||
class AgencyOrganization(Organization):
|
||||
class Meta:
|
||||
verbose_name = _("agency")
|
||||
verbose_name_plural = _("agencies")
|
||||
|
||||
|
||||
class ClientOrganization(Organization):
|
||||
class Meta:
|
||||
verbose_name = _("client")
|
||||
verbose_name_plural = _("clients")
|
||||
|
||||
uses_simple_project_flow = models.BooleanField(null=False, default=False)
|
||||
|
||||
|
||||
class SupplierOrganization(Organization):
|
||||
class Meta:
|
||||
verbose_name = _("supplier")
|
||||
verbose_name_plural = _("suppliers")
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
from rules import always_deny, predicate
|
||||
|
||||
|
||||
@predicate
|
||||
def can_read_brand(user, brand):
|
||||
return always_deny
|
||||
|
||||
|
||||
@predicate
|
||||
def can_read_category(user, category):
|
||||
return always_deny
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from outbo.apps.core.serializers import PolymorphicSerializer
|
||||
from outbo.apps.organizations.models import (
|
||||
AgencyOrganization,
|
||||
ClientOrganization,
|
||||
SupplierOrganization,
|
||||
Brand,
|
||||
Category,
|
||||
Organization,
|
||||
)
|
||||
|
||||
|
||||
# Organizations
|
||||
class _BaseOrganizationSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
fields = (
|
||||
"id",
|
||||
"name",
|
||||
)
|
||||
|
||||
|
||||
class _OrganizationSerializer:
|
||||
class List(_BaseOrganizationSerializer):
|
||||
class Meta(_BaseOrganizationSerializer.Meta):
|
||||
model = Organization
|
||||
|
||||
|
||||
class _AgencyOrganizationSerializer:
|
||||
class List(_BaseOrganizationSerializer):
|
||||
class Meta(_BaseOrganizationSerializer.Meta):
|
||||
model = AgencyOrganization
|
||||
|
||||
|
||||
class _ClientOrganizationSerializer:
|
||||
class List(_BaseOrganizationSerializer):
|
||||
class Meta(_BaseOrganizationSerializer.Meta):
|
||||
model = ClientOrganization
|
||||
|
||||
|
||||
class _SupplierOrganizationSerializer:
|
||||
class List(_BaseOrganizationSerializer):
|
||||
class Meta(_BaseOrganizationSerializer.Meta):
|
||||
model = SupplierOrganization
|
||||
|
||||
|
||||
class _BaseOrganizationPolymorphicSerializer(PolymorphicSerializer):
|
||||
model_serializer_mapping = {
|
||||
AgencyOrganization: _AgencyOrganizationSerializer.List,
|
||||
ClientOrganization: _ClientOrganizationSerializer.List,
|
||||
SupplierOrganization: _SupplierOrganizationSerializer.List,
|
||||
Organization: _OrganizationSerializer.List,
|
||||
}
|
||||
|
||||
|
||||
class OrganizationSerializer:
|
||||
class Retrieve(_BaseOrganizationPolymorphicSerializer):
|
||||
pass
|
||||
|
||||
class List(_BaseOrganizationPolymorphicSerializer):
|
||||
pass
|
||||
|
||||
|
||||
# Brands
|
||||
class _BaseBrandSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Brand
|
||||
fields = ["name"]
|
||||
|
||||
|
||||
class BrandSerializer(serializers.ModelSerializer):
|
||||
# Create & Update not needed
|
||||
class Retrieve(_BaseBrandSerializer):
|
||||
pass
|
||||
|
||||
class List(_BaseBrandSerializer):
|
||||
class Meta(_BaseBrandSerializer.Meta):
|
||||
fields = ["id"] + _BaseBrandSerializer.Meta.fields
|
||||
|
||||
|
||||
# Categories
|
||||
class _BaseCategorySerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Category
|
||||
fields = ["name"]
|
||||
|
||||
|
||||
class CategorySerializer:
|
||||
class Retrieve(_BaseCategorySerializer):
|
||||
pass
|
||||
|
||||
class List(_BaseCategorySerializer):
|
||||
class Meta(_BaseCategorySerializer.Meta):
|
||||
fields = ["id"] + _BaseCategorySerializer.Meta.fields
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
from rest_framework import routers
|
||||
|
||||
from outbo.apps.organizations.viewsets import BrandViewSet, CategoryViewSet
|
||||
|
||||
app_name = "organizations"
|
||||
router = routers.SimpleRouter()
|
||||
router.register(prefix="brands", viewset=BrandViewSet)
|
||||
router.register(prefix="categories", viewset=CategoryViewSet)
|
||||
|
||||
urlpatterns = router.urls
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
from outbo.apps.core.viewsets import (
|
||||
MultipleSerializerViewSet,
|
||||
AutoPermissionViewSetMixin,
|
||||
ListModelMixin,
|
||||
RetrieveModelMixin,
|
||||
)
|
||||
from outbo.apps.organizations.models import Brand, Category
|
||||
from outbo.apps.organizations.serializers import BrandSerializer, CategorySerializer
|
||||
|
||||
|
||||
class BrandViewSet(
|
||||
RetrieveModelMixin,
|
||||
ListModelMixin,
|
||||
AutoPermissionViewSetMixin,
|
||||
MultipleSerializerViewSet,
|
||||
):
|
||||
queryset = Brand.objects.all()
|
||||
serializer_class_set = BrandSerializer
|
||||
|
||||
|
||||
class CategoryViewSet(
|
||||
RetrieveModelMixin,
|
||||
ListModelMixin,
|
||||
AutoPermissionViewSetMixin,
|
||||
MultipleSerializerViewSet,
|
||||
):
|
||||
|
||||
queryset = Category.objects.all()
|
||||
serializer_class_set = CategorySerializer
|
||||
Reference in new issue
Block a user