function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Kristiana GrangerKristiana Granger 

Logic Building - Between Parent child Object - Kind of Searching - sorting

I have below requirment - 
Train and Coach are 2 objects. Where I need to build logic based on train schedule and availibility. From UI side admin can add the coach to the train. 

Train (Parent Object - From, To, Timings)
Coach (Child Object - From, To, Timings) Field is there. 

Now from UI side when user book the tickets. based on given 3 fields I need to add coachs in the train. lets say next week on monday there will 3 trains are schedule from X to Y location. now today we see many passanger book the train from X to Y location. so basically, based on timings I need to add number of coaches in next week train so I can accomodate all customers. Its not like 1 train run with 5-6 coach, while other train runs with 30-35 coach. there has to balance. 

Please let me know if need further clarification in scenario. 
Best Answer chosen by Kristiana Granger
Prateek Prasoon 25Prateek Prasoon 25
Firstly, you can define the Train and Coach objects in Salesforce as custom objects with the appropriate fields.
Next, you can create a Visualforce page to display the available coaches for a given train. Here's an example of the Visualforce page

<apex:page controller="TrainController">
    <apex:form >
        <apex:pageBlock title="Select Train">
            <apex:pageBlockSection>
                <apex:inputField value="{!selectedTrain}" />
            </apex:pageBlockSection>
            <apex:pageBlockButtons >
                <apex:commandButton action="{!showAvailableCoaches}" value="Show Available Coaches" rerender="coachList" />
            </apex:pageBlockButtons>
        </apex:pageBlock>
        <apex:outputPanel id="coachList">
            <apex:pageBlock title="Available Coaches">
                <apex:pageBlockTable value="{!availableCoaches}" var="coach">
                    <apex:column value="{!coach.Name}" />
                </apex:pageBlockTable>
            </apex:pageBlock>
        </apex:outputPanel>
    </apex:form>
</apex:page>

TrainController Apex class is used to display the available coaches for a selected train.

public class TrainController {
    public Train__c selectedTrain { get; set; }
    public List<Coach__c> availableCoaches { get; set; }
 
    public void showAvailableCoaches() {
        // Get the available coaches for the selected train
        availableCoaches = [SELECT Id, Name FROM Coach__c WHERE Train__c = :selectedTrain.Id];
    }
}
trigger on the booking object that listens for new bookings and updates the related train record with the number of coaches needed based on the available coaches and the number of passengers.
trigger BookingTrigger on Booking__c (after insert) {
    List<Train__c> trainsToUpdate = new List<Train__c>();
    Set<Id> trainIds = new Set<Id>();
    Map<Id, Integer> trainToPassengerCount = new Map<Id, Integer>();
 
    // Aggregate the passenger count for each train
    for (Booking__c booking : Trigger.new) {
        trainIds.add(booking.Train__c);
        if (trainToPassengerCount.containsKey(booking.Train__c)) {
            trainToPassengerCount.put(booking.Train__c, trainToPassengerCount.get(booking.Train__c) + booking.Passenger_Count__c);
        } else {
            trainToPassengerCount.put(booking.Train__c, booking.Passenger_Count__c);
        }
    }
 
    // Query for the available coaches for each train
    Map<Id, Integer> trainToCoachCount = new Map<Id, Integer>();
    for (Coach__c coach : [SELECT Id, Train__c, Seats__c FROM Coach__c WHERE Train__c IN :trainIds]) {
        if (trainToCoachCount.containsKey(coach.Train__c)) {
            trainToCoachCount.put(coach.Train__c, trainToCoachCount.get(coach.Train__c) + coach.Seats__c);
        } else {
            trainToCoachCount.put(coach.Train__c, coach.Seats__c);
        }
    }
 
    // Update the train records with the number of coaches needed
    for (Id trainId : trainIds) {
        if (trainToPassengerCount.containsKey(trainId) && trainToCoachCount.containsKey(trainId)) {
            Integer passengerCount = trainToPassengerCount.get(trainId);
            Integer coachCount = trainToCoachCount.get(trainId) / 50;
            Integer coachesNeeded = (passengerCount / 50) + 1;
 
            if (coachCount < coachesNeeded) {
                Integer coachesToAdd = coachesNeeded - coachCount;
                Train__c train = new Train__c(Id = trainId, Coaches__c = coachCount + coachesToAdd);
                trainsToUpdate.add(train);
            }
        }
    }
 
    if (trainsToUpdate.size() > 0) {
        update trainsToUpdate;
    }
}

If you find my answer helpful, Please mark it as the best answer. Thanks!

All Answers

