
Introduction
Developing an effective customer management system for a large retail chain like Reliance Retail requires a thoughtful application of Object-Oriented Programming (OOP) principles. In this comprehensive tutorial, we’ll walk through the process of designing and implementing a robust customer management system using C# and OOP best practices to solve real-world retail challenges.
The Real-World Problem
Reliance Retail faces challenges managing their diverse customer base across India. They need a system that can:
- Maintain customer data (name, age, geography, purchase history)
- Handle different types of customers (paying customers and inquiry-only customers)
- Apply various discount rules (senior citizen, weekend, location-based)
- Manage different delivery mechanisms (home delivery, in-store pickup)
Core OOP Principles
Before diving into the solution, let’s understand the key OOP principles that will serve as our foundation:
1. Abstraction
Definition: Abstraction is the concept of hiding the complex implementation details and showing only the necessary features of an object.
Real-world analogy: When you use a smartphone, you simply tap icons without needing to understand the underlying electronic circuitry.
In our system: We’ll create abstract concepts like Customer and DiscountStrategy to represent complex entities while hiding implementation details.
Example in C#:
// Abstraction example using an abstract class
public abstract class Customer
{
public string Name { get; set; }
}
## Analyzing the OOP Implementation
Let’s analyze how our solution addresses Reliance Retail’s customer management challenges through OOP principles:

### Abstraction in Action
In our implementation, we abstracted the concept of a “Customer” into a base class with essential properties and behaviors. By defining abstract methods like `CalculateDiscount()` and `GetCustomerType()`, we created a clean interface while hiding the implementation details.
This abstraction allows the OrderProcessor to work with any customer type without knowing the specific implementation details of how discounts are calculated for each customer type.
### Encapsulation Benefits
Our classes carefully control access to their internal data:
– The `Address` class encapsulates the validation logic for address components
– The `PremiumCustomer` class encapsulates membership validity checks and renewals
– The `CorporateCustomer` class encapsulates credit limit management
This encapsulation ensures data integrity and provides a clean interface for other parts of the system to interact with these classes.
### Inheritance Advantages
The customer hierarchy demonstrates the power of inheritance:
Customer (abstract) ├── RegularCustomer ├── PremiumCustomer ├── CorporateCustomer ├── InquiryCustomer
By inheriting from the base `Customer` class, each specialized customer type gets common functionality for free while adding its own unique behaviors. This approach reduces code duplication and creates a clear type hierarchy.
### Polymorphism in Practice
Our system exhibits polymorphism in several ways:
1. **Method Overriding**: Each customer type overrides `CalculateDiscount()` with its own implementation
2. **Interface Implementation**: Various discount and delivery strategies implement their respective interfaces
3. **Dynamic Binding**: The OrderProcessor works with any customer type without knowing the specific implementation
This polymorphic design allows the system to be highly extensible. Adding new customer types or discount strategies doesn’t require changing existing code.
### Relationship Patterns
Our implementation demonstrates different relationships between classes:
1. **Association**: Customers are associated with Orders, but both exist independently
2. **Aggregation**: A RetailStore aggregates Departments, which can exist outside the store
3. **Composition**: An Order is composed of OrderItems, which cannot exist without the Order
These relationship patterns help model the real-world connections between business entities accurately.
## Key Design Patterns Used
Our implementation leverages several design patterns:
### Strategy Pattern
We used the Strategy pattern for both discount calculation and delivery mechanisms:
– `IDiscountStrategy` with concrete implementations like `SeniorCitizenDiscountStrategy`
– `IDeliveryStrategy` with implementations like `HomeDeliveryStrategy`
This pattern allows algorithms to be selected at runtime, making the system flexible and extensible.
### Factory Method Pattern (Implied)
The `InquiryCustomer.ConvertToRegularCustomer()` method acts as a factory that creates a new `RegularCustomer` instance based on existing data.
## Extensibility of the System
The object-oriented design makes the system highly extensible:
1. **Adding New Customer Types**: Create a new class that inherits from `Customer`
2. **Adding New Discount Strategies**: Implement the `IDiscountStrategy` interface
3. **Adding New Delivery Methods**: Implement the `IDeliveryStrategy` interface
These changes can be made without modifying existing code, adhering to the Open/Closed Principle.
## Conclusion
Through careful application of OOP principles in C#, we’ve created a flexible, maintainable, and extensible customer management system for Reliance Retail. The system successfully handles:
– Different customer types with varied behaviors
– Complex discount rules
– Multiple delivery mechanisms
– Customer lifecycle management
The implementation demonstrates how abstraction, encapsulation, inheritance, polymorphism, and proper class relationships combine to solve real-world business problems.
This approach not only meets the current requirements but also provides a solid foundation for future enhancements as Reliance Retail’s business continues to evolve.

