diff --git a/libs/net/dal/Migrations/1.3.14/Down/PostDown/00-CbraReportFunctions.sql b/libs/net/dal/Migrations/1.3.14/Down/PostDown/00-CbraReportFunctions.sql
new file mode 100644
index 000000000..1286af47b
--- /dev/null
+++ b/libs/net/dal/Migrations/1.3.14/Down/PostDown/00-CbraReportFunctions.sql
@@ -0,0 +1,334 @@
+DO $$
+BEGIN
+
+-- CBRA report view --
+CREATE OR REPLACE VIEW public.vw_cbra_published_contents AS
+SELECT DISTINCT
+ c.id
+ , c.source
+ , c.source_id
+ , c.series_id
+ , c.media_type_id
+ , c.published_on
+ , COALESCE(ss.name, '') AS series_name
+FROM content c
+LEFT JOIN source s ON c.source_id = s.id
+LEFT JOIN series ss ON c.series_id = ss.id
+JOIN (
+ SELECT unnest(string_to_array(setting.value::TEXT, ','::TEXT)::INTEGER[]) AS media_type_id
+ FROM setting
+ WHERE setting.name::text = 'CBRAReportMediaTypeIds'::TEXT
+ ) m ON c.media_type_id = m.media_type_id
+WHERE ((ss.id IS NOT NULL AND ss.is_cbra_source = true)
+ OR (ss.id IS NULL AND s.is_cbra_source = true))
+AND c.status = 2;
+
+DROP FUNCTION IF EXISTS public.fn_cbra_report_total_entries(date, date);
+DROP FUNCTION IF EXISTS public.fn_cbra_report_totals_by_broadcaster(date, date);
+DROP FUNCTION IF EXISTS public.fn_cbra_report_totals_by_program(date, date);
+DROP FUNCTION IF EXISTS public.fn_cbra_report_staff_summary(date, date);
+DROP FUNCTION IF EXISTS public.fn_cbra_report_total_excerpts(date, date);
+
+-- Function: fn_cbra_report_total_excerpts
+CREATE OR REPLACE FUNCTION public.fn_cbra_report_total_excerpts (
+ f_from_date DATE
+ , f_to_date DATE
+ )
+ RETURNS TABLE(category CHARACTER varying, totals numeric)
+ LANGUAGE 'plpgsql'
+AS $BODY$
+DECLARE cbra_unqualified integer;
+DECLARE cbra_totals integer;
+DECLARE cbra_action_id integer;
+BEGIN
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_table_content_total_excerpts (
+ content_id NUMERIC
+ );
+ INSERT INTO temp_table_content_total_excerpts
+ SELECT DISTINCT c.id
+ FROM public.vw_cbra_published_contents c
+ WHERE c.published_on >= f_from_date
+ AND c.published_on <= f_to_date;
+
+ SELECT
+ CAST("value" AS INTEGER) INTO cbra_action_id
+ FROM setting
+ WHERE "name" = 'CBRAUnqualifiedActionId'
+ LIMIT 1;
+
+ SELECT COUNT(*) INTO cbra_unqualified
+ FROM content_action ca
+ JOIN temp_table_content_total_excerpts c ON ca.content_id = c.content_id
+ WHERE ca.action_id = cbra_action_id
+ AND CASE WHEN ca.value = ''
+ THEN false
+ ELSE CAST(ca.value AS BOOLEAN)
+ END = true;
+
+ SELECT COUNT(*) INTO cbra_totals
+ FROM temp_table_content_total_excerpts;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_table_total_excerpts (
+ category VARCHAR(255)
+ , totals NUMERIC
+ );
+ INSERT INTO temp_table_total_excerpts
+ SELECT
+ 'Total Number of Excerpts'
+ , (cbra_totals - cbra_unqualified);
+
+ INSERT INTO temp_table_total_excerpts
+ SELECT
+ 'Total Number of Excerpts which do not meet the definition of Qualified Subject Matter'
+ , cbra_unqualified;
+
+ INSERT iNto temp_table_total_excerpts
+ SELECT
+ 'Total Number of Excerpts over 10 min.'
+ , (
+ SELECT COUNT(*)
+ FROM temp_table_content_total_excerpts c
+ LEFT JOIN file_reference f ON f.content_id = c.content_id
+ WHERE COALESCE(f.running_time,0)/60000 >= 10
+ );
+
+ INSERT INTO temp_table_total_excerpts
+ SELECT
+ 'Total'
+ , cbra_totals;
+
+ RETURN query
+ SELECT
+ tt.category
+ , CAST(tt.totals AS DECIMAL) AS totals
+ FROM temp_table_total_excerpts tt;
+
+ DROP TABLE IF EXISTS temp_table_content_total_excerpts;
+ DROP TABLE IF EXISTS temp_table_total_excerpts;
+
+END;
+$BODY$;
+
+-- Function: fn_cbra_report_staff_summary
+CREATE OR REPLACE FUNCTION public.fn_cbra_report_staff_summary (
+ f_from_date DATE
+ , f_to_date DATE
+ )
+RETURNS TABLE(staff TEXT, cbra_hours NUMERIC)
+LANGUAGE 'plpgsql'
+AS $BODY$
+BEGIN
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_table_staff_summary AS
+ SELECT
+ tt.user_id
+ , CAST(SUM(COALESCE(tt.Effort,0)) AS DECIMAL) AS cbra_hours
+ FROM time_tracking tt
+ JOIN public.vw_cbra_published_contents c ON tt.content_id = c.id
+ WHERE c.published_on >= f_from_date
+ AND c.published_on <= f_to_date
+ GROUP BY tt.user_id;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_user_table_staff_summary AS
+ SELECT DISTINCT
+ id
+ , first_name
+ , last_name
+ FROM public.user;
+
+ RETURN query
+
+ SELECT
+ u.first_name || ' ' || u.last_name
+ , tt.cbra_hours
+ FROM temp_table_staff_summary tt
+ JOIN temp_user_table_staff_summary u ON tt.user_id = u.id;
+
+ DROP TABLE temp_table_staff_summary;
+ DROP TABLE temp_user_table_staff_summary;
+END;
+$BODY$;
+
+-- Function: fn_cbra_report_total_entries
+CREATE OR REPLACE FUNCTION public.fn_cbra_report_total_entries (
+ f_from_date DATE
+ , f_to_date DATE
+ )
+RETURNS TABLE (
+ day_of_week TEXT
+ , total_count NUMERIC
+ , total_cbra NUMERIC
+)
+LANGUAGE 'plpgsql'
+AS $BODY$
+BEGIN
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_total_table_total_entries AS
+ SELECT
+ DATE_PART('dow', published_on) AS day_of_week
+ , COUNT(*) AS total_count
+ FROM content
+ WHERE published_on >= f_from_date
+ AND published_on <= f_to_date
+ GROUP BY DATE_PART('dow', published_on);
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_cbra_total_table_total_entries AS
+ SELECT
+ DATE_PART('dow', c.published_on) AS day_of_week
+ , COUNT(c.*) AS total_count
+ FROM public.vw_cbra_published_contents c
+ WHERE c.published_on >= f_from_date
+ AND c.published_on <= f_to_date
+ GROUP BY DATE_PART('dow', c.published_on);
+
+ RETURN query
+ SELECT
+ CASE
+ WHEN tt.day_of_week=0 THEN 'Sunday'
+ WHEN tt.day_of_week=1 THEN 'Monday'
+ WHEN tt.day_of_week=2 THEN 'Tuesday'
+ WHEN tt.day_of_week=3 THEN 'Wednesday'
+ WHEN tt.day_of_week=4 THEN 'Thursday'
+ WHEN tt.day_of_week=5 THEN 'Friday'
+ WHEN tt.day_of_week=6 THEN 'Saturday'
+ ELSE 'other'
+ END AS day_of_week
+ , CAST(COALESCE(tt.total_count,0) AS DECIMAL) AS total_count
+ , CAST(COALESCE(c.total_count, 0) AS DECIMAL) AS total_cbra
+ FROM temp_total_table_total_entries tt
+ LEFT JOIN temp_cbra_total_table_total_entries c ON tt.day_of_week = c.day_of_week;
+
+ DROP TABLE IF EXISTS temp_total_table_total_entries;
+ DROP TABLE IF EXISTS temp_cbra_total_table_total_entries;
+END;
+$BODY$;
+
+-- Function: fn_cbra_report_totals_by_broadcaster
+CREATE OR REPLACE FUNCTION public.fn_cbra_report_totals_by_broadcaster (
+ f_from_date DATE,
+ f_to_date DATE
+)
+RETURNS TABLE (
+ source_type CHARACTER varying
+ , total_running_time TEXT
+ , percentage_of_total_running_time NUMERIC
+)
+LANGUAGE 'plpgsql'
+AS $BODY$
+DECLARE sum_total_running_time NUMERIC;
+begin
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_table_content_by_broadcaster (
+ content_id NUMERIC,
+ source CHARACTER varying(100)
+ );
+ INSERT INTO temp_table_content_by_broadcaster
+ SELECT DISTINCT c.id, c.source
+ FROM public.vw_cbra_published_contents c
+ WHERE c.published_on >= f_from_date
+ AND c.published_on <= f_to_date;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_table_by_broadcaster AS
+ SELECT
+ c.source,
+ SUM(COALESCE(f.running_time,0)) AS total_running_time
+ FROM temp_table_content_by_broadcaster c
+ LEFT JOIN file_reference f ON f.content_id = c.content_id
+ GROUP BY c.source;
+
+ select sum(COALESCE(tt.total_running_time,0)) INTO sum_total_running_time
+ from temp_table_by_broadcaster tt;
+
+ RETURN query
+ SELECT
+ tt.source
+ , TO_CHAR((CAST(COALESCE(tt.total_running_time,0) AS DECIMAL)/1000)*'1 SECOND'::INTERVAL, 'HH24:MI:SS') AS total_running_time
+ , COALESCE(tt.total_running_time,0) / CASE COALESCE(sum_total_running_time,0)
+ WHEN 0 THEN 1
+ ELSE COALESCE(sum_total_running_time,0)
+ END AS percentage_of_total_running_time
+ FROM temp_table_by_broadcaster tt;
+
+ DROP TABLE IF EXISTS temp_table_content_by_broadcaster;
+ DROP TABLE IF EXISTS temp_table_by_broadcaster;
+
+END;
+$BODY$;
+
+-- Function: fn_cbra_report_totals_by_program
+CREATE OR REPLACE FUNCTION public.fn_cbra_report_totals_by_program(
+ f_from_date DATE,
+ f_to_date DATE)
+ RETURNS TABLE(
+ media_type CHARACTER varying
+ , source_type CHARACTER varying
+ , series CHARACTER varying
+ , total_count BIGINT
+ , total_running_time TEXT
+ , percentage_of_total_running_time NUMERIC
+ )
+ LANGUAGE 'plpgsql'
+AS $BODY$
+DECLARE sum_total_running_time NUMERIC;
+BEGIN
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_table_content_by_program (
+ content_id NUMERIC,
+ source CHARACTER VARYING(100),
+ source_id NUMERIC,
+ series_id NUMERIC,
+ series_name CHARACTER VARYING(100),
+ media_type_id INTEGER,
+ media_type_name CHARACTER VARYING(100));
+ INSERT INTO temp_table_content_by_program
+ SELECT DISTINCT
+ c.id
+ , c.source
+ , c.source_id
+ , c.series_id
+ , c.series_name
+ , c.media_type_id
+ , COALESCE(mm.name, '')
+ FROM public.vw_cbra_published_contents c
+ JOIN media_type mm ON mm.id = c.media_type_id
+ WHERE c.published_on >= f_from_date
+ AND c.published_on <= f_to_date;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_table_by_program AS
+ SELECT
+ c.media_type_id,
+ c.source,
+ c.source_id,
+ c.series_id,
+ c.series_name,
+ c.media_type_name,
+ COUNT(*) AS total_count,
+ SUM(COALESCE(f.running_time,0)) AS total_running_time
+ FROM temp_table_content_by_program c
+ LEFT JOIN file_reference f ON f.content_id = c.content_id
+ GROUP BY c.media_type_id, c.source, c.source_id, c.series_id, c.series_name, c.media_type_name;
+
+ SELECT SUM(COALESCE(tt.total_running_time,0)) INTO sum_total_running_time
+ FROM temp_table_by_program tt;
+
+ RETURN query
+ SELECT
+ tt.media_type_name AS media_type,
+ tt.source,
+ tt.series_name,
+ tt.total_count,
+ TO_CHAR((cast(COALESCE(tt.total_running_time,0) AS DECIMAL)/1000)*'1 SECOND'::INTERVAL, 'HH24:MI:SS') AS total_running_time,
+ COALESCE(tt.total_running_time,0) / CASE COALESCE(sum_total_running_time,0)
+ WHEN 0 THEN 1
+ ELSE COALESCE(sum_total_running_time,0)
+ END AS percentage_of_total_running_time
+ FROM temp_table_by_program tt;
+
+ DROP TABLE IF EXISTS temp_table_content_by_program;
+ DROP TABLE IF EXISTS temp_table_by_program;
+
+END;
+$BODY$;
+
+END $$;
diff --git a/libs/net/dal/Migrations/1.3.14/Up/PostUp/00-CbraReportFunctions.sql b/libs/net/dal/Migrations/1.3.14/Up/PostUp/00-CbraReportFunctions.sql
new file mode 100644
index 000000000..fe5ed2c18
--- /dev/null
+++ b/libs/net/dal/Migrations/1.3.14/Up/PostUp/00-CbraReportFunctions.sql
@@ -0,0 +1,334 @@
+DO $$
+BEGIN
+
+-- CBRA report view --
+CREATE OR REPLACE VIEW public.vw_cbra_published_contents AS
+SELECT DISTINCT
+ c.id
+ , c.source
+ , c.source_id
+ , c.series_id
+ , c.media_type_id
+ , timezone('utc'::text, timezone('America/Vancouver'::text, c.published_on)) AS published_on
+ , COALESCE(ss.name, '') AS series_name
+FROM content c
+LEFT JOIN source s ON c.source_id = s.id
+LEFT JOIN series ss ON c.series_id = ss.id
+JOIN (
+ SELECT unnest(string_to_array(setting.value::TEXT, ','::TEXT)::INTEGER[]) AS media_type_id
+ FROM setting
+ WHERE setting.name::text = 'CBRAReportMediaTypeIds'::TEXT
+ ) m ON c.media_type_id = m.media_type_id
+WHERE ((ss.id IS NOT NULL AND ss.is_cbra_source = true)
+ OR (ss.id IS NULL AND s.is_cbra_source = true))
+AND c.status = 2;
+
+DROP FUNCTION IF EXISTS public.fn_cbra_report_total_entries(date, date);
+DROP FUNCTION IF EXISTS public.fn_cbra_report_totals_by_broadcaster(date, date);
+DROP FUNCTION IF EXISTS public.fn_cbra_report_totals_by_program(date, date);
+DROP FUNCTION IF EXISTS public.fn_cbra_report_staff_summary(date, date);
+DROP FUNCTION IF EXISTS public.fn_cbra_report_total_excerpts(date, date);
+
+-- Function: fn_cbra_report_total_excerpts
+CREATE OR REPLACE FUNCTION public.fn_cbra_report_total_excerpts (
+ f_from_date DATE
+ , f_to_date DATE
+ )
+ RETURNS TABLE(category CHARACTER varying, totals numeric)
+ LANGUAGE 'plpgsql'
+AS $BODY$
+DECLARE cbra_unqualified integer;
+DECLARE cbra_totals integer;
+DECLARE cbra_action_id integer;
+BEGIN
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_table_content_total_excerpts (
+ content_id NUMERIC
+ );
+ INSERT INTO temp_table_content_total_excerpts
+ SELECT DISTINCT c.id
+ FROM public.vw_cbra_published_contents c
+ WHERE c.published_on >= f_from_date
+ AND c.published_on < f_to_date + '1 day'::interval;
+
+ SELECT
+ CAST("value" AS INTEGER) INTO cbra_action_id
+ FROM setting
+ WHERE "name" = 'CBRAUnqualifiedActionId'
+ LIMIT 1;
+
+ SELECT COUNT(*) INTO cbra_unqualified
+ FROM content_action ca
+ JOIN temp_table_content_total_excerpts c ON ca.content_id = c.content_id
+ WHERE ca.action_id = cbra_action_id
+ AND CASE WHEN ca.value = ''
+ THEN false
+ ELSE CAST(ca.value AS BOOLEAN)
+ END = true;
+
+ SELECT COUNT(*) INTO cbra_totals
+ FROM temp_table_content_total_excerpts;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_table_total_excerpts (
+ category VARCHAR(255)
+ , totals NUMERIC
+ );
+ INSERT INTO temp_table_total_excerpts
+ SELECT
+ 'Total Number of Excerpts'
+ , (cbra_totals - cbra_unqualified);
+
+ INSERT INTO temp_table_total_excerpts
+ SELECT
+ 'Total Number of Excerpts which do not meet the definition of Qualified Subject Matter'
+ , cbra_unqualified;
+
+ INSERT iNto temp_table_total_excerpts
+ SELECT
+ 'Total Number of Excerpts over 10 min.'
+ , (
+ SELECT COUNT(*)
+ FROM temp_table_content_total_excerpts c
+ LEFT JOIN file_reference f ON f.content_id = c.content_id
+ WHERE COALESCE(f.running_time,0)/60000 >= 10
+ );
+
+ INSERT INTO temp_table_total_excerpts
+ SELECT
+ 'Total'
+ , cbra_totals;
+
+ RETURN query
+ SELECT
+ tt.category
+ , CAST(tt.totals AS DECIMAL) AS totals
+ FROM temp_table_total_excerpts tt;
+
+ DROP TABLE IF EXISTS temp_table_content_total_excerpts;
+ DROP TABLE IF EXISTS temp_table_total_excerpts;
+
+END;
+$BODY$;
+
+-- Function: fn_cbra_report_staff_summary
+CREATE OR REPLACE FUNCTION public.fn_cbra_report_staff_summary (
+ f_from_date DATE
+ , f_to_date DATE
+ )
+RETURNS TABLE(staff TEXT, cbra_hours TEXT)
+LANGUAGE 'plpgsql'
+AS $BODY$
+BEGIN
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_table_staff_summary AS
+ SELECT
+ tt.user_id
+ , TO_CHAR((CAST(SUM(COALESCE(tt.Effort,0))*60 AS DECIMAL))*'1 SECOND'::INTERVAL, 'HH24:MI:SS') AS cbra_hours
+ FROM time_tracking tt
+ JOIN public.vw_cbra_published_contents c ON tt.content_id = c.id
+ WHERE c.published_on >= f_from_date
+ AND c.published_on < f_to_date + '1 day'::interval
+ GROUP BY tt.user_id;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_user_table_staff_summary AS
+ SELECT DISTINCT
+ id
+ , first_name
+ , last_name
+ FROM public.user;
+
+ RETURN query
+
+ SELECT
+ u.first_name || ' ' || u.last_name
+ , tt.cbra_hours
+ FROM temp_table_staff_summary tt
+ JOIN temp_user_table_staff_summary u ON tt.user_id = u.id;
+
+ DROP TABLE temp_table_staff_summary;
+ DROP TABLE temp_user_table_staff_summary;
+END;
+$BODY$;
+
+-- Function: fn_cbra_report_total_entries
+CREATE OR REPLACE FUNCTION public.fn_cbra_report_total_entries (
+ f_from_date DATE
+ , f_to_date DATE
+ )
+RETURNS TABLE (
+ day_of_week TEXT
+ , total_count NUMERIC
+ , total_cbra NUMERIC
+)
+LANGUAGE 'plpgsql'
+AS $BODY$
+BEGIN
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_total_table_total_entries AS
+ SELECT
+ DATE_PART('dow', published_on) AS day_of_week
+ , COUNT(*) AS total_count
+ FROM content
+ WHERE timezone('utc'::text, timezone('America/Vancouver'::text, published_on)) >= f_from_date
+ AND timezone('utc'::text, timezone('America/Vancouver'::text, published_on)) < f_to_date + '1 day'::interval
+ GROUP BY DATE_PART('dow', published_on);
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_cbra_total_table_total_entries AS
+ SELECT
+ DATE_PART('dow', c.published_on) AS day_of_week
+ , COUNT(c.*) AS total_count
+ FROM public.vw_cbra_published_contents c
+ WHERE c.published_on >= f_from_date
+ AND c.published_on < f_to_date + '1 day'::interval
+ GROUP BY DATE_PART('dow', c.published_on);
+
+ RETURN query
+ SELECT
+ CASE
+ WHEN tt.day_of_week=0 THEN 'Sunday'
+ WHEN tt.day_of_week=1 THEN 'Monday'
+ WHEN tt.day_of_week=2 THEN 'Tuesday'
+ WHEN tt.day_of_week=3 THEN 'Wednesday'
+ WHEN tt.day_of_week=4 THEN 'Thursday'
+ WHEN tt.day_of_week=5 THEN 'Friday'
+ WHEN tt.day_of_week=6 THEN 'Saturday'
+ ELSE 'other'
+ END AS day_of_week
+ , CAST(COALESCE(tt.total_count,0) AS DECIMAL) AS total_count
+ , CAST(COALESCE(c.total_count, 0) AS DECIMAL) AS total_cbra
+ FROM temp_total_table_total_entries tt
+ LEFT JOIN temp_cbra_total_table_total_entries c ON tt.day_of_week = c.day_of_week;
+
+ DROP TABLE IF EXISTS temp_total_table_total_entries;
+ DROP TABLE IF EXISTS temp_cbra_total_table_total_entries;
+END;
+$BODY$;
+
+-- Function: fn_cbra_report_totals_by_broadcaster
+CREATE OR REPLACE FUNCTION public.fn_cbra_report_totals_by_broadcaster (
+ f_from_date DATE,
+ f_to_date DATE
+)
+RETURNS TABLE (
+ source_type CHARACTER varying
+ , total_running_time TEXT
+ , percentage_of_total_running_time NUMERIC
+)
+LANGUAGE 'plpgsql'
+AS $BODY$
+DECLARE sum_total_running_time NUMERIC;
+begin
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_table_content_by_broadcaster (
+ content_id NUMERIC,
+ source CHARACTER varying(100)
+ );
+ INSERT INTO temp_table_content_by_broadcaster
+ SELECT DISTINCT c.id, c.source
+ FROM public.vw_cbra_published_contents c
+ WHERE c.published_on >= f_from_date
+ AND c.published_on < f_to_date + '1 day'::interval;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_table_by_broadcaster AS
+ SELECT
+ c.source,
+ SUM(COALESCE(f.running_time,0)) AS total_running_time
+ FROM temp_table_content_by_broadcaster c
+ LEFT JOIN file_reference f ON f.content_id = c.content_id
+ GROUP BY c.source;
+
+ select sum(COALESCE(tt.total_running_time,0)) INTO sum_total_running_time
+ from temp_table_by_broadcaster tt;
+
+ RETURN query
+ SELECT
+ tt.source
+ , TO_CHAR((CAST(COALESCE(tt.total_running_time,0) AS DECIMAL)/1000)*'1 SECOND'::INTERVAL, 'HH24:MI:SS') AS total_running_time
+ , COALESCE(tt.total_running_time,0) / CASE COALESCE(sum_total_running_time,0)
+ WHEN 0 THEN 1
+ ELSE COALESCE(sum_total_running_time,0)
+ END AS percentage_of_total_running_time
+ FROM temp_table_by_broadcaster tt;
+
+ DROP TABLE IF EXISTS temp_table_content_by_broadcaster;
+ DROP TABLE IF EXISTS temp_table_by_broadcaster;
+
+END;
+$BODY$;
+
+-- Function: fn_cbra_report_totals_by_program
+CREATE OR REPLACE FUNCTION public.fn_cbra_report_totals_by_program(
+ f_from_date DATE,
+ f_to_date DATE)
+ RETURNS TABLE(
+ media_type CHARACTER varying
+ , source_type CHARACTER varying
+ , series CHARACTER varying
+ , total_count BIGINT
+ , total_running_time TEXT
+ , percentage_of_total_running_time NUMERIC
+ )
+ LANGUAGE 'plpgsql'
+AS $BODY$
+DECLARE sum_total_running_time NUMERIC;
+BEGIN
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_table_content_by_program (
+ content_id NUMERIC,
+ source CHARACTER VARYING(100),
+ source_id NUMERIC,
+ series_id NUMERIC,
+ series_name CHARACTER VARYING(100),
+ media_type_id INTEGER,
+ media_type_name CHARACTER VARYING(100));
+ INSERT INTO temp_table_content_by_program
+ SELECT DISTINCT
+ c.id
+ , c.source
+ , c.source_id
+ , c.series_id
+ , c.series_name
+ , c.media_type_id
+ , COALESCE(mm.name, '')
+ FROM public.vw_cbra_published_contents c
+ JOIN media_type mm ON mm.id = c.media_type_id
+ WHERE c.published_on >= f_from_date
+ AND c.published_on < f_to_date + '1 day'::interval;
+
+ CREATE TEMPORARY TABLE IF NOT EXISTS temp_table_by_program AS
+ SELECT
+ c.media_type_id,
+ c.source,
+ c.source_id,
+ c.series_id,
+ c.series_name,
+ c.media_type_name,
+ COUNT(*) AS total_count,
+ SUM(COALESCE(f.running_time,0)) AS total_running_time
+ FROM temp_table_content_by_program c
+ LEFT JOIN file_reference f ON f.content_id = c.content_id
+ GROUP BY c.media_type_id, c.source, c.source_id, c.series_id, c.series_name, c.media_type_name;
+
+ SELECT SUM(COALESCE(tt.total_running_time,0)) INTO sum_total_running_time
+ FROM temp_table_by_program tt;
+
+ RETURN query
+ SELECT
+ tt.media_type_name AS media_type,
+ tt.source,
+ tt.series_name,
+ tt.total_count,
+ TO_CHAR((cast(COALESCE(tt.total_running_time,0) AS DECIMAL)/1000)*'1 SECOND'::INTERVAL, 'HH24:MI:SS') AS total_running_time,
+ COALESCE(tt.total_running_time,0) / CASE COALESCE(sum_total_running_time,0)
+ WHEN 0 THEN 1
+ ELSE COALESCE(sum_total_running_time,0)
+ END AS percentage_of_total_running_time
+ FROM temp_table_by_program tt;
+
+ DROP TABLE IF EXISTS temp_table_content_by_program;
+ DROP TABLE IF EXISTS temp_table_by_program;
+
+END;
+$BODY$;
+
+END $$;
diff --git a/libs/net/dal/Migrations/20241230195906_1.3.14.Designer.cs b/libs/net/dal/Migrations/20241230195906_1.3.14.Designer.cs
new file mode 100644
index 000000000..3822a654f
--- /dev/null
+++ b/libs/net/dal/Migrations/20241230195906_1.3.14.Designer.cs
@@ -0,0 +1,7485 @@
+//
+using System;
+using System.Collections.Generic;
+using System.Text.Json;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using TNO.DAL;
+using TNO.Entities.Models;
+
+#nullable disable
+
+namespace TNO.DAL.Migrations
+{
+ [DbContext(typeof(TNOContext))]
+ [Migration("20241230195906_1.3.14")]
+ partial class _1314
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "9.0.0")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("TNO.Entities.AVOverviewInstance", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("IsPublished")
+ .HasColumnType("boolean");
+
+ b.Property("PublishedOn")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("published_on");
+
+ b.Property("Response")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("jsonb")
+ .HasColumnName("response")
+ .HasDefaultValueSql("'{}'::jsonb");
+
+ b.Property("TemplateType")
+ .HasColumnType("integer")
+ .HasColumnName("template_type");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("Id");
+
+ b.HasIndex("PublishedOn")
+ .IsUnique();
+
+ b.HasIndex("TemplateType", "PublishedOn");
+
+ b.ToTable("av_overview_instance");
+ });
+
+ modelBuilder.Entity("TNO.Entities.AVOverviewSection", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Anchors")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("anchors");
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("InstanceId")
+ .HasColumnType("bigint")
+ .HasColumnName("av_overview_instance_id");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("name");
+
+ b.Property("OtherSource")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("other_source");
+
+ b.Property("SeriesId")
+ .HasColumnType("integer")
+ .HasColumnName("series_id");
+
+ b.Property("SortOrder")
+ .HasColumnType("integer")
+ .HasColumnName("sort_order");
+
+ b.Property("SourceId")
+ .HasColumnType("integer")
+ .HasColumnName("source_id");
+
+ b.Property("StartTime")
+ .IsRequired()
+ .HasMaxLength(8)
+ .HasColumnType("character varying(8)")
+ .HasColumnName("start_time");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("Id");
+
+ b.HasIndex("InstanceId");
+
+ b.HasIndex("SeriesId");
+
+ b.HasIndex("SourceId");
+
+ b.ToTable("av_overview_section");
+ });
+
+ modelBuilder.Entity("TNO.Entities.AVOverviewSectionItem", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("ContentId")
+ .HasColumnType("bigint")
+ .HasColumnName("content_id");
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("ItemType")
+ .HasColumnType("integer")
+ .HasColumnName("item_type");
+
+ b.Property("SectionId")
+ .HasColumnType("integer")
+ .HasColumnName("av_overview_section_id");
+
+ b.Property("SortOrder")
+ .HasColumnType("integer")
+ .HasColumnName("sort_order");
+
+ b.Property("Summary")
+ .IsRequired()
+ .HasMaxLength(2000)
+ .HasColumnType("character varying(2000)")
+ .HasColumnName("summary");
+
+ b.Property("Time")
+ .IsRequired()
+ .HasMaxLength(8)
+ .HasColumnType("character varying(8)")
+ .HasColumnName("time");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ContentId");
+
+ b.HasIndex("SectionId");
+
+ b.ToTable("av_overview_section_item");
+ });
+
+ modelBuilder.Entity("TNO.Entities.AVOverviewTemplate", b =>
+ {
+ b.Property("TemplateType")
+ .HasColumnType("integer")
+ .HasColumnName("template_type");
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("TemplateId")
+ .HasColumnType("integer")
+ .HasColumnName("report_template_id");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("TemplateType");
+
+ b.HasIndex("TemplateId");
+
+ b.ToTable("av_overview_template");
+ });
+
+ modelBuilder.Entity("TNO.Entities.AVOverviewTemplateSection", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Anchors")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("anchors");
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("name");
+
+ b.Property("OtherSource")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("other_source");
+
+ b.Property("SeriesId")
+ .HasColumnType("integer")
+ .HasColumnName("series_id");
+
+ b.Property("SortOrder")
+ .HasColumnType("integer")
+ .HasColumnName("sort_order");
+
+ b.Property("SourceId")
+ .HasColumnType("integer")
+ .HasColumnName("source_id");
+
+ b.Property("StartTime")
+ .IsRequired()
+ .HasMaxLength(8)
+ .HasColumnType("character varying(8)")
+ .HasColumnName("start_time");
+
+ b.Property("TemplateType")
+ .HasColumnType("integer")
+ .HasColumnName("av_overview_template_id");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("Id");
+
+ b.HasIndex("SeriesId");
+
+ b.HasIndex("SourceId");
+
+ b.HasIndex("TemplateType");
+
+ b.ToTable("av_overview_template_section");
+ });
+
+ modelBuilder.Entity("TNO.Entities.AVOverviewTemplateSectionItem", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("ItemType")
+ .HasColumnType("integer")
+ .HasColumnName("item_type");
+
+ b.Property("SectionId")
+ .HasColumnType("integer")
+ .HasColumnName("av_overview_template_section_id");
+
+ b.Property("SortOrder")
+ .HasColumnType("integer")
+ .HasColumnName("sort_order");
+
+ b.Property("Summary")
+ .IsRequired()
+ .HasMaxLength(2000)
+ .HasColumnType("character varying(2000)")
+ .HasColumnName("summary");
+
+ b.Property("Time")
+ .IsRequired()
+ .HasMaxLength(8)
+ .HasColumnType("character varying(8)")
+ .HasColumnName("time");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("Id");
+
+ b.HasIndex("SectionId");
+
+ b.ToTable("av_overview_template_section_item");
+ });
+
+ modelBuilder.Entity("TNO.Entities.Action", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("DefaultValue")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("default_value")
+ .HasDefaultValueSql("''");
+
+ b.Property("Description")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasMaxLength(2000)
+ .HasColumnType("character varying(2000)")
+ .HasColumnName("description")
+ .HasDefaultValueSql("''");
+
+ b.Property("IsEnabled")
+ .HasColumnType("boolean")
+ .HasColumnName("is_enabled");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("name");
+
+ b.Property("SortOrder")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasDefaultValue(0)
+ .HasColumnName("sort_order");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("ValueLabel")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("value_label")
+ .HasDefaultValueSql("''");
+
+ b.Property("ValueType")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasDefaultValue(0)
+ .HasColumnName("value_type");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("Id");
+
+ b.HasIndex(new[] { "ValueType", "ValueLabel" }, "IX_action");
+
+ b.HasIndex(new[] { "IsEnabled", "Name" }, "IX_action_is_enabled");
+
+ b.HasIndex(new[] { "Name" }, "IX_name")
+ .IsUnique();
+
+ b.ToTable("action");
+ });
+
+ modelBuilder.Entity("TNO.Entities.CBRAReportStaffSummary", b =>
+ {
+ b.Property("CbraHours")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("cbra_hours");
+
+ b.Property("Staff")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("staff");
+
+ b.ToTable((string)null);
+
+ b.ToView(null, (string)null);
+ });
+
+ modelBuilder.Entity("TNO.Entities.CBRAReportTotalEntries", b =>
+ {
+ b.Property("DayOfWeek")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("day_of_week");
+
+ b.Property("TotalCbra")
+ .HasColumnType("numeric")
+ .HasColumnName("total_cbra");
+
+ b.Property("TotalCount")
+ .HasColumnType("numeric")
+ .HasColumnName("total_count");
+
+ b.ToTable((string)null);
+
+ b.ToView(null, (string)null);
+ });
+
+ modelBuilder.Entity("TNO.Entities.CBRAReportTotalExcerpts", b =>
+ {
+ b.Property("Category")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("category");
+
+ b.Property("Totals")
+ .HasColumnType("integer")
+ .HasColumnName("totals");
+
+ b.ToTable((string)null);
+
+ b.ToView(null, (string)null);
+ });
+
+ modelBuilder.Entity("TNO.Entities.CBRAReportTotalsByBroadcaster", b =>
+ {
+ b.Property("PercentageOfTotalRunningTime")
+ .HasColumnType("numeric")
+ .HasColumnName("percentage_of_total_running_time");
+
+ b.Property("SourceType")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("source_type");
+
+ b.Property("TotalRunningTime")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("total_running_time");
+
+ b.ToTable((string)null);
+
+ b.ToView(null, (string)null);
+ });
+
+ modelBuilder.Entity("TNO.Entities.CBRAReportTotalsByProgram", b =>
+ {
+ b.Property("MediaType")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("media_type");
+
+ b.Property("PercentageOfTotalRunningTime")
+ .HasColumnType("numeric")
+ .HasColumnName("percentage_of_total_running_time");
+
+ b.Property("Series")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("series");
+
+ b.Property("SourceType")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("source_type");
+
+ b.Property("TotalCount")
+ .HasColumnType("numeric")
+ .HasColumnName("total_count");
+
+ b.Property("TotalRunningTime")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("total_running_time");
+
+ b.ToTable((string)null);
+
+ b.ToView(null, (string)null);
+ });
+
+ modelBuilder.Entity("TNO.Entities.Cache", b =>
+ {
+ b.Property("Key")
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("key");
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Description")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasMaxLength(2000)
+ .HasColumnType("character varying(2000)")
+ .HasColumnName("description")
+ .HasDefaultValueSql("''");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasMaxLength(150)
+ .HasColumnType("character varying(150)")
+ .HasColumnName("value");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("Key");
+
+ b.HasIndex(new[] { "Key", "Value" }, "IX_cache");
+
+ b.ToTable("cache");
+ });
+
+ modelBuilder.Entity("TNO.Entities.ChartTemplate", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Description")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasMaxLength(2000)
+ .HasColumnType("character varying(2000)")
+ .HasColumnName("description")
+ .HasDefaultValueSql("''");
+
+ b.Property("IsEnabled")
+ .HasColumnType("boolean")
+ .HasColumnName("is_enabled");
+
+ b.Property("IsPublic")
+ .HasColumnType("boolean")
+ .HasColumnName("is_public");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("name");
+
+ b.Property("Settings")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("jsonb")
+ .HasColumnName("settings")
+ .HasDefaultValueSql("'{}'::jsonb");
+
+ b.Property("SortOrder")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasDefaultValue(0)
+ .HasColumnName("sort_order");
+
+ b.Property("Template")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("template");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Name")
+ .IsUnique();
+
+ b.HasIndex(new[] { "IsEnabled", "Name" }, "IX_charttemplate_is_enabled");
+
+ b.ToTable("chart_template");
+ });
+
+ modelBuilder.Entity("TNO.Entities.Connection", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Configuration")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("jsonb")
+ .HasColumnName("configuration")
+ .HasDefaultValueSql("'{}'::jsonb");
+
+ b.Property("ConnectionType")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasDefaultValue(0)
+ .HasColumnName("connection_type");
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Description")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasMaxLength(2000)
+ .HasColumnType("character varying(2000)")
+ .HasColumnName("description")
+ .HasDefaultValueSql("''");
+
+ b.Property("IsEnabled")
+ .HasColumnType("boolean")
+ .HasColumnName("is_enabled");
+
+ b.Property("IsReadOnly")
+ .HasColumnType("boolean")
+ .HasColumnName("is_read_only");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("name");
+
+ b.Property("SortOrder")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasDefaultValue(0)
+ .HasColumnName("sort_order");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("Id");
+
+ b.HasIndex(new[] { "IsEnabled", "Name" }, "IX_connection_is_enabled");
+
+ b.HasIndex(new[] { "Name" }, "IX_name")
+ .IsUnique()
+ .HasDatabaseName("IX_name1");
+
+ b.ToTable("connection");
+ });
+
+ modelBuilder.Entity("TNO.Entities.Content", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Body")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("body");
+
+ b.Property("Byline")
+ .IsRequired()
+ .HasMaxLength(500)
+ .HasColumnType("character varying(500)")
+ .HasColumnName("byline");
+
+ b.Property("ContentType")
+ .HasColumnType("integer")
+ .HasColumnName("content_type");
+
+ b.Property("ContributorId")
+ .HasColumnType("integer")
+ .HasColumnName("contributor_id");
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Edition")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("edition");
+
+ b.Property("ExternalUid")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasMaxLength(500)
+ .HasColumnType("character varying(500)")
+ .HasDefaultValue("")
+ .HasColumnName("external_uid");
+
+ b.Property("Headline")
+ .IsRequired()
+ .HasMaxLength(500)
+ .HasColumnType("character varying(500)")
+ .HasColumnName("headline");
+
+ b.Property("IngestTypeId")
+ .HasColumnType("integer");
+
+ b.Property("IsApproved")
+ .HasColumnType("boolean")
+ .HasColumnName("is_approved");
+
+ b.Property("IsHidden")
+ .HasColumnType("boolean")
+ .HasColumnName("is_hidden");
+
+ b.Property("IsPrivate")
+ .HasColumnType("boolean")
+ .HasColumnName("is_private");
+
+ b.Property("LicenseId")
+ .HasColumnType("integer")
+ .HasColumnName("license_id");
+
+ b.Property("MediaTypeId")
+ .HasColumnType("integer")
+ .HasColumnName("media_type_id");
+
+ b.Property("OtherSource")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("source");
+
+ b.Property("OwnerId")
+ .HasColumnType("integer")
+ .HasColumnName("owner_id");
+
+ b.Property("Page")
+ .IsRequired()
+ .HasMaxLength(20)
+ .HasColumnType("character varying(20)")
+ .HasColumnName("page");
+
+ b.Property("PostedOn")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("posted_on");
+
+ b.Property("PublishedOn")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("published_on");
+
+ b.Property("Section")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("section");
+
+ b.Property("SeriesId")
+ .HasColumnType("integer")
+ .HasColumnName("series_id");
+
+ b.Property("SourceId")
+ .HasColumnType("integer")
+ .HasColumnName("source_id");
+
+ b.Property("SourceUrl")
+ .IsRequired()
+ .HasMaxLength(500)
+ .HasColumnType("character varying(500)")
+ .HasColumnName("source_url");
+
+ b.Property("Status")
+ .HasColumnType("integer")
+ .HasColumnName("status");
+
+ b.Property("Summary")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("summary");
+
+ b.Property("Uid")
+ .IsRequired()
+ .HasMaxLength(500)
+ .HasColumnType("character varying(500)")
+ .HasColumnName("uid");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.Property>("Versions")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("jsonb")
+ .HasColumnName("versions")
+ .HasDefaultValueSql("'{}'::jsonb");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ContributorId");
+
+ b.HasIndex("IngestTypeId");
+
+ b.HasIndex("LicenseId");
+
+ b.HasIndex("MediaTypeId");
+
+ b.HasIndex("OwnerId");
+
+ b.HasIndex("SeriesId");
+
+ b.HasIndex("SourceId");
+
+ b.HasIndex(new[] { "ContentType", "OtherSource", "Uid", "Page", "Status", "IsHidden" }, "IX_content");
+
+ b.HasIndex(new[] { "PublishedOn", "CreatedOn" }, "IX_content_dates");
+
+ b.HasIndex(new[] { "Headline" }, "IX_headline");
+
+ b.HasIndex(new[] { "Edition", "Section", "Byline" }, "IX_print_content");
+
+ b.ToTable("content");
+ });
+
+ modelBuilder.Entity("TNO.Entities.ContentAction", b =>
+ {
+ b.Property("ContentId")
+ .HasColumnType("bigint")
+ .HasColumnName("content_id");
+
+ b.Property("ActionId")
+ .HasColumnType("integer")
+ .HasColumnName("action_id");
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasMaxLength(150)
+ .HasColumnType("character varying(150)")
+ .HasColumnName("value");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("ContentId", "ActionId");
+
+ b.HasIndex("ActionId");
+
+ b.ToTable("content_action");
+ });
+
+ modelBuilder.Entity("TNO.Entities.ContentLabel", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("ContentId")
+ .HasColumnType("bigint")
+ .HasColumnName("content_id");
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Key")
+ .IsRequired()
+ .HasMaxLength(50)
+ .HasColumnType("character varying(50)")
+ .HasColumnName("key");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("value");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ContentId");
+
+ b.HasIndex(new[] { "Key", "Value" }, "IX_content_label");
+
+ b.ToTable("content_label");
+ });
+
+ modelBuilder.Entity("TNO.Entities.ContentLink", b =>
+ {
+ b.Property("ContentId")
+ .HasColumnType("bigint")
+ .HasColumnName("content_id");
+
+ b.Property("LinkId")
+ .HasColumnType("bigint")
+ .HasColumnName("link_id");
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("value");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("ContentId", "LinkId");
+
+ b.HasIndex("LinkId");
+
+ b.ToTable("content_link");
+ });
+
+ modelBuilder.Entity("TNO.Entities.ContentLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("ContentId")
+ .HasColumnType("bigint")
+ .HasColumnName("content_id");
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Message")
+ .IsRequired()
+ .HasMaxLength(2000)
+ .HasColumnType("character varying(2000)")
+ .HasColumnName("message");
+
+ b.Property("Status")
+ .HasColumnType("integer")
+ .HasColumnName("status");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ContentId");
+
+ b.ToTable("content_log");
+ });
+
+ modelBuilder.Entity("TNO.Entities.ContentReference", b =>
+ {
+ b.Property("Source")
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("source");
+
+ b.Property("Uid")
+ .HasMaxLength(500)
+ .HasColumnType("character varying(500)")
+ .HasColumnName("uid");
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Metadata")
+ .HasColumnType("jsonb")
+ .HasColumnName("metadata");
+
+ b.Property("PublishedOn")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("published_on");
+
+ b.Property("SourceUpdateOn")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("source_updated_on");
+
+ b.Property("Status")
+ .HasColumnType("integer")
+ .HasColumnName("status");
+
+ b.Property("Topic")
+ .IsRequired()
+ .HasMaxLength(50)
+ .HasColumnType("character varying(50)")
+ .HasColumnName("topic");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("Source", "Uid");
+
+ b.HasIndex(new[] { "PublishedOn", "Status" }, "IX_content_reference");
+
+ b.HasIndex(new[] { "Source", "Uid" }, "IX_source_uid");
+
+ b.ToTable("content_reference");
+ });
+
+ modelBuilder.Entity("TNO.Entities.ContentTag", b =>
+ {
+ b.Property("ContentId")
+ .HasColumnType("bigint")
+ .HasColumnName("content_id");
+
+ b.Property("TagId")
+ .HasColumnType("integer")
+ .HasColumnName("tag_id");
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("ContentId", "TagId");
+
+ b.HasIndex("TagId");
+
+ b.ToTable("content_tag");
+ });
+
+ modelBuilder.Entity("TNO.Entities.ContentTonePool", b =>
+ {
+ b.Property("ContentId")
+ .HasColumnType("bigint")
+ .HasColumnName("content_id");
+
+ b.Property("TonePoolId")
+ .HasColumnType("integer")
+ .HasColumnName("tone_pool_id");
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Value")
+ .HasColumnType("integer")
+ .HasColumnName("value");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("ContentId", "TonePoolId");
+
+ b.HasIndex("TonePoolId");
+
+ b.ToTable("content_tone");
+ });
+
+ modelBuilder.Entity("TNO.Entities.ContentTopic", b =>
+ {
+ b.Property("ContentId")
+ .HasColumnType("bigint")
+ .HasColumnName("content_id");
+
+ b.Property("TopicId")
+ .HasColumnType("integer")
+ .HasColumnName("topic_id");
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Score")
+ .HasColumnType("integer")
+ .HasColumnName("score");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("ContentId", "TopicId");
+
+ b.HasIndex("TopicId");
+
+ b.ToTable("content_topic");
+ });
+
+ modelBuilder.Entity("TNO.Entities.ContentTypeAction", b =>
+ {
+ b.Property("ContentType")
+ .HasColumnType("integer")
+ .HasColumnName("content_type");
+
+ b.Property("ActionId")
+ .HasColumnType("integer")
+ .HasColumnName("action_id");
+
+ b.Property("CreatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("created_by");
+
+ b.Property("CreatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("created_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("UpdatedBy")
+ .IsRequired()
+ .HasMaxLength(250)
+ .HasColumnType("character varying(250)")
+ .HasColumnName("updated_by");
+
+ b.Property("UpdatedOn")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("updated_on")
+ .HasDefaultValueSql("CURRENT_TIMESTAMP");
+
+ b.Property("Version")
+ .IsConcurrencyToken()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("version")
+ .HasDefaultValueSql("0");
+
+ b.HasKey("ContentType", "ActionId");
+
+ b.HasIndex("ActionId");
+
+ b.ToTable("content_type_action");
+ });
+
+ modelBuilder.Entity("TNO.Entities.Contributor", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Aliases")
+ .HasMaxLength(500)
+ .HasColumnType("character varying(500)")
+ .HasColumnName("aliases");
+
+ b.Property("AutoTranscribe")
+ .HasColumnType("boolean")
+ .HasColumnName("auto_transcribe");
+
+ b.Property