from ..models import CostFactor from .. import db import logging logger = logging.getLogger(__name__) # Single source of truth for default cost factors DEFAULT_COST_FACTORS = [ # Mold Type Factors {'category': 'mold', 'name': 'Flat', 'factor_value': 1.0, 'description': 'Standard flat outsole'}, {'category': 'mold', 'name': 'Flat with Top/Heel Tip', 'factor_value': 1.25, 'description': 'Flat with additional tip features'}, {'category': 'mold', 'name': 'Top PL', 'factor_value': 1.05, 'description': 'Top part line mold'}, {'category': 'mold', 'name': 'Visible PL', 'factor_value': 1.28, 'description': 'Visible part line mold'}, {'category': 'mold', 'name': 'Short PL (Heel/Forefoot)', 'factor_value': 1.18, 'description': 'Short part line for specific areas'}, {'category': 'mold', 'name': 'Wave PL', 'factor_value': 1.32, 'description': 'Wave pattern part line'}, {'category': 'mold', 'name': 'Multi-color PL', 'factor_value': 1.35, 'description': 'Multi-color part line mold'}, {'category': 'mold', 'name': '2 Plates Mold', 'factor_value': 1.0, 'description': 'Standard 2-plate configuration'}, {'category': 'mold', 'name': '3 Plates Mold', 'factor_value': 1.35, 'description': 'Complex 3-plate configuration'}, {'category': 'mold', 'name': '2 Plates with in-mold channel', 'factor_value': 1.25, 'description': '2-plate with channel features'}, {'category': 'mold', 'name': 'Breathable + in-mold channel', 'factor_value': 1.45, 'description': 'Breathable with channel features'}, {'category': 'mold', 'name': 'Sandal with Upper Bandage', 'factor_value': 1.15, 'description': 'Sandal with bandage features'}, {'category': 'mold', 'name': '2 Plate without Upper Bandage', 'factor_value': 1.05, 'description': 'Standard 2-plate sandal'}, {'category': 'mold', 'name': 'Co-shot mold', 'factor_value': 1.25, 'description': 'Multi-material injection'}, {'category': 'mold', 'name': 'Foaming mold', 'factor_value': 1.4, 'description': 'Foam injection process'}, # Complexity Factors {'category': 'complexity', 'name': 'high_sidewall', 'factor_value': 0.18, 'calculation_formula': 'Base Price × 0.18', 'description': 'Additional cost for high sidewall molds'}, {'category': 'complexity', 'name': 'slider', 'factor_value': 0.1, 'calculation_formula': 'Base Price × (Number of Sliders × 0.10)', 'description': 'Cost per slider added to mold'}, {'category': 'complexity', 'name': 'cavity', 'factor_value': 0.12, 'calculation_formula': 'Base Price × ((Number of Cavities - 1) × 0.12)', 'description': 'Cost for additional cavities beyond 1'}, # Texture Factors {'category': 'texture', 'name': 'adidas_digital', 'factor_value': 0.0, 'percentage': '0%', 'description': 'No additional cost for standard adidas texture'}, {'category': 'texture', 'name': 'customized texture', 'factor_value': 0.15, 'percentage': '15%', 'description': '15% of base price for custom texture'}, {'category': 'texture', 'name': 'laser', 'factor_value': 0.2, 'percentage': '20%', 'description': '20% of base price for laser texture'}, # Tax Rates {'category': 'tax', 'name': 'China', 'factor_value': 0.06, 'percentage': '6%', 'description': '6% VAT for China'}, {'category': 'tax', 'name': 'Vietnam', 'factor_value': 0.10, 'percentage': '10%', 'description': '10% VAT for Vietnam'}, {'category': 'tax', 'name': 'Indonesia', 'factor_value': 0.07, 'percentage': '7%', 'description': '7% VAT for Indonesia'}, # Base Price {'category': 'base', 'name': 'DEFAULT_NET_BASE', 'factor_value': 12.5, 'description': 'Default base price for calculations'} ] def load_cost_factors_from_db(): """ Load cost factors from database and return them in the same format as constants. Falls back to hardcoded values if database is not available. """ try: # Get all active cost factors factors = CostFactor.query.filter_by(is_active=True).all() if not factors: logger.warning("No cost factors found in database, using hardcoded defaults") return get_default_cost_factors() # Build the cost factors structure cost_factors = { 'mold': {}, 'complexity': {}, 'texture': {} } tax_rates = {} default_net_base = 12.5 # Default value for factor in factors: if factor.category == 'mold': cost_factors['mold'][factor.name] = factor.factor_value elif factor.category == 'complexity': cost_factors['complexity'][factor.name] = factor.factor_value elif factor.category == 'texture': cost_factors['texture'][factor.name] = factor.factor_value elif factor.category == 'tax': tax_rates[factor.name] = factor.factor_value elif factor.category == 'base': default_net_base = factor.factor_value logger.info(f"Loaded {len(factors)} cost factors from database") return cost_factors, tax_rates, default_net_base except Exception as e: logger.error(f"Error loading cost factors from database: {str(e)}") logger.info("Falling back to hardcoded cost factors") return get_default_cost_factors() def get_default_cost_factors(): """Return hardcoded cost factors as fallback - derived from single source of truth""" cost_factors = { 'mold': {}, 'complexity': {}, 'texture': {} } tax_rates = {} default_net_base = 12.5 # Build the structure from the single source of truth for factor_data in DEFAULT_COST_FACTORS: category = factor_data['category'] name = factor_data['name'] value = factor_data['factor_value'] if category == 'mold': cost_factors['mold'][name] = value elif category == 'complexity': cost_factors['complexity'][name] = value elif category == 'texture': cost_factors['texture'][name] = value elif category == 'tax': tax_rates[name] = value elif category == 'base': default_net_base = value return cost_factors, tax_rates, default_net_base def get_cost_factors(): """Get current cost factors (from database or defaults)""" return load_cost_factors_from_db() def initialize_default_cost_factors(): """Initialize the database with default cost factors if none exist""" try: if CostFactor.query.count() == 0: logger.info("Initializing database with default cost factors") # Use the single source of truth for factor_data in DEFAULT_COST_FACTORS: factor = CostFactor(**factor_data) db.session.add(factor) db.session.commit() logger.info(f"Initialized {len(DEFAULT_COST_FACTORS)} default cost factors") except Exception as e: logger.error(f"Error initializing default cost factors: {str(e)}") db.session.rollback() raise