## Further Improvements
To take this system to the next level, consider these enhancements:
1. **Persistence Layer**: Add database integration using the Repository pattern
2. **Unit Testing**: Create comprehensive unit tests for all classes
3. **Logging and Monitoring**: Implement cross-cutting concerns
4. **User Interface**: Develop a web or mobile frontend
5. **Event-Driven Architecture**: Implement events and handlers for system integration
By building on this solid OOP foundation, you can create an enterprise-grade retail management system that scales with your business needs.
public string Email { get; set; }
public string Phone { get; set; }
// Abstract method – every customer type must implement their own version
public abstract decimal CalculateLoyaltyPoints(decimal purchaseAmount);
// Concrete method shared by all customer types
public virtual void SendNotification(string message)
{
Console.WriteLine($”Sending notification to {Name}: {message}”);
}
2. Encapsulation
Definition: Encapsulation is the bundling of data and methods that operate on that data within a single unit (class) and restricting access to some of the object’s components.
Real-world analogy: A medicine capsule encapsulates the drug, hiding its bitter taste while providing the benefits.
In our system: Customer’s personal data will be encapsulated, with controlled access through properties and methods.
Example in C#:
// Encapsulation example
public class Address
{
// Private fields - inaccessible from outside
private string _addressLine1;
private string _addressLine2;
private string _city;
private string _state;
private string _postalCode;
// Public properties with validation
public string AddressLine1
{
get { return _addressLine1; }
set
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentException("Address line 1 cannot be empty");
_addressLine1 = value;
}
}
public string City
{
get { return _city; }
set
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentException("City cannot be empty");
_city = value;
}
}
// Encapsulated method that uses the private data
public string GetFormattedAddress()
{
string formattedAddress = $"{_addressLine1}";
if (!string.IsNullOrWhiteSpace(_addressLine2))
formattedAddress += $", {_addressLine2}";
formattedAddress += $", {_city}, {_state} {_postalCode}";
return formattedAddress;
}
}
3. Inheritance
Definition: Inheritance is a mechanism where a new class inherits properties and behaviors from an existing class.
Real-world analogy: A smartphone inherits basic functionalities of a phone (calling, texting) but adds new features.
In our system: We’ll create specialized customer types (Premium, Regular, Corporate) that inherit from a base Customer class.
Example in C#:
// Base class
public abstract class Customer
{
public string Id { get; set; }
public string Name { get; set; }
public DateTime RegistrationDate { get; set; }
public Address Address { get; set; }
public abstract decimal CalculateDiscount(decimal purchaseAmount);
}
// Inheritance example - Regular customer inherits from Customer
public class RegularCustomer : Customer
{
public int LoyaltyPoints { get; set; }
public override decimal CalculateDiscount(decimal purchaseAmount)
{
// Regular customers get 5% discount
return purchaseAmount * 0.05m;
}
public void AddLoyaltyPoints(decimal purchaseAmount)
{
LoyaltyPoints += (int)(purchaseAmount / 100);
}
}
// Another derived class
public class PremiumCustomer : Customer
{
public DateTime MembershipValidUntil { get; set; }
public PremiumTier Tier { get; set; }
public override decimal CalculateDiscount(decimal purchaseAmount)
{
// Premium customers get better discounts based on their tier
return Tier switch
{
PremiumTier.Silver => purchaseAmount * 0.10m,
PremiumTier.Gold => purchaseAmount * 0.15m,
PremiumTier.Platinum => purchaseAmount * 0.20m,
_ => purchaseAmount * 0.05m
};
}
public bool RenewMembership(int months)
{
MembershipValidUntil = MembershipValidUntil.AddMonths(months);
return true;
}
}
public enum PremiumTier
{
Silver,
Gold,
Platinum
}
4. Polymorphism
Definition: Polymorphism allows objects of different classes to be treated as objects of a common superclass, with each responding differently to the same method call.
Real-world analogy: A remote control (same interface) works differently for a TV, DVD player, or sound system.
In our system: Different customer types will implement discount calculations differently, yet they can all be treated as “customers.”
Example in C#:
// Polymorphism example
public class OrderProcessor
{
public decimal CalculateOrderTotal(Customer customer, List<OrderItem> items)
{
decimal subtotal = items.Sum(item => item.Price * item.Quantity);
// Polymorphic call - each customer type calculates discount differently
decimal discount = customer.CalculateDiscount(subtotal);
return subtotal - discount;
}
public void ProcessOrder(Order order)
{
// We can treat any type of customer polymorphically
Console.WriteLine($"Processing order for {order.Customer.Name}");
// This will call the appropriate implementation based on the actual customer type
decimal finalAmount = CalculateOrderTotal(order.Customer, order.Items);
Console.WriteLine($"Order total after discounts: {finalAmount}");
}
}
// Usage example
public void DemonstratePolymorphism()
{
var processor = new OrderProcessor();
var items = new List<OrderItem>
{
new OrderItem { ProductName = "Smartphone", Price = 12000, Quantity = 1 },
new OrderItem { ProductName = "Screen Protector", Price = 500, Quantity = 2 }
};
// Using different customer types polymorphically
Customer regularCustomer = new RegularCustomer { Name = "Rajesh Kumar" };
Customer premiumCustomer = new PremiumCustomer {
Name = "Priya Sharma",
Tier = PremiumTier.Gold
};
Customer corporateCustomer = new CorporateCustomer {
Name = "ABC Corp",
CreditLimit = 100000
};
// Process orders with different customer types
var order1 = new Order { Customer = regularCustomer, Items = items };
var order2 = new Order { Customer = premiumCustomer, Items = items };
var order3 = new Order { Customer = corporateCustomer, Items = items };
processor.ProcessOrder(order1); // Uses RegularCustomer's discount calculation
processor.ProcessOrder(order2); // Uses PremiumCustomer's discount calculation
processor.ProcessOrder(order3); // Uses CorporateCustomer's discount calculation
}
5. Relationships Between Classes
Object-oriented design involves several types of relationships between classes:

