Skip to main content
The SalesPriceProvider manages the state and business logic for calculating sales prices based on cost and profit margins. It supports both markup (profit on cost) and margin (profit on sales) calculations.

Overview

This provider handles two types of profit calculations:
  • Markup: Calculate profit as a percentage of cost (e.g., 50% markup on 100cost=100 cost = 150 selling price)
  • Margin: Calculate profit as a percentage of selling price (e.g., 50% margin means cost is 50% of selling price)
All inputs are persisted across app sessions using SharedPreferences.

Enums

MarginType

Defines the method of profit calculation.
enum MarginType {
  markup,
  margin,
}
markup
MarginType
Calculate profit as a percentage of cost (Profit / Cost × 100)
margin
MarginType
Calculate profit as a percentage of sales price (Profit / Sales Price × 100)

Constructor

SalesPriceProvider(SharedPreferences prefs)
prefs
SharedPreferences
required
The SharedPreferences instance used for persisting calculator state

Getters

Calculation Results

baseSalePrice
double?
The selling price before tax (cost + profit)
finalPrice
double?
The final selling price including tax
profitAmount
double?
The dollar amount of profit on this sale
taxAmount
double?
The calculated tax amount based on the base sale price
errorMessage
String?
Error message if validation fails, null otherwise

Configuration

marginType
MarginType
The current profit calculation method (markup or margin)

Input State

costInput
String
The persisted cost input string
profitPercentInput
String
The persisted profit percentage input string
taxInput
String
The persisted tax percentage input string

Methods

calculatePrice

Calculates the sales price based on cost and profit percentage.
void calculatePrice({
  required String costStr,
  required String profitPercentStr,
  String taxStr = '0',
})
costStr
String
required
The base cost of the product
profitPercentStr
String
required
The desired profit percentage (interpreted based on marginType)
taxStr
String
default:"0"
Optional tax percentage to apply to the base sale price

Calculation Formulas

For Markup (Profit on Cost):
profitAmount = cost × (profitPercent / 100)
baseSalePrice = cost + profitAmount
Example: $100 cost with 50% markup:
  • Profit = 100×0.50=100 × 0.50 = 50
  • Sale Price = 100+100 + 50 = $150
For Margin (Profit on Sales):
baseSalePrice = cost / (1 - (profitPercent / 100))
profitAmount = baseSalePrice - cost
Example: $100 cost with 50% margin:
  • Sale Price = 100/(10.50)=100 / (1 - 0.50) = 200
  • Profit = 200200 - 100 = $100
Tax Calculation:
taxAmount = baseSalePrice × (taxPercent / 100)
finalPrice = baseSalePrice + taxAmount

Validation

The method validates:
  • All numeric inputs are valid numbers
  • No negative values
  • For margin calculation: profit percentage must be less than 100%
If validation fails, errorMessage is set and results are cleared.

setMarginType

Changes the margin calculation type and persists the selection.
void setMarginType(MarginType type)
type
MarginType
required
The new margin type to use for calculations
This method automatically persists the selection to SharedPreferences and notifies listeners.

clear

Resets all inputs and calculation results.
void clear()
This method:
  • Clears all input strings
  • Removes persisted values from SharedPreferences
  • Clears all calculation results
  • Clears any error messages
  • Notifies listeners of the state change

Usage Example

import 'package:provider/provider.dart';
import 'package:numix/features/sales_price_calculator/providers/sales_price_provider.dart';

// In your widget
final provider = context.read<SalesPriceProvider>();

// Calculate with markup
provider.setMarginType(MarginType.markup);
provider.calculatePrice(
  costStr: '100.00',
  profitPercentStr: '50',  // 50% markup
  taxStr: '8.5',           // 8.5% tax
);

// Access results
if (provider.errorMessage != null) {
  print('Error: ${provider.errorMessage}');
} else {
  print('Base Sale Price: \$${provider.baseSalePrice}');
  print('Profit Amount: \$${provider.profitAmount}');
  print('Tax: \$${provider.taxAmount}');
  print('Final Price: \$${provider.finalPrice}');
}

// Switch to margin calculation
provider.setMarginType(MarginType.margin);
provider.calculatePrice(
  costStr: '100.00',
  profitPercentStr: '50',  // 50% margin on sales
  taxStr: '8.5',
);

// Clear all
provider.clear();

Markup vs Margin Comparison

Understanding the difference between markup and margin is critical for pricing:Markup: Profit as a percentage of cost
  • Formula: (Profit / Cost) × 100
  • Example: 100cost,100 cost, 50 profit = 50% markup
  • Common in retail and wholesale
Margin: Profit as a percentage of selling price
  • Formula: (Profit / Sales Price) × 100
  • Example: 150sale,150 sale, 50 profit = 33.3% margin
  • Common in financial analysis
Note: A 50% markup equals a 33.3% margin, while a 50% margin equals a 100% markup.

UI Integration

Use with Consumer widgets for reactive updates:
Consumer<SalesPriceProvider>(
  builder: (context, provider, child) {
    if (provider.finalPrice != null) {
      return Column(
        children: [
          Text('Sale Price: \$${provider.baseSalePrice!.toStringAsFixed(2)}'),
          Text('Profit: \$${provider.profitAmount!.toStringAsFixed(2)}'),
          Text('Final (with tax): \$${provider.finalPrice!.toStringAsFixed(2)}'),
        ],
      );
    }
    return const SizedBox.shrink();
  },
)

Persistence

All user inputs are automatically persisted using the following SharedPreferences keys:
  • sales_cost - Product cost
  • sales_profit - Profit percentage
  • sales_tax - Tax percentage
  • sales_margin_type - Margin type (0 = markup, 1 = margin)
The provider automatically restores these values when initialized.

Build docs developers (and LLMs) love