Files
mold_cost_online_tool/app/utils/cost_factor_loader.py

139 lines
7.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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