Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace consultancies status column with session events #583

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 7 additions & 1 deletion src/euphorie/client/browser/consultancy.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,13 @@ def handle_POST(self):
),
)
self.sqlsession.add(event)
self.context.session.consultancy.status = "validated"
if not self.context.session.is_locked:
locking_view = api.content.get_view(
name="locking_view",
context=self.context,
request=self.request,
)
locking_view.create_event("lock_set")
self.notify_admins()
self.redirect()

Expand Down
7 changes: 0 additions & 7 deletions src/euphorie/client/browser/locking.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,6 @@ def is_locked(self):
"""Return whether the session is locked."""
return self.context.session.is_locked

def is_validated(self):
"""Return whether the session is validated."""
consultancy = self.context.session.consultancy
if consultancy and consultancy.status == "validated":
return True
return self.context.session.consultancy

def show_actions(self):
"""Return whether we should show the actions in the menu."""
if self.is_locked:
Expand Down
3 changes: 1 addition & 2 deletions src/euphorie/client/browser/templates/consultancy.pt
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
id="content-pane"
tal:define="
consultant context/session/consultancy/account|nothing;
status context/session/consultancy/status|nothing;
is_validated python:status == 'validated';
is_validated context/session/is_validated|nothing;
current_user webhelpers/get_current_account;
role_consultant python: consultant and current_user == consultant;
"
Expand Down
3 changes: 0 additions & 3 deletions src/euphorie/client/browser/webhelpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1064,9 +1064,6 @@ def can_lock_session(self):
@property
@memoize
def can_unlock_session(self):
session = self.traversed_session.session
if session.is_validated:
return False
return self.can_lock_session

@property
Expand Down
9 changes: 1 addition & 8 deletions src/euphorie/client/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,11 +449,6 @@ class Consultancy(BaseObject):
back_populates="consultancy",
)

status = schema.Column(
types.Unicode(255),
default="pending",
)


@implementer(IUser)
class Account(BaseObject):
Expand Down Expand Up @@ -829,14 +824,12 @@ def is_validated(self):
.order_by(SessionEvent.time.desc())
)
# TODO: There should be something to remove the validation at a certain point
# see https://github.com/syslabcom/scrum/issues/1160
return bool(query.count())

@property
def is_locked(self):
"""Check if the session is locked."""
if self.is_validated:
return True

event = self.last_locking_event
if not event:
return False
Expand Down
91 changes: 86 additions & 5 deletions src/euphorie/client/tests/test_consultancy.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from euphorie.content.tests.utils import BASIC_SURVEY
from euphorie.testing import EuphorieIntegrationTestCase
from plone import api
from time import sleep
from z3c.saconfig import Session
from zope.interface import alsoProvides

Expand Down Expand Up @@ -158,6 +159,12 @@ def test_validate_permission_denied_to_other_member(self):
account=self.consultant,
session=self.traversed_session.session,
)
event = SessionEvent(
account_id=self.consultant.id,
session_id=self.traversed_session.session.id,
action="validation_requested",
)
self.session.add(event)
with api.env.adopt_user(user=other_member):
with self._get_view(
"panel-validate-risk-assessment",
Expand Down Expand Up @@ -215,6 +222,12 @@ def test_validate_risk_assessment(self):
account=self.consultant,
session=self.traversed_session.session,
)
event = SessionEvent(
account_id=self.consultant.id,
session_id=self.traversed_session.session.id,
action="validation_requested",
)
self.session.add(event)
self.session.flush()
with api.env.adopt_user(user=self.consultant):
with self._get_view(
Expand All @@ -231,7 +244,7 @@ def test_validate_risk_assessment(self):
self.traversed_session.session.consultancy.account,
self.consultant,
)
self.assertEqual(self.traversed_session.session.consultancy.status, "validated")
self.assertTrue(self.traversed_session.session.is_validated)
with api.env.adopt_user(user=self.owner):
with self._get_view(
"consultancy",
Expand All @@ -251,8 +264,7 @@ def test_validate_risk_assessment(self):
timedelta(seconds=5),
)

