US #55: Custom fields - 3️⃣ 😩 🐯
parent
2893213932
commit
32ff494ddd
|
@ -0,0 +1,87 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models, migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('custom_attributes', '0002_issuecustomattributesvalues_taskcustomattributesvalues_userstorycustomattributesvalues'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
# Function: Remove a key in a json field
|
||||||
|
migrations.RunSQL(
|
||||||
|
"""
|
||||||
|
CREATE OR REPLACE FUNCTION "json_object_delete_keys"("json" json, VARIADIC "keys_to_delete" text[])
|
||||||
|
RETURNS json
|
||||||
|
LANGUAGE sql
|
||||||
|
IMMUTABLE
|
||||||
|
STRICT
|
||||||
|
AS $function$
|
||||||
|
SELECT COALESCE ((SELECT ('{' || string_agg(to_json("key") || ':' || "value", ',') || '}')
|
||||||
|
FROM json_each("json")
|
||||||
|
WHERE "key" <> ALL ("keys_to_delete")),
|
||||||
|
'{}')::json $function$;
|
||||||
|
""",
|
||||||
|
reverse_sql="""DROP FUNCTION IF EXISTS "json_object_delete_keys";"""
|
||||||
|
),
|
||||||
|
|
||||||
|
# Function: Romeve a key in the json field of *_custom_attributes_values.values
|
||||||
|
migrations.RunSQL(
|
||||||
|
"""
|
||||||
|
CREATE OR REPLACE FUNCTION "clean_key_in_custom_attributes_values"()
|
||||||
|
RETURNS trigger
|
||||||
|
AS $clean_key_in_custom_attributes_values$
|
||||||
|
DECLARE
|
||||||
|
key text;
|
||||||
|
tablename text;
|
||||||
|
BEGIN
|
||||||
|
key := OLD.id::text;
|
||||||
|
tablename := TG_ARGV[0]::text;
|
||||||
|
|
||||||
|
EXECUTE 'UPDATE ' || quote_ident(tablename) || '
|
||||||
|
SET values = json_object_delete_keys(values, ' || quote_literal(key) || ')';
|
||||||
|
|
||||||
|
RETURN NULL;
|
||||||
|
END; $clean_key_in_custom_attributes_values$
|
||||||
|
LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
""",
|
||||||
|
reverse_sql="""DROP FUNCTION IF EXISTS "clean_key_in_custom_attributes_values";"""
|
||||||
|
),
|
||||||
|
|
||||||
|
# Trigger: Clean userstorycustomattributes values before remove a userstorycustomattribute
|
||||||
|
migrations.RunSQL(
|
||||||
|
"""
|
||||||
|
CREATE TRIGGER "update_userstorycustomvalues_afeter_remove_userstorycustomattribute"
|
||||||
|
BEFORE DELETE ON custom_attributes_userstorycustomattribute
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE PROCEDURE clean_key_in_custom_attributes_values('custom_attributes_userstorycustomattributesvalues');
|
||||||
|
""",
|
||||||
|
reverse_sql="""DROP TRIGGER "update_userstorycustomvalues_afeter_remove_userstorycustomattribute";"""
|
||||||
|
),
|
||||||
|
|
||||||
|
# Trigger: Clean taskcustomattributes values before remove a taskcustomattribute
|
||||||
|
migrations.RunSQL(
|
||||||
|
"""
|
||||||
|
CREATE TRIGGER "update_taskcustomvalues_afeter_remove_taskcustomattribute"
|
||||||
|
BEFORE DELETE ON custom_attributes_taskcustomattribute
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE PROCEDURE clean_key_in_custom_attributes_values('custom_attributes_taskcustomattributesvalues');
|
||||||
|
""",
|
||||||
|
reverse_sql="""DROP TRIGGER "update_taskcustomvalues_afeter_remove_taskcustomattribute";"""
|
||||||
|
),
|
||||||
|
|
||||||
|
# Trigger: Clean issuecustomattributes values before remove a issuecustomattribute
|
||||||
|
migrations.RunSQL(
|
||||||
|
"""
|
||||||
|
CREATE TRIGGER "update_issuecustomvalues_afeter_remove_issuecustomattribute"
|
||||||
|
BEFORE DELETE ON custom_attributes_issuecustomattribute
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE PROCEDURE clean_key_in_custom_attributes_values('custom_attributes_issuecustomattributesvalues');
|
||||||
|
""",
|
||||||
|
reverse_sql="""DROP TRIGGER "update_issuecustomvalues_afeter_remove_issuecustomattribute";"""
|
||||||
|
)
|
||||||
|
]
|
|
@ -269,3 +269,37 @@ def test_issue_custom_attributes_values_delete_us(client):
|
||||||
assert response.status_code == 204
|
assert response.status_code == 204
|
||||||
assert not issue.__class__.objects.filter(id=issue.id).exists()
|
assert not issue.__class__.objects.filter(id=issue.id).exists()
|
||||||
assert not custom_attrs_val.__class__.objects.filter(id=custom_attrs_val.id).exists()
|
assert not custom_attrs_val.__class__.objects.filter(id=custom_attrs_val.id).exists()
|
||||||
|
|
||||||
|
|
||||||
|
#########################################################
|
||||||
|
# Test tristres triggers :-P
|
||||||
|
#########################################################
|
||||||
|
|
||||||
|
def test_trigger_update_issuecustomvalues_afeter_remove_issuecustomattribute():
|
||||||
|
issue = f.IssueFactory()
|
||||||
|
member = f.MembershipFactory(user=issue.project.owner,
|
||||||
|
project=issue.project,
|
||||||
|
is_owner=True)
|
||||||
|
|
||||||
|
custom_attr_1 = f.IssueCustomAttributeFactory(project=issue.project)
|
||||||
|
ct1_id = "{}".format(custom_attr_1.id)
|
||||||
|
custom_attr_2 = f.IssueCustomAttributeFactory(project=issue.project)
|
||||||
|
ct2_id = "{}".format(custom_attr_2.id)
|
||||||
|
|
||||||
|
custom_attrs_val = f.IssueCustomAttributesValuesFactory(
|
||||||
|
project=issue.project,
|
||||||
|
issue=issue,
|
||||||
|
values= {
|
||||||
|
ct1_id: "test_1",
|
||||||
|
ct2_id: "test_2"
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert ct1_id in custom_attrs_val.values.keys()
|
||||||
|
assert ct2_id in custom_attrs_val.values.keys()
|
||||||
|
|
||||||
|
custom_attr_2.delete()
|
||||||
|
custom_attrs_val = custom_attrs_val.__class__.objects.get(id=custom_attrs_val.id)
|
||||||
|
|
||||||
|
assert ct1_id in custom_attrs_val.values.keys()
|
||||||
|
assert ct2_id not in custom_attrs_val.values.keys()
|
||||||
|
|
|
@ -266,3 +266,37 @@ def test_task_custom_attributes_values_delete_us(client):
|
||||||
assert response.status_code == 204
|
assert response.status_code == 204
|
||||||
assert not task.__class__.objects.filter(id=task.id).exists()
|
assert not task.__class__.objects.filter(id=task.id).exists()
|
||||||
assert not custom_attrs_val.__class__.objects.filter(id=custom_attrs_val.id).exists()
|
assert not custom_attrs_val.__class__.objects.filter(id=custom_attrs_val.id).exists()
|
||||||
|
|
||||||
|
|
||||||
|
#########################################################
|
||||||
|
# Test tristres triggers :-P
|
||||||
|
#########################################################
|
||||||
|
|
||||||
|
def test_trigger_update_userstorycustomvalues_afeter_remove_userstorycustomattribute():
|
||||||
|
user_story = f.UserStoryFactory()
|
||||||
|
member = f.MembershipFactory(user=user_story.project.owner,
|
||||||
|
project=user_story.project,
|
||||||
|
is_owner=True)
|
||||||
|
|
||||||
|
custom_attr_1 = f.UserStoryCustomAttributeFactory(project=user_story.project)
|
||||||
|
ct1_id = "{}".format(custom_attr_1.id)
|
||||||
|
custom_attr_2 = f.UserStoryCustomAttributeFactory(project=user_story.project)
|
||||||
|
ct2_id = "{}".format(custom_attr_2.id)
|
||||||
|
|
||||||
|
custom_attrs_val = f.UserStoryCustomAttributesValuesFactory(
|
||||||
|
project=user_story.project,
|
||||||
|
user_story=user_story,
|
||||||
|
values= {
|
||||||
|
ct1_id: "test_1",
|
||||||
|
ct2_id: "test_2"
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert ct1_id in custom_attrs_val.values.keys()
|
||||||
|
assert ct2_id in custom_attrs_val.values.keys()
|
||||||
|
|
||||||
|
custom_attr_2.delete()
|
||||||
|
custom_attrs_val = custom_attrs_val.__class__.objects.get(id=custom_attrs_val.id)
|
||||||
|
|
||||||
|
assert ct1_id in custom_attrs_val.values.keys()
|
||||||
|
assert ct2_id not in custom_attrs_val.values.keys()
|
||||||
|
|
|
@ -266,3 +266,37 @@ def test_userstory_custom_attributes_values_delete_us(client):
|
||||||
assert response.status_code == 204
|
assert response.status_code == 204
|
||||||
assert not user_story.__class__.objects.filter(id=user_story.id).exists()
|
assert not user_story.__class__.objects.filter(id=user_story.id).exists()
|
||||||
assert not custom_attrs_val.__class__.objects.filter(id=custom_attrs_val.id).exists()
|
assert not custom_attrs_val.__class__.objects.filter(id=custom_attrs_val.id).exists()
|
||||||
|
|
||||||
|
|
||||||
|
#########################################################
|
||||||
|
# Test tristres triggers :-P
|
||||||
|
#########################################################
|
||||||
|
|
||||||
|
def test_trigger_update_userstorycustomvalues_afeter_remove_userstorycustomattribute():
|
||||||
|
user_story = f.UserStoryFactory()
|
||||||
|
member = f.MembershipFactory(user=user_story.project.owner,
|
||||||
|
project=user_story.project,
|
||||||
|
is_owner=True)
|
||||||
|
|
||||||
|
custom_attr_1 = f.UserStoryCustomAttributeFactory(project=user_story.project)
|
||||||
|
ct1_id = "{}".format(custom_attr_1.id)
|
||||||
|
custom_attr_2 = f.UserStoryCustomAttributeFactory(project=user_story.project)
|
||||||
|
ct2_id = "{}".format(custom_attr_2.id)
|
||||||
|
|
||||||
|
custom_attrs_val = f.UserStoryCustomAttributesValuesFactory(
|
||||||
|
project=user_story.project,
|
||||||
|
user_story=user_story,
|
||||||
|
values= {
|
||||||
|
ct1_id: "test_1",
|
||||||
|
ct2_id: "test_2"
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert ct1_id in custom_attrs_val.values.keys()
|
||||||
|
assert ct2_id in custom_attrs_val.values.keys()
|
||||||
|
|
||||||
|
custom_attr_2.delete()
|
||||||
|
custom_attrs_val = custom_attrs_val.__class__.objects.get(id=custom_attrs_val.id)
|
||||||
|
|
||||||
|
assert ct1_id in custom_attrs_val.values.keys()
|
||||||
|
assert ct2_id not in custom_attrs_val.values.keys()
|
||||||
|
|
Loading…
Reference in New Issue