diff --git a/compendium_v2/db/model.py b/compendium_v2/db/model.py
index d619c1f362e0855015838400fc319fc4c102ffb6..a9d92279471b062e8e45a03ab5a4355b5b123369 100644
--- a/compendium_v2/db/model.py
+++ b/compendium_v2/db/model.py
@@ -124,6 +124,7 @@ class Policy(db.Model):
     acceptable_use: Mapped[str]
     privacy_notice: Mapped[str]
     data_protection: Mapped[str]
+    gender_equality: Mapped[str]
 
 
 class TrafficVolume(db.Model):
diff --git a/compendium_v2/migrations/versions/3cef2a22ebf1_add_gender_equality_policy.py b/compendium_v2/migrations/versions/3cef2a22ebf1_add_gender_equality_policy.py
new file mode 100644
index 0000000000000000000000000000000000000000..e627c11131106dae14620b7c79963d4ff22a2970
--- /dev/null
+++ b/compendium_v2/migrations/versions/3cef2a22ebf1_add_gender_equality_policy.py
@@ -0,0 +1,32 @@
+"""empty message
+
+Revision ID: 3cef2a22ebf1
+Revises: 3730c7f1ea1b
+Create Date: 2023-09-07 14:29:11.149798
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '3cef2a22ebf1'
+down_revision = '3730c7f1ea1b'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    with op.batch_alter_table('policy', schema=None) as batch_op:
+        batch_op.add_column(sa.Column('gender_equality', sa.String(), nullable=False))
+
+    # ### end Alembic commands ###
+
+
+def downgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    with op.batch_alter_table('policy', schema=None) as batch_op:
+        batch_op.drop_column('gender_equality')
+
+    # ### end Alembic commands ###
diff --git a/compendium_v2/publishers/survey_publisher_2022.py b/compendium_v2/publishers/survey_publisher_2022.py
index f0591e531ce30f76367c43f4c3b551f95ddbae3c..ab415b59d2a192c8f318ef4b61472c03fbce2a41 100644
--- a/compendium_v2/publishers/survey_publisher_2022.py
+++ b/compendium_v2/publishers/survey_publisher_2022.py
@@ -500,7 +500,8 @@ def transfer_policies(nren_dict):
         'connectiviy':     {2022: 16475, 2021: 16068, 2020: 15724, 2019: 15309, 2018: 14914},
         'acceptable_use':  {2022: 16477, 2021: 16070, 2020: 15726, 2019: 15311, 2018: 14916},
         'privacy':         {2022: 16479, 2021: 16072, 2020: 15728, 2019: 15575},
-        'data_protection': {2022: 16481, 2021: 16074, 2020: 15730, 2019: 15577}
+        'data_protection': {2022: 16481, 2021: 16074, 2020: 15730, 2019: 15577},
+        'gender':          {2022: 16761}  # TODO older years too??
     }
 
     data = {}
diff --git a/compendium_v2/publishers/survey_publisher_v2.py b/compendium_v2/publishers/survey_publisher_v2.py
index 09570b376dd81976e6259bfea5666fffb2eb9c15..7ec6b8c1a11d16ecfdf0a96ce6462620ef276146 100644
--- a/compendium_v2/publishers/survey_publisher_v2.py
+++ b/compendium_v2/publishers/survey_publisher_v2.py
@@ -8,7 +8,9 @@ from compendium_v2.db.model import BudgetEntry, ChargingStructure, ECProject, Fe
 from compendium_v2.db.survey_model import ResponseStatus, SurveyResponse
 
 
-def map_2023(year, nren, answers):
+def map_2023(nren, answers):
+    year = 2023
+
     for table_class in [BudgetEntry, ChargingStructure, ECProject, FundingSource, InstitutionURLs,
                         NrenStaff, ParentOrganization, Policy, SubOrganization, TrafficVolume]:
         db.session.execute(delete(table_class).where(table_class.year == 2023))
@@ -51,16 +53,22 @@ def map_2023(year, nren, answers):
     subs = answers.get("suborganization_details")
     if subs:
         for sub in subs:
+            role = sub.get("suborganization_role", "")
+            if role == "other":
+                role = sub.get("suborganization_role-Comment", "")
             db.session.add(SubOrganization(
                 nren_id=nren.id, nren=nren, year=year,
                 organization=sub.get("suborganization_name"),
-                role=sub.get("suborganization_role")  # TODO handle 'other' option properly
+                role=role
             ))
 
     ec_projects = answers.get("ec_project_names")
     if ec_projects:
         for ec_project in ec_projects:
-            db.session.add(ECProject(nren_id=nren.id, nren=nren, year=year, project=ec_project.get("ec_project_name")))
+            if ec_project:
+                db.session.add(
+                    ECProject(nren_id=nren.id, nren=nren, year=year, project=ec_project.get("ec_project_name"))
+                )
 
     strategy = answers.get("corporate_strategy_url", "")
     policies = answers.get("policies", {})
@@ -73,15 +81,14 @@ def map_2023(year, nren, answers):
             connectivity=policies.get("connectivity_policy", {}).get("url", ""),
             acceptable_use=policies.get("acceptable_use_policy", {}).get("url", ""),
             privacy_notice=policies.get("privacy_notice", {}).get("url", ""),
-            data_protection=policies.get("data_protection_contact", {}).get("url", "")
-            # TODO gender_equality_policy missing?
+            data_protection=policies.get("data_protection_contact", {}).get("url", ""),
+            gender_equality=policies.get("gender_equality_policy", {}).get("url", "")
         ))
 
     traffic_estimate = answers.get("traffic_estimate")
     if traffic_estimate:
         db.session.add(TrafficVolume(
             nren_id=nren.id, nren=nren, year=year,
-            strategic_plan=strategy,
             to_customers=Decimal(traffic_estimate.get("to_customers")),
             from_customers=Decimal(traffic_estimate.get("from_customers")),
             to_external=Decimal(traffic_estimate.get("to_external")),
@@ -90,10 +97,12 @@ def map_2023(year, nren, answers):
 
     institution_urls = answers.get("connected_sites_lists")
     if institution_urls:
-        db.session.add(InstitutionURLs(
-            nren_id=nren.id, nren=nren, year=year,
-            urls=institution_urls,
-        ))
+        urls=[i.get("connected_sites_url", "") for i in institution_urls if i.get("connected_sites_url", "") != ""]
+        if urls:
+            db.session.add(InstitutionURLs(
+                nren_id=nren.id, nren=nren, year=year,
+                urls=urls
+            ))
 
 
 def publish(year):
@@ -109,4 +118,4 @@ def publish(year):
     mapping_function = question_mapping[year]
 
     for response in responses:
-        mapping_function(year, response.nren, response.answers)
+        mapping_function(response.nren, response.answers)
diff --git a/test/data/2023_all_questions_answered.json b/test/data/2023_all_questions_answered.json
new file mode 100644
index 0000000000000000000000000000000000000000..5a6a78f10bc96b7abef485fd29cc0249fe938b7a
--- /dev/null
+++ b/test/data/2023_all_questions_answered.json
@@ -0,0 +1,908 @@
+{
+    "abbreviation_english": "MREN/UoM",
+    "abbreviation_national_languages": "UCG",
+    "alienwave_internal": "No",
+    "alienwave_services": "Yes",
+    "alienwave_services_number": "66",
+    "audit_specifics": "isooo  557",
+    "audits": "Yes",
+    "budget": "124.76",
+    "business_continuity_plans": "Yes",
+    "business_continuity_plans_specifics": "no",
+    "central_procurement_amount": "57676",
+    "central_software_procurement": "Yes",
+    "certificate_service": [
+        "other",
+        "TCS",
+        "Digicert",
+        "Sectigo",
+        "GlobalSign",
+        "GeoDaddy",
+        "GeoTrust",
+        "Entrust Datacard"
+    ],
+    "certificate_service-Comment": "earer",
+    "charging_mechanism": "usage_based_fee",
+    "city": "Podgorica",
+    "commercial_charging_levels": {
+        "collaboration": {
+            "charging_level": "no_charges_if_r_e_requested"
+        },
+        "peering": {
+            "charging_level": "higher_than_r_e_charges"
+        },
+        "services": {
+            "charging_level": "same_as_r_e_charges"
+        }
+    },
+    "commercial_organizations": {
+        "commercial_collaboration": {
+            "connection": "yes_incl_other"
+        },
+        "commercial_general": {
+            "connection": "no_policy"
+        },
+        "commercial_r_e": {
+            "connection": "no_but_direct_peering"
+        },
+        "commercial_service_provider": {
+            "connection": "no_other"
+        },
+        "university_spin_off": {
+            "connection": "no_financial"
+        }
+    },
+    "commodity_vs_r_e": {
+        "commodity": "99",
+        "r_e": "1"
+    },
+    "connected_sites_lists": [
+        {
+            "connected_sites_url": "http://erse.com"
+        },
+        {},
+        {
+            "connected_sites_url": "https://wwe.com"
+        }
+    ],
+    "connected_users_comments": "cygfu",
+    "connectivity_level": {
+        "cultural": {
+            "highest_speed": "100",
+            "highest_speed_connection_percentage": "100",
+            "typical_speed": "100"
+        },
+        "for_profit_orgs": {
+            "highest_speed": "7"
+        },
+        "further_education": {
+            "highest_speed": "100",
+            "typical_speed": "100"
+        },
+        "government": {
+            "highest_speed": "100",
+            "highest_speed_connection_percentage": "100",
+            "typical_speed": "100"
+        },
+        "hospitals": {
+            "typical_speed": "7"
+        },
+        "institutes": {
+            "highest_speed": "100",
+            "highest_speed_connection_percentage": "100",
+            "typical_speed": "100"
+        },
+        "iros": {
+            "highest_speed": "7"
+        },
+        "primary_schools": {
+            "typical_speed": "7"
+        },
+        "secondary_schools": {
+            "typical_speed": "7"
+        },
+        "universities": {
+            "highest_speed": "1000",
+            "highest_speed_connection_percentage": "60",
+            "typical_speed": "100"
+        }
+    },
+    "connectivity_proportions": {
+        "cultural": {
+            "covered": "no_other",
+            "nr_connected": "1"
+        },
+        "for_profit_orgs": {
+            "covered": "yes_national_nren",
+            "nr_of_users": "3"
+        },
+        "further_education": {
+            "covered": "yes_incl_other",
+            "market_share_percentage": "1",
+            "nr_connected": "0"
+        },
+        "government": {
+            "covered": "yes_national_nren",
+            "nr_connected": "1"
+        },
+        "hospitals": {
+            "covered": "unsure",
+            "market_share_percentage": "32"
+        },
+        "institutes": {
+            "covered": "no_financial",
+            "nr_connected": "2"
+        },
+        "iros": {
+            "covered": "yes_national_nren",
+            "nr_of_users": "3"
+        },
+        "primary_schools": {
+            "nr_connected": "55"
+        },
+        "secondary_schools": {
+            "covered": "sometimes",
+            "nr_connected": "0"
+        },
+        "universities": {
+            "covered": "yes_national_nren",
+            "market_share_percentage": "1",
+            "nr_connected": "19",
+            "nr_of_users": "20000"
+        }
+    },
+    "corporate_strategy": "Yes",
+    "corporate_strategy_url": "https://serere.com",
+    "country": "Montenegro",
+    "crisis_exercises": [
+        "geant_workshops",
+        "national_excercises",
+        "tabletop_exercises",
+        "other_excercises",
+        "none",
+        "simulation_excercises",
+        "real_crisis"
+    ],
+    "crisis_management_procedure": "No",
+    "dark_fibre_lease": "Yes",
+    "dark_fibre_lease_duration": "10",
+    "dark_fibre_lease_kilometers_inside_country": "405",
+    "dark_fibre_lease_kilometers_outside_country": "0",
+    "dark_fibre_nren": "Yes",
+    "dark_fibre_nren_kilometers_inside_country": "1",
+    "ec_project_names": [
+        {
+            "ec_project_name": "dgdg"
+        },
+        {},
+        {
+            "ec_project_name": "st"
+        },
+        {
+            "ec_project_name": "rrrrr"
+        }
+    ],
+    "ec_projects": "Yes",
+    "email_address": "cis@ucg.ac.me",
+    "external_connections": [
+        {
+            "capacity": "1",
+            "from_organization": "GEANT",
+            "interconnection_method": "geant",
+            "link_name": "GEANT",
+            "to_organization": "MREN"
+        },
+        {
+            "capacity": "1",
+            "from_organization": "MTEL",
+            "interconnection_method": "direct",
+            "link_name": "Mtel",
+            "to_organization": "MREN"
+        },
+        {
+            "capacity": "1",
+            "from_organization": "MREN",
+            "interconnection_method": "internet_exchange",
+            "link_name": "IXP",
+            "to_organization": "MREN"
+        },
+        {
+            "interconnection_method": "other"
+        },
+        {
+            "capacity": "1.1"
+        },
+        {
+            "from_organization": "a",
+            "interconnection_method": "open_exchange",
+            "to_organization": "a"
+        }
+    ],
+    "fibre_light": "other",
+    "fibre_light-Comment": "jj",
+    "formal_service_management_framework": "Yes",
+    "full_name_english": "Montenegrin Research and Education Network/University of Montenegro",
+    "full_name_national_languages": "Crnogorska naucnko istrazivacka mreza/Univerzitet Crne Gore",
+    "income_sources": {
+        "client_institutions": "0",
+        "european_funding": "20",
+        "gov_public_bodies": "70",
+        "other": "10"
+    },
+    "max_capacity": "1",
+    "monitoring_tools": [
+        "status_dashboard",
+        "historical_traffic_volumes",
+        "netflow_analysis",
+        "looking_glass",
+        "other"
+    ],
+    "monitoring_tools-Comment": "hiui",
+    "netflow_vendors": "ghhhh",
+    "network_automation": "Planned",
+    "network_automation_tasks": [
+        "config_management",
+        "provisioning",
+        "data_collection",
+        "compliance",
+        "reporting",
+        "troubleshooting"
+    ],
+    "network_comments": "dfghjk",
+    "network_map_urls": [
+        {
+            "network_map_url": "http://netmon.ucg.ac.me/mantra/"
+        }
+    ],
+    "network_weather": "Yes",
+    "network_weather_url": "http://weather.com",
+    "nfv": "Planned",
+    "nfv_types": [
+        "routers",
+        "firewalls",
+        "load_balancers",
+        "vpn_concentrators",
+        "other"
+    ],
+    "nfv_types-Comment": "rtghjk",
+    "non_r_and_e_peers": "0",
+    "operational_process_automation": "Yes",
+    "operational_process_automation_tools": "ghioil;",
+    "organization_comments": "hkhoj",
+    "parent_organization": "Yes",
+    "parent_organization_name": "sdtfgd",
+    "passive_monitoring": "Yes",
+    "passive_monitoring_tech": "both",
+    "pert_team": "Planned",
+    "phone_number": "+382 20 414 282",
+    "policies": {
+        "acceptable_use_policy": {
+            "available": [
+                "yes"
+            ],
+            "url": "http://www.ucg.ac.me/skladiste/blog_1028/objava_10/fajlovi/Pravila%20o%20koriscenju%20Akademske%20mreze%20Univerziteta%20Crne%20Gore.pdf"
+        },
+        "connectivity_policy": {
+            "available": [
+                "yes"
+            ],
+            "url": "http://www.ucg.ac.me/skladiste/blog_1028/objava_10/fajlovi/Pravila%20o%20koriscenju%20Akademske%20mreze%20Univerziteta%20Crne%20Gore.pdf"
+        },
+        "data_protection_contact": {
+            "available": [
+                "yes"
+            ]
+        },
+        "environmental_policy": {
+            "available": [
+                "yes"
+            ],
+            "url": "http://mren.ac.me/documents/Environmental%20policy%20for%20MREN.pdf"
+        },
+        "equal_opportunity_policy": {},
+        "gender_equality_policy": {
+            "available": [
+                "yes"
+            ],
+            "url": "https://www.ucg.ac.me/objava/blog/616808/objava/148423-plan-rodne-ravnopravnosti-univerziteta-crne-gore"
+        },
+        "privacy_notice": {}
+    },
+    "policy_comments": "cgju",
+    "postal_code": "81000",
+    "remote_campuses": "Yes",
+    "remote_campuses_specifics": [
+        {
+            "connected": "No",
+            "country": "fyuyg"
+        },
+        {
+            "country": "g"
+        }
+    ],
+    "security_controls": [
+        "monitoring",
+        "acl",
+        "anti_virus",
+        "firewall",
+        "anti_spam",
+        "ddos_mitigation",
+        "ips_ids",
+        "segmentation",
+        "integrity_checking",
+        "other"
+    ],
+    "security_controls-Comment": "vgjh",
+    "service_comments": "aarrrggg",
+    "service_level_targets": "No",
+    "service_matrix": {
+        "cultural": {
+            "service_types": [
+                "multimedia"
+            ]
+        },
+        "for_profit_orgs": {
+            "service_types": [
+                "multimedia"
+            ]
+        },
+        "further_education": {
+            "service_types": [
+                "collaboration"
+            ]
+        },
+        "government": {
+            "service_types": [
+                "identity",
+                "network_services",
+                "collaboration",
+                "security",
+                "isp_support",
+                "multimedia"
+            ]
+        },
+        "hospitals": {
+            "service_types": [
+                "professional_services"
+            ]
+        },
+        "institutes": {
+            "service_types": [
+                "identity",
+                "network_services",
+                "collaboration",
+                "security",
+                "isp_support",
+                "storage_and_hosting",
+                "multimedia"
+            ]
+        },
+        "iros": {
+            "service_types": [
+                "collaboration"
+            ]
+        },
+        "primary_schools": {
+            "service_types": [
+                "network_services"
+            ]
+        },
+        "secondary_schools": {
+            "service_types": [
+                "collaboration"
+            ]
+        },
+        "universities": {
+            "service_types": [
+                "identity",
+                "network_services",
+                "collaboration",
+                "security",
+                "isp_support",
+                "storage_and_hosting",
+                "multimedia"
+            ]
+        }
+    },
+    "service_portfolio_eosc_portal": "Yes",
+    "services_collaboration": {
+        "e-portfolio": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "identifier-reg": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "journal-library-access": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "mailing-lists": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "project-collaboration-toolkit": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "scheduling-tool": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "survey-tool": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "virtual-learning-environment": {
+            "additional_information": "zd",
+            "offered": [
+                "yes"
+            ]
+        },
+        "voip": {
+            "description": "dzf",
+            "offered": [
+                "yes"
+            ]
+        },
+        "web-email-hosting": {
+            "name": "zdf",
+            "offered": [
+                "yes"
+            ]
+        }
+    },
+    "services_hosting": {
+        "cloud-service-end-user": {
+            "name": "zdf\"'\\'\\\"",
+            "offered": [
+                "yes"
+            ]
+        },
+        "content-delivery-hosting": {
+            "description": "zdf\nzsd",
+            "offered": [
+                "yes"
+            ]
+        },
+        "disaster-recovery": {
+            "additional_information": "zfzd",
+            "offered": [
+                "yes"
+            ]
+        },
+        "dns-server": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "email-services": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "filesender": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "saas": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "storage-co-location": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "virtual-machines-iaas": {
+            "offered": [
+                "yes"
+            ]
+        }
+    },
+    "services_identity": {
+        "aai": {
+            "name": "zdf",
+            "offered": [
+                "yes"
+            ]
+        },
+        "eduroam-wifi": {
+            "description": "zdf",
+            "offered": [
+                "yes"
+            ]
+        },
+        "interfederation": {
+            "additional_information": "zdf\nzfzd",
+            "offered": [
+                "yes"
+            ]
+        }
+    },
+    "services_isp": {
+        "domain-registration": {
+            "name": "zdfzd",
+            "offered": [
+                "yes"
+            ]
+        },
+        "ip-address-allocation": {
+            "additional_information": "dfzd",
+            "description": "zdf",
+            "offered": [
+                "yes"
+            ]
+        },
+        "ix-operation": {
+            "additional_information": "zdfzd",
+            "offered": [
+                "yes"
+            ]
+        },
+        "nameserver": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "timeserver-ntp": {
+            "offered": [
+                "yes"
+            ]
+        }
+    },
+    "services_multimedia": {
+        "internet-radio-tv": {
+            "name": "zf",
+            "offered": [
+                "yes"
+            ]
+        },
+        "video-portal": {
+            "additional_information": "zdf",
+            "offered": [
+                "yes"
+            ]
+        },
+        "videoconferencing": {
+            "description": "zd",
+            "offered": [
+                "yes"
+            ]
+        },
+        "web-conferencing": {
+            "offered": [
+                "yes"
+            ]
+        }
+    },
+    "services_network": {
+        "connectivity": {
+            "name": "zfz",
+            "offered": [
+                "yes"
+            ]
+        },
+        "home-vpn": {
+            "description": "zdfdzf",
+            "offered": [
+                "yes"
+            ]
+        },
+        "ipv6": {
+            "additional_information": "zdfd",
+            "offered": [
+                "yes"
+            ]
+        },
+        "lambda": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "managed-router": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "multicast": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "netflow": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "network-monitoring": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "open-lightpath-exchange": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "pert": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "point-to-point-circuit-vpn": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "quality-of-service": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "user-monitoring": {
+            "offered": [
+                "yes"
+            ]
+        }
+    },
+    "services_on_eosc_portal_list": [
+        {},
+        {
+            "service_name": "dy"
+        },
+        {
+            "service_name": "rrr"
+        }
+    ],
+    "services_professional": {
+        "consultancy": {
+            "additional_information": "dfd",
+            "offered": [
+                "yes"
+            ]
+        },
+        "dissemination": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "procurement": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "software-licenses": {
+            "description": "zdfzd",
+            "offered": [
+                "yes"
+            ]
+        },
+        "user-conference": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "user-portal": {
+            "name": "zdfdz",
+            "offered": [
+                "yes"
+            ]
+        }
+    },
+    "services_security": {
+        "anti-spam": {
+            "name": "zdfzd",
+            "offered": [
+                "yes"
+            ]
+        },
+        "csirt": {
+            "description": "zdf",
+            "offered": [
+                "yes"
+            ]
+        },
+        "ddos-prevention": {
+            "additional_information": "zdf",
+            "offered": [
+                "yes"
+            ]
+        },
+        "firewall-on-demand": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "intrusion": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "pgp-key": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "security-audit": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "vulnerability-testing": {
+            "offered": [
+                "yes"
+            ]
+        },
+        "web-filtering": {
+            "offered": [
+                "yes"
+            ]
+        }
+    },
+    "siem_soc_vendor": [
+        "Exabeam",
+        "Splunk",
+        "IBM Qradar",
+        "LogRythm",
+        "Securonix",
+        "other"
+    ],
+    "siem_soc_vendor-Comment": "figuoho",
+    "staff_employment_type": {
+        "permanent_fte": "5.6",
+        "subcontracted_fte": "56"
+    },
+    "staff_roles": {
+        "nontechnical_fte": "1",
+        "technical_fte": "2"
+    },
+    "street_name_and_number": "Cetinjska 2",
+    "suborganization_details": [
+        {
+            "suborganization_name": "Aaerer",
+            "suborganization_role": "other",
+            "suborganization_role-Comment": "Treer"
+        },
+        {
+            "suborganization_name": "gg",
+            "suborganization_role": "hpc"
+        },
+        {
+            "suborganization_name": "werser"
+        }
+    ],
+    "suborganizations": "Yes",
+    "traffic_carriers": {
+        "cultural": {
+            "carry_mechanism": "other"
+        },
+        "for_profit_orgs": {
+            "carry_mechanism": "commercial_provider_backbone"
+        },
+        "further_education": {
+            "carry_mechanism": "nren_local_loops"
+        },
+        "government": {
+            "carry_mechanism": "commercial_provider_backbone"
+        },
+        "hospitals": {
+            "carry_mechanism": "nren_local_loops"
+        },
+        "institutes": {
+            "carry_mechanism": "other"
+        },
+        "iros": {
+            "carry_mechanism": "regional_nren_backbone"
+        },
+        "primary_schools": {
+            "carry_mechanism": "man"
+        },
+        "secondary_schools": {
+            "carry_mechanism": "regional_nren_backbone"
+        },
+        "universities": {
+            "carry_mechanism": "commercial_provider_backbone"
+        }
+    },
+    "traffic_estimate": {
+        "from_customers": "34",
+        "from_external": "3",
+        "to_customers": "3",
+        "to_external": "22"
+    },
+    "traffic_growth": {
+        "cultural": {
+            "growth_rate": "50"
+        },
+        "for_profit_orgs": {
+            "growth_rate": "0"
+        },
+        "further_education": {
+            "growth_rate": "0"
+        },
+        "government": {
+            "growth_rate": "50"
+        },
+        "hospitals": {
+            "growth_rate": "0"
+        },
+        "institutes": {
+            "growth_rate": "50"
+        },
+        "iros": {
+            "growth_rate": "0"
+        },
+        "primary_schools": {
+            "growth_rate": "0"
+        },
+        "secondary_schools": {
+            "growth_rate": "0"
+        },
+        "universities": {
+            "growth_rate": "100"
+        }
+    },
+    "traffic_load": {
+        "cultural": {
+            "average_from_institutions_to_network": "10",
+            "average_to_institutions_from_network": "10",
+            "peak_from_institutions_to_network": "50",
+            "peak_to_institutions_from_network": "10"
+        },
+        "for_profit_orgs": {
+            "average_to_institutions_from_network": "5"
+        },
+        "further_education": {
+            "average_from_institutions_to_network": "5"
+        },
+        "government": {
+            "average_from_institutions_to_network": "10",
+            "average_to_institutions_from_network": "50",
+            "peak_from_institutions_to_network": "100",
+            "peak_to_institutions_from_network": "50"
+        },
+        "hospitals": {
+            "peak_to_institutions_from_network": "5"
+        },
+        "institutes": {
+            "average_from_institutions_to_network": "20",
+            "average_to_institutions_from_network": "80",
+            "peak_from_institutions_to_network": "50",
+            "peak_to_institutions_from_network": "50"
+        },
+        "iros": {
+            "peak_from_institutions_to_network": "5"
+        },
+        "primary_schools": {
+            "peak_from_institutions_to_network": "5"
+        },
+        "secondary_schools": {
+            "average_to_institutions_from_network": "5"
+        },
+        "universities": {
+            "average_from_institutions_to_network": "60",
+            "average_to_institutions_from_network": "130",
+            "peak_from_institutions_to_network": "300",
+            "peak_to_institutions_from_network": "150"
+        }
+    },
+    "traffic_statistics": "Yes",
+    "traffic_statistics_urls": [
+        {
+            "traffic_statistics_url": "http://netmon.cis.ac.me/cacti/graph_view.php?action=tree&tree_id=36&leaf_id=1430"
+        }
+    ],
+    "typical_capacity": "567",
+    "website": "http://www.remcotukker.com"
+}
\ No newline at end of file
diff --git a/test/test_survey_publisher_v2.py b/test/test_survey_publisher_v2.py
new file mode 100644
index 0000000000000000000000000000000000000000..3f6a122b1d0c91b866516b7cd6984ae87eee1796
--- /dev/null
+++ b/test/test_survey_publisher_v2.py
@@ -0,0 +1,99 @@
+from decimal import Decimal
+import json
+import os
+
+from sqlalchemy import func, select
+
+from compendium_v2 import db
+from compendium_v2.db import model
+from compendium_v2.publishers.survey_publisher_v2 import map_2023
+
+
+JSON_FILE = os.path.join(os.path.dirname(__file__), "data", "2023_all_questions_answered.json")
+
+
+def test_v2_publisher_empty(app):
+    data = {}
+
+    with app.app_context():
+        nren = model.NREN(name='name', country='country')
+        db.session.commit()
+
+    with app.app_context():
+        map_2023(nren, {"data": data})
+        db.session.commit()
+
+    with app.app_context():
+        budget_count = db.session.scalar(select(func.count(model.BudgetEntry.year)))
+        assert budget_count == 0
+        # the main thing is actually that it doesnt crash
+
+
+def test_v2_publisher_full(app):
+    with open(JSON_FILE) as json_data:
+        data = json.load(json_data)
+
+    with app.app_context():
+        nren = model.NREN(name='name', country='country')
+        db.session.commit()
+
+    with app.app_context():
+        map_2023(nren, {"data": data})
+        db.session.commit()
+
+    with app.app_context():
+        budget = db.session.scalar(select(model.BudgetEntry.budget))
+        assert budget == Decimal("124.76")
+
+        funding_source = db.session.scalar(select(model.FundingSource))
+        assert funding_source.client_institutions == Decimal("0")
+        assert funding_source.european_funding == Decimal("20")
+        assert funding_source.gov_public_bodies == Decimal("70")
+        assert funding_source.commercial == Decimal("0")
+        assert funding_source.other == Decimal("10")
+
+        charging_structure = db.session.scalar(select(model.ChargingStructure.fee_type))
+        assert charging_structure == model.FeeType.usage_based_fee
+
+        staff = db.session.scalar(select(model.NrenStaff))
+        assert staff.permanent_fte == Decimal("5.6")
+        assert staff.subcontracted_fte == Decimal("56")
+        assert staff.technical_fte == Decimal("2")
+        assert staff.non_technical_fte == Decimal("1")
+
+        parent = db.session.scalar(select(model.ParentOrganization.organization))
+        assert parent == "sdtfgd"
+
+        subs = db.session.scalars(select(model.SubOrganization).order_by(model.SubOrganization.organization))
+        subs = [s for s in subs]
+        assert subs[0].organization == "Aaerer"
+        assert subs[0].role == "Treer"
+        assert subs[1].organization == "gg"
+        assert subs[1].role == "hpc"
+        assert subs[2].organization == "werser"
+        assert subs[2].role == ""
+
+        projects = db.session.scalars(select(model.ECProject.project).order_by(model.ECProject.project))
+        projects = [p for p in projects]
+        assert projects[0] == "dgdg"
+        assert projects[1] == "rrrrr"
+        assert projects[2] == "st"
+
+        policy = db.session.scalar(select(model.Policy))
+        assert policy.strategic_plan == "https://serere.com"
+        assert policy.environmental == "http://mren.ac.me/documents/Environmental%20policy%20for%20MREN.pdf"
+        assert policy.equal_opportunity == ""
+        assert policy.connectivity == "http://www.ucg.ac.me/skladiste/blog_1028/objava_10/fajlovi/Pravila%20o%20koriscenju%20Akademske%20mreze%20Univerziteta%20Crne%20Gore.pdf"
+        assert policy.acceptable_use == "http://www.ucg.ac.me/skladiste/blog_1028/objava_10/fajlovi/Pravila%20o%20koriscenju%20Akademske%20mreze%20Univerziteta%20Crne%20Gore.pdf"
+        assert policy.privacy_notice == ""
+        assert policy.data_protection == ""
+        assert policy.gender_equality == "https://www.ucg.ac.me/objava/blog/616808/objava/148423-plan-rodne-ravnopravnosti-univerziteta-crne-gore"
+
+        traffic = db.session.scalar(select(model.TrafficVolume))
+        assert traffic.to_customers == Decimal("3")
+        assert traffic.from_customers == Decimal("34")
+        assert traffic.to_external == Decimal("22")
+        assert traffic.from_external == Decimal("3")
+
+        client_urls = db.session.scalar(select(model.InstitutionURLs))
+        assert client_urls.urls == ["http://erse.com", "https://wwe.com"]