Q:

Duplicate id in list: broken script

I have a script:
List<Apartment__c> apartmentsToUpd = new List<Apartment__c>();
List<House__c> houses = [SELECT Id, Tenants__c, EntryDate__c, DepartureDate__c, Opportunity__c FROM House__c
                        WHERE DAY_ONLY(EntryDate__c) >= : Date.TODAY() AND Status__c != 'Canceled' AND Tenants__c > 0];
List<Id> oppId = new List<Id>();
for(House__c h : houses){
    oppId.add(h.Opportunity__c);
}

List<Apartment__c> aps = [SELECT Id, Tenants__c, DepartureDate__c, Booking__r.Opportunity__c FROM Apartment__c
                        WHERE DAY_ONLY(DepartureDate__c) >= : Date.TODAY() AND Booking__r.Opportunity__c IN : oppId];

for(House__c house : houses){                
    Date hCheckInDate = Date.newinstance(house.EntryDate__c.year(), house.EntryDate__c.month(), house.EntryDate__c.day());

    for(Apartment__c apUpd : aps){
        Date apCheckOutDate = Date.newinstance(apUpd.DepartureDate__c.year(), apUpd.DepartureDate__c.month(), apUpd.DepartureDate__c.day());

        if(apCheckOutDate == hCheckInDate && house.Opportunity__c == apUpd.Booking__r.Opportunity__c && String.valueOF(house.Tenants__c) != apUpd.Tenants__c){
            //I'm getting here null if it's null, or nothing, even if there is a correct value:
            System.debug(apUpd.Tenants__c);
            apUpd.Tenants__c = String.valueOf(house.Tenants__c);
        } else{
            apUpd.Tenants__c = '';
        }
        apartmentsToUpd.add(apUpd);
    }
}
if(!apartmentsToUpd.isEmpty()){
    try {
        //'System.ListException: Duplicate id in list':
        update apartmentsToUpd;
    } catch (Exception e) {
        System.debug(e);
    }
}

My Opportunity is a parent for Houses, and House is a parent for Apartment. Each House can have only 1 Apartment and Houses dates for 1 Opportunity cannot overlap (there are rules for this).
I don't know why I'm getting no value in my System.debug and how to avoid the System.ListException: Duplicate id in list error. Can you help me?

A:

For Question #1

//I'm getting here null if it's null, or nothing, even if there is a correct value:
System.debug(apUpd.Tenants__c);

For the question about the System.debug issue, I can't answer that specifically as I don't know what field type it is (though I suspect it is a Number field), or what your data looks like, but the most likely scenario that I can think of is that the Apartment's Tenants__c field is blank or the House's Tentants__c field has a value that translates to a blank String with String.valueOf(). But again, without more information, I can't say what is happening there.

For Question #2
What I can answer more definitely is why you are getting that duplicate Id error. It has to do with this code block right here
for(House__c house : houses){                
    Date hCheckInDate = Date.newinstance(house.EntryDate__c.year(), house.EntryDate__c.month(), house.EntryDate__c.day());

    for(Apartment__c apUpd : aps){
        Date apCheckOutDate = Date.newinstance(apUpd.DepartureDate__c.year(), apUpd.DepartureDate__c.month(), apUpd.DepartureDate__c.day());

        if(apCheckOutDate == hCheckInDate && house.Opportunity__c == apUpd.Booking__r.Opportunity__c && String.valueOF(house.Tenants__c) != apUpd.Tenants__c){
            //I'm getting here null if it's null, or nothing, even if there is a correct value:
            System.debug(apUpd.Tenants__c);
            apUpd.Tenants__c = String.valueOf(house.Tenants__c);
        } else{
            apUpd.Tenants__c = '';
        }
        apartmentsToUpd.add(apUpd);
    }
}

You are looping through all the Houses that you queried, and with each House that you loop through, you're then looping through all of the queried Apartments. Within each loop of the Apartment list, you are adding the apartment to the update list (apartmentsToUpd), regardless of whether or not that Apt was related to the House. So, if you have more than one House in the House List (houses), then for every House past the first, it will add another instance of each Apartment to the update list. Since they have Ids attached to them, it is causing multiple records in the list to share Ids, and that is what is throwing the error you are experiencing.
...
And, now that I think of it, since this is preventing updates to the Apartments, the debug might be empty since the Apartments are not getting updated, so the data has not yet populated on the Tenants__c field on the Apartments. That's just a theory though.

