mirror of
https://github.com/andwati/telecom-platform.git
synced 2026-10-18 02:52:53 +00:00
refactor: Extract CRUD operations from pricing service into separate file and improve discount extraction logic
- Move CreateRule, GetRule, UpdateRule, DeleteRule, ListRules, CalculatePrice, and ApplyRules to pricing_service_crud.go - Remove duplicate struct and constructor comments from pricing_service.go - Replace hardcoded discount values in extractDiscountValue with actual rule Actions field parsing - Add AdjustmentType-based discount calculation for Percentage, Fixed, Multiply, and Override
This commit is contained in:
@@ -9,7 +9,6 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PricingService implements the pricing business logic
|
|
||||||
type PricingService struct {
|
type PricingService struct {
|
||||||
repository pricing.Repository
|
repository pricing.Repository
|
||||||
engine pricing.RuleEngine
|
engine pricing.RuleEngine
|
||||||
@@ -17,7 +16,6 @@ type PricingService struct {
|
|||||||
logger *logrus.Logger
|
logger *logrus.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPricingService creates a new pricing service
|
|
||||||
func NewPricingService(
|
func NewPricingService(
|
||||||
repository pricing.Repository,
|
repository pricing.Repository,
|
||||||
engine pricing.RuleEngine,
|
engine pricing.RuleEngine,
|
||||||
@@ -32,182 +30,6 @@ func NewPricingService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateRule creates a new pricing rule
|
|
||||||
func (s *PricingService) CreateRule(ctx context.Context, rule *pricing.PricingRule) (*pricing.PricingRule, error) {
|
|
||||||
// Validate rule
|
|
||||||
if err := s.validator.ValidateRule(ctx, rule); err != nil {
|
|
||||||
return nil, fmt.Errorf("validation failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create rule
|
|
||||||
if err := s.repository.CreateRule(ctx, rule); err != nil {
|
|
||||||
s.logger.WithError(err).Error("Failed to create pricing rule")
|
|
||||||
return nil, fmt.Errorf("failed to create rule: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.logger.WithFields(logrus.Fields{
|
|
||||||
"rule_id": rule.ID,
|
|
||||||
"tenant_id": rule.TenantID,
|
|
||||||
"type": rule.Type,
|
|
||||||
}).Info("Pricing rule created successfully")
|
|
||||||
|
|
||||||
return rule, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRule retrieves a pricing rule by ID
|
|
||||||
func (s *PricingService) GetRule(ctx context.Context, id string) (*pricing.PricingRule, error) {
|
|
||||||
rule, err := s.repository.GetRule(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
s.logger.WithError(err).WithField("rule_id", id).Error("Failed to get pricing rule")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return rule, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateRule updates an existing pricing rule
|
|
||||||
func (s *PricingService) UpdateRule(ctx context.Context, id string, rule *pricing.PricingRule) (*pricing.PricingRule, error) {
|
|
||||||
// Validate rule
|
|
||||||
if err := s.validator.ValidateRule(ctx, rule); err != nil {
|
|
||||||
return nil, fmt.Errorf("validation failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update rule
|
|
||||||
if err := s.repository.UpdateRule(ctx, rule); err != nil {
|
|
||||||
s.logger.WithError(err).WithField("rule_id", id).Error("Failed to update pricing rule")
|
|
||||||
return nil, fmt.Errorf("failed to update rule: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.logger.WithFields(logrus.Fields{
|
|
||||||
"rule_id": rule.ID,
|
|
||||||
"tenant_id": rule.TenantID,
|
|
||||||
"type": rule.Type,
|
|
||||||
}).Info("Pricing rule updated successfully")
|
|
||||||
|
|
||||||
return rule, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteRule deletes a pricing rule
|
|
||||||
func (s *PricingService) DeleteRule(ctx context.Context, id string) error {
|
|
||||||
// Get rule for logging
|
|
||||||
rule, err := s.repository.GetRule(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete rule
|
|
||||||
if err := s.repository.DeleteRule(ctx, id); err != nil {
|
|
||||||
s.logger.WithError(err).WithField("rule_id", id).Error("Failed to delete pricing rule")
|
|
||||||
return fmt.Errorf("failed to delete rule: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.logger.WithFields(logrus.Fields{
|
|
||||||
"rule_id": rule.ID,
|
|
||||||
"tenant_id": rule.TenantID,
|
|
||||||
"type": rule.Type,
|
|
||||||
}).Info("Pricing rule deleted successfully")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListRules lists pricing rules with filtering
|
|
||||||
func (s *PricingService) ListRules(ctx context.Context, filter *pricing.PricingFilter) ([]*pricing.PricingRule, error) {
|
|
||||||
rules, err := s.repository.ListRules(ctx, filter)
|
|
||||||
if err != nil {
|
|
||||||
s.logger.WithError(err).Error("Failed to list pricing rules")
|
|
||||||
return nil, fmt.Errorf("failed to list rules: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return rules, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CalculatePrice calculates the final price based on active rules
|
|
||||||
func (s *PricingService) CalculatePrice(ctx context.Context, pricingCtx *pricing.PricingContext) (*pricing.PricingResult, error) {
|
|
||||||
// Validate context
|
|
||||||
if err := s.validator.ValidateContext(ctx, pricingCtx); err != nil {
|
|
||||||
return nil, fmt.Errorf("invalid pricing context: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get active rules for tenant
|
|
||||||
rules, err := s.repository.GetActiveRules(ctx, pricingCtx.TenantID)
|
|
||||||
if err != nil {
|
|
||||||
s.logger.WithError(err).WithField("tenant_id", pricingCtx.TenantID).Error("Failed to get active rules")
|
|
||||||
return nil, fmt.Errorf("failed to get active rules: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply rules to calculate final price
|
|
||||||
result, err := s.ApplyRules(ctx, pricingCtx, rules)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.logger.WithFields(logrus.Fields{
|
|
||||||
"tenant_id": pricingCtx.TenantID,
|
|
||||||
"product_id": pricingCtx.ProductID,
|
|
||||||
"original_price": result.OriginalPrice,
|
|
||||||
"final_price": result.FinalPrice,
|
|
||||||
"rules_applied": len(result.AppliedRules),
|
|
||||||
}).Info("Price calculated successfully")
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApplyRules applies specific rules to a pricing context
|
|
||||||
func (s *PricingService) ApplyRules(ctx context.Context, pricingCtx *pricing.PricingContext, rules []*pricing.PricingRule) (*pricing.PricingResult, error) {
|
|
||||||
result := &pricing.PricingResult{
|
|
||||||
OriginalPrice: pricingCtx.BasePrice,
|
|
||||||
AdjustedPrice: pricingCtx.BasePrice,
|
|
||||||
FinalPrice: pricingCtx.BasePrice,
|
|
||||||
Currency: pricingCtx.Currency,
|
|
||||||
AppliedRules: make([]pricing.AppliedRule, 0),
|
|
||||||
Metadata: make(map[string]any),
|
|
||||||
}
|
|
||||||
|
|
||||||
currentPrice := pricingCtx.BasePrice
|
|
||||||
|
|
||||||
// Apply rules in priority order
|
|
||||||
for _, rule := range rules {
|
|
||||||
shouldApply, err := s.engine.EvaluateRule(ctx, rule, pricingCtx)
|
|
||||||
if err != nil {
|
|
||||||
s.logger.WithError(err).WithField("rule_id", rule.ID).Error("Failed to evaluate rule")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if shouldApply {
|
|
||||||
adjustedPrice, err := s.engine.ApplyRule(ctx, rule, pricingCtx, currentPrice)
|
|
||||||
if err != nil {
|
|
||||||
s.logger.WithError(err).WithField("rule_id", rule.ID).Error("Failed to apply rule")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate discount amount
|
|
||||||
discount := currentPrice - adjustedPrice
|
|
||||||
|
|
||||||
// Update result
|
|
||||||
currentPrice = adjustedPrice
|
|
||||||
result.AppliedRules = append(result.AppliedRules, pricing.AppliedRule{
|
|
||||||
RuleID: rule.ID,
|
|
||||||
RuleName: rule.Name,
|
|
||||||
Type: string(rule.Type),
|
|
||||||
Adjustment: discount,
|
|
||||||
})
|
|
||||||
|
|
||||||
s.logger.WithFields(logrus.Fields{
|
|
||||||
"rule_id": rule.ID,
|
|
||||||
"rule_name": rule.Name,
|
|
||||||
"adjustment": discount,
|
|
||||||
"new_price": adjustedPrice,
|
|
||||||
}).Debug("Rule applied")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finalize result
|
|
||||||
result.FinalPrice = currentPrice
|
|
||||||
result.Discount = result.OriginalPrice - result.FinalPrice
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateRule validates a pricing rule
|
// ValidateRule validates a pricing rule
|
||||||
func (s *PricingService) ValidateRule(ctx context.Context, rule *pricing.PricingRule) error {
|
func (s *PricingService) ValidateRule(ctx context.Context, rule *pricing.PricingRule) error {
|
||||||
return s.validator.ValidateRule(ctx, rule)
|
return s.validator.ValidateRule(ctx, rule)
|
||||||
@@ -264,8 +86,7 @@ func (s *PricingService) GetAnalytics(ctx context.Context, tenantID string) (*pr
|
|||||||
|
|
||||||
// calculateDiscountStatistics calculates actual discount statistics from pricing history
|
// calculateDiscountStatistics calculates actual discount statistics from pricing history
|
||||||
func (s *PricingService) calculateDiscountStatistics(ctx context.Context) (pricing.DiscountStatistics, error) {
|
func (s *PricingService) calculateDiscountStatistics(ctx context.Context) (pricing.DiscountStatistics, error) {
|
||||||
// Get all rules to estimate discount usage
|
// Retrieve all rules and compute discount statistics from their action values
|
||||||
// Use empty filter to get all rules
|
|
||||||
filter := &pricing.PricingFilter{}
|
filter := &pricing.PricingFilter{}
|
||||||
allRules, err := s.repository.ListRules(ctx, filter)
|
allRules, err := s.repository.ListRules(ctx, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -299,8 +120,6 @@ func (s *PricingService) calculateDiscountStatistics(ctx context.Context) (prici
|
|||||||
var smallestDiscount float64 = -1
|
var smallestDiscount float64 = -1
|
||||||
|
|
||||||
for _, rule := range activeRules {
|
for _, rule := range activeRules {
|
||||||
// Extract discount value from rule actions
|
|
||||||
// This would be more sophisticated in a real implementation
|
|
||||||
discountValue := extractDiscountValue(rule)
|
discountValue := extractDiscountValue(rule)
|
||||||
|
|
||||||
if discountValue > 0 {
|
if discountValue > 0 {
|
||||||
@@ -338,29 +157,32 @@ func (s *PricingService) calculateDiscountStatistics(ctx context.Context) (prici
|
|||||||
|
|
||||||
// extractDiscountValue extracts discount value from rule actions
|
// extractDiscountValue extracts discount value from rule actions
|
||||||
func extractDiscountValue(rule *pricing.PricingRule) float64 {
|
func extractDiscountValue(rule *pricing.PricingRule) float64 {
|
||||||
// In a real implementation, this would parse the rule actions to extract discount values
|
// Extract the actual discount value from the rule's Actions field
|
||||||
// For now, we'll use a simplified approach based on rule type
|
actionValue := rule.Actions.Value
|
||||||
|
if actionValue == 0 {
|
||||||
|
return 0.0
|
||||||
|
}
|
||||||
|
|
||||||
switch rule.Type {
|
switch rule.Actions.AdjustmentType {
|
||||||
case pricing.RuleTypePercentageDiscount:
|
case pricing.AdjustmentTypePercentage:
|
||||||
// For percentage discount rules, assume a standard discount percentage
|
// Value represents the percentage discount directly
|
||||||
return 10.0 // 10% discount as example
|
return actionValue
|
||||||
case pricing.RuleTypeFixedDiscount:
|
case pricing.AdjustmentTypeFixed:
|
||||||
// For fixed discount rules, assume a fixed amount
|
// Value represents a fixed monetary discount
|
||||||
return 15.0 // $15 discount as example
|
return actionValue
|
||||||
case pricing.RuleTypeMultiplier:
|
case pricing.AdjustmentTypeMultiply:
|
||||||
// For multiplier rules, assume a discount factor
|
// Multiplier < 1.0 implies a discount; convert to percentage
|
||||||
return 5.0 // 5% discount as example
|
if actionValue < 1.0 {
|
||||||
case pricing.RuleTypeTieredPricing:
|
return (1.0 - actionValue) * 100
|
||||||
// For tiered pricing rules, assume variable discount
|
}
|
||||||
return 20.0 // 20% discount as example
|
return 0.0
|
||||||
case pricing.RuleTypeDynamicPricing:
|
case pricing.AdjustmentTypeOverride:
|
||||||
// For dynamic pricing rules, assume market-based discount
|
// Override replaces the price; if NewPrice is set, compute savings
|
||||||
return 12.5 // 12.5% discount as example
|
if rule.Actions.NewPrice != nil && *rule.Actions.NewPrice < actionValue {
|
||||||
case pricing.RuleTypeConditionalPricing:
|
return actionValue - *rule.Actions.NewPrice
|
||||||
// For conditional pricing rules, assume conditional discount
|
}
|
||||||
return 8.0 // 8% discount as example
|
return 0.0
|
||||||
default:
|
default:
|
||||||
return 0.0 // No discount for other rule types
|
return actionValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,186 @@
|
|||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/pricing"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// CreateRule creates a new pricing rule
|
||||||
|
func (s *PricingService) CreateRule(ctx context.Context, rule *pricing.PricingRule) (*pricing.PricingRule, error) {
|
||||||
|
// Validate rule
|
||||||
|
if err := s.validator.ValidateRule(ctx, rule); err != nil {
|
||||||
|
return nil, fmt.Errorf("validation failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create rule
|
||||||
|
if err := s.repository.CreateRule(ctx, rule); err != nil {
|
||||||
|
s.logger.WithError(err).Error("Failed to create pricing rule")
|
||||||
|
return nil, fmt.Errorf("failed to create rule: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.logger.WithFields(logrus.Fields{
|
||||||
|
"rule_id": rule.ID,
|
||||||
|
"tenant_id": rule.TenantID,
|
||||||
|
"type": rule.Type,
|
||||||
|
}).Info("Pricing rule created successfully")
|
||||||
|
|
||||||
|
return rule, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRule retrieves a pricing rule by ID
|
||||||
|
func (s *PricingService) GetRule(ctx context.Context, id string) (*pricing.PricingRule, error) {
|
||||||
|
rule, err := s.repository.GetRule(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.WithError(err).WithField("rule_id", id).Error("Failed to get pricing rule")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rule, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateRule updates an existing pricing rule
|
||||||
|
func (s *PricingService) UpdateRule(ctx context.Context, id string, rule *pricing.PricingRule) (*pricing.PricingRule, error) {
|
||||||
|
// Validate rule
|
||||||
|
if err := s.validator.ValidateRule(ctx, rule); err != nil {
|
||||||
|
return nil, fmt.Errorf("validation failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update rule
|
||||||
|
if err := s.repository.UpdateRule(ctx, rule); err != nil {
|
||||||
|
s.logger.WithError(err).WithField("rule_id", id).Error("Failed to update pricing rule")
|
||||||
|
return nil, fmt.Errorf("failed to update rule: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.logger.WithFields(logrus.Fields{
|
||||||
|
"rule_id": rule.ID,
|
||||||
|
"tenant_id": rule.TenantID,
|
||||||
|
"type": rule.Type,
|
||||||
|
}).Info("Pricing rule updated successfully")
|
||||||
|
|
||||||
|
return rule, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRule deletes a pricing rule
|
||||||
|
func (s *PricingService) DeleteRule(ctx context.Context, id string) error {
|
||||||
|
// Get rule for logging
|
||||||
|
rule, err := s.repository.GetRule(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete rule
|
||||||
|
if err := s.repository.DeleteRule(ctx, id); err != nil {
|
||||||
|
s.logger.WithError(err).WithField("rule_id", id).Error("Failed to delete pricing rule")
|
||||||
|
return fmt.Errorf("failed to delete rule: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.logger.WithFields(logrus.Fields{
|
||||||
|
"rule_id": rule.ID,
|
||||||
|
"tenant_id": rule.TenantID,
|
||||||
|
"type": rule.Type,
|
||||||
|
}).Info("Pricing rule deleted successfully")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRules lists pricing rules with filtering
|
||||||
|
func (s *PricingService) ListRules(ctx context.Context, filter *pricing.PricingFilter) ([]*pricing.PricingRule, error) {
|
||||||
|
rules, err := s.repository.ListRules(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.WithError(err).Error("Failed to list pricing rules")
|
||||||
|
return nil, fmt.Errorf("failed to list rules: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return rules, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CalculatePrice calculates the final price based on active rules
|
||||||
|
func (s *PricingService) CalculatePrice(ctx context.Context, pricingCtx *pricing.PricingContext) (*pricing.PricingResult, error) {
|
||||||
|
// Validate context
|
||||||
|
if err := s.validator.ValidateContext(ctx, pricingCtx); err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid pricing context: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get active rules for tenant
|
||||||
|
rules, err := s.repository.GetActiveRules(ctx, pricingCtx.TenantID)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.WithError(err).WithField("tenant_id", pricingCtx.TenantID).Error("Failed to get active rules")
|
||||||
|
return nil, fmt.Errorf("failed to get active rules: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply rules to calculate final price
|
||||||
|
result, err := s.ApplyRules(ctx, pricingCtx, rules)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.logger.WithFields(logrus.Fields{
|
||||||
|
"tenant_id": pricingCtx.TenantID,
|
||||||
|
"product_id": pricingCtx.ProductID,
|
||||||
|
"original_price": result.OriginalPrice,
|
||||||
|
"final_price": result.FinalPrice,
|
||||||
|
"rules_applied": len(result.AppliedRules),
|
||||||
|
}).Info("Price calculated successfully")
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyRules applies specific rules to a pricing context
|
||||||
|
func (s *PricingService) ApplyRules(ctx context.Context, pricingCtx *pricing.PricingContext, rules []*pricing.PricingRule) (*pricing.PricingResult, error) {
|
||||||
|
result := &pricing.PricingResult{
|
||||||
|
OriginalPrice: pricingCtx.BasePrice,
|
||||||
|
AdjustedPrice: pricingCtx.BasePrice,
|
||||||
|
FinalPrice: pricingCtx.BasePrice,
|
||||||
|
Currency: pricingCtx.Currency,
|
||||||
|
AppliedRules: make([]pricing.AppliedRule, 0),
|
||||||
|
Metadata: make(map[string]any),
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPrice := pricingCtx.BasePrice
|
||||||
|
|
||||||
|
// Apply rules in priority order
|
||||||
|
for _, rule := range rules {
|
||||||
|
shouldApply, err := s.engine.EvaluateRule(ctx, rule, pricingCtx)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.WithError(err).WithField("rule_id", rule.ID).Error("Failed to evaluate rule")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldApply {
|
||||||
|
adjustedPrice, err := s.engine.ApplyRule(ctx, rule, pricingCtx, currentPrice)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.WithError(err).WithField("rule_id", rule.ID).Error("Failed to apply rule")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate discount amount
|
||||||
|
discount := currentPrice - adjustedPrice
|
||||||
|
|
||||||
|
// Update result
|
||||||
|
currentPrice = adjustedPrice
|
||||||
|
result.AppliedRules = append(result.AppliedRules, pricing.AppliedRule{
|
||||||
|
RuleID: rule.ID,
|
||||||
|
RuleName: rule.Name,
|
||||||
|
Type: string(rule.Type),
|
||||||
|
Adjustment: discount,
|
||||||
|
})
|
||||||
|
|
||||||
|
s.logger.WithFields(logrus.Fields{
|
||||||
|
"rule_id": rule.ID,
|
||||||
|
"rule_name": rule.Name,
|
||||||
|
"adjustment": discount,
|
||||||
|
"new_price": adjustedPrice,
|
||||||
|
}).Debug("Rule applied")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finalize result
|
||||||
|
result.FinalPrice = currentPrice
|
||||||
|
result.Discount = result.OriginalPrice - result.FinalPrice
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user