diff --git a/.github/workflows/models.yml b/.github/workflows/models.yml new file mode 100644 index 000000000..aed269800 --- /dev/null +++ b/.github/workflows/models.yml @@ -0,0 +1,30 @@ +name: Validate models.yml +on: [push, pull_request] +jobs: + validate: + name: Validate models.yml + runs-on: ubuntu-latest + steps: + - name: Set up Go 1.15 + uses: actions/setup-go@v1 + with: + go-version: 1.15 + + - name: Install validator + run: go get github.com/OpenSlides/openslides-modelsvalidate/cmd/modelsvalidate + + - name: Check out code + uses: actions/checkout@v2 + + - name: Validate models.yml + run: $HOME/go/bin/modelsvalidate docs/models.yml + + check-old: + name: Check old models.txt + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v2 + + - name: Check MD5 hash of old models.txt + run: echo "4dee769da047e0169b5fe1280f3ea2f0 docs/models.txt" | md5sum --check diff --git a/docs/models.yml b/docs/models.yml new file mode 100644 index 000000000..dcfa6b60c --- /dev/null +++ b/docs/models.yml @@ -0,0 +1,1666 @@ +--- +# Types: +# - Nativ datatypes: string, number, boolean, JSON +# - HTML: A string with HTML content. +# - HTMLVideo: A string with HTML content (with video tags). +# - float: Numbers that are expected to be non-integer. Formatted as in rfc7159. +# - decimal(X): Decimal values represented as a string with X decimal places. +# At the moment we support only X == 6. +# - datetime: Datetime as a unix timestamp. Why a number? This enables queries +# in the DB. And we do not need more precision than 1 second. +# - []: This indicates and arbitrary array of the given type. At the moment +# we support only some types. You can add JSON Schema properties for items +# using the extra property `items` +# Relations: +# - We have the following types: `relation`, `relation-list`, `generic-relation` +# and `generic-relation-list`. +# - Non-generic relations: The simple syntax for such a field +# `to: /`. This is a reference to a collection. The reverse +# relation field in this collection is . E. g. in a motion the field +# `category_id` links to one category where the field `motion_ids` contains the +# motion id. The simple notation for the field is `motion_category/motion_ids`. +# The reverse field has type `relation-list` and is related back to +# `motion/category_id`. The type indicates that there are many +# motion ids. +# - Generic relations: The difference to non-generic relations is that you have a +# list of possible collections. Therefor we split the simple notation up to the +# properties `collection` and `field`. +# Structured fields: +# - There are template fields (see autoupdate service interface) with a `$` as +# the placeholder. We have three different types: `template`, +# `structured-relation` and `structured-tag`. +# - The type `template` describes a structured field for the given model. The +# property `replacement` describes the meaning of the template. The property +# `fields` contains the definition for all the fields that come from the template +# field. +# - The type `structured-relation` describes the content of a related field as a +# structured field (with properties `name`, `replacement` and `through`). +# - The type `structured-tag` describes the content of a related field as a +# structured field where the template is filled with arbitrary strings instead of +# instance ids. +# JSON Schema Properties: +# - You can add JSON Schema properties like `enum` and `description` to the fields. + +organisation: + id: number + name: string + description: HTML + + # Configs + legal_notice: string + privacy_policy: string + login_text: string + theme: string + custom_translations: JSON + + committee_ids: + type: relation-list + to: committee/organisation_id + role_ids: + type: relation-list + to: role/organisation_id + superadmin_role_id: + type: relation + to: role/superadmin_role_for_organisation_id + resource_ids: + type: relation-list + to: resource/organisation_id + +user: + id: number + username: string + title: string + first_name: string + last_name: string + is_active: boolean + is_committee: boolean + password: string + default_password: string + about_me: HTML + gender: string + comment: HTML + number: string + structure_level: string + email: string + last_email_send: string + vote_weight: decimal(6) + + role_id: + type: relation + to: role/user_ids # Attention: prevent impelenting a "default-role" or let a + # user create such a role! This would cause the user_ids-array for this + # role to explode in size. If a user has no role, it should be handles as + # the user has no permission in the organisation and is a "normal" delegate + # there. Just a few users (expected <100) should even get a role and all + # other don't. + + # Meeting and committee + is_present_in_meeting_ids: + type: relation-list + to: meeting/present_user_ids + meeting_id: + type: relation + to: meeting/temporary_user_ids # Temporary users + guest_meeting_ids: + type: relation-list + to: meeting/guest_ids # Guests in meetings + committee_as_member_ids: + type: relation-list + to: committee/member_ids + committee_as_manager_ids: + type: relation-list + to: committee/manager_ids + + # Projection + projection_ids: + type: relation-list + to: projection/element_id + current_projector_ids: + type: relation-list + to: projector/current_element_ids + + # All foreign keys are meeting-specific: + # - Keys are smaller (Space is in O(n^2) for n keys + # in the relation), so this saves storagespace + # - This makes quering things like this possible: + # "Give me all groups for User X in Meeting Y" without + # the need to get all groups and filter them for the meeting + group_$_ids: + type: template + replacement: meeting_id + fields: + type: relation-list + to: group/user_ids + speaker_$_ids: + type: template + replacement: meeting_id + fields: + type: relation-list + to: speaker/user_id + personal_note_$_ids: + type: template + replacement: meeting_id + fields: + type: relation-list + to: personal_note/user_id + supported_motion_$_ids: + type: template + replacement: meeting_id + fields: + type: relation-list + to: motion/supporter_ids + submitted_motion_$_ids: + type: template + replacement: meeting_id + fields: + type: relation-list + to: motion_submitter/user_id + motion_poll_voted_$_ids: + type: template + replacement: meeting_id + fields: + type: relation-list + to: motion_poll/voted_ids + motion_vote_$_ids: + type: template + replacement: meeting_id + fields: + type: relation-list + to: motion_vote/user_id + assignment_candidate_$_ids: + type: template + replacement: meeting_id + fields: + type: relation-list + to: assignment_candidate/user_id + assignment_poll_voted_$_ids: + type: template + replacement: meeting_id + fields: + type: relation-list + to: assignment_poll/voted_ids + assignment_option_$_ids: + type: template + replacement: meeting_id + fields: + type: relation-list + to: assignment_option/user_id + assignment_vote_$_ids: + type: template + replacement: meeting_id + fields: + type: relation-list + to: assignment_vote/user_id + +role: + id: number + name: string + permissions: string[] + + organisation_id: + type: relation + to: organisation/role_ids + superadmin_role_for_organisation_id: + type: relation + to: organisation/superadmin_role_id + user_ids: + type: relation-list + to: user/role_id + +# New: Resource +# Resources are organsation wide "mediafiles", like logos for the organisatio or +# organisation-wide fonts. Therefore, no permission checks are done and the user +# must not be logged in to retrieve files. A resource has a token, e.g. `web_header` +# or `pdf_font_italic`, so the client knowns, where to put the resource. +resource: + id: number + token: string + filesize: number + mimetype: string + + organisation_id: + type: relation + to: organisation/resource_ids + +committee: + id: number + name: + type: string + required: true + description: HTML + + meeting_ids: + type: relation-list + to: meeting/committee_id + template_meeting_id: + type: relation + to: meeting/template_for_committee_id + default_meeting_id: + type: relation + to: meeting/default_meeting_for_committee_id + member_ids: + type: relation-list + to: user/committee_as_member_ids + manager_ids: + type: relation-list + to: user/committee_as_manager_ids + forward_to_committee_ids: + type: relation-list + to: committee/receive_forwardings_from_committee_ids + receive_forwardings_from_committee_ids: + type: relation-list + to: committee/forward_to_committee_ids + organisation_id: + type: relation + to: organisation/committee_ids + required: true + +meeting: + id: number + welcome_title: string + welcome_text: HTMLVideo + + # General + name: + type: string + maxLength: 100 + description: + type: string + maxLength: 100 + location: string + start_time: datetime + end_time: datetime + custom_translations: JSON + + # System + url_name: + type: string + description: For unique urls. + template_for_committee_id: + type: relation + to: committee/template_meeting_id + enable_anonymous: boolean + + # Jitsi/Livestream settings + conference_show: boolean + conference_auto_connect: boolean + conference_los_restriction: boolean + conference_stream_url: string + + # Projector + projector_default_countdown_time: number + projector_countdown_warning_time: + type: number + minimum: 0 + + # Exports + export_csv_encoding: + type: string + enum: + - utf-8 + - iso-8859-15 + export_csv_separator: string + export_pdf_pagenumber_alignment: + type: string + enum: + - left + - right + - center + export_pdf_fontsize: + type: number + enum: + - 10 + - 11 + - 12 + export_pdf_pagesize: + type: string + enum: + - A4 + - A5 + + # Agenda + agenda_show_subtitles: boolean + agenda_enable_numbering: boolean + agenda_number_prefix: + type: string + maxLength: 20 + agenda_numeral_system: + type: string + enum: + - arabic + - roman + agenda_item_creation: + type: string + enum: + - always + - never + - default_yes + - default_no + agenda_new_items_default_visibility: + type: number + enum: + - 1 + - 2 + - 3 + agenda_show_internal_items_on_projector: boolean + + # List of speakers + list_of_speakers_amount_last_on_projector: + type: number + minimum: 0 + list_of_speakers_amount_next_on_projector: boolean + list_of_speakers_couple_countdown: boolean + list_of_speakers_show_amount_of_speakers_on_slide: boolean + list_of_speakers_present_users_only: boolean + list_of_speakers_show_first_contribution: boolean + + # Motions + motions_default_workflow_id: + type: relation + to: motion_workflow/default_workflow_meeting_id + required: true + motions_default_amendment_workflow_id: + type: relation + to: motion_workflow/default_amendment_workflow_meeting_id + required: true + motions_default_statute_amendment_workflow_id: + type: relation + to: motion_workflow/default_statute_amendment_workflow_meeting_id + required: true + motions_preamble: string + motions_default_line_numbering: + type: string + enum: + - outside + - inline + - none + motions_line_length: + type: number + minimium: 40 + motions_reason_required: boolean + motions_enable_text_on_projector: boolean + motions_enable_reason_on_projector: boolean + motions_enable_sidebox_on_projector: boolean + motions_enable_recommendation_on_projector: boolean + motions_show_referring_motions: boolean + motions_show_sequential_number: boolean + motions_recommendations_by: string + motions_statute_recommendations_by: string + motions_recommendation_text_mode: + type: string + enum: + - original + - changed + - diff + - agreed + motions_default_sorting: string + motions_identifier_type: + type: string + enum: + - per_category + - serially_numbered + - manually + motions_identifier_min_digits: number + motions_identifier_with_blank: boolean + motions_statutes_enabled: boolean + motions_amendments_enabled: boolean + motions_amendments_in_main_list: boolean + motions_amendments_of_amendments: boolean + motions_amendments_prefix: string + motions_amendments_text_mode: + type: string + enum: + - freestyle + - fulltext + - paragraph + motions_amendments_multiple_paragraphs: boolean + motions_supporters_min_amount: + type: number + minimum: 0 + motions_supporters_enable_autoremove: boolean + motions_export_title: string + motions_export_preamble: string + motions_export_submitter_recommendation: boolean + motions_export_follow_recommendation: boolean + + motion_poll_ballot_paper_selection: + type: string + enum: + - NUMBER_OF_DELEGATES + - NUMBER_OF_ALL_PARTICIPANTS + - CUSTOM_NUMBER + motion_poll_ballot_paper_number: number + motion_poll_default_type: string + motion_poll_default_100_percent_base: string + motion_poll_default_majority_method: string + motion_poll_default_group_ids: + type: relation-list + to: group/used_as_motion_poll_default_id + + # Users + users_sort_by: + type: string + enum: + - first_name + - last_name + - number + users_enable_presence_view: boolean + users_enable_vote_weight: boolean + users_allow_self_set_present: boolean + users_pdf_welcometitle: string + users_pdf_welcometext: string + users_pdf_url: string + users_pdf_wlan_ssid: string + users_pdf_wlan_password: string + users_pdf_wlan_encryption: + type: string + enum: + - "" + - WEP + - WPA + - nopass + users_email_sender: string + users_email_replyto: string + users_email_subject: string + users_email_body: string + + # Assignments + assignemnts_export_title: string + assignments_export_preamble: string + + assignment_poll_ballot_paper_selection: + type: string + enum: + - NUMBER_OF_DELEGATES + - NUMBER_OF_ALL_PARTICIPANTS + - CUSTOM_NUMBER + assignment_poll_ballot_paper_number: number + assignment_poll_add_candidates_to_list_of_speakers: boolean + assignment_poll_sort_poll_result_by_votes: boolean + assignment_poll_default_type: string + assignment_poll_default_method: string + assignment_poll_default_100_percent_base: string + assignment_poll_default_majority_method: string + assignment_poll_default_group_ids: + type: relation-list + to: group/used_as_assignment_poll_default_id + + projector_ids: + type: relation-list + to: projector/meeting_id + projectiondefault_ids: + type: relation-list + to: projectiondefault/meeting_id + projector_message_ids: + type: relation-list + to: projector_message/meeting_id + projector_countdown_ids: + type: relation-list + to: projector_countdown/meeting_id + tag_ids: + type: relation-list + to: tag/meeting_id + agenda_item_ids: + type: relation-list + to: agenda_item/meeting_id + list_of_speakers_ids: + type: relation-list + to: list_of_speakers/meeting_id + topic_ids: + type: relation-list + to: topic/meeting_id + group_ids: + type: relation-list + to: group/meeting_id + mediafile_ids: + type: relation-list + to: mediafile/meeting_id + motion_ids: + type: relation-list + to: motion/meeting_id + motion_comment_section_ids: + type: relation-list + to: motion_comment_section/meeting_id + motion_category_ids: + type: relation-list + to: motion_category/meeting_id + motion_block_ids: + type: relation-list + to: motion_block/meeting_id + motion_workflow_ids: + type: relation-list + to: motion_workflow/meeting_id + motion_statute_paragraph_ids: + type: relation-list + to: motion_statute_paragraph/meeting_id + motion_poll_ids: + type: relation-list + to: motion_poll/meeting_id + assignment_ids: + type: relation-list + to: assignment/meeting_id + assignment_poll_ids: + type: relation-list + to: assignment_poll/meeting_id + + # No relations to a meeting: + # user; OK, because not meeting-specific + # personal_note + # projection + # speaker + # motion_option + # motion_vote + # motion_comment + # motion_submitter + # motion_change_recommendation + # motion_state + # assignment_candidate + # assignment_option + # assignment_vote + + # Logos and Fonts + logo_$_id: + type: template + replacement: location + fields: + type: relation + to: + collection: mediafile + field: + name: used_as_logo_$_in_meeting_id + type: structured-tag + replacement: location + font_$_id: + type: template + replacement: location + fields: + type: relation + to: + collection: mediafile + field: + name: used_as_font_$_in_meeting_id + type: structured-tag + replacement: location + # Examples: + # logo_web_header: Mediafile; + # font_italic_pdf: Mediafile; + # The client can define these resources. There is no need + # to have whitelist/blacklist on the server. The places must + # be checked: They must match `[a-z]([a-z_]*[a-z])?` and must + # not be longer than 32 characters. + + # Other relations + committee_id: + type: relation + to: committee/meeting_ids + required: true + default_meeting_for_committee_id: + type: relation + to: committee/default_meeting_id + present_user_ids: + type: relation-list + to: user/is_present_in_meeting_ids + temporary_user_ids: + type: relation-list + to: user/meeting_id + guest_ids: + type: relation-list + to: user/guest_meeting_ids + user_ids: + type: number[] + decription: Calculated. All ids from temporary_user_ids, guest_ids and all users assigned to groups. + read_only: true + reference_projector_id: + type: relation + to: projector/used_as_reference_projector_meeting_id + + default_group_id: + type: relation + to: group/default_group_for_meeting_id + required: true + superadmin_group_id: + type: relation + to: group/superadmin_group_for_meeting_id + +group: + id: number + name: + type: string + required: true + permissions: string[] + + user_ids: + type: relation-list + to: + collection: user + field: + name: group_$_ids + type: structured-relation + replacement: meeting_id + default_group_for_meeting_id: + type: relation + to: meeting/default_group_id + superadmin_group_for_meeting_id: + type: relation + to: meeting/superadmin_group_id + mediafile_access_group_ids: + type: relation-list + to: mediafile/access_group_ids + mediafile_inherited_access_group_ids: + type: relation-list + to: mediafile/inherited_access_group_ids + description: Calculated field. + read_only: true + read_comment_section_ids: + type: relation-list + to: motion_comment_section/read_group_ids + write_comment_section_ids: + type: relation-list + to: motion_comment_section/write_group_ids + motion_poll_ids: + type: relation-list + to: motion_poll/entitled_group_ids + assignment_poll_ids: + type: relation-list + to: assignment_poll/entitled_group_ids + used_as_motion_poll_default_id: + type: relation + to: meeting/motion_poll_default_group_ids + used_as_assignment_poll_default_id: + type: relation + to: meeting/assignment_poll_default_group_ids + meeting_id: + type: relation + to: meeting/group_ids + required: true + +personal_note: + id: number + note: HTML + star: boolean + + user_id: + type: relation + to: + collection: user + field: + name: personal_note_$_ids + type: structured-relation + replacement: meeting_id + content_object_id: + type: generic-relation + to: + collection: + - motion + field: personal_note_ids + +tag: + id: number + name: + type: string + required: true + + tagged_ids: + type: generic-relation-list + to: + collection: + - agenda_item + - assignment + - motion + - topic + field: tag_ids + meeting_id: + type: relation + to: meeting/tag_ids + required: true + +agenda_item: + id: number + item_number: string + comment: string + closed: boolean + type: + type: number + enum: + - 1 + - 2 + - 3 + duration: + type: number + description: Given in seconds + minimum: 0 + is_internal: + type: boolean + description: Calculated by the server + read_only: true + is_hidden: + type: boolean + description: Calculated by the server + read_only: true + level: + type: number + description: Calculated by the server + read_only: true + weight: + type: number + default: 0 + + content_object_id: + type: generic-relation + to: + collection: + - motion + - motion_block + - assignment + - topic + field: agenda_item_id + required: true + parent_id: + type: relation + to: agenda_item/child_ids + child_ids: + type: relation-list + to: agenda_item/parent_id + tag_ids: + type: relation-list + to: tag/tagged_ids + projection_ids: + type: relation-list + to: projection/element_id + current_projector_ids: + type: relation-list + to: projector/current_element_ids + meeting_id: + type: relation + to: meeting/agenda_item_ids + required: true + +list_of_speakers: + id: number + closed: boolean + + content_object_id: + type: generic-relation + to: + collection: + - motion + - motion_block + - assignment + - topic + - mediafile + field: list_of_speakers_id + required: true + speaker_ids: + type: relation-list + to: speaker/list_of_speakers_id + projection_ids: + type: relation-list + to: projection/element_id + current_projector_ids: + type: relation-list + to: projector/current_element_ids + meeting_id: + type: relation + to: meeting/list_of_speakers_ids + required: true + +speaker: + id: number + begin_time: + type: datetime + read_only: true + end_time: + type: datetime + read_only: true + weight: + type: number + default: 0 + marked: boolean + + list_of_speakers_id: + type: relation + to: list_of_speakers/speaker_ids + required: true + user_id: + type: relation + to: + collection: user + field: + name: speaker_$_ids + type: structured-relation + replacement: meeting_id + required: true + +topic: + id: number + title: + type: string + required: true + text: HTMLVideo + + attachment_ids: + type: relation-list + to: mediafile/attachment_ids + agenda_item_id: + type: relation + to: agenda_item/content_object_id + required: true + list_of_speakers_id: + type: relation + to: list_of_speakers/content_object_id + required: true + tag_ids: + type: relation-list + to: tag/tagged_ids + meeting_id: + type: relation + to: meeting/topic_ids + required: true + +motion: + id: number + number: string + sequential_number: + type: number + description: The (positive) serial number of this motion. This number is auto-generated and read-only. + read_only: true + title: + type: string + required: true + text: HTML + amendment_paragraph_$: + type: template + replacement: paragraph_number + fields: HTML + modified_final_version: HTML + reason: HTML + category_weight: + type: number + default: 0 + state_extension: string + recommendation_extension: string + sort_weight: + type: number + default: 0 + created: + type: datetime + read_only: true + last_modified: + type: datetime + read_only: true + + lead_motion_id: + type: relation + to: motion/amendment_ids + amendment_ids: + type: relation-list + to: motion/lead_motion_id + sort_parent_id: + type: relation + to: motion/sort_child_ids + sort_child_ids: + type: relation-list + to: motion/sort_parent_id + origin_id: + type: relation + to: motion/derived_motion_ids # Note: The related motions may not be in the same meeting + derived_motion_ids: + type: relation-list + to: motion/origin_id # Note: The related motions may not be in the same meeting + forwarding_tree_motion_ids: number[] # Calculated: All children (derived_motion_ids), grand children, ... and all parents (origin_id). + state_id: + type: relation + to: motion_state/motion_ids + required: true + recommendation_id: + type: relation + to: motion_state/motion_recommendation_ids + recommendation_extension_reference_ids: + type: generic-relation-list + to: + collection: + - motion + field: referenced_in_motion_recommendation_extension_ids + referenced_in_motion_recommendation_extension_ids: + type: relation-list + to: motion/recommendation_extension_reference_ids + category_id: + type: relation + to: motion_category/motion_ids + block_id: + type: relation + to: motion_block/motion_ids + submitter_ids: + type: relation-list + to: motion_submitter/motion_id + supporter_ids: + type: relation-list + to: + collection: user + field: + name: supported_motion_$_ids + type: structured-relation + replacement: meeting_id + poll_ids: + type: relation-list + to: motion_poll/motion_id + change_recommendation_ids: + type: relation-list + to: motion_change_recommendation/motion_id + statute_paragraph_id: + type: relation + to: motion_statute_paragraph/motion_ids + comment_ids: + type: relation-list + to: motion_comment/motion_id + agenda_item_id: + type: relation + to: agenda_item/content_object_id + list_of_speakers_id: + type: relation + to: list_of_speakers/content_object_id + required: true + tag_ids: + type: relation-list + to: tag/tagged_ids + attachment_ids: + type: relation-list + to: mediafile/attachment_ids + projection_ids: + type: relation-list + to: projection/element_id + current_projector_ids: + type: relation-list + to: projector/current_element_ids + personal_note_ids: + type: relation-list + to: personal_note/content_object_id + meeting_id: + type: relation + to: meeting/motion_ids + required: true + +motion_submitter: + id: number + weight: + type: number + default: 0 + + user_id: + type: relation + to: + collection: user + field: + name: submitted_motion_$_ids + type: structured-relation + replacement: meeting_id + motion_id: + type: relation + to: motion/submitter_ids + +motion_comment: + id: number + comment: HTML + + motion_id: + type: relation + to: motion/comment_ids + required: true + section_id: + type: relation + to: motion_comment_section/comment_ids + required: true + +motion_comment_section: + id: number + name: + type: string + required: true + weight: + type: number + default: 0 + + comment_ids: + type: relation-list + to: motion_comment/section_id + read_group_ids: + type: relation-list + to: group/read_comment_section_ids + write_group_ids: + type: relation-list + to: group/write_comment_section_ids + meeting_id: + type: relation + to: meeting/motion_comment_section_ids + required: true + +motion_category: + id: number + name: + type: string + required: true + prefix: + type: string + required: true + weight: + type: number + default: 0 + level: + type: number + description: Calculated field. + read_only: true + + parent_id: + type: relation + to: motion_category/child_ids + child_ids: + type: relation-list + to: motion_category/parent_id + motion_ids: + type: relation-list + to: motion/category_id + meeting_id: + type: relation + to: meeting/motion_category_ids + required: true + +motion_block: + id: number + title: + type: string + required: true + internal: boolean + + motion_ids: + type: relation-list + to: motion/block_id + agenda_item_id: + type: relation + to: agenda_item/content_object_id + list_of_speakers_id: + type: relation + to: list_of_speakers/content_object_id + required: true + projection_ids: + type: relation-list + to: projection/element_id + current_projector_ids: + type: relation-list + to: projector/current_element_ids + meeting_id: + type: relation + to: meeting/motion_block_ids + required: true + +motion_change_recommendation: + id: number + rejected: boolean + internal: boolean + type: + type: number + enum: + - 0 + - 1 + - 2 + - 3 + other_description: string + line_from: + type: number + minimum: 0 + line_to: + type: number + minimum: 0 + text: HTML + creation_time: + type: datetime + read_only: true + + motion_id: + type: relation + to: motion/change_recommendation_ids + required: true + +motion_state: + id: number + name: + type: string + required: true + recommendation_label: string + css_class: + type: string + enum: + - gray + - red + - green + - lightblue + - yellow + restrictions: + type: string[] + items: + enum: + - motions.can_see_internal + - motions.can_manage_metadata + - motions.can_manage + - is_submitter + allow_support: boolean + allow_create_poll: boolean + allow_submitter_edit: boolean + set_number: boolean + show_state_extension_field: boolean + merge_amendment_into_final: + type: number + default: 0 + enum: + - -1 + - 0 + - 1 + show_recommendation_extension_field: boolean + + next_state_ids: + type: relation-list + to: motion_state/previous_state_ids + previous_state_ids: + type: relation-list + to: motion_state/next_state_ids + motion_ids: + type: relation-list + to: motion/state_id + motion_recommendation_ids: + type: relation-list + to: motion/recommendation_id + workflow_id: + type: relation + to: motion_workflow/state_ids + required: true + first_state_of_workflow_id: + type: relation + to: motion_workflow/first_state_id + +motion_workflow: + id: number + name: + type: string + required: true + + state_ids: + type: relation-list + to: motion_state/workflow_id + first_state_id: + type: relation + to: motion_state/first_state_of_workflow_id + required: true + default_workflow_meeting_id: + type: relation + to: meeting/motions_default_workflow_id + default_amendment_workflow_meeting_id: + type: relation + to: meeting/motions_default_amendment_workflow_id + default_statute_amendment_workflow_meeting_id: + type: relation + to: meeting/motions_default_statute_amendment_workflow_id + meeting_id: + type: relation + to: meeting/motion_workflow_ids + required: true + +motion_statute_paragraph: + id: number + title: + type: string + required: true + text: HTML + weight: + type: number + default: 0 + + motion_ids: + type: relation-list + to: motion/statute_paragraph_id + meeting_id: + type: relation + to: meeting/motion_statute_paragraph_ids + required: true + +motion_poll: + id: number + pollmethod: string + state: number + type: string + title: string + onehundred_percent_base: string + majority_method: string + votesvalid: decimal(6) + votesinvalid: decimal(6) + votescast: decimal(6) + user_has_voted: boolean # This is user specific and set during restriction + + motion_id: + type: relation + to: motion/poll_ids + option_ids: + type: relation-list + to: motion_option/poll_id + voted_ids: + type: relation-list + to: + collection: user + field: + name: motion_poll_voted_$_ids + type: structured-relation + replacement: meeting_id + entitled_group_ids: + type: relation-list + to: group/motion_poll_ids + projection_ids: + type: relation-list + to: projection/element_id + current_projector_ids: + type: relation-list + to: projector/current_element_ids + meeting_id: + type: relation + to: meeting/motion_poll_ids + +motion_option: + id: number + yes: decimal(6) + no: decimal(6) + abstain: decimal(6) + + poll_id: + type: relation + to: motion_poll/option_ids + vote_ids: + type: relation-list + to: motion_vote/option_id + +motion_vote: + id: number + weight: decimal(6) + value: string + + option_id: + type: relation + to: motion_option/vote_ids + user_id: + type: relation + to: + collection: user + field: + name: motion_vote_$_ids + type: structured-relation + replacement: meeting_id + +assignment: + id: number + title: + type: string + required: true + description: HTML + open_posts: + type: number + minimum: 0 + phase: + type: number + enum: + - 1 + - 2 + - 3 + default_poll_description: string + number_poll_candidates: boolean + + candidate_ids: + type: relation-list + to: assignment_candidate/assignment_id + poll_ids: + type: relation-list + to: assignment_poll/assignment_id + agenda_item_id: + type: relation + to: agenda_item/content_object_id + list_of_speakers_id: + type: relation + to: list_of_speakers/content_object_id + required: true + tag_ids: + type: relation-list + to: tag/tagged_ids + attachment_ids: + type: relation-list + to: mediafile/attachment_ids + projection_ids: + type: relation-list + to: projection/element_id + current_projector_ids: + type: relation-list + to: projector/current_element_ids + meeting_id: + type: relation + to: meeting/assignment_ids + required: true + +assignment_candidate: + id: number + weight: + type: number + default: 0 + + assignment_id: + type: relation + to: assignment/candidate_ids + user_id: + type: relation + to: + collection: user + field: + name: assignment_candidate_$_ids + type: structured-relation + replacement: meeting_id + +assignment_poll: + id: number + description: string + pollmethod: string + votes_amount: number + allow_multiple_votes_per_candidate: boolean + global_abstain: boolean + global_no: boolean + amount_global_abstain: decimal(6) + amount_global_no: decimal(6) + state: number + title: string + type: string + onehundred_percent_base: string + majority_method: string + votescast: decimal(6) + votesinvalid: decimal(6) + votesvalid: decimal(6) + user_has_voted: boolean # This is user specific and set during restriction + + assignment_id: + type: relation + to: assignment/poll_ids + voted_ids: + type: relation-list + to: + collection: user + field: + name: assignment_poll_voted_$_ids + type: structured-relation + replacement: meeting_id + entitled_group_ids: + type: relation-list + to: group/assignment_poll_ids + option_ids: + type: relation-list + to: assignment_option/poll_id + projection_ids: + type: relation-list + to: projection/element_id + current_projector_ids: + type: relation-list + to: projector/current_element_ids + meeting_id: + type: relation + to: meeting/assignment_poll_ids + +assignment_option: + id: number + yes: decimal(6) + no: decimal(6) + abstain: decimal(6) + weight: + type: number + default: 0 + + poll_id: + type: relation + to: assignment_poll/option_ids + user_id: + type: relation + to: + collection: user + field: + name: assignment_option_$_ids + type: structured-relation + replacement: meeting_id + vote_ids: + type: relation-list + to: assignment_vote/option_id + +assignment_vote: + id: number + value: string + weight: decimal(6) + + option_id: + type: relation + to: assignment_option/vote_ids + user_id: + type: relation + to: + collection: user + field: + name: assignment_vote_$_ids + type: structured-relation + replacement: meeting_id + +# Mediafiles are delivered by the mediafile server with the URL +# `/media//path` +mediafile: + id: number + title: + type: string + description: Title and parent_id must be unique. + is_directory: boolean + filesize: + type: number + description: In bytes, not the human readable format anymore. + read_only: true + filename: + type: string + descriptin: The uploaded filename. Will be used for downloading. Only writeable on create. + required: true + mimetype: string + pdf_information: JSON + create_timestamp: datetime + has_inherited_access_groups: + type: boolean + description: Calculated field. + read_only: true + + inherited_access_group_ids: + type: relation-list + to: group/mediafile_inherited_access_group_ids + description: Calculated field. + read_only: true + access_group_ids: + type: relation-list + to: group/mediafile_access_group_ids + parent_id: + type: relation + to: mediafile/child_ids + child_ids: + type: relation-list + to: mediafile/parent_id + list_of_speakers_id: + type: relation + to: list_of_speakers/content_object_id + required: true + projection_ids: + type: relation-list + to: projection/element_id + current_projector_ids: + type: relation-list + to: projector/current_element_ids + attachment_ids: + type: generic-relation-list + to: + collection: + - motion + - topic + - assignment + field: attachment_ids + meeting_id: + type: relation + to: meeting/mediafile_ids + required: true + + # Reverse relations for meetings, if a mediafile is used as a special resource + used_as_logo_$_in_meeting_id: + type: template + replacement: location + fields: + type: relation + to: + collection: meeting + field: + name: logo_$_id + type: structured-tag + replacement: location + used_as_font_$_in_meeting_id: + type: template + replacement: location + fields: + type: relation + to: + collection: meeting + field: + name: font_$_id + type: structured-tag + replacement: location + +projector: + id: number + name: string + scale: number + scroll: number + width: number + aspect_ratio_numerator: number + aspect_ratio_denominator: number + color: string + background_color: string + header_background_color: string + header_font_color: string + header_h1_color: string + chyron_background_color: string + chyron_font_color: string + show_header_footer: boolean + show_title: boolean + show_logo: boolean + + current_projection_ids: + type: relation-list + to: projection/current_projector_id + # A relation to the currently projected elements to get a direct link, if + # the element is projected. + current_element_ids: + type: generic-relation-list + to: + collection: + - motion + - mediafile + - list_of_speakers + - motion_block + - assignment + - agenda_item + - user + - assignment_poll + - motion_poll + - projector_message + - projector_countdown + field: current_projector_ids + preview_projection_ids: + type: relation-list + to: projection/preview_projector_id + history_projection_ids: + type: relation-list + to: projection/history_projector_id + used_as_reference_projector_meeting_id: + type: relation + to: meeting/reference_projector_id + projectiondefault_ids: + type: relation-list + to: projectiondefault/projector_id + meeting_id: + type: relation + to: meeting/projector_ids + +# A projection is a M2M model between an element that is assigned to a +# projector. This element can either be the current one projected, in the +# preview, or in the history, but not more than one once. A projection is +# projector-specific, meaning that once a projection is created for a projector +# and element, these references will not change. +projection: + id: number + options: JSON + + current_projector_id: + type: relation + to: projector/current_projection_ids + preview_projector_id: + type: relation + to: projector/preview_projection_ids + history_projector_id: + type: relation + to: projector/history_projection_ids + element_id: + type: generic-relation + to: + collection: + - motion + - mediafile + - list_of_speakers + - motion_block + - assignment + - agenda_item + - user + - assignment_poll + - motion_poll + - projector_message + - projector_countdown + field: projection_ids + +projectiondefault: + id: number + name: string + display_name: string + + projector_id: + type: relation + to: projector/projectiondefault_ids + meeting_id: + type: relation + to: meeting/projectiondefault_ids + +projector_message: + id: number + message: HTML + + projection_ids: + type: relation-list + to: projection/element_id + current_projector_ids: + type: relation-list + to: projector/current_element_ids + meeting_id: + type: relation + to: meeting/projector_message_ids + +projector_countdown: + id: number + title: string + description: string + default_time: number + countdown_time: number # float? + running: boolean + + projection_ids: + type: relation-list + to: projection/element_id + current_projector_ids: + type: relation-list + to: projector/current_element_ids + meeting_id: + type: relation + to: meeting/projector_countdown_ids