mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 10:31:13 -05:00
Fix ride model technical specs
Implement plan to fix ride model technical specifications pipeline. This includes creating a new migration for the `ride_model_submission_technical_specifications` table, updating `entitySubmissionHelpers.ts` to handle insertion of technical specifications, and modifying the edge function `process-selective-approval/index.ts` to fetch these specifications. This ensures no data loss for ride model technical specifications.
This commit is contained in:
@@ -3413,6 +3413,47 @@ export type Database = {
|
||||
},
|
||||
]
|
||||
}
|
||||
ride_model_submission_technical_specifications: {
|
||||
Row: {
|
||||
category: string | null
|
||||
created_at: string | null
|
||||
display_order: number | null
|
||||
id: string
|
||||
ride_model_submission_id: string
|
||||
spec_name: string
|
||||
spec_unit: string | null
|
||||
spec_value: string
|
||||
}
|
||||
Insert: {
|
||||
category?: string | null
|
||||
created_at?: string | null
|
||||
display_order?: number | null
|
||||
id?: string
|
||||
ride_model_submission_id: string
|
||||
spec_name: string
|
||||
spec_unit?: string | null
|
||||
spec_value: string
|
||||
}
|
||||
Update: {
|
||||
category?: string | null
|
||||
created_at?: string | null
|
||||
display_order?: number | null
|
||||
id?: string
|
||||
ride_model_submission_id?: string
|
||||
spec_name?: string
|
||||
spec_unit?: string | null
|
||||
spec_value?: string
|
||||
}
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "fk_ride_model_submission"
|
||||
columns: ["ride_model_submission_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "ride_model_submissions"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
]
|
||||
}
|
||||
ride_model_submissions: {
|
||||
Row: {
|
||||
banner_image_id: string | null
|
||||
|
||||
@@ -170,6 +170,15 @@ export interface CompanyFormData {
|
||||
card_image_id?: string;
|
||||
}
|
||||
|
||||
interface TechnicalSpecification {
|
||||
spec_name: string;
|
||||
spec_value: string;
|
||||
spec_type?: 'string' | 'number' | 'boolean' | 'date';
|
||||
category?: string;
|
||||
unit?: string;
|
||||
display_order?: number;
|
||||
}
|
||||
|
||||
export interface RideModelFormData {
|
||||
name: string;
|
||||
slug: string;
|
||||
@@ -182,6 +191,7 @@ export interface RideModelFormData {
|
||||
banner_image_id?: string;
|
||||
card_image_url?: string;
|
||||
card_image_id?: string;
|
||||
_technical_specifications?: TechnicalSpecification[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1590,6 +1600,53 @@ export async function submitRideModelCreation(
|
||||
|
||||
if (itemError) throw itemError;
|
||||
|
||||
// Insert into ride_model_submissions table for relational integrity
|
||||
const { data: rideModelSubmissionData, error: rideModelSubmissionError } = await supabase
|
||||
.from('ride_model_submissions')
|
||||
.insert({
|
||||
submission_id: submissionData.id,
|
||||
name: data.name,
|
||||
slug: data.slug,
|
||||
manufacturer_id: data.manufacturer_id,
|
||||
category: data.category,
|
||||
ride_type: data.ride_type || data.category,
|
||||
description: data.description || null,
|
||||
banner_image_url: data.banner_image_url || null,
|
||||
banner_image_id: data.banner_image_id || null,
|
||||
card_image_url: data.card_image_url || null,
|
||||
card_image_id: data.card_image_id || null
|
||||
})
|
||||
.select()
|
||||
.single();
|
||||
|
||||
if (rideModelSubmissionError) {
|
||||
logger.error('Failed to insert ride model submission', { error: rideModelSubmissionError });
|
||||
throw rideModelSubmissionError;
|
||||
}
|
||||
|
||||
// Insert technical specifications into submission table
|
||||
if ((data as any)._technical_specifications?.length > 0) {
|
||||
const { error: techSpecError } = await supabase
|
||||
.from('ride_model_submission_technical_specifications')
|
||||
.insert(
|
||||
(data as any)._technical_specifications.map((spec: any) => ({
|
||||
ride_model_submission_id: rideModelSubmissionData.id,
|
||||
spec_name: spec.spec_name,
|
||||
spec_value: spec.spec_value,
|
||||
spec_unit: spec.spec_unit || null,
|
||||
category: spec.category || null,
|
||||
display_order: spec.display_order || 0
|
||||
}))
|
||||
);
|
||||
|
||||
if (techSpecError) {
|
||||
logger.error('Failed to insert ride model technical specs', { error: techSpecError });
|
||||
throw techSpecError;
|
||||
}
|
||||
|
||||
logger.log('✅ Ride model technical specifications inserted:', (data as any)._technical_specifications.length);
|
||||
}
|
||||
|
||||
return { submitted: true, submissionId: submissionData.id };
|
||||
}
|
||||
|
||||
@@ -1664,6 +1721,53 @@ export async function submitRideModelUpdate(
|
||||
|
||||
if (itemError) throw itemError;
|
||||
|
||||
// Insert into ride_model_submissions table for relational integrity
|
||||
const { data: rideModelSubmissionData, error: rideModelSubmissionError } = await supabase
|
||||
.from('ride_model_submissions')
|
||||
.insert({
|
||||
submission_id: submissionData.id,
|
||||
name: data.name,
|
||||
slug: data.slug,
|
||||
manufacturer_id: data.manufacturer_id,
|
||||
category: data.category,
|
||||
ride_type: data.ride_type || data.category,
|
||||
description: data.description || null,
|
||||
banner_image_url: data.banner_image_url || null,
|
||||
banner_image_id: data.banner_image_id || null,
|
||||
card_image_url: data.card_image_url || null,
|
||||
card_image_id: data.card_image_id || null
|
||||
})
|
||||
.select()
|
||||
.single();
|
||||
|
||||
if (rideModelSubmissionError) {
|
||||
logger.error('Failed to insert ride model update submission', { error: rideModelSubmissionError });
|
||||
throw rideModelSubmissionError;
|
||||
}
|
||||
|
||||
// Insert technical specifications into submission table
|
||||
if ((data as any)._technical_specifications?.length > 0) {
|
||||
const { error: techSpecError } = await supabase
|
||||
.from('ride_model_submission_technical_specifications')
|
||||
.insert(
|
||||
(data as any)._technical_specifications.map((spec: any) => ({
|
||||
ride_model_submission_id: rideModelSubmissionData.id,
|
||||
spec_name: spec.spec_name,
|
||||
spec_value: spec.spec_value,
|
||||
spec_unit: spec.spec_unit || null,
|
||||
category: spec.category || null,
|
||||
display_order: spec.display_order || 0
|
||||
}))
|
||||
);
|
||||
|
||||
if (techSpecError) {
|
||||
logger.error('Failed to insert ride model update technical specs', { error: techSpecError });
|
||||
throw techSpecError;
|
||||
}
|
||||
|
||||
logger.log('✅ Ride model update technical specifications inserted:', (data as any)._technical_specifications.length);
|
||||
}
|
||||
|
||||
return { submitted: true, submissionId: submissionData.id };
|
||||
}
|
||||
|
||||
|
||||
@@ -1954,7 +1954,30 @@ async function createRideModel(supabase: any, data: any): Promise<string> {
|
||||
let rideModelId: string;
|
||||
|
||||
// Extract relational data before transformation
|
||||
const technicalSpecifications = data._technical_specifications || [];
|
||||
let technicalSpecifications = data._technical_specifications || [];
|
||||
|
||||
// If no inline specs provided, fetch from submission table
|
||||
if (technicalSpecifications.length === 0 && data.submission_id) {
|
||||
const { data: submissionData } = await supabase
|
||||
.from('ride_model_submissions')
|
||||
.select('id')
|
||||
.eq('submission_id', data.submission_id)
|
||||
.single();
|
||||
|
||||
if (submissionData) {
|
||||
const { data: submissionSpecs } = await supabase
|
||||
.from('ride_model_submission_technical_specifications')
|
||||
.select('*')
|
||||
.eq('ride_model_submission_id', submissionData.id);
|
||||
|
||||
if (submissionSpecs && submissionSpecs.length > 0) {
|
||||
edgeLogger.info('Fetched technical specs from submission table', {
|
||||
count: submissionSpecs.length
|
||||
});
|
||||
technicalSpecifications = submissionSpecs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove internal fields
|
||||
delete data._technical_specifications;
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
-- Create submission table for ride model technical specifications
|
||||
-- This ensures technical specs flow through the submission pipeline without data loss
|
||||
|
||||
CREATE TABLE ride_model_submission_technical_specifications (
|
||||
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
||||
ride_model_submission_id UUID NOT NULL,
|
||||
spec_name TEXT NOT NULL,
|
||||
spec_value TEXT NOT NULL,
|
||||
spec_unit TEXT,
|
||||
category TEXT,
|
||||
display_order INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
|
||||
CONSTRAINT fk_ride_model_submission
|
||||
FOREIGN KEY (ride_model_submission_id)
|
||||
REFERENCES ride_model_submissions(id)
|
||||
ON DELETE CASCADE,
|
||||
|
||||
CONSTRAINT unique_ride_model_submission_spec
|
||||
UNIQUE(ride_model_submission_id, spec_name)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_ride_model_submission_specs_submission
|
||||
ON ride_model_submission_technical_specifications(ride_model_submission_id);
|
||||
|
||||
-- Enable RLS
|
||||
ALTER TABLE ride_model_submission_technical_specifications ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Moderators can view all submission specs
|
||||
CREATE POLICY "Moderators can view all ride model submission specs"
|
||||
ON ride_model_submission_technical_specifications
|
||||
FOR SELECT
|
||||
USING (
|
||||
is_moderator(auth.uid()) AND
|
||||
((NOT has_mfa_enabled(auth.uid())) OR has_aal2())
|
||||
);
|
||||
|
||||
-- Users can view their own submission specs
|
||||
CREATE POLICY "Users can view their own ride model submission specs"
|
||||
ON ride_model_submission_technical_specifications
|
||||
FOR SELECT
|
||||
USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM ride_model_submissions rms
|
||||
JOIN content_submissions cs ON cs.id = rms.submission_id
|
||||
WHERE rms.id = ride_model_submission_technical_specifications.ride_model_submission_id
|
||||
AND cs.user_id = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
-- Users can insert their own submission specs
|
||||
CREATE POLICY "Users can insert their own ride model submission specs"
|
||||
ON ride_model_submission_technical_specifications
|
||||
FOR INSERT
|
||||
WITH CHECK (
|
||||
EXISTS (
|
||||
SELECT 1 FROM ride_model_submissions rms
|
||||
JOIN content_submissions cs ON cs.id = rms.submission_id
|
||||
WHERE rms.id = ride_model_submission_technical_specifications.ride_model_submission_id
|
||||
AND cs.user_id = auth.uid()
|
||||
)
|
||||
AND NOT is_user_banned(auth.uid())
|
||||
);
|
||||
|
||||
-- Moderators can update submission specs
|
||||
CREATE POLICY "Moderators can update ride model submission specs"
|
||||
ON ride_model_submission_technical_specifications
|
||||
FOR UPDATE
|
||||
USING (
|
||||
is_moderator(auth.uid()) AND
|
||||
((NOT has_mfa_enabled(auth.uid())) OR has_aal2())
|
||||
);
|
||||
|
||||
-- Moderators can delete submission specs
|
||||
CREATE POLICY "Moderators can delete ride model submission specs"
|
||||
ON ride_model_submission_technical_specifications
|
||||
FOR DELETE
|
||||
USING (
|
||||
is_moderator(auth.uid()) AND
|
||||
((NOT has_mfa_enabled(auth.uid())) OR has_aal2())
|
||||
);
|
||||
|
||||
COMMENT ON TABLE ride_model_submission_technical_specifications IS
|
||||
'Stores technical specifications for ride models during moderation - prevents data loss in submission pipeline';
|
||||
Reference in New Issue
Block a user