Skip to content

Commit

Permalink
[STTNHUB-376] Add config to not cancel Planning when Event is cancelled
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkLark86 committed Nov 18, 2024
1 parent d7abac0 commit 7352f6d
Show file tree
Hide file tree
Showing 11 changed files with 208 additions and 22 deletions.
2 changes: 2 additions & 0 deletions client/components/ContentProfiles/FieldTab/FieldEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export class FieldEditor extends React.Component<IProps, IState> {
'schema.required': {enabled: !(this.props.disableRequired || this.props.systemRequired)},
'schema.read_only': {enabled: this.props.item.name === 'related_plannings'},
'schema.planning_auto_publish': {enabled: this.props.item.name === 'related_plannings'},
'schema.cancel_plan_with_event': {enabled: this.props.item.name === 'related_plannings'},
'schema.field_type': {enabled: fieldType != null},
'schema.minlength': {enabled: !disableMinMax},
'schema.maxlength': {enabled: !disableMinMax},
Expand Down Expand Up @@ -190,6 +191,7 @@ export class FieldEditor extends React.Component<IProps, IState> {
'schema.languages': {enabled: true, index: 12},
'schema.default_language': {enabled: true, index: 13},
'schema.planning_auto_publish': {enabled: true, index: 14},
'schema.cancel_plan_with_event': {enabled: true, index: 14},
'schema.default_value': {enabled: true, index: 11},
},
{
Expand Down
11 changes: 11 additions & 0 deletions client/components/fields/resources/profiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ registerEditorField(
true
);

registerEditorField(
'schema.cancel_plan_with_event',
EditorFieldCheckbox,
() => ({
label: superdeskApi.localization.gettext('Cancel planning items with Event'),
field: 'schema.cancel_plan_with_event',
}),
null,
true
);

registerEditorField(
'schema.planning_auto_publish',
EditorFieldCheckbox,
Expand Down
3 changes: 3 additions & 0 deletions client/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,7 @@ export interface IProfileSchemaTypeList extends IBaseProfileSchemaType<'list'> {
mandatory_in_list?: {[key: string]: any};
vocabularies?: Array<IVocabulary['_id']>;
planning_auto_publish?: boolean;
cancel_plan_with_event?: boolean;
}

export interface IProfileSchemaTypeInteger extends IBaseProfileSchemaType<'integer'> {}
Expand Down Expand Up @@ -1149,6 +1150,7 @@ export interface IEventFormProfile {
reference: IProfileEditorField;
slugline: IProfileEditorField;
subject: IProfileEditorField;
related_plannings: IProfileEditorField;
};
name: 'event';
schema: {
Expand All @@ -1172,6 +1174,7 @@ export interface IEventFormProfile {
reference: IProfileSchemaTypeString;
slugline: IProfileSchemaTypeString;
subject: IProfileSchemaTypeList;
related_plannings: IProfileSchemaTypeList;
};
}

Expand Down
75 changes: 57 additions & 18 deletions client/utils/planning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ import {planningConfig} from '../config';

const isCoverageAssigned = (coverage) => !!get(coverage, 'assigned_to.desk');

function isCancelPlanWithEventDisabled(): boolean {
return (planningApi.events.getEditorProfile().schema.related_plannings?.cancel_plan_with_event ?? true) === false;
}

function canPostPlanning(
planning: IPlanningItem,
event: IEventItem,
Expand All @@ -81,14 +85,19 @@ function canPostPlanning(
!!privileges[PRIVILEGES.PLANNING_MANAGEMENT] &&
!lockUtils.isLockRestricted(planning, session, locks) &&
getPostedState(planning) !== POST_STATE.USABLE &&
(isNil(event) || getItemWorkflowState(event) !== WORKFLOW_STATE.KILLED) &&
!isItemSpiked(planning) &&
!isItemSpiked(event) &&
(!isItemCancelled(planning) || getItemWorkflowState(planning) === WORKFLOW_STATE.KILLED) &&
!isItemCancelled(event) &&
!isItemRescheduled(planning) &&
!isItemRescheduled(event) &&
!isNotForPublication(planning)
!isNotForPublication(planning) &&
(!isItemCancelled(planning) || getItemWorkflowState(planning) === WORKFLOW_STATE.KILLED) &&
(
isNil(event)
|| isCancelPlanWithEventDisabled()
|| (
getItemWorkflowState(event) !== WORKFLOW_STATE.KILLED
&& !isItemSpiked(event)
&& !isItemRescheduled(event)
)
)
);
}

Expand Down Expand Up @@ -119,11 +128,17 @@ function canEditPlanning(
!!privileges[PRIVILEGES.PLANNING_MANAGEMENT] &&
!lockUtils.isLockRestricted(planning, session, locks) &&
!isItemSpiked(planning) &&
!isItemSpiked(event) &&
!(getPostedState(planning) === POST_STATE.USABLE && !privileges[PRIVILEGES.POST_PLANNING]) &&
!isItemRescheduled(planning) &&
(!isItemExpired(planning) || privileges[PRIVILEGES.EDIT_EXPIRED]) &&
(isNil(event) || getItemWorkflowState(event) !== WORKFLOW_STATE.KILLED)
(
isNil(event)
|| isCancelPlanWithEventDisabled()
|| (
getItemWorkflowState(event) !== WORKFLOW_STATE.KILLED &&
!isItemSpiked(event)
)
)
);
}

Expand All @@ -137,9 +152,13 @@ function canModifyPlanning(
!!privileges[PRIVILEGES.PLANNING_MANAGEMENT] &&
!lockUtils.isItemLocked(planning, locks) &&
!isItemSpiked(planning) &&
!isItemSpiked(event) &&
!isItemCancelled(planning) &&
!isItemRescheduled(planning)
!isItemRescheduled(planning) &&
(
isNil(event)
|| isCancelPlanWithEventDisabled()
|| !isItemSpiked(event)
)
);
}

Expand Down Expand Up @@ -215,10 +234,14 @@ function canUnspikePlanning(
isItemSpiked(plan) &&
!!privileges[PRIVILEGES.UNSPIKE_PLANNING] &&
!!privileges[PRIVILEGES.PLANNING_MANAGEMENT] &&
!isItemSpiked(event) &&
(
!isItemExpired(plan) ||
!!privileges[PRIVILEGES.EDIT_EXPIRED]
) &&
(
isNil(event)
|| isCancelPlanWithEventDisabled()
|| !isItemSpiked(event)
)
);
}
Expand All @@ -234,7 +257,11 @@ function canDuplicatePlanning(
!isItemSpiked(plan) &&
!!privileges[PRIVILEGES.PLANNING_MANAGEMENT] &&
!lockUtils.isLockRestricted(plan, session, locks) &&
!isItemSpiked(event)
(
isNil(event)
|| isCancelPlanWithEventDisabled()
|| !isItemSpiked(event)
)
);
}

