Skip to main content

Overview

The PayMode model represents different payment methods accepted by the supermarket. It provides a flexible way to manage payment options like cash, credit cards, debit cards, mobile payments, and other transaction types.

Class Definition

namespace SupermarketWEB.Models
{
    public class PayMode
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Observation { get; set; }
    }
}

Properties

Id
int
required
Primary key and unique identifier for the payment mode. Auto-generated by the database.
Name
string
required
The payment method name. Examples: “Cash”, “Credit Card”, “Debit Card”, “Mobile Payment”, “Gift Card”, “Bank Transfer”.
Observation
string
required
Additional notes, instructions, or details about the payment method. Can include processing fees, acceptance criteria, or special handling instructions.

Usage Examples

Creating Payment Methods

var cashPayment = new PayMode
{
    Name = "Cash",
    Observation = "Physical currency. No processing fees. Exact change preferred."
};

context.PayModes.Add(cashPayment);
await context.SaveChangesAsync();

Seeding Default Payment Methods

public static class PayModeSeeder
{
    public static async Task SeedPayModes(SupermarketContext context)
    {
        if (!await context.PayModes.AnyAsync())
        {
            var payModes = new List<PayMode>
            {
                new PayMode 
                { 
                    Name = "Cash", 
                    Observation = "Physical currency payment. No fees." 
                },
                new PayMode 
                { 
                    Name = "Credit Card", 
                    Observation = "Major credit cards accepted. 2.5% processing fee." 
                },
                new PayMode 
                { 
                    Name = "Debit Card", 
                    Observation = "PIN-based debit card payments. 1% processing fee." 
                },
                new PayMode 
                { 
                    Name = "Mobile Wallet", 
                    Observation = "Apple Pay, Google Pay, Samsung Pay. Contactless." 
                },
                new PayMode 
                { 
                    Name = "Bank Transfer", 
                    Observation = "Direct bank transfer. Verification required." 
                }
            };

            context.PayModes.AddRange(payModes);
            await context.SaveChangesAsync();
        }
    }
}

Querying Payment Methods

// Get all payment modes
var payModes = await context.PayModes
    .OrderBy(p => p.Name)
    .ToListAsync();

// Get specific payment mode by name
var cashPayment = await context.PayModes
    .FirstOrDefaultAsync(p => p.Name == "Cash");

// Search payment modes
var searchResults = await context.PayModes
    .Where(p => p.Name.Contains(searchTerm) || 
                p.Observation.Contains(searchTerm))
    .ToListAsync();

Updating Payment Method

var payMode = await context.PayModes.FindAsync(payModeId);
if (payMode != null)
{
    payMode.Name = "Contactless Card";
    payMode.Observation = "Tap to pay with contactless-enabled credit or debit cards. Limit $100 per transaction.";
    await context.SaveChangesAsync();
}

Disabling Payment Method

If you need to temporarily disable payment methods without deleting them, consider adding an IsActive boolean property.
// Enhanced PayMode with IsActive flag
public class PayMode
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Observation { get; set; }
    public bool IsActive { get; set; } = true;
}

// Query only active payment methods
var activePayModes = await context.PayModes
    .Where(p => p.IsActive)
    .ToListAsync();

Database Schema

When migrated to the database, the PayMode table has the following structure:
ColumnTypeNullableKey
IdintNoPrimary Key (Identity)
Namenvarchar(MAX)No
Observationnvarchar(MAX)No
Consider adding a unique constraint on the Name field to prevent duplicate payment method names:
modelBuilder.Entity<PayMode>()
    .HasIndex(p => p.Name)
    .IsUnique();

Observation Field Usage

The Observation field is flexible and can store various types of information:

Processing Details

Transaction fees, processing times, verification requirements

Acceptance Criteria

Minimum/maximum amounts, supported card types, restrictions

Special Instructions

Handling procedures, employee notes, system integration details

Customer Information

Benefits, rewards programs, customer-facing terms

Integration Examples

Payment Processing Service

public class PaymentService
{
    private readonly SupermarketContext _context;

    public PaymentService(SupermarketContext context)
    {
        _context = context;
    }

    public async Task<bool> ProcessPayment(int payModeId, decimal amount)
    {
        var payMode = await _context.PayModes.FindAsync(payModeId);
        
        if (payMode == null)
            return false;

        // Process based on payment method
        switch (payMode.Name.ToLower())
        {
            case "cash":
                return ProcessCashPayment(amount);
            case "credit card":
                return await ProcessCreditCardPayment(amount);
            case "mobile payment":
                return await ProcessMobilePayment(amount);
            default:
                return false;
        }
    }

    private bool ProcessCashPayment(decimal amount)
    {
        // Cash payment logic
        return true;
    }

    private async Task<bool> ProcessCreditCardPayment(decimal amount)
    {
        // Credit card payment logic
        return await Task.FromResult(true);
    }

    private async Task<bool> ProcessMobilePayment(decimal amount)
    {
        // Mobile payment logic
        return await Task.FromResult(true);
    }
}
// In a controller or service
public async Task<List<SelectListItem>> GetPaymentMethodsDropdown()
{
    return await context.PayModes
        .OrderBy(p => p.Name)
        .Select(p => new SelectListItem
        {
            Value = p.Id.ToString(),
            Text = p.Name
        })
        .ToListAsync();
}

Data Annotations Enhancement

Enhance the model with validation attributes:
using System.ComponentModel.DataAnnotations;

public class PayMode
{
    public int Id { get; set; }
    
    [Required(ErrorMessage = "Payment method name is required")]
    [StringLength(100, MinimumLength = 2)]
    public string Name { get; set; }
    
    [Required(ErrorMessage = "Observation is required")]
    [StringLength(500)]
    [Display(Name = "Notes/Instructions")]
    public string Observation { get; set; }
}

Best Practices

  1. Unique Names: Ensure payment method names are unique and consistent
  2. Clear Observations: Provide detailed, actionable information in the Observation field
  3. Standard Naming: Use consistent naming conventions (e.g., “Credit Card” not “CreditCard” or “credit_card”)
  4. Seeding: Always seed default payment methods during initial setup
  5. Active Flag: Consider adding an IsActive property instead of deleting payment methods
  6. Audit Trail: Track when payment methods are created, modified, or disabled
  7. Localization: Consider multi-language support for international deployments
  8. Integration: Document external payment gateway integrations in Observation field

Extended Properties

For more advanced scenarios, consider extending the model:
public class PayMode
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Observation { get; set; }
    
    // Extended properties
    public bool IsActive { get; set; } = true;
    public decimal ProcessingFeePercentage { get; set; }
    public decimal MinimumAmount { get; set; }
    public decimal MaximumAmount { get; set; }
    public bool RequiresVerification { get; set; }
    public string IconUrl { get; set; }
    public int DisplayOrder { get; set; }
}

Relationships

The PayMode model currently operates as an independent entity. In a complete point-of-sale system, you might extend this to include:
  • Sales/Transactions collection (one-to-many with Sale entity)
  • Payment gateway configuration
  • Fee structure tables
  • Transaction logs

Build docs developers (and LLMs) love