Skip to content
This repository was archived by the owner on Nov 20, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6f4633c
Model Updates
mjducut-oe Oct 31, 2023
50cccb4
Item schema adjustment
mjducut-oe Oct 31, 2023
ef4743d
Jobs and Tasks schema adjustment
mjducut-oe Oct 31, 2023
193479b
Further schema adjustments
mjducut-oe Oct 31, 2023
08a57cb
Added validator on related_model
mjducut-oe Oct 31, 2023
e061ee8
Added bypass on custom_fields
mjducut-oe Oct 31, 2023
b76a0e5
Model Updates
mjducut-oe Oct 31, 2023
e977c5c
Item schema adjustment
mjducut-oe Oct 31, 2023
4b92e7a
Jobs and Tasks schema adjustment
mjducut-oe Oct 31, 2023
c536416
Further schema adjustments
mjducut-oe Oct 31, 2023
3f32e61
Added validator on related_model
mjducut-oe Oct 31, 2023
7b67464
Added bypass on custom_fields
mjducut-oe Oct 31, 2023
a94e734
Merge branch 'feat/custom-field-column' of https://github.com/factryf…
mjducut-oe Nov 1, 2023
9db6326
Model Updates
mjducut-oe Oct 31, 2023
4467dd5
Item schema adjustment
mjducut-oe Oct 31, 2023
9d47e6c
Jobs and Tasks schema adjustment
mjducut-oe Oct 31, 2023
9455607
Further schema adjustments
mjducut-oe Oct 31, 2023
3b3d6b7
Added validator on related_model
mjducut-oe Oct 31, 2023
d67493f
Added bypass on custom_fields
mjducut-oe Oct 31, 2023
df0e5f8
Model Updates
mjducut-oe Oct 31, 2023
8685743
Added validator on related_model
mjducut-oe Oct 31, 2023
c83b0ad
Merge branch 'feat/custom-field-column' of https://github.com/factryf…
mjducut-oe Nov 2, 2023
5cdee8d
Merge branch 'main' of https://github.com/factryflow/factryflow into …
mjducut-oe Nov 3, 2023
abc554a
Pytest workaround on db access
mjducut-oe Nov 3, 2023
ffd74a2
Upgraded pytest for compatibility
mjducut-oe Nov 3, 2023
4089798
Added tests on customfields
mjducut-oe Nov 6, 2023
ab788ba
Merge branch 'main' into feat/custom-field-column
mjducut-oe Nov 13, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Generated by Django 4.2.6 on 2023-10-31 03:06

from django.db import migrations, models
import api.models.custom_field


class Migration(migrations.Migration):

dependencies = [
('api', '0004_customfield_historicalcustomfield_customfieldvalue_and_more'),
]

operations = [
migrations.RemoveIndex(
model_name='customfield',
name='custom_fiel_id_b33a4d_idx',
),
migrations.RemoveField(
model_name='customfield',
name='label',
),
migrations.RemoveField(
model_name='customfield',
name='style',
),
migrations.RemoveField(
model_name='customfield',
name='validation',
),
migrations.RemoveField(
model_name='customfieldvalue',
name='value',
),
migrations.RemoveField(
model_name='historicalcustomfield',
name='label',
),
migrations.RemoveField(
model_name='historicalcustomfield',
name='style',
),
migrations.RemoveField(
model_name='historicalcustomfield',
name='validation',
),
migrations.AddField(
model_name='historicalitem',
name='custom_fields',
field=models.JSONField(blank=True, null=True),
),
migrations.AddField(
model_name='historicaljob',
name='custom_fields',
field=models.JSONField(blank=True, null=True),
),
migrations.AddField(
model_name='historicaltask',
name='custom_fields',
field=models.JSONField(blank=True, null=True),
),
migrations.AddField(
model_name='item',
name='custom_fields',
field=models.JSONField(blank=True, null=True),
),
migrations.AddField(
model_name='job',
name='custom_fields',
field=models.JSONField(blank=True, null=True),
),
migrations.AddField(
model_name='task',
name='custom_fields',
field=models.JSONField(blank=True, null=True),
),
migrations.AlterField(
model_name='customfield',
name='field_type',
field=models.CharField(choices=[('text', 'Text'), ('number', 'Number'), ('date', 'Date'), ('boolean', 'Boolean'), ('datetime', 'DateTime'), ('time', 'Time')], max_length=50),
),
migrations.AlterField(
model_name='historicalcustomfield',
name='field_type',
field=models.CharField(choices=[('text', 'Text'), ('number', 'Number'), ('date', 'Date'), ('boolean', 'Boolean'), ('datetime', 'DateTime'), ('time', 'Time')], max_length=50),
),
migrations.AddIndex(
model_name='customfield',
index=models.Index(fields=['id', 'field_name', 'related_model'], name='custom_fiel_id_0ed23a_idx'),
),
migrations.AlterField(
model_name='customfield',
name='related_model',
field=models.CharField(max_length=255, validators=[api.models.custom_field.validate_related_model]),
),
migrations.AlterField(
model_name='historicalcustomfield',
name='related_model',
field=models.CharField(max_length=255, validators=[api.models.custom_field.validate_related_model]),
),
]
17 changes: 12 additions & 5 deletions backend/api/models/custom_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,28 @@
from django.db import models
from django.utils import timezone
from simple_history.models import HistoricalRecords
from django.apps import apps
from django.core.exceptions import ValidationError