Association
Definition: An association represents a relationship between two or more classes where the objects have their own lifecycle and there is no ownership.
Real-world analogy: A customer shops at a store – both exist independently.
In our system: Customers are associated with sales associates who help them.
// Association example
public class SalesAssociate
{
public string Id { get; set; }
public string Name { get; set; }
public string Department { get; set; }
// A sales associate can assist many customers (association)
public void AssistCustomer(Customer customer)
{
Console.WriteLine($"{Name} is assisting {customer.Name}");
}
}
// Usage
public void DemonstrateAssociation()
{
var customer = new RegularCustomer { Name = "Neha Singh" };
var associate = new SalesAssociate { Name = "Arjun Mehta", Department = "Electronics" };
// Association - both objects exist independently
associate.AssistCustomer(customer);
}
Aggregation
Definition: Aggregation is a specialized form of association that represents a “has-a” relationship, where one class contains references to other classes, but the contained objects can exist independently.
Real-world analogy: A shopping cart contains items, but items can exist outside the cart.
In our system: A retail store has multiple departments, each with their own employees.
// Aggregation example
public class Department
{
public string Name { get; set; }
public string FloorNumber { get; set; }
public List<SalesAssociate> Associates { get; set; } = new List<SalesAssociate>();
public void AddAssociate(SalesAssociate associate)
{
Associates.Add(associate);
}
}
public class RetailStore
{
public string Name { get; set; }
public string Location { get; set; }
// Aggregation: Store has departments, but departments can exist independently
public List<Department> Departments { get; set; } = new List<Department>();
public void AddDepartment(Department department)
{
Departments.Add(department);
}
}
// Usage
public void DemonstrateAggregation()
{
var electronicsAssociate = new SalesAssociate { Name = "Vikram Patel" };
var apparelAssociate = new SalesAssociate { Name = "Sneha Gupta" };
var electronics = new Department { Name = "Electronics", FloorNumber = "2" };
electronics.AddAssociate(electronicsAssociate);
var apparel = new Department { Name = "Apparel", FloorNumber = "1" };
apparel.AddAssociate(apparelAssociate);
var relianceStore = new RetailStore { Name = "Reliance Retail", Location = "Mumbai" };
relianceStore.AddDepartment(electronics);
relianceStore.AddDepartment(apparel);
// If the store closes, departments and associates can still exist
}
Composition
Definition: Composition is a strong form of aggregation where the contained objects cannot exist independently of the container.
Real-world analogy: A house contains rooms; if the house is destroyed, the rooms cease to exist.
In our system: An order contains line items that cannot exist without the order.
// Composition example
public class Order
{
public string OrderId { get; private set; }
public Customer Customer { get; set; }
public DateTime OrderDate { get; private set; }
// Composition: OrderItems cannot exist without an Order
private List<OrderItem> _items = new List<OrderItem>();
public Order()
{
OrderId = Guid.NewGuid().ToString();
OrderDate = DateTime.Now;
}
// The Order controls the lifecycle of its items
public void AddItem(string productName, decimal price, int quantity)
{
var item = new OrderItem(this, productName, price, quantity);
_items.Add(item);
}
public IReadOnlyList<OrderItem> Items => _items.AsReadOnly();
public decimal CalculateTotal()
{
return _items.Sum(item => item.SubTotal);
}
}
public class OrderItem
{
private Order _parentOrder;
public string ProductName { get; private set; }
public decimal Price { get; private set; }
public int Quantity { get; private set; }
public decimal SubTotal => Price * Quantity;
// OrderItem can only be created by an Order (composition)
internal OrderItem(Order order, string productName, decimal price, int quantity)
{
_parentOrder = order;
ProductName = productName;
Price = price;
Quantity = quantity;
}
}
// Usage
public void DemonstrateComposition()
{
var customer = new RegularCustomer { Name = "Amit Verma" };
var order = new Order { Customer = customer };
// Order creates and owns its items
order.AddItem("LED TV", 45000, 1);
order.AddItem("HDMI Cable", 500, 2);
// If order is deleted, items are automatically deleted
decimal total = order.CalculateTotal();
Console.WriteLine($"Order total: {total}");
}
Putting It All Together: Reliance Retail Customer Management System
Now let’s implement a complete solution for Reliance Retail’s customer management system:

