🔧 FIX: Restore missing calculator files from src/ to app/ directory
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
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
|
||||
Reference in New Issue
Block a user