def validate_related_model(value):
try:
apps.get_model('api', value)
except LookupError:
raise ValidationError(f"'{value}' is not a valid model in the app.")

class CustomField(models.Model):
FIELD_TYPES = [
("text", "Text"),
("number", "Number"),
("date", "Date"),
("boolean", "Boolean"),
("datetime", "DateTime"),
("time", "Time"),
]

field_name = models.CharField(max_length=255)
field_type = models.CharField(max_length=50, choices=FIELD_TYPES)
related_model = models.CharField(max_length=255)
label = models.CharField(max_length=255, null=True, blank=True)
validation = models.JSONField(null=True, blank=True)
style = models.JSONField(null=True, blank=True)
related_model = models.CharField(max_length=255, validators= [validate_related_model])

# Metadata
created_at = models.DateTimeField(default=timezone.now)
Expand All @@ -42,4 +49,4 @@ def __str__(self):

class Meta:
db_table = "custom_fields"
indexes = [models.Index(fields=["id", "field_name"])]
indexes = [models.Index(fields=["id", "field_name", "related_model"])]
1 change: 1 addition & 0 deletions backend/api/models/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
class Item(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(blank=True, null=True)
custom_fields = models.JSONField(blank=True, null=True)

# Metadata
created_at = models.DateTimeField(default=timezone.now)
Expand Down
1 change: 1 addition & 0 deletions backend/api/models/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Job(OrderedModelBase):
job_status = models.ForeignKey(JobStatus, on_delete=models.DO_NOTHING)
job_type = models.ForeignKey(JobType, on_delete=models.DO_NOTHING)
dependencies = models.ManyToManyField("Dependency", related_name="jobs")
custom_fields = models.JSONField(blank=True, null=True)

# Metadata
created_at = models.DateTimeField(default=timezone.now)
Expand Down
1 change: 1 addition & 0 deletions backend/api/models/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class Task(models.Model):
planned_start_datetime = models.DateTimeField(blank=True, null=True)
planned_end_datetime = models.DateTimeField(blank=True, null=True)
dependencies = models.ManyToManyField("Dependency", related_name="tasks")
custom_fields = models.JSONField(blank=True, null=True)

# Metadata
created_at = models.DateTimeField(default=timezone.now)
Expand Down
5 changes: 4 additions & 1 deletion backend/api/schemas/base.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# schemas.py

from typing import List
from typing import List, Optional

from ninja import ModelSchema
from pydantic.fields import Field
from api.utils.generate_custom_schema import generate_custom_field_schema

from api.models import (
CustomField,
Expand Down Expand Up @@ -75,6 +76,7 @@ class JobBaseOut(ModelSchema):
job_type: JobTypeOut
task_ids: List[int] = Field([], alias="task_id_list")
dependency_ids: List[int] = Field([], alias="dependency_id_list")
custom_fields: Optional[generate_custom_field_schema(model_name= 'Job', class_suffix= 'Job')]

class Config:
model = Job
Expand Down Expand Up @@ -118,6 +120,7 @@ class TaskBaseOut(ModelSchema):
predecessor_ids: List[int] = Field([], alias="predecessor_id_list")
successor_ids: List[int] = Field([], alias="successor_id_list")
dependency_ids: List[int] = Field([], alias="dependency_id_list")
custom_fields: Optional[generate_custom_field_schema(model_name= 'Task', class_suffix= 'Task')]

class Config:
model = Task
Expand Down
4 changes: 2 additions & 2 deletions backend/api/schemas/custom_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ class FieldType(str, Enum):
NUMBER = "number"
DATE = "date"
BOOLEAN = "boolean"
DATETIME = "datetime"
TIME = "time"

class CustomFieldIn(ModelSchema):
field_type : FieldType
label : Optional[str]

class Config:
model = CustomField
model_fields = [
Expand Down
3 changes: 3 additions & 0 deletions backend/api/schemas/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@
from ninja import ModelSchema, Schema

from api.models import Item
from api.utils.generate_custom_schema import generate_custom_field_schema


class ItemIn(Schema):
name: str
description: Optional[str] = None
custom_fields: Optional[generate_custom_field_schema(model_name= 'Item', class_suffix= 'Item')]


class ItemOut(ModelSchema):
custom_fields: Optional[generate_custom_field_schema(model_name= 'Item', class_suffix= 'Item')]
class Config:
model = Item
model_fields = "__all__"
4 changes: 3 additions & 1 deletion backend/api/schemas/job.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# schemas.py
from typing import List
from typing import List, Optional

from ninja import ModelSchema
from pydantic import Field

from api.models import Job
from api.schemas.base import DependencyBaseOut, JobBaseOut, TaskBaseOut
from api.utils.generate_custom_schema import generate_custom_field_schema


class JobIn(ModelSchema):
Expand All @@ -14,6 +15,7 @@ class JobIn(ModelSchema):
dependency_ids: List[int] = Field(default=[])
task_ids: List[int] = Field(default=[])
order: int = Field(None, alias="priority")
custom_fields: Optional[generate_custom_field_schema(model_name= 'Job', class_suffix= 'Job')]

class Config:
model = Job
Expand Down
4 changes: 3 additions & 1 deletion backend/api/schemas/task.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# schemas.py
from typing import List
from typing import List, Optional

from ninja import ModelSchema
from pydantic import Field

from api.models import Task
from api.schemas.base import DependencyBaseOut, TaskBaseOut
from api.utils.generate_custom_schema import generate_custom_field_schema


class TaskIn(ModelSchema):
Expand All @@ -17,6 +18,7 @@ class TaskIn(ModelSchema):
predecessor_ids: List[int] = Field(default=[])
successor_ids: List[int] = Field(default=[])
dependency_ids: List[int] = Field(default=[])
custom_fields: Optional[generate_custom_field_schema(model_name= 'Task', class_suffix= 'Task')]

class Config:
model = Task
Expand Down
1 change: 1 addition & 0 deletions backend/api/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class JobFactory(ModelFactory[JobIn]):
priority = 1
dependency_ids = []
task_ids = []
custom_fields = {}


class UserFactory(ModelFactory[UserIn]):
Expand Down
46 changes: 46 additions & 0 deletions backend/api/tests/test_custom_field.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import json
import pytest

# Test params
test_params = [
({
"field_name": "cust_item_first_part",
"related_model": "Item",
"field_type": ["text", "number", "date", "boolean", "datetime", "time"]
}, 201),

({
"field_name": "cust_item_first_part",
"related_model": "NonExistentModel",
"field_type": ["text"]
}, 400),

({
"field_name": "cust_item_first_part",
"related_model": "Item",
"field_type": ["float"] # This should fail
}, 400),
]


@pytest.mark.django_db
@pytest.mark.parametrize(
'input, expected_status_code',
test_params
)
def test_create_customfields(api_client, input: dict, expected_status_code):
for type in input.get('field_type'):
cf_data = input
cf_data['field_type'] = type

response = api_client.post(
"/api/custom-fields/",
json.dumps(cf_data),
content_type="application/json"
)
assert response.status_code == expected_status_code
\
@pytest.mark.django_db
def test_get_customfields(api_client):
response = api_client.get("/api/custom-fields/")
assert response.status_code == 200
2 changes: 1 addition & 1 deletion backend/api/tests/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import pytest


from api.tests.factories import UserCreateFactory, UserFactory


Expand Down Expand Up @@ -81,5 +82,4 @@ def test_update_user_password(api_client, test_update_password_data):
@pytest.mark.django_db
def test_get_current_user(api_client):
response = api_client.get("/api/users/me/")

assert response.status_code == 200
Loading