# TODO check that assessment is locked
# self.assertTrue(self.traversed_session.session.locked)
self.assertTrue(self.traversed_session.session.is_locked)

self.assertEqual(len(mail_fixture.storage), 2)
recipients = {
Expand All @@ -264,12 +276,81 @@ def test_validate_risk_assessment(self):
{"[email protected]", "[email protected]"},
)

# We need to wait at least one second because the datetime
# is stored with that accuracy
sleep(1)

# if locking is enabled...
api.portal.set_registry_record("euphorie.use_locking_feature", True)
# ... then admin/owner can unlock
with api.env.adopt_user(user=self.owner):
with self._get_view(
"locking_view",
self.traversed_session,
self.traversed_session.session,
) as view:
view.unset_lock()

self.session.flush()
self.assertTrue(self.traversed_session.session.is_validated)
self.assertFalse(self.traversed_session.session.is_locked)

def test_validate_locked_risk_assessment(self):
self.traversed_session.session.consultancy = Consultancy(
account=self.consultant,
session=self.traversed_session.session,
)
event = SessionEvent(
account_id=self.consultant.id,
session_id=self.traversed_session.session.id,
action="validation_requested",
)
self.session.add(event)

api.portal.set_registry_record("euphorie.use_locking_feature", True)
with api.env.adopt_user(user=self.owner):
with self._get_view(
"locking_view",
self.traversed_session,
self.traversed_session.session,
) as view:
view.set_lock()
original_lock_event = view.last_locking_event

# Some time passes before the consultant validates the assessment
sleep(3)

with api.env.adopt_user(user=self.consultant):
with self._get_view(
"panel-validate-risk-assessment",
self.traversed_session,
self.traversed_session.session,
) as view:
view.request.method = "POST"
view.request.form = {"approved": "1"}
view()

# consultant stays set
self.assertEqual(
self.traversed_session.session.consultancy.account,
self.consultant,
)
self.assertTrue(self.traversed_session.session.is_validated)
self.assertTrue(self.traversed_session.session.is_locked)
with self._get_view(
"locking_view",
self.traversed_session,
self.traversed_session.session,
) as view:
lock_event = view.last_locking_event
self.assertEqual(lock_event.account, self.owner)
self.assertEqual(lock_event.time, original_lock_event.time)

def test_delete_consultant(self):
now = datetime.utcnow().replace(tzinfo=timezone.utc)
self.traversed_session.session.consultancy = Consultancy(
account=self.consultant,
session=self.traversed_session.session,
status="validated",
)
event = SessionEvent(
account_id=self.consultant.id,
Expand All @@ -289,7 +370,7 @@ def test_delete_consultant(self):
self.session.delete(self.consultant)
self.session.flush()

self.assertEqual(self.traversed_session.session.consultancy.status, "validated")
self.assertTrue(self.traversed_session.session.is_validated)
with api.env.adopt_user(user=self.owner):
with self._get_view(
"consultancy",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""Drop consultancy status column

Revision ID: 20230531153726
Revises: 20230515143459
Create Date: 2023-05-31 15:41:06.990714

"""
from alembic import op
from euphorie.deployment.upgrade.utils import has_column

import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = "20230531153726"
down_revision = "20230515143459"
branch_labels = None
depends_on = None


def upgrade():
if has_column("consultancy", "status"):
op.drop_column("consultancy", "status")


def downgrade():
if not has_column("consultancy", "status"):
op.add_column(
"consultancy",
sa.Column(
"status", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from euphorie.deployment.upgrade.utils import alembic_upgrade_to
from ftw.upgrade import UpgradeStep


class DropConsultancyStatusColumn(UpgradeStep):
"""Drop consultancy status column."""

def __call__(self):
alembic_upgrade_to(self.target_version)