// 坯布入库事务处理 Edge Function // 确保 completed_quantity 和 inventory_records 数据一致性 import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'; Deno.serve(async (req) => { // CORS 预检 if (req.method === 'OPTIONS') { return new Response('ok', { headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', }, }); } const corsHeaders = { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', }; try { const body = await req.json(); const { planId, quantity, rolls, warehouseId, warehouseLocation, operatorId, pricePerMeter, } = body; // 参数验证 if (!planId || !quantity || quantity <= 0) { return new Response( JSON.stringify({ error: '缺少必要参数或数量无效' }), { status: 400, headers: corsHeaders } ); } // 获取认证信息 const authHeader = req.headers.get('Authorization') || ''; // 创建管理员客户端(绕过 RLS) const supabaseAdmin = createClient( Deno.env.get('SUPABASE_URL')!, Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!, ); // 开始事务处理 // 1. 获取当前计划信息 const { data: plan, error: planError } = await supabaseAdmin .from('production_plans') .select('completed_quantity, target_quantity, purchaser_id') .eq('id', planId) .maybeSingle(); if (planError || !plan) { return new Response( JSON.stringify({ error: '获取计划信息失败: ' + (planError?.message || '计划不存在') }), { status: 404, headers: corsHeaders } ); } // 2. 计算新的已完成数量 const newCompletedQuantity = (plan.completed_quantity || 0) + quantity; // 3. 检查是否超过目标数量 if (newCompletedQuantity > plan.target_quantity) { return new Response( JSON.stringify({ error: `入库数量超过剩余数量 (${plan.target_quantity - (plan.completed_quantity || 0)}米)` }), { status: 400, headers: corsHeaders } ); } const now = new Date().toISOString(); // 4. 更新计划的 completed_quantity const { error: updateError } = await supabaseAdmin .from('production_plans') .update({ completed_quantity: newCompletedQuantity }) .eq('id', planId); if (updateError) { return new Response( JSON.stringify({ error: '更新计划数量失败: ' + updateError.message }), { status: 500, headers: corsHeaders } ); } // 5. 创建入库记录 const insertData: any = { plan_id: planId, quantity: quantity, rolls: rolls || 0, warehouse_location: warehouseLocation || '', operator_id: operatorId, price_per_meter: pricePerMeter || 0, created_at: now, }; if (warehouseId) { insertData.warehouse_id = warehouseId; } const { data: inventoryRecord, error: insertError } = await supabaseAdmin .from('inventory_records') .insert(insertData) .select() .single(); if (insertError) { // 如果入库记录创建失败,需要回滚 completed_quantity // 注意:这里简化处理,实际生产环境应使用数据库事务 await supabaseAdmin .from('production_plans') .update({ completed_quantity: plan.completed_quantity }) .eq('id', planId); return new Response( JSON.stringify({ error: '创建入库记录失败: ' + insertError.message }), { status: 500, headers: corsHeaders } ); } // 6. 返回成功结果 return new Response( JSON.stringify({ success: true, data: { inventoryRecord, completedQuantity: newCompletedQuantity, progress: Math.round((newCompletedQuantity / plan.target_quantity) * 100), }, }), { headers: corsHeaders } ); } catch (error) { const message = error instanceof Error ? error.message : 'Unknown error'; return new Response( JSON.stringify({ error: '服务器错误: ' + message }), { status: 500, headers: corsHeaders } ); } });