Step 1: Define the Core Customer Hierarchy
// The base Customer class
public abstract class Customer
{
public string Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public Address Address { get; set; }
public DateTime RegistrationDate { get; }
protected Customer()
{
Id = Guid.NewGuid().ToString();
RegistrationDate = DateTime.Now;
}
// Abstract methods that derived classes must implement
public abstract decimal CalculateDiscount(decimal purchaseAmount);
public abstract CustomerType GetCustomerType();
// Virtual method that can be overridden
public virtual void SendNotification(string message)
{
Console.WriteLine($"Sending email to {Email}: {message}");
}
}
// Customer types
public enum CustomerType
{
Regular,
Premium,
Corporate,
InquiryOnly
}
// Regular paying customer
public class RegularCustomer : Customer
{
public int LoyaltyPoints { get; private set; }
public override decimal CalculateDiscount(decimal purchaseAmount)
{
decimal discount = 0;
// Base discount of 5%
discount += purchaseAmount * 0.05m;
// Additional discount based on loyalty points
if (LoyaltyPoints > 1000)
discount += purchaseAmount * 0.02m;
return discount;
}
public override CustomerType GetCustomerType()
{
return CustomerType.Regular;
}
public void AddLoyaltyPoints(int points)
{
LoyaltyPoints += points;
}
}
// Premium customer with membership
public class PremiumCustomer : Customer
{
public DateTime MembershipValidUntil { get; private set; }
public PremiumTier Tier { get; set; }
public PremiumCustomer()
{
// Default 1-year membership
MembershipValidUntil = DateTime.Now.AddYears(1);
}
public override decimal CalculateDiscount(decimal purchaseAmount)
{
return Tier switch
{
PremiumTier.Silver => purchaseAmount * 0.10m,
PremiumTier.Gold => purchaseAmount * 0.15m,
PremiumTier.Platinum => purchaseAmount * 0.20m,
_ => purchaseAmount * 0.08m
};
}
public override CustomerType GetCustomerType()
{
return CustomerType.Premium;
}
public bool RenewMembership(int months)
{
MembershipValidUntil = MembershipValidUntil.AddMonths(months);
return true;
}
public bool IsMembershipValid()
{
return MembershipValidUntil > DateTime.Now;
}
}
// Corporate customer for B2B relationships
public class CorporateCustomer : Customer
{
public string CompanyName { get; set; }
public string GstNumber { get; set; }
public decimal CreditLimit { get; set; }
public decimal CurrentCredit { get; private set; }
public override decimal CalculateDiscount(decimal purchaseAmount)
{
// Volume-based discount for corporate customers
if (purchaseAmount > 100000)
return purchaseAmount * 0.25m;
else if (purchaseAmount > 50000)
return purchaseAmount * 0.20m;
else
return purchaseAmount * 0.12m;
}
public override CustomerType GetCustomerType()
{
return CustomerType.Corporate;
}
public bool CanPurchaseOnCredit(decimal amount)
{
return (CurrentCredit + amount) <= CreditLimit;
}
public void AddCredit(decimal amount)
{
CurrentCredit += amount;
}
public void SettleCredit(decimal amount)
{
if (amount > CurrentCredit)
CurrentCredit = 0;
else
CurrentCredit -= amount;
}
}
// Inquiry-only customer (not making purchases yet)
public class InquiryCustomer : Customer
{
public string InterestArea { get; set; }
public DateTime LastContactDate { get; set; }
public override decimal CalculateDiscount(decimal purchaseAmount)
{
// Inquiry customers don't get discounts yet
return 0;
}
public override CustomerType GetCustomerType()
{
return CustomerType.InquiryOnly;
}
// Override notification method to use phone instead of email
public override void SendNotification(string message)
{
Console.WriteLine($"Sending SMS to {Phone}: {message}");
}
public void UpdateLastContact()
{
LastContactDate = DateTime.Now;
}
// Method to convert to a regular customer when ready to purchase
public RegularCustomer ConvertToRegularCustomer()
{
var regularCustomer = new RegularCustomer
{
Id = this.Id,
Name = this.Name,
Email = this.Email,
Phone = this.Phone,
Address = this.Address
};
// Give some bonus loyalty points as welcome
regularCustomer.AddLoyaltyPoints(100);
return regularCustomer;
}
}
Step 2: Implement the Discount Strategies using Strategy Pattern
// Strategy pattern for applying different discount rules
public interface IDiscountStrategy
{
decimal ApplyDiscount(decimal amount, Customer customer);
string DiscountName { get; }
}
// Senior citizen discount
public class SeniorCitizenDiscountStrategy : IDiscountStrategy
{
public string DiscountName => "Senior Citizen Discount";
public decimal ApplyDiscount(decimal amount, Customer customer)
{
// For simplicity, we'll assume we can determine age from customer data
// In a real system, we would check the customer's age from their profile
bool isSeniorCitizen = true; // This would be calculated from birthdate
if (isSeniorCitizen)
return amount * 0.10m;
else
return 0;
}
}
// Weekend discount
public class WeekendDiscountStrategy : IDiscountStrategy
{
public string DiscountName => "Weekend Special";
public decimal ApplyDiscount(decimal amount, Customer customer)
{
// Check if today is weekend
bool isWeekend = DateTime.Now.DayOfWeek == DayOfWeek.Saturday ||
DateTime.Now.DayOfWeek == DayOfWeek.Sunday;
if (isWeekend)
return amount * 0.07m;
else
return 0;
}
}
// Location-based discount
public class LocationBasedDiscountStrategy : IDiscountStrategy
{
private readonly List<string> _promotionalCities = new List<string>
{
"Mumbai", "Delhi", "Bangalore", "Hyderabad", "Chennai"
};
public string DiscountName => "Location Special";
public decimal ApplyDiscount(decimal amount, Customer customer)
{
if (customer.Address != null &&
_promotionalCities.Contains(customer.Address.City))
{
return amount * 0.05m;
}
return 0;
}
}
// First purchase discount
public class FirstPurchaseDiscountStrategy : IDiscountStrategy
{
public string DiscountName => "First Purchase Bonus";
public decimal ApplyDiscount(decimal amount, Customer customer)
{
// Check if this is customer's first purchase
// In a real system, we would query order history
bool isFirstPurchase = true; // This would be determined from order history
if (isFirstPurchase)
return amount * 0.15m;
else
return 0;
}
}
Step 3: Implement Delivery Mechanisms
// Delivery strategy interface
public interface IDeliveryStrategy
{
void DeliverOrder(Order order);
decimal CalculateDeliveryCharge(Order order);
string DeliveryType { get; }
}
// Home delivery
public class HomeDeliveryStrategy : IDeliveryStrategy
{
public string DeliveryType => "Home Delivery";
public void DeliverOrder(Order order)
{
Console.WriteLine($"Preparing order {order.OrderId} for home delivery to {order.Customer.Address.GetFormattedAddress()}");
// Additional home delivery logic here
}
public decimal CalculateDeliveryCharge(Order order)
{
// Base delivery charge
decimal charge = 50;
// Free delivery for orders above Rs. 2000
if (order.CalculateTotal() > 2000)
return 0;
// Extra charge for remote locations
if (!IsMetroCity(order.Customer.Address.City))
charge += 30;
return charge;
}
private bool IsMetroCity(string city)
{
var metroCities = new[] { "Mumbai", "Delhi", "Kolkata", "Chennai", "Bangalore", "Hyderabad" };
return metroCities.Contains(city);
}
}
// In-store pickup
public class StorePickupStrategy : IDeliveryStrategy
{
public string DeliveryType => "Store Pickup";
public void DeliverOrder(Order order)
{
Console.WriteLine($"Preparing order {order.OrderId} for in-store pickup");
// Additional store pickup logic here
}
public decimal CalculateDeliveryCharge(Order order)
{
// Store pickup is always free
return 0;
}
}
// Express delivery
public class ExpressDeliveryStrategy : IDeliveryStrategy
{
public string DeliveryType => "Express Delivery";
public void DeliverOrder(Order order)
{
Console.WriteLine($"Rushing order {order.OrderId} for express delivery to {order.Customer.Address.GetFormattedAddress()}");
// Additional express delivery logic here
}
public decimal CalculateDeliveryCharge(Order order)
{
// Express delivery has higher base charge
return 200;
}
}
Step 4: Implement the Order Processing System
// Order processing system
public class OrderProcessor
{
private readonly List<IDiscountStrategy> _discountStrategies;
public OrderProcessor()
{
// Initialize discount strategies
_discountStrategies = new List<IDiscountStrategy>
{
new SeniorCitizenDiscountStrategy(),
new WeekendDiscountStrategy(),
new LocationBasedDiscountStrategy(),
new FirstPurchaseDiscountStrategy()
};
}
public decimal CalculateFinalAmount(Order order)
{
decimal subtotal = order.CalculateTotal();
// Apply customer-specific discount (polymorphism in action)
decimal customerDiscount = order.Customer.CalculateDiscount(subtotal);
// Apply additional contextual discounts
decimal additionalDiscount = 0;
foreach (var strategy in _discountStrategies)
{
additionalDiscount += strategy.ApplyDiscount(subtotal, order.Customer);
}
// Cap total discount at 30%
decimal totalDiscount = Math.Min(customerDiscount + additionalDiscount, subtotal * 0.3m);
// Add delivery charges
decimal deliveryCharge = order.DeliveryStrategy.CalculateDeliveryCharge(order);
return subtotal - totalDiscount + deliveryCharge;
}
public void ProcessOrder(Order order)
{
// Calculate final amount
decimal finalAmount = CalculateFinalAmount(order);
Console.WriteLine($"Processing order {order.OrderId} for {order.Customer.Name}");
Console.WriteLine($"Subtotal: {order.CalculateTotal():C}");
Console.WriteLine($"Final amount after discounts and delivery: {finalAmount:C}");
// Process payment
bool paymentSuccess = ProcessPayment(order, finalAmount);
if (paymentSuccess)
{
// Update inventory
UpdateInventory(order);
// Arrange delivery
order.DeliveryStrategy.DeliverOrder(order);
// Send confirmation to customer
order.Customer.SendNotification($"Your order #{order.OrderId} has been confirmed and will be delivered via {order.DeliveryStrategy.DeliveryType}.");
}
}
private bool ProcessPayment(Order order, decimal amount)
{
// Payment processing logic would go here
Console.WriteLine($"Processing payment of {amount:C}");
// For corporate customers, check credit limit
if (order.Customer is CorporateCustomer corpCustomer)
{
if (corpCustomer.CanPurchaseOnCredit(amount))
{
corpCustomer.AddCredit(amount);
Console.WriteLine($"Added {amount:C} to corporate account credit");
return true;
}
else
{
Console.WriteLine("Credit limit exceeded");
return false;
}
}
// For regular payment processing
Console.WriteLine("Payment successful");
return true;
}
private void UpdateInventory(Order order)
{
// Inventory update logic would go here
Console.WriteLine("Updating inventory");
foreach (var item in order.Items)
{
Console.WriteLine($"Reducing inventory for {item.ProductName} by {item.Quantity}");
}
}
}
Step 5: Create a Customer Management System
// Customer management system
public class CustomerManagementSystem
{
private readonly Dictionary<string, Customer> _customers = new Dictionary<string, Customer>();
public void RegisterCustomer(Customer customer)
{
if (!_customers.ContainsKey(customer.Id))
{
_customers.Add(customer.Id, customer);
Console.WriteLine($"Customer {customer.Name} registered successfully.");
}
else
{
Console.WriteLine("Customer already exists.");
}
}
public Customer GetCustomer(string customerId)
{
if (_customers.TryGetValue(customerId, out Customer customer))
return customer;
return null;
}
public List<Customer> SearchCustomers(Func<Customer, bool> predicate)
{
return _customers.Values.Where(predicate).ToList();
}
public void UpdateCustomer(Customer customer)
{
if (_customers.ContainsKey(customer.Id))
{
_customers[customer.Id] = customer;
Console.WriteLine($"Customer {customer.Name} updated successfully.");
}
else
{
Console.WriteLine("Customer not found.");
}
}
public void ConvertInquiryToRegular(string customerId)
{
if (_customers.TryGetValue(customerId, out Customer customer) &&
customer is InquiryCustomer inquiryCustomer)
{
var regularCustomer = inquiryCustomer.ConvertToRegularCustomer();
_customers[customerId] = regularCustomer;
Console.WriteLine($"Customer {customer.Name} converted from inquiry to regular customer.");
}
else
{
Console.WriteLine("Customer not found or not an inquiry customer.");
}
}
public void SendPromotionalOffers(string offerMessage, CustomerType? targetType = null)
{
var targetCustomers = targetType.HasValue
? _customers.Values.Where(c => c.GetCustomerType() == targetType.Value)
: _customers.Values;
foreach (var customer in targetCustomers)
{
customer.SendNotification(offerMessage);
}
Console.WriteLine($"Sent promotional offers to {targetCustomers.Count()} customers.");
}
}
Step 6: Demonstration of the Complete System
public class RetailDemo
{
public static void Main()
{
// Initialize systems
var customerSystem = new CustomerManagementSystem();
var processor = new OrderProcessor();
// Create customers of different types
var regularCustomer = new RegularCustomer
{
Name = "Rajesh Kumar",
Email = "rajesh.kumar@example.com",
Phone = "9876543210",
Address = new Address
{
AddressLine1 = "123 Main Street",
City = "Mumbai",
State = "Maharashtra",
_postalCode = "400001"
}
};
var premiumCustomer = new PremiumCustomer
{
Name = "Priya Sharma",
Email = "priya.sharma@example.com",
Phone = "8765432109",
Address = new Address
{
AddressLine1 = "456 Park Avenue",
City = "Delhi",
State = "Delhi",
_postalCode = "110001"
},
Tier = PremiumTier.Gold
};
var corporateCustomer = new CorporateCustomer
{
Name = "Infosys Ltd.",
Email = "procurement@infosys.com",
Phone = "1234567890",
Address = new Address
{
AddressLine1 = "Electronics City",
City = "Bangalore",
State = "Karnataka",
_postalCode = "560100"
},
CompanyName = "Infosys Ltd.",
GstNumber = "29AAACI7411F1ZS",
CreditLimit = 500000
};
var inquiryCustomer = new InquiryCustomer
{
Name = "Suresh Patel",
Email = "suresh.patel@example.com",
Phone = "7654321098",
Address = new Address
{
AddressLine1 = "789 Lake View",
City = "Ahmedabad",
State = "Gujarat",
_postalCode = "380015"
},
InterestArea = "Electronics",
LastContactDate = DateTime.Now.AddDays(-5)
};
// Register customers
customerSystem.RegisterCustomer(regularCustomer);
customerSystem.RegisterCustomer(premiumCustomer);
customerSystem.RegisterCustomer(corporateCustomer);
customerSystem.RegisterCustomer(inquiryCustomer);
// Create orders
var order1 = new Order { Customer = regularCustomer };
order1.AddItem("Smartphone", 15000, 1);
order1.AddItem("Screen Protector", 500, 2);
order1.DeliveryStrategy = new HomeDeliveryStrategy();
var order2 = new Order { Customer = premiumCustomer };
order2.AddItem("Laptop", 65000, 1);
order2.AddItem("External Hard Drive", 5000, 1);
order2.AddItem("Laptop Bag", 2000, 1);
order2.DeliveryStrategy = new ExpressDeliveryStrategy();
var order3 = new Order { Customer = corporateCustomer };
order3.AddItem("Office Desk", 8000, 10);
order3.AddItem("Office Chair", 5000, 10);
order3.AddItem("Desk Lamp", 1500, 10);
order3.DeliveryStrategy = new StorePickupStrategy();
// Process orders
Console.WriteLine("\n=== Processing Regular Customer Order ===");
processor.ProcessOrder(order1);
Console.WriteLine("\n=== Processing Premium Customer Order ===");
processor.ProcessOrder(order2);
Console.WriteLine("\n=== Processing Corporate Customer Order ===");
processor.ProcessOrder(order3);
// Convert inquiry customer to regular
Console.WriteLine("\n=== Converting Inquiry Customer to Regular ===");
customerSystem.ConvertInquiryToRegular(inquiryCustomer.Id);
// Send targeted promotions
Console.WriteLine("\n=== Sending Promotional Offers ===");
customerSystem.SendPromotionalOffers("Special weekend sale: 20% off on all electronics!", CustomerType.Regular);
customerSystem.SendPromotionalOffers("Premium members exclusive: Early access to new arrivals!", CustomerType.Premium);
// Search customers
Console.WriteLine("\n=== Finding Premium Customers in Delhi ===");
var delhiPremiumCustomers = customerSystem.SearchCustomers(c =>
c.GetCustomerType() == CustomerType.Premium &&
c.Address.City == "Delhi");
foreach (var customer in delhiPremiumCustomers)
{
Console.WriteLine($"Found: {customer.Name}");
}
}
}
