From ca5f215ad522610b92709aa3002f336f97f82daf Mon Sep 17 00:00:00 2001 From: Holger Burbach Date: Sat, 6 Feb 2021 21:27:31 +0100 Subject: [PATCH] voting identifier templates for proposition types --- ...dentifier_template_for_propositiontypes.py | 37 +++++++++++++++++++ .../concepts/ballot/ballot_views.py | 17 ++++++++- .../proposition_type_contracts.py | 1 + src/ekklesia_portal/datamodel.py | 8 ++++ .../translations/de/LC_MESSAGES/messages.po | 3 ++ .../translations/en/LC_MESSAGES/messages.po | 4 ++ 6 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 alembic/versions/cbe0faa6a28a_voting_identifier_template_for_propositiontypes.py diff --git a/alembic/versions/cbe0faa6a28a_voting_identifier_template_for_propositiontypes.py b/alembic/versions/cbe0faa6a28a_voting_identifier_template_for_propositiontypes.py new file mode 100644 index 00000000..670fb77c --- /dev/null +++ b/alembic/versions/cbe0faa6a28a_voting_identifier_template_for_propositiontypes.py @@ -0,0 +1,37 @@ +"""voting_identifier_template for propositiontypes + +Revision ID: cbe0faa6a28a +Revises: e2ce064655e8 +Create Date: 2021-02-10 15:56:33.797513 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'cbe0faa6a28a' +down_revision = 'e2ce064655e8' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('voting_id_counter', + sa.Column('proposition_type_id', sa.Integer(), nullable=False), + sa.Column('voting_phase_id', sa.Integer(), nullable=False), + sa.Column('counter', sa.Integer(), nullable=True), + sa.ForeignKeyConstraint(['proposition_type_id'], ['propositiontypes.id'], name=op.f('fk_voting_id_counter_proposition_type_id_propositiontypes')), + sa.ForeignKeyConstraint(['voting_phase_id'], ['votingphases.id'], name=op.f('fk_voting_id_counter_voting_phase_id_votingphases')), + sa.PrimaryKeyConstraint('proposition_type_id', 'voting_phase_id', name=op.f('pk_voting_id_counter')) + ) + op.add_column('propositiontypes', sa.Column('voting_identifier_template', sa.Text(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('propositiontypes', 'voting_identifier_template') + op.drop_table('voting_id_counter') + # ### end Alembic commands ### diff --git a/src/ekklesia_portal/concepts/ballot/ballot_views.py b/src/ekklesia_portal/concepts/ballot/ballot_views.py index 072446c8..f2946adc 100644 --- a/src/ekklesia_portal/concepts/ballot/ballot_views.py +++ b/src/ekklesia_portal/concepts/ballot/ballot_views.py @@ -2,8 +2,9 @@ from webob.exc import HTTPBadRequest from ekklesia_portal.app import App -from ekklesia_portal.datamodel import Ballot, SubjectArea, VotingPhase +from ekklesia_portal.datamodel import Ballot, SubjectArea, VotingPhase, VotingIdCounter from ekklesia_portal.permission import EditPermission +import logging from .ballot_cells import BallotCell, BallotsCell, EditBallotCell from .ballot_contracts import BallotForm @@ -68,4 +69,18 @@ def update(self, request, appstruct): return HTTPBadRequest() self.update(**appstruct) + + if self.voting_id is not None: + for proposition in self.propositions: + if not proposition.voting_identifier and self.proposition_type.voting_identifier_template: + v_id_cnt = request.q(VotingIdCounter).filter(VotingIdCounter.proposition_type_id == self.proposition_type_id, VotingIdCounter.voting_phase_id == self.voting_id).scalar() + if v_id_cnt is None: + v_id_cnt = VotingIdCounter(proposition_type_id = self.proposition_type_id, voting_phase_id = self.voting_id, counter= 0) + request.db_session.add(v_id_cnt) + v_id_cnt.counter += 1 + try: + proposition.voting_identifier= self.proposition_type.voting_identifier_template.format(v_id_cnt.counter) + except Exception as e: + logging.error("proposition type {0}: invalid voting identifier template {1}".format(self.proposition_type.name, self.proposition_type.voting_identifier_template)) + return redirect(request.link(self)) diff --git a/src/ekklesia_portal/concepts/proposition_type/proposition_type_contracts.py b/src/ekklesia_portal/concepts/proposition_type/proposition_type_contracts.py index 2f5135d0..9943d259 100644 --- a/src/ekklesia_portal/concepts/proposition_type/proposition_type_contracts.py +++ b/src/ekklesia_portal/concepts/proposition_type/proposition_type_contracts.py @@ -8,6 +8,7 @@ class PropositionTypeSchema(Schema): name = string_property(title=_('name'), validator=Length(max=64)) abbreviation = string_property(title=_('abbreviation'), validator=Length(max=3)) + voting_identifier_template = string_property(title=_('voting_identifier_template'), validator=Length(min=0, max=30), missing=None) description = string_property(title=_('description'), validator=Length(min=10, max=4000), missing='') policy_id = int_property(title=_('policy')) diff --git a/src/ekklesia_portal/datamodel.py b/src/ekklesia_portal/datamodel.py index bcbb0efe..47782a62 100644 --- a/src/ekklesia_portal/datamodel.py +++ b/src/ekklesia_portal/datamodel.py @@ -277,6 +277,7 @@ class PropositionType(Base): # Antragsart id: int = C(Integer, Sequence('id_seq', optional=True), primary_key=True) name: str = C(Text, unique=True, nullable=False) abbreviation: str = C(Text, unique=True, nullable=False) + voting_identifier_template: str = C(Text, nullable=True) description: str = C(Text, server_default='') policy_id: int = C(Integer, ForeignKey('policies.id'), nullable=False) policy: Policy = relationship("Policy", back_populates="proposition_types") @@ -323,6 +324,13 @@ class VotingPhaseType(Base): voting_type = C(Enum(VotingType), nullable=False) # online, urn, assembly, board +class VotingIdCounter(Base): + __tablename__ = 'voting_id_counter' + proposition_type_id: int = C(Integer, ForeignKey('propositiontypes.id'), primary_key=True) + voting_phase_id: int = C(Integer, ForeignKey('votingphases.id'), primary_key=True) + counter: int = C(Integer, nullable=True) + + class VotingPhase(Base): # Abstimmungsperiode __tablename__ = 'votingphases' __table_args__ = ( diff --git a/src/ekklesia_portal/translations/de/LC_MESSAGES/messages.po b/src/ekklesia_portal/translations/de/LC_MESSAGES/messages.po index a873a888..13aca2b8 100644 --- a/src/ekklesia_portal/translations/de/LC_MESSAGES/messages.po +++ b/src/ekklesia_portal/translations/de/LC_MESSAGES/messages.po @@ -1313,6 +1313,9 @@ msgstr "Nein" msgid "vote_by_user_abstention" msgstr "Enthaltung" +msgid "voting_identifier_template" +msgstr "Muster für Bezeichner" + #~ msgid "translation" #~ msgstr "Übersetzung" diff --git a/src/ekklesia_portal/translations/en/LC_MESSAGES/messages.po b/src/ekklesia_portal/translations/en/LC_MESSAGES/messages.po index d58bd972..7582f62a 100644 --- a/src/ekklesia_portal/translations/en/LC_MESSAGES/messages.po +++ b/src/ekklesia_portal/translations/en/LC_MESSAGES/messages.po @@ -1301,6 +1301,10 @@ msgstr "No" msgid "vote_by_user_abstention" msgstr "Abstention" +msgid "voting_identifier_template" +msgstr "Template For Identifier" + + #~ msgid "follow" #~ msgstr "Follow"