https://github.com/pandatecham/be-lib-commission-calculator
Commission calculation helper nugget package
https://github.com/pandatecham/be-lib-commission-calculator
Last synced: about 2 months ago
JSON representation
Commission calculation helper nugget package
- Host: GitHub
- URL: https://github.com/pandatecham/be-lib-commission-calculator
- Owner: PandaTechAM
- License: mit
- Created: 2023-10-29T00:08:28.000Z (over 2 years ago)
- Default Branch: development
- Last Pushed: 2026-02-28T14:57:05.000Z (4 months ago)
- Last Synced: 2026-02-28T16:56:44.719Z (4 months ago)
- Language: C#
- Size: 198 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# Pandatech.CommissionCalculator
High-performance commission calculation engine for .NET 8+ supporting proportional and absolute commission models with tiered ranges, min/max constraints, and automatic validation.
## Installation
```bash
dotnet add package Pandatech.CommissionCalculator
```
## Quick Start
### Define Commission Rule
```csharp
using CommissionCalculator.DTO;
var rule = new CommissionRule
{
CalculationType = CalculationType.Proportional,
DecimalPlace = 4,
CommissionRangeConfigs = new List
{
new()
{
RangeStart = 0,
RangeEnd = 500,
Type = CommissionType.FlatRate,
CommissionAmount = 25,
MinCommission = 0,
MaxCommission = 0
},
new()
{
RangeStart = 500,
RangeEnd = 1000,
Type = CommissionType.Percentage,
CommissionAmount = 0.1m,
MinCommission = 70,
MaxCommission = 90
},
new()
{
RangeStart = 1000,
RangeEnd = 10000,
Type = CommissionType.Percentage,
CommissionAmount = 0.2m,
MinCommission = 250,
MaxCommission = 1500
},
new()
{
RangeStart = 10000,
RangeEnd = 0, // 0 = infinity
Type = CommissionType.FlatRate,
CommissionAmount = 2000,
MinCommission = 0,
MaxCommission = 0
}
}
};
```
### Calculate Commission
**Standard (principal-based):**
```csharp
decimal principal = 1000m;
decimal commission = Commission.ComputeCommission(principal, rule);
// Result: 25 (flat) + 70 (min enforced) = 95
```
**Selector-based (different selection and application values):**
```csharp
decimal orderPrice = 2000m; // Amount to calculate commission on
decimal ticketCount = 3m; // Value to select the range
// Select range based on ticketCount, apply commission to orderPrice
decimal commission = Commission.ComputeCommission(orderPrice, ticketCount, rule);
```
**Use case:** When the value that determines which range to use (e.g., ticket quantity) differs from the amount you calculate commission on (e.g., order total).
## Calculation Types
### Proportional (Tiered)
Commission accumulates across tiers as the amount increases:
```csharp
var proportional = new CommissionRule
{
CalculationType = CalculationType.Proportional,
CommissionRangeConfigs = new List
{
new() { RangeStart = 0, RangeEnd = 100, Type = CommissionType.Percentage, CommissionAmount = 0.05m },
new() { RangeStart = 100, RangeEnd = 0, Type = CommissionType.Percentage, CommissionAmount = 0.03m }
}
};
// For $200:
// - First $100: $100 * 5% = $5
// - Next $100: $100 * 3% = $3
// Total: $8
```
### Absolute (Flat per tier)
Only the matching tier's commission applies:
```csharp
var absolute = new CommissionRule
{
CalculationType = CalculationType.Absolute,
CommissionRangeConfigs = new List
{
new() { RangeStart = 0, RangeEnd = 100, Type = CommissionType.FlatRate, CommissionAmount = 10 },
new() { RangeStart = 100, RangeEnd = 0, Type = CommissionType.FlatRate, CommissionAmount = 25 }
}
};
// For $200: $25 (uses second tier only)
```
## Range Configuration
### CommissionRangeConfigs Properties
| Property | Type | Description |
|----------|------|-------------|
| `RangeStart` | decimal | Start of range (inclusive) |
| `RangeEnd` | decimal | End of range (exclusive), **0 = infinity** |
| `Type` | CommissionType | `FlatRate` or `Percentage` |
| `CommissionAmount` | decimal | Commission value (flat amount or percentage like 0.1 for 10%) |
| `MinCommission` | decimal | Minimum commission for this range |
| `MaxCommission` | decimal | Maximum commission for this range, **0 = infinity** |
### CommissionType
- **FlatRate**: Returns `CommissionAmount` directly (min/max ignored)
- **Percentage**: Calculates `principal × CommissionAmount`, clamped by min/max
### Percentage Limits
For safety, percentage commissions are limited to ±1000%:
```csharp
// ✅ Valid: 10% = 0.1
CommissionAmount = 0.1m
// ❌ Invalid: 1500% = 15 (throws exception)
CommissionAmount = 15m
```
## Validation
### Automatic Validation
Validation occurs automatically on first use:
```csharp
decimal commission = Commission.ComputeCommission(1000m, rule);
// Validates rule, caches normalized version, computes result
```
### Manual Validation
```csharp
bool isValid = Commission.ValidateRule(rule);
```
### Validation Rules
✅ **Required:**
- At least one range starting at 0
- Ranges must be contiguous (no gaps)
- Ranges must cover [0, ∞)
- `MaxCommission ≥ MinCommission` (when MaxCommission ≠ 0)
❌ **Forbidden:**
- Overlapping ranges
- Gaps in coverage
- Equal `RangeStart` and `RangeEnd` (except single range: both 0)
- Percentage commission outside ±1000% (±10 as decimal)
## DateTime Overlap Checker
Utility for validating commission period overlaps:
```csharp
using CommissionCalculator.Helper;
using CommissionCalculator.DTO;
var period1 = new List
{
new(new DateTime(2024, 1, 1), new DateTime(2024, 1, 10))
};
var period2 = new List
{
new(new DateTime(2024, 1, 5), new DateTime(2024, 1, 15))
};
bool hasOverlap = DateTimeOverlapChecker.HasOverlap(period1, period2);
// Result: true
```
## Performance
- **5+ million calculations/second** (after initial validation/normalization)
- **Zero allocations** per calculation (after cache hit)
- **Binary search** for range lookup: O(log n)
- **Prefix sum optimization** for proportional calculations
- **ConditionalWeakTable** caching of normalized rules
**Performance characteristics:**
```
First calculation: ~50μs (validation + normalization + computation)
Subsequent calculations: ~200ns (cache hit + binary search + math)
Memory: ~1KB per cached rule
```
## Advanced Usage
### Single Range (Flat Commission)
```csharp
var flatRule = new CommissionRule
{
CalculationType = CalculationType.Absolute,
CommissionRangeConfigs = new List
{
new()
{
RangeStart = 0,
RangeEnd = 0, // Special case: both 0 for single range
Type = CommissionType.FlatRate,
CommissionAmount = 50,
MinCommission = 0,
MaxCommission = 0
}
}
};
// Any amount: $50 commission
```
### Progressive Percentage with Caps
```csharp
var capped = new CommissionRule
{
CalculationType = CalculationType.Proportional,
CommissionRangeConfigs = new List
{
new()
{
RangeStart = 0,
RangeEnd = 1000,
Type = CommissionType.Percentage,
CommissionAmount = 0.05m,
MinCommission = 10, // At least $10
MaxCommission = 50 // No more than $50 per tier
},
new()
{
RangeStart = 1000,
RangeEnd = 0,
Type = CommissionType.Percentage,
CommissionAmount = 0.02m,
MinCommission = 20,
MaxCommission = 0 // Unlimited on second tier
}
}
};
```
### Selector-Based Example
```csharp
// Event ticketing: commission based on ticket count, applied to total price
var ticketRule = new CommissionRule
{
CalculationType = CalculationType.Absolute, // Required for selector-based
CommissionRangeConfigs = new List
{
new() { RangeStart = 0, RangeEnd = 10, Type = CommissionType.Percentage, CommissionAmount = 0.1m },
new() { RangeStart = 10, RangeEnd = 0, Type = CommissionType.Percentage, CommissionAmount = 0.05m }
}
};
decimal orderTotal = 500m;
decimal ticketsSold = 15m;
// Uses second range (15 tickets), applies 5% to $500 order
decimal commission = Commission.ComputeCommission(orderTotal, ticketsSold, ticketRule);
// Result: $25
```
## Conventions
- **Infinity as 0**: Set `RangeEnd = 0` or `MaxCommission = 0` to represent ∞
- **Complete coverage**: Rules must cover [0, ∞) with no gaps
- **Exclusive end**: `RangeEnd` is exclusive (range is [Start, End))
- **Decimal precision**: Use `DecimalPlace` to control rounding (default: 4)
## Common Patterns
### Affiliate Marketing
```csharp
// Higher commission for higher sales
CalculationType = CalculationType.Absolute
Ranges:
$0-$1000: 5%
$1000-$5000: 7%
$5000+: 10%
```
### Payment Processing
```csharp
// Tiered fees that accumulate
CalculationType = CalculationType.Proportional
Ranges:
$0-$10,000: 2.9% + $0.30 min
$10,000+: 1.5%
```
### Broker Fees
```csharp
// Fixed fee per transaction tier
CalculationType = CalculationType.Absolute
Ranges:
$0-$10,000: $9.99
$10,000-$100,000: $19.99
$100,000+: $49.99
```
## License
MIT