Spaces:
Running
Running
| // services.js - Core Business Logic with Supabase | |
| import { appState } from './state.js'; | |
| import { refreshUI, showToast } from './ui.js'; | |
| import { supabase } from './supabaseClient.js'; | |
| export async function handleUpdateStock(productName, quantity) { | |
| if (isNaN(quantity) || quantity <= 0) return; | |
| const recipe = appState.productRecipes[productName]; | |
| if (!recipe) { | |
| showToast(`Error: No recipe found for ${productName}.`, 'error'); | |
| return; | |
| } | |
| const stockUpdates = []; | |
| for (const materialName in recipe) { | |
| const required = recipe[materialName] * quantity; | |
| const material = appState.materials.find(m => m.name === materialName); | |
| if (!material || material.currentStock < required) { | |
| showToast(`Insufficient materials for ${quantity}x ${productName}. Needed ${required} of ${materialName}, but only have ${material ? material.currentStock : 0}.`, 'error'); | |
| return; | |
| } | |
| stockUpdates.push({ | |
| id: material.id, | |
| newStock: material.currentStock - required | |
| }); | |
| } | |
| showToast(`Producing ${quantity}x ${productName}...`, 'info'); | |
| try { | |
| for (const update of stockUpdates) { | |
| const { error } = await supabase | |
| .from('materials') | |
| .update({ current_stock: update.newStock, updated_at: new Date().toISOString() }) | |
| .eq('id', update.id); | |
| if (error) throw error; | |
| } | |
| const { error: logError } = await supabase | |
| .from('production_log') | |
| .insert({ product_name: productName, quantity: quantity }); | |
| if (logError) throw logError; | |
| for (const update of stockUpdates) { | |
| const material = appState.materials.find(m => m.id === update.id); | |
| if (material) material.currentStock = update.newStock; | |
| } | |
| appState.productionLog.unshift({ productName, quantity, date: new Date().toISOString() }); | |
| refreshUI(); | |
| showToast(`Produced ${quantity}x ${productName}.`, 'success'); | |
| document.querySelectorAll('.dashboard-card').forEach(card => { | |
| const h3 = card.querySelector('h3'); | |
| if (h3 && h3.textContent === productName) { | |
| card.querySelector('input').value = '0'; | |
| } | |
| }); | |
| } catch (error) { | |
| showToast(`Production failed: ${error.message}`, 'error'); | |
| } | |
| } | |
| export async function handleRestock(materialName, quantity) { | |
| if (isNaN(quantity) || quantity <= 0) return; | |
| const material = appState.materials.find(m => m.name === materialName); | |
| if (!material) return; | |
| const newStock = material.currentStock + quantity; | |
| try { | |
| const { data, error } = await supabase | |
| .from('materials') | |
| .update({ current_stock: newStock, updated_at: new Date().toISOString() }) | |
| .eq('id', material.id) | |
| .select(); | |
| if (error) throw error; | |
| material.currentStock = data[0].current_stock; | |
| showToast(`Restocked ${quantity} ${material.unit} of ${materialName}.`, 'success'); | |
| refreshUI(); | |
| } catch (error) { | |
| showToast(`Restock failed: ${error.message}`, 'error'); | |
| } | |
| } | |
| export async function handleSetStock(materialName, newStock) { | |
| if (isNaN(newStock) || newStock < 0) { | |
| showToast('Stock must be a valid positive number.', 'error'); | |
| refreshUI(); | |
| return; | |
| } | |
| const material = appState.materials.find(m => m.name === materialName); | |
| if (!material) return; | |
| try { | |
| const { data, error } = await supabase | |
| .from('materials') | |
| .update({ current_stock: newStock, updated_at: new Date().toISOString() }) | |
| .eq('id', material.id) | |
| .select(); | |
| if (error) throw error; | |
| material.currentStock = data[0].current_stock; | |
| showToast(`Stock for ${materialName} set to ${newStock}.`, 'success'); | |
| refreshUI(); | |
| } catch (error) { | |
| showToast(`Failed to set stock: ${error.message}`, 'error'); | |
| } | |
| } |