Expand All @@ -249,12 +276,16 @@ function canCancelPlanning(
!!privileges[PRIVILEGES.PLANNING_MANAGEMENT] &&
!lockUtils.isLockRestricted(planning, session, locks) &&
getItemWorkflowState(planning) === WORKFLOW_STATE.SCHEDULED &&
getItemWorkflowState(event) !== WORKFLOW_STATE.SPIKED &&
!(
getPostedState(planning) === POST_STATE.USABLE &&
!privileges[PRIVILEGES.POST_PLANNING]
) &&
!isItemExpired(planning)
!isItemExpired(planning) &&
(
isNil(event)
|| isCancelPlanWithEventDisabled()
|| !isItemSpiked(event)
)
);
}

Expand All @@ -269,13 +300,17 @@ function canCancelAllCoverage(
!!privileges[PRIVILEGES.PLANNING_MANAGEMENT] &&
!isItemSpiked(planning) &&
!lockUtils.isLockRestricted(planning, session, locks) &&
getItemWorkflowState(event) !== WORKFLOW_STATE.SPIKED &&
canCancelAllCoverageForPlanning(planning) &&
!(
getPostedState(planning) === POST_STATE.USABLE &&
!privileges[PRIVILEGES.POST_PLANNING]
) &&
!isItemExpired(planning)
!isItemExpired(planning) &&
(
isNil(event)
|| isCancelPlanWithEventDisabled()
|| !isItemSpiked(event)
)
);
}

Expand Down Expand Up @@ -358,9 +393,13 @@ function canAddCoverages(
!!privileges[PRIVILEGES.PLANNING_MANAGEMENT] &&
lockUtils.isItemLocked(planning, locks) &&
lockUtils.isItemLockedInThisSession(planning, session, locks) &&
(isNil(event) || !isItemCancelled(event)) &&
(!isItemCancelled(planning) || isItemKilled(planning)) && !isItemRescheduled(planning) &&
!isItemExpired(planning)
!isItemExpired(planning) &&
(
isNil(event)
|| isCancelPlanWithEventDisabled()
|| !isItemCancelled(event)
)
);
}

