import '../../models/clinic_discount.dart'; import '../../models/job.dart'; import '../../models/prosthetic_product.dart'; class PricingBreakdown { const PricingBreakdown({ required this.billableUnits, required this.unitPrice, required this.baseAmount, required this.discountAmount, required this.finalAmount, required this.appliedDiscounts, }); final int billableUnits; final double unitPrice; final double baseAmount; final double discountAmount; final double finalAmount; final List appliedDiscounts; } class PricingService { PricingService._(); static final instance = PricingService._(); int billableUnitsForType(ProstheticType type, int memberCount) { final safeCount = memberCount <= 0 ? 1 : memberCount; return switch (type) { ProstheticType.tamProtez || ProstheticType.parsiyel => 1, _ => safeCount, }; } String unitLabelForType(ProstheticType type) { return switch (type) { ProstheticType.tamProtez || ProstheticType.parsiyel => 'vaka', _ => 'diş', }; } PricingBreakdown calculate({ required ProstheticProduct product, required ProstheticType prostheticType, required int memberCount, required String clinicTenantId, required List discounts, }) { final billableUnits = billableUnitsForType(prostheticType, memberCount); final unitPrice = product.unitPrice ?? 0; final baseAmount = unitPrice * billableUnits; final applicable = discounts.where((discount) { if (!discount.isActive) return false; if (!(discount.appliesToAll || discount.clinicTenantId == clinicTenantId)) { return false; } if (!(discount.appliesToAllTypes || discount.prostheticType == prostheticType.value)) { return false; } if (discount.minQuantity > 0 && billableUnits < discount.minQuantity) { return false; } return true; }).toList(); double running = baseAmount; for (final discount in applicable) { running = discount.discountType == DiscountType.percentage ? running * (1 - discount.discountValue / 100) : running - discount.discountValue; } final finalAmount = running.clamp(0, double.infinity).toDouble(); return PricingBreakdown( billableUnits: billableUnits, unitPrice: unitPrice, baseAmount: baseAmount, discountAmount: (baseAmount - finalAmount) .clamp(0, double.infinity) .toDouble(), finalAmount: finalAmount, appliedDiscounts: applicable, ); } }