Shri RajShri Raj
To solve this requirement, you could write a trigger on the Coach object that will check the available coaches and assign them to the corresponding train.
Here's an example solution:
Add a field on the Train object to track the number of available seats.
Create a method that will be called when a coach is added or removed from a train. This method will update the available seats on the Train object by counting the number of available seats on each coach assigned to the train.
Write a trigger on the Coach object that will be fired when a coach is added or removed from a train. This trigger will call the method from step 2.
Write a query to get all trains for the given route and date, and sort them by the number of available seats.
Loop through the sorted list of trains and assign coaches to them based on the number of available seats and the number of passengers. You may need to add some additional logic to handle situations where there are not enough coaches available to accommodate all passengers.
Save the coach assignments to the database.
Optionally, you can send a notification to the admin to let them know which trains have been assigned coaches.
This solution should help you balance the number of coaches on each train based on the number of passengers and available seats.
Prateek Prasoon 25Prateek Prasoon 25
Firstly, you can define the Train and Coach objects in Salesforce as custom objects with the appropriate fields.
Next, you can create a Visualforce page to display the available coaches for a given train. Here's an example of the Visualforce page

<apex:page controller="TrainController">
    <apex:form >
        <apex:pageBlock title="Select Train">
            <apex:pageBlockSection>
                <apex:inputField value="{!selectedTrain}" />
            </apex:pageBlockSection>
            <apex:pageBlockButtons >
                <apex:commandButton action="{!showAvailableCoaches}" value="Show Available Coaches" rerender="coachList" />
            </apex:pageBlockButtons>
        </apex:pageBlock>
        <apex:outputPanel id="coachList">
            <apex:pageBlock title="Available Coaches">
                <apex:pageBlockTable value="{!availableCoaches}" var="coach">
                    <apex:column value="{!coach.Name}" />
                </apex:pageBlockTable>
            </apex:pageBlock>
        </apex:outputPanel>
    </apex:form>
</apex:page>

TrainController Apex class is used to display the available coaches for a selected train.

public class TrainController {
    public Train__c selectedTrain { get; set; }
    public List<Coach__c> availableCoaches { get; set; }
 
    public void showAvailableCoaches() {
        // Get the available coaches for the selected train
        availableCoaches = [SELECT Id, Name FROM Coach__c WHERE Train__c = :selectedTrain.Id];
    }
}
trigger on the booking object that listens for new bookings and updates the related train record with the number of coaches needed based on the available coaches and the number of passengers.
trigger BookingTrigger on Booking__c (after insert) {
    List<Train__c> trainsToUpdate = new List<Train__c>();
    Set<Id> trainIds = new Set<Id>();
    Map<Id, Integer> trainToPassengerCount = new Map<Id, Integer>();
 
    // Aggregate the passenger count for each train
    for (Booking__c booking : Trigger.new) {
        trainIds.add(booking.Train__c);
        if (trainToPassengerCount.containsKey(booking.Train__c)) {
            trainToPassengerCount.put(booking.Train__c, trainToPassengerCount.get(booking.Train__c) + booking.Passenger_Count__c);
        } else {
            trainToPassengerCount.put(booking.Train__c, booking.Passenger_Count__c);
        }
    }
 
    // Query for the available coaches for each train
    Map<Id, Integer> trainToCoachCount = new Map<Id, Integer>();
    for (Coach__c coach : [SELECT Id, Train__c, Seats__c FROM Coach__c WHERE Train__c IN :trainIds]) {
        if (trainToCoachCount.containsKey(coach.Train__c)) {
            trainToCoachCount.put(coach.Train__c, trainToCoachCount.get(coach.Train__c) + coach.Seats__c);
        } else {
            trainToCoachCount.put(coach.Train__c, coach.Seats__c);
        }
    }
 
    // Update the train records with the number of coaches needed
    for (Id trainId : trainIds) {
        if (trainToPassengerCount.containsKey(trainId) && trainToCoachCount.containsKey(trainId)) {
            Integer passengerCount = trainToPassengerCount.get(trainId);
            Integer coachCount = trainToCoachCount.get(trainId) / 50;
            Integer coachesNeeded = (passengerCount / 50) + 1;
 
            if (coachCount < coachesNeeded) {
                Integer coachesToAdd = coachesNeeded - coachCount;
                Train__c train = new Train__c(Id = trainId, Coaches__c = coachCount + coachesToAdd);
                trainsToUpdate.add(train);
            }
        }
    }
 
    if (trainsToUpdate.size() > 0) {
        update trainsToUpdate;
    }
}

If you find my answer helpful, Please mark it as the best answer. Thanks!
This was selected as the best answer