Scaling Subscriptions: Implementing Flexible Plan and Agent Management in Inmotech-Backend
Imagine a gym membership system where every family member needs their own access, but the family's main plan dictates how many members can join and when their access expires. This challenge is similar to what we tackled in Inmotech-Backend, enhancing our subscription management to support more flexible agency and agent-level plans.
The Challenge: From Static to Dynamic
Previously, our subscription model might have been simpler, perhaps focusing solely on agency-level plans. However, as our platform grew, the need arose for greater granularity. Agencies required the ability to manage a specific number of agents under a given plan, with each agent having their own distinct subscription, all while respecting an overall agency plan expiration.
This meant our existing Plan and Agencia (Agency) entities needed significant enhancements, and a new Suscripcion (Subscription) model had to be introduced to track individual agents' access.
The Solution: A Granular Subscription Model
To address this, we introduced several key features:
Plan.maxAgentes: This new attribute on thePlanentity defines the maximum number of agents an agency can provision under that specific plan. It acts as a hard limit, preventing agencies from exceeding their purchased capacity.Agencia.fechaExpiracionPlan: Each agency now has afechaExpiracionPlan(plan expiration date). This date dictates the end of the agency's current plan and, by extension, affects all individual agent subscriptions linked to that agency.- Individual
Suscripcionfor Agents: Instead of a single agency-wide subscription, eachAgente(Agent) now receives their ownSuscripcionobject. This allows for individual tracking of an agent's active status, features, and links directly to the agency's overarching plan and its constraints. AgencyPlanModel: To tie everything together, anAgencyPlanModelwas developed, representing the comprehensive view of an agency's plan, its associated limits, and the status of its agents' subscriptions.
This new structure provides the flexibility needed for agencies to upgrade or downgrade plans, and for agents to join or leave, all within a clear, governed framework.
Implementing the Logic
Managing these new entities and their relationships required careful design, leveraging patterns like the Repository Pattern for data persistence and retrieval. When an agency attempts to add a new agent, or when an existing agent's subscription is renewed, the system now performs several checks:
- Agent Limit Check: Does the agency's current
Planallow for another agent (maxAgentes)? - Plan Expiration Check: Is the agency's
fechaExpiracionPlanstill valid? An agent cannot have an active subscription if the agency's plan has expired.
Here's a simplified Java example demonstrating how such a check might be integrated when creating a new agent subscription:
public class SubscriptionService {
private AgentRepository agentRepository; // Injected via constructor or Spring @Autowired
private AgencyRepository agencyRepository;
private PlanRepository planRepository;
public Subscription createAgentSubscription(String agencyId, String agentName) throws Exception {
Agency agency = agencyRepository.findById(agencyId);
if (agency == null) {
throw new IllegalArgumentException("Agency not found.");
}
Plan currentPlan = planRepository.findById(agency.getPlanId());
if (currentPlan == null) {
throw new IllegalStateException("Agency plan not found.");
}
long activeAgents = agentRepository.countActiveAgentsByAgency(agencyId);
if (activeAgents >= currentPlan.getMaxAgents()) {
throw new IllegalStateException("Agent limit reached for current plan.");
}
if (agency.getFechaExpiracionPlan().before(new Date())) {
throw new IllegalStateException("Agency plan has expired.");
}
// Logic to create and persist new Agent and Subscription entities
Agent newAgent = new Agent(agentName, agencyId);
Subscription newSubscription = new Subscription(newAgent.getId(), currentPlan.getId(), agency.getFechaExpiracionPlan());
agentRepository.save(newAgent);
// subscriptionRepository.save(newSubscription); // Assuming a separate repo for subscriptions
return newSubscription;
}
}
This code snippet illustrates how the SubscriptionService would use repositories to fetch Agency and Plan data, perform validation based on maxAgentes and fechaExpiracionPlan, and then proceed with creating the Agent and Subscription.
The Benefits
This refactoring provides significant advantages:
- Enhanced Flexibility: Agencies can now pick plans that precisely match their operational scale.
- Improved Billing Accuracy: Individual subscriptions allow for more granular tracking and billing.
- Scalability: The modular approach makes it easier to introduce new plan features or subscription types in the future.
- Clearer Data Model: The relationships between plans, agencies, agents, and their subscriptions are now explicit and well-defined.
By building this more robust and flexible subscription infrastructure, we've laid the groundwork for future growth and more tailored service offerings within Inmotech-Backend.
Generated with Gitvlg.com