mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-28 23:46:58 -05:00
Compare commits
2 Commits
1700411b91
...
cc58267c93
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc58267c93 | ||
|
|
36790600b9 |
@@ -10,6 +10,7 @@ import { ScrollArea } from '@/components/ui/scroll-area';
|
|||||||
import { VersionComparisonDialog } from './VersionComparisonDialog';
|
import { VersionComparisonDialog } from './VersionComparisonDialog';
|
||||||
import { RollbackDialog } from './RollbackDialog';
|
import { RollbackDialog } from './RollbackDialog';
|
||||||
import { useEntityVersions } from '@/hooks/useEntityVersions';
|
import { useEntityVersions } from '@/hooks/useEntityVersions';
|
||||||
|
import { useUserRole } from '@/hooks/useUserRole';
|
||||||
import type { EntityType } from '@/types/versioning';
|
import type { EntityType } from '@/types/versioning';
|
||||||
|
|
||||||
interface EntityVersionHistoryProps {
|
interface EntityVersionHistoryProps {
|
||||||
@@ -28,6 +29,7 @@ const changeTypeColors = {
|
|||||||
|
|
||||||
export function EntityVersionHistory({ entityType, entityId, entityName }: EntityVersionHistoryProps) {
|
export function EntityVersionHistory({ entityType, entityId, entityName }: EntityVersionHistoryProps) {
|
||||||
const { versions, loading, rollbackToVersion } = useEntityVersions(entityType, entityId);
|
const { versions, loading, rollbackToVersion } = useEntityVersions(entityType, entityId);
|
||||||
|
const { isModerator } = useUserRole();
|
||||||
const [selectedVersions, setSelectedVersions] = useState<string[]>([]);
|
const [selectedVersions, setSelectedVersions] = useState<string[]>([]);
|
||||||
const [compareDialogOpen, setCompareDialogOpen] = useState(false);
|
const [compareDialogOpen, setCompareDialogOpen] = useState(false);
|
||||||
const [rollbackDialogOpen, setRollbackDialogOpen] = useState(false);
|
const [rollbackDialogOpen, setRollbackDialogOpen] = useState(false);
|
||||||
@@ -128,7 +130,7 @@ export function EntityVersionHistory({ entityType, entityId, entityName }: Entit
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!version.is_current && (
|
{!version.is_current && isModerator() && (
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
@@ -136,6 +138,7 @@ export function EntityVersionHistory({ entityType, entityId, entityName }: Entit
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
handleRollback(version.version_id);
|
handleRollback(version.version_id);
|
||||||
}}
|
}}
|
||||||
|
title="Moderator only: Restore this version"
|
||||||
>
|
>
|
||||||
<RotateCcw className="h-4 w-4 mr-1" />
|
<RotateCcw className="h-4 w-4 mr-1" />
|
||||||
Restore
|
Restore
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ export function RollbackDialog({
|
|||||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Restore Previous Version</DialogTitle>
|
<DialogTitle>Restore Previous Version (Moderator Action)</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
You are about to restore "{entityName}" to a previous version. This will create a new version with the restored data.
|
You are about to restore "{entityName}" to a previous version. This will create a new version with the restored data. This action will be logged in the audit trail.
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
|
|||||||
@@ -164,10 +164,16 @@ export function useEntityVersions(entityType: EntityType, entityId: string) {
|
|||||||
p_reason: reason
|
p_reason: reason
|
||||||
});
|
});
|
||||||
|
|
||||||
if (error) throw error;
|
if (error) {
|
||||||
|
// Check for authorization error (insufficient_privilege)
|
||||||
|
if (error.code === '42501') {
|
||||||
|
throw new Error('Only moderators can restore previous versions');
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
if (isMountedRef.current) {
|
if (isMountedRef.current) {
|
||||||
toast.success('Successfully rolled back to previous version');
|
toast.success('Successfully restored to previous version');
|
||||||
await fetchVersions();
|
await fetchVersions();
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
@@ -175,7 +181,9 @@ export function useEntityVersions(entityType: EntityType, entityId: string) {
|
|||||||
const errorMsg = getErrorMessage(error);
|
const errorMsg = getErrorMessage(error);
|
||||||
logger.error('Failed to rollback version', { entityType, entityId, targetVersionId, error: errorMsg });
|
logger.error('Failed to rollback version', { entityType, entityId, targetVersionId, error: errorMsg });
|
||||||
if (isMountedRef.current) {
|
if (isMountedRef.current) {
|
||||||
toast.error(errorMsg);
|
toast.error('Failed to restore version', {
|
||||||
|
description: errorMsg
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2777,6 +2777,10 @@ export type Database = {
|
|||||||
}
|
}
|
||||||
ride_model_versions: {
|
ride_model_versions: {
|
||||||
Row: {
|
Row: {
|
||||||
|
banner_image_id: string | null
|
||||||
|
banner_image_url: string | null
|
||||||
|
card_image_id: string | null
|
||||||
|
card_image_url: string | null
|
||||||
category: string
|
category: string
|
||||||
change_reason: string | null
|
change_reason: string | null
|
||||||
change_type: Database["public"]["Enums"]["version_change_type"]
|
change_type: Database["public"]["Enums"]["version_change_type"]
|
||||||
@@ -2787,12 +2791,17 @@ export type Database = {
|
|||||||
manufacturer_id: string | null
|
manufacturer_id: string | null
|
||||||
name: string
|
name: string
|
||||||
ride_model_id: string
|
ride_model_id: string
|
||||||
|
ride_type: string | null
|
||||||
slug: string
|
slug: string
|
||||||
submission_id: string | null
|
submission_id: string | null
|
||||||
version_id: string
|
version_id: string
|
||||||
version_number: number
|
version_number: number
|
||||||
}
|
}
|
||||||
Insert: {
|
Insert: {
|
||||||
|
banner_image_id?: string | null
|
||||||
|
banner_image_url?: string | null
|
||||||
|
card_image_id?: string | null
|
||||||
|
card_image_url?: string | null
|
||||||
category: string
|
category: string
|
||||||
change_reason?: string | null
|
change_reason?: string | null
|
||||||
change_type?: Database["public"]["Enums"]["version_change_type"]
|
change_type?: Database["public"]["Enums"]["version_change_type"]
|
||||||
@@ -2803,12 +2812,17 @@ export type Database = {
|
|||||||
manufacturer_id?: string | null
|
manufacturer_id?: string | null
|
||||||
name: string
|
name: string
|
||||||
ride_model_id: string
|
ride_model_id: string
|
||||||
|
ride_type?: string | null
|
||||||
slug: string
|
slug: string
|
||||||
submission_id?: string | null
|
submission_id?: string | null
|
||||||
version_id?: string
|
version_id?: string
|
||||||
version_number: number
|
version_number: number
|
||||||
}
|
}
|
||||||
Update: {
|
Update: {
|
||||||
|
banner_image_id?: string | null
|
||||||
|
banner_image_url?: string | null
|
||||||
|
card_image_id?: string | null
|
||||||
|
card_image_url?: string | null
|
||||||
category?: string
|
category?: string
|
||||||
change_reason?: string | null
|
change_reason?: string | null
|
||||||
change_type?: Database["public"]["Enums"]["version_change_type"]
|
change_type?: Database["public"]["Enums"]["version_change_type"]
|
||||||
@@ -2819,6 +2833,7 @@ export type Database = {
|
|||||||
manufacturer_id?: string | null
|
manufacturer_id?: string | null
|
||||||
name?: string
|
name?: string
|
||||||
ride_model_id?: string
|
ride_model_id?: string
|
||||||
|
ride_type?: string | null
|
||||||
slug?: string
|
slug?: string
|
||||||
submission_id?: string | null
|
submission_id?: string | null
|
||||||
version_id?: string
|
version_id?: string
|
||||||
|
|||||||
@@ -168,7 +168,12 @@ export interface RideModelVersion extends BaseVersionWithProfile {
|
|||||||
slug: string;
|
slug: string;
|
||||||
manufacturer_id: string | null;
|
manufacturer_id: string | null;
|
||||||
category: string;
|
category: string;
|
||||||
|
ride_type: string;
|
||||||
description: string | null;
|
description: string | null;
|
||||||
|
banner_image_url: string | null;
|
||||||
|
banner_image_id: string | null;
|
||||||
|
card_image_url: string | null;
|
||||||
|
card_image_id: string | null;
|
||||||
// Note: technical_specs removed - use ride_model_technical_specifications table
|
// Note: technical_specs removed - use ride_model_technical_specifications table
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
-- Add missing fields to ride_model_versions table
|
||||||
|
ALTER TABLE ride_model_versions
|
||||||
|
ADD COLUMN IF NOT EXISTS ride_type TEXT,
|
||||||
|
ADD COLUMN IF NOT EXISTS banner_image_url TEXT,
|
||||||
|
ADD COLUMN IF NOT EXISTS banner_image_id TEXT,
|
||||||
|
ADD COLUMN IF NOT EXISTS card_image_url TEXT,
|
||||||
|
ADD COLUMN IF NOT EXISTS card_image_id TEXT;
|
||||||
|
|
||||||
|
-- Update create_relational_version() trigger to include missing ride model fields
|
||||||
|
CREATE OR REPLACE FUNCTION public.create_relational_version()
|
||||||
|
RETURNS TRIGGER AS $$
|
||||||
|
DECLARE
|
||||||
|
v_version_number integer;
|
||||||
|
v_created_by uuid;
|
||||||
|
v_change_type version_change_type;
|
||||||
|
v_submission_id uuid;
|
||||||
|
v_version_table text;
|
||||||
|
v_entity_id_col text;
|
||||||
|
BEGIN
|
||||||
|
-- Determine version table name
|
||||||
|
v_version_table := TG_TABLE_NAME || '_versions';
|
||||||
|
v_entity_id_col := TG_TABLE_NAME || '_id';
|
||||||
|
|
||||||
|
-- Get user from session config (set by edge function)
|
||||||
|
BEGIN
|
||||||
|
v_created_by := current_setting('app.current_user_id', true)::uuid;
|
||||||
|
EXCEPTION WHEN OTHERS THEN
|
||||||
|
v_created_by := auth.uid();
|
||||||
|
END;
|
||||||
|
|
||||||
|
-- Get submission ID if available
|
||||||
|
BEGIN
|
||||||
|
v_submission_id := current_setting('app.submission_id', true)::uuid;
|
||||||
|
EXCEPTION WHEN OTHERS THEN
|
||||||
|
v_submission_id := NULL;
|
||||||
|
END;
|
||||||
|
|
||||||
|
-- Determine change type
|
||||||
|
IF TG_OP = 'INSERT' THEN
|
||||||
|
v_change_type := 'created';
|
||||||
|
v_version_number := 1;
|
||||||
|
ELSIF TG_OP = 'UPDATE' THEN
|
||||||
|
-- Only version if data actually changed (ignore updated_at, view counts, ratings)
|
||||||
|
IF (OLD.name, OLD.slug, OLD.description, OLD.status) IS NOT DISTINCT FROM
|
||||||
|
(NEW.name, NEW.slug, NEW.description, NEW.status) THEN
|
||||||
|
RETURN NEW;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
v_change_type := 'updated';
|
||||||
|
|
||||||
|
-- Mark previous version as not current
|
||||||
|
EXECUTE format('UPDATE %I SET is_current = false WHERE %I = $1 AND is_current = true',
|
||||||
|
v_version_table, v_entity_id_col)
|
||||||
|
USING NEW.id;
|
||||||
|
|
||||||
|
-- Get next version number
|
||||||
|
EXECUTE format('SELECT COALESCE(MAX(version_number), 0) + 1 FROM %I WHERE %I = $1',
|
||||||
|
v_version_table, v_entity_id_col)
|
||||||
|
INTO v_version_number
|
||||||
|
USING NEW.id;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Insert version record based on table type
|
||||||
|
IF TG_TABLE_NAME = 'parks' THEN
|
||||||
|
INSERT INTO public.park_versions (
|
||||||
|
park_id, version_number, created_by, change_type, submission_id,
|
||||||
|
name, slug, description, park_type, status, location_id, operator_id, property_owner_id,
|
||||||
|
opening_date, closing_date, opening_date_precision, closing_date_precision,
|
||||||
|
website_url, phone, email, banner_image_url, banner_image_id, card_image_url, card_image_id
|
||||||
|
) VALUES (
|
||||||
|
NEW.id, v_version_number, v_created_by, v_change_type, v_submission_id,
|
||||||
|
NEW.name, NEW.slug, NEW.description, NEW.park_type, NEW.status, NEW.location_id, NEW.operator_id, NEW.property_owner_id,
|
||||||
|
NEW.opening_date, NEW.closing_date, NEW.opening_date_precision, NEW.closing_date_precision,
|
||||||
|
NEW.website_url, NEW.phone, NEW.email, NEW.banner_image_url, NEW.banner_image_id, NEW.card_image_url, NEW.card_image_id
|
||||||
|
);
|
||||||
|
|
||||||
|
ELSIF TG_TABLE_NAME = 'rides' THEN
|
||||||
|
INSERT INTO public.ride_versions (
|
||||||
|
ride_id, version_number, created_by, change_type, submission_id,
|
||||||
|
name, slug, description, category, status, park_id, manufacturer_id, designer_id, ride_model_id,
|
||||||
|
opening_date, closing_date, opening_date_precision, closing_date_precision,
|
||||||
|
height_requirement_cm, age_requirement, max_speed_kmh, duration_seconds, capacity_per_hour,
|
||||||
|
gforce_max, inversions_count, length_meters, height_meters, drop_meters,
|
||||||
|
banner_image_url, banner_image_id, card_image_url, card_image_id, image_url,
|
||||||
|
ride_sub_type, coaster_type, seating_type, intensity_level,
|
||||||
|
track_material, support_material, propulsion_method,
|
||||||
|
water_depth_cm, splash_height_meters, wetness_level, flume_type, boat_capacity,
|
||||||
|
theme_name, story_description, show_duration_seconds, animatronics_count, projection_type, ride_system, scenes_count,
|
||||||
|
rotation_type, motion_pattern, platform_count, swing_angle_degrees, rotation_speed_rpm, arm_length_meters, max_height_reached_meters,
|
||||||
|
min_age, max_age, educational_theme, character_theme,
|
||||||
|
transport_type, route_length_meters, stations_count, vehicle_capacity, vehicles_count, round_trip_duration_seconds
|
||||||
|
) VALUES (
|
||||||
|
NEW.id, v_version_number, v_created_by, v_change_type, v_submission_id,
|
||||||
|
NEW.name, NEW.slug, NEW.description, NEW.category, NEW.status, NEW.park_id, NEW.manufacturer_id, NEW.designer_id, NEW.ride_model_id,
|
||||||
|
NEW.opening_date, NEW.closing_date, NEW.opening_date_precision, NEW.closing_date_precision,
|
||||||
|
NEW.height_requirement, NEW.age_requirement, NEW.max_speed_kmh, NEW.duration_seconds, NEW.capacity_per_hour,
|
||||||
|
NEW.max_g_force, NEW.inversions, NEW.length_meters, NEW.max_height_meters, NEW.drop_height_meters,
|
||||||
|
NEW.banner_image_url, NEW.banner_image_id, NEW.card_image_url, NEW.card_image_id, NEW.image_url,
|
||||||
|
NEW.ride_sub_type, NEW.coaster_type, NEW.seating_type, NEW.intensity_level,
|
||||||
|
NEW.track_material, NEW.support_material, NEW.propulsion_method,
|
||||||
|
NEW.water_depth_cm, NEW.splash_height_meters, NEW.wetness_level, NEW.flume_type, NEW.boat_capacity,
|
||||||
|
NEW.theme_name, NEW.story_description, NEW.show_duration_seconds, NEW.animatronics_count, NEW.projection_type, NEW.ride_system, NEW.scenes_count,
|
||||||
|
NEW.rotation_type, NEW.motion_pattern, NEW.platform_count, NEW.swing_angle_degrees, NEW.rotation_speed_rpm, NEW.arm_length_meters, NEW.max_height_reached_meters,
|
||||||
|
NEW.min_age, NEW.max_age, NEW.educational_theme, NEW.character_theme,
|
||||||
|
NEW.transport_type, NEW.route_length_meters, NEW.stations_count, NEW.vehicle_capacity, NEW.vehicles_count, NEW.round_trip_duration_seconds
|
||||||
|
);
|
||||||
|
|
||||||
|
ELSIF TG_TABLE_NAME = 'companies' THEN
|
||||||
|
INSERT INTO public.company_versions (
|
||||||
|
company_id, version_number, created_by, change_type, submission_id,
|
||||||
|
name, slug, description, company_type, person_type, founded_year, founded_date, founded_date_precision,
|
||||||
|
headquarters_location, website_url, logo_url, banner_image_url, banner_image_id, card_image_url, card_image_id
|
||||||
|
) VALUES (
|
||||||
|
NEW.id, v_version_number, v_created_by, v_change_type, v_submission_id,
|
||||||
|
NEW.name, NEW.slug, NEW.description, NEW.company_type, NEW.person_type, NEW.founded_year, NEW.founded_date, NEW.founded_date_precision,
|
||||||
|
NEW.headquarters_location, NEW.website_url, NEW.logo_url, NEW.banner_image_url, NEW.banner_image_id, NEW.card_image_url, NEW.card_image_id
|
||||||
|
);
|
||||||
|
|
||||||
|
ELSIF TG_TABLE_NAME = 'ride_models' THEN
|
||||||
|
INSERT INTO public.ride_model_versions (
|
||||||
|
ride_model_id, version_number, created_by, change_type, submission_id,
|
||||||
|
name, slug, manufacturer_id, category, ride_type, description,
|
||||||
|
banner_image_url, banner_image_id, card_image_url, card_image_id
|
||||||
|
) VALUES (
|
||||||
|
NEW.id, v_version_number, v_created_by, v_change_type, v_submission_id,
|
||||||
|
NEW.name, NEW.slug, NEW.manufacturer_id, NEW.category, NEW.ride_type, NEW.description,
|
||||||
|
NEW.banner_image_url, NEW.banner_image_id, NEW.card_image_url, NEW.card_image_id
|
||||||
|
);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql SECURITY DEFINER SET search_path = public;
|
||||||
@@ -0,0 +1,205 @@
|
|||||||
|
-- Drop the broken JSONB-based rollback function
|
||||||
|
DROP FUNCTION IF EXISTS public.rollback_to_version(TEXT, UUID, UUID, UUID, TEXT);
|
||||||
|
|
||||||
|
-- Create new relational rollback function with moderator-only access
|
||||||
|
CREATE OR REPLACE FUNCTION public.rollback_to_version(
|
||||||
|
p_entity_type TEXT,
|
||||||
|
p_entity_id UUID,
|
||||||
|
p_target_version_id UUID,
|
||||||
|
p_changed_by UUID,
|
||||||
|
p_reason TEXT
|
||||||
|
)
|
||||||
|
RETURNS UUID
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
SECURITY DEFINER
|
||||||
|
SET search_path = 'public'
|
||||||
|
AS $$
|
||||||
|
DECLARE
|
||||||
|
v_version_table TEXT;
|
||||||
|
v_entity_table TEXT;
|
||||||
|
v_entity_id_col TEXT;
|
||||||
|
v_new_version_id UUID;
|
||||||
|
v_version_data RECORD;
|
||||||
|
BEGIN
|
||||||
|
-- CRITICAL: Check authorization FIRST
|
||||||
|
IF NOT is_moderator(p_changed_by) THEN
|
||||||
|
RAISE EXCEPTION 'Only moderators can rollback versions'
|
||||||
|
USING ERRCODE = '42501'; -- insufficient_privilege
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Validate entity type
|
||||||
|
IF p_entity_type NOT IN ('park', 'ride', 'company', 'ride_model') THEN
|
||||||
|
RAISE EXCEPTION 'Invalid entity type: %', p_entity_type;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Determine table names
|
||||||
|
v_version_table := p_entity_type || '_versions';
|
||||||
|
v_entity_id_col := p_entity_type || '_id';
|
||||||
|
v_entity_table := CASE p_entity_type
|
||||||
|
WHEN 'park' THEN 'parks'
|
||||||
|
WHEN 'ride' THEN 'rides'
|
||||||
|
WHEN 'company' THEN 'companies'
|
||||||
|
WHEN 'ride_model' THEN 'ride_models'
|
||||||
|
END;
|
||||||
|
|
||||||
|
-- Get the target version data
|
||||||
|
EXECUTE format('SELECT * FROM %I WHERE version_id = $1', v_version_table)
|
||||||
|
INTO v_version_data
|
||||||
|
USING p_target_version_id;
|
||||||
|
|
||||||
|
IF v_version_data IS NULL THEN
|
||||||
|
RAISE EXCEPTION 'Version not found: %', p_target_version_id;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Set session variables for trigger
|
||||||
|
PERFORM set_config('app.current_user_id', p_changed_by::text, true);
|
||||||
|
PERFORM set_config('app.submission_id', '', true);
|
||||||
|
|
||||||
|
-- Restore entity data based on type
|
||||||
|
IF p_entity_type = 'park' THEN
|
||||||
|
UPDATE parks SET
|
||||||
|
name = v_version_data.name,
|
||||||
|
slug = v_version_data.slug,
|
||||||
|
description = v_version_data.description,
|
||||||
|
park_type = v_version_data.park_type,
|
||||||
|
status = v_version_data.status,
|
||||||
|
location_id = v_version_data.location_id,
|
||||||
|
operator_id = v_version_data.operator_id,
|
||||||
|
property_owner_id = v_version_data.property_owner_id,
|
||||||
|
opening_date = v_version_data.opening_date,
|
||||||
|
closing_date = v_version_data.closing_date,
|
||||||
|
opening_date_precision = v_version_data.opening_date_precision,
|
||||||
|
closing_date_precision = v_version_data.closing_date_precision,
|
||||||
|
website_url = v_version_data.website_url,
|
||||||
|
phone = v_version_data.phone,
|
||||||
|
email = v_version_data.email,
|
||||||
|
banner_image_url = v_version_data.banner_image_url,
|
||||||
|
banner_image_id = v_version_data.banner_image_id,
|
||||||
|
card_image_url = v_version_data.card_image_url,
|
||||||
|
card_image_id = v_version_data.card_image_id,
|
||||||
|
updated_at = NOW()
|
||||||
|
WHERE id = p_entity_id;
|
||||||
|
|
||||||
|
ELSIF p_entity_type = 'ride' THEN
|
||||||
|
UPDATE rides SET
|
||||||
|
name = v_version_data.name,
|
||||||
|
slug = v_version_data.slug,
|
||||||
|
description = v_version_data.description,
|
||||||
|
category = v_version_data.category,
|
||||||
|
status = v_version_data.status,
|
||||||
|
park_id = v_version_data.park_id,
|
||||||
|
manufacturer_id = v_version_data.manufacturer_id,
|
||||||
|
designer_id = v_version_data.designer_id,
|
||||||
|
ride_model_id = v_version_data.ride_model_id,
|
||||||
|
opening_date = v_version_data.opening_date,
|
||||||
|
closing_date = v_version_data.closing_date,
|
||||||
|
opening_date_precision = v_version_data.opening_date_precision,
|
||||||
|
closing_date_precision = v_version_data.closing_date_precision,
|
||||||
|
height_requirement = v_version_data.height_requirement_cm,
|
||||||
|
age_requirement = v_version_data.age_requirement,
|
||||||
|
max_speed_kmh = v_version_data.max_speed_kmh,
|
||||||
|
duration_seconds = v_version_data.duration_seconds,
|
||||||
|
capacity_per_hour = v_version_data.capacity_per_hour,
|
||||||
|
max_g_force = v_version_data.gforce_max,
|
||||||
|
inversions = v_version_data.inversions_count,
|
||||||
|
length_meters = v_version_data.length_meters,
|
||||||
|
max_height_meters = v_version_data.height_meters,
|
||||||
|
drop_height_meters = v_version_data.drop_meters,
|
||||||
|
banner_image_url = v_version_data.banner_image_url,
|
||||||
|
banner_image_id = v_version_data.banner_image_id,
|
||||||
|
card_image_url = v_version_data.card_image_url,
|
||||||
|
card_image_id = v_version_data.card_image_id,
|
||||||
|
image_url = v_version_data.image_url,
|
||||||
|
ride_sub_type = v_version_data.ride_sub_type,
|
||||||
|
coaster_type = v_version_data.coaster_type,
|
||||||
|
seating_type = v_version_data.seating_type,
|
||||||
|
intensity_level = v_version_data.intensity_level,
|
||||||
|
track_material = v_version_data.track_material,
|
||||||
|
support_material = v_version_data.support_material,
|
||||||
|
propulsion_method = v_version_data.propulsion_method,
|
||||||
|
water_depth_cm = v_version_data.water_depth_cm,
|
||||||
|
splash_height_meters = v_version_data.splash_height_meters,
|
||||||
|
wetness_level = v_version_data.wetness_level,
|
||||||
|
flume_type = v_version_data.flume_type,
|
||||||
|
boat_capacity = v_version_data.boat_capacity,
|
||||||
|
theme_name = v_version_data.theme_name,
|
||||||
|
story_description = v_version_data.story_description,
|
||||||
|
show_duration_seconds = v_version_data.show_duration_seconds,
|
||||||
|
animatronics_count = v_version_data.animatronics_count,
|
||||||
|
projection_type = v_version_data.projection_type,
|
||||||
|
ride_system = v_version_data.ride_system,
|
||||||
|
scenes_count = v_version_data.scenes_count,
|
||||||
|
rotation_type = v_version_data.rotation_type,
|
||||||
|
motion_pattern = v_version_data.motion_pattern,
|
||||||
|
platform_count = v_version_data.platform_count,
|
||||||
|
swing_angle_degrees = v_version_data.swing_angle_degrees,
|
||||||
|
rotation_speed_rpm = v_version_data.rotation_speed_rpm,
|
||||||
|
arm_length_meters = v_version_data.arm_length_meters,
|
||||||
|
max_height_reached_meters = v_version_data.max_height_reached_meters,
|
||||||
|
min_age = v_version_data.min_age,
|
||||||
|
max_age = v_version_data.max_age,
|
||||||
|
educational_theme = v_version_data.educational_theme,
|
||||||
|
character_theme = v_version_data.character_theme,
|
||||||
|
transport_type = v_version_data.transport_type,
|
||||||
|
route_length_meters = v_version_data.route_length_meters,
|
||||||
|
stations_count = v_version_data.stations_count,
|
||||||
|
vehicle_capacity = v_version_data.vehicle_capacity,
|
||||||
|
vehicles_count = v_version_data.vehicles_count,
|
||||||
|
round_trip_duration_seconds = v_version_data.round_trip_duration_seconds,
|
||||||
|
updated_at = NOW()
|
||||||
|
WHERE id = p_entity_id;
|
||||||
|
|
||||||
|
ELSIF p_entity_type = 'company' THEN
|
||||||
|
UPDATE companies SET
|
||||||
|
name = v_version_data.name,
|
||||||
|
slug = v_version_data.slug,
|
||||||
|
description = v_version_data.description,
|
||||||
|
company_type = v_version_data.company_type,
|
||||||
|
person_type = v_version_data.person_type,
|
||||||
|
founded_year = v_version_data.founded_year,
|
||||||
|
founded_date = v_version_data.founded_date,
|
||||||
|
founded_date_precision = v_version_data.founded_date_precision,
|
||||||
|
headquarters_location = v_version_data.headquarters_location,
|
||||||
|
website_url = v_version_data.website_url,
|
||||||
|
logo_url = v_version_data.logo_url,
|
||||||
|
banner_image_url = v_version_data.banner_image_url,
|
||||||
|
banner_image_id = v_version_data.banner_image_id,
|
||||||
|
card_image_url = v_version_data.card_image_url,
|
||||||
|
card_image_id = v_version_data.card_image_id,
|
||||||
|
updated_at = NOW()
|
||||||
|
WHERE id = p_entity_id;
|
||||||
|
|
||||||
|
ELSIF p_entity_type = 'ride_model' THEN
|
||||||
|
UPDATE ride_models SET
|
||||||
|
name = v_version_data.name,
|
||||||
|
slug = v_version_data.slug,
|
||||||
|
manufacturer_id = v_version_data.manufacturer_id,
|
||||||
|
category = v_version_data.category,
|
||||||
|
ride_type = v_version_data.ride_type,
|
||||||
|
description = v_version_data.description,
|
||||||
|
banner_image_url = v_version_data.banner_image_url,
|
||||||
|
banner_image_id = v_version_data.banner_image_id,
|
||||||
|
card_image_url = v_version_data.card_image_url,
|
||||||
|
card_image_id = v_version_data.card_image_id,
|
||||||
|
updated_at = NOW()
|
||||||
|
WHERE id = p_entity_id;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Update the newly created version with restored change type and reason
|
||||||
|
EXECUTE format('
|
||||||
|
UPDATE %I
|
||||||
|
SET
|
||||||
|
change_type = $1,
|
||||||
|
change_reason = $2
|
||||||
|
WHERE %I = $3
|
||||||
|
AND is_current = true
|
||||||
|
RETURNING version_id
|
||||||
|
', v_version_table, v_entity_id_col)
|
||||||
|
INTO v_new_version_id
|
||||||
|
USING 'restored'::version_change_type,
|
||||||
|
'Restored to version ' || v_version_data.version_number || ': ' || p_reason,
|
||||||
|
p_entity_id;
|
||||||
|
|
||||||
|
RETURN v_new_version_id;
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
Reference in New Issue
Block a user