Expand Down
106 changes: 106 additions & 0 deletions server/features/events_post.feature
Original file line number Diff line number Diff line change
Expand Up @@ -1257,3 +1257,109 @@ Feature: Events Post
"""
{"failed_planning_ids": [{"_id": "123", "error": ["Related planning : SLUGLINE is a required field"]}]}
"""

@auth
@vocabulary
Scenario: Unposting an event will not unpost planning based on config
Given "planning_types"
"""
[{
"_id": "event",
"name": "event",
"schema": {
"related_plannings": {
"planning_auto_publish": false,
"cancel_plan_with_event": false
}
}
}]
"""
When we post to "events"
"""
{
"name": "TestEvent",
"slugline": "TestEvent",
"dates": {
"start": "2029-11-21T12:00:00.000Z",
"end": "2029-11-21T14:00:00.000Z",
"tz": "Australia/Sydney"
}
}
"""
When we post to "/planning"
"""
{
"item_class": "item class value",
"headline": "test headline",
"slugline": "test slugline",
"planning_date": "2016-01-02",
"event_item": "#events._id#"
}
"""
Then we get OK response
When we post to "/events/post"
"""
{
"event": "#events._id#",
"etag": "#events._etag#",
"pubstatus": "usable"
}
"""
Then we get OK response
When we post to "/planning/post"
"""
{
"planning": "#planning._id#",
"etag": "#planning._etag#",
"pubstatus": "usable"
}
"""
Then we get OK response
When we post to "/events/post"
"""
{
"event": "#events._id#",
"etag": "#events._etag#",
"pubstatus": "cancelled"
}
"""
Then we get OK response
When we get "events/#events._id#"
Then we get existing resource
"""
{
"state": "killed",
"pubstatus": "cancelled"
}
"""
When we get "planning/#planning._id#"
Then we get existing resource
"""
{
"state": "scheduled",
"pubstatus": "usable"
}
"""
When we patch "/planning/#planning._id#"
"""
{"headline": "Updated headline"}
"""
Then we get OK response
When we post to "/planning/post"
"""
{
"planning": "#planning._id#",
"etag": "#planning._etag#",
"pubstatus": "cancelled"
}
"""
Then we get OK response
When we post to "/planning/post"
"""
{
"planning": "#planning._id#",
"etag": "#planning._etag#",
"pubstatus": "usable"
}
"""
Then we get OK response
1 change: 1 addition & 0 deletions server/planning/content_profiles/profiles/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class EventSchema(BaseSchema):
related_plannings = schema.ListField()
related_plannings.schema["read_only"] = False
related_plannings.schema["planning_auto_publish"] = False
related_plannings.schema["cancel_plan_with_event"] = True
registration_details = TextField(field_type="multi_line")
invitation_details = TextField(field_type="multi_line")
accreditation_info = TextField(field_type="single_line")
Expand Down
7 changes: 7 additions & 0 deletions server/planning/content_profiles/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,10 @@ def is_post_planning_with_event_enabled() -> bool:
return get_planning_schema("event")["schema"]["related_plannings"]["planning_auto_publish"] is True
except (KeyError, TypeError):
return False


def is_cancel_planning_with_event_enabled() -> bool:
try:
return get_planning_schema("event")["schema"]["related_plannings"]["cancel_plan_with_event"] is True
except (KeyError, TypeError):
return True
5 changes: 4 additions & 1 deletion server/planning/events/events_post.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
get_version_item_for_post,
)
from planning.utils import try_cast_object_id
from planning.content_profiles.utils import is_post_planning_with_event_enabled
from planning.content_profiles.utils import is_post_planning_with_event_enabled, is_cancel_planning_with_event_enabled


class EventsPostResource(EventsResource):
Expand Down Expand Up @@ -239,6 +239,9 @@ def post_related_plannings(self, plannings, new_post_state):
except Exception as e:
failed_planning_ids.append({"_id": doc["planning"], "error": getattr(e, "description", str(e))})
return failed_planning_ids
elif not is_cancel_planning_with_event_enabled():
return

for planning in plannings:
if not planning.get("pubstatus") and planning.get("state") in [
WORKFLOW_STATE.INGESTED,
Expand Down
Loading

0 comments on commit 7352f6d

Please sign in to comment.