2

Problem :

I have an Array of Objects in which We get the Employee work hours per month like this :

{
    "allocationId": 227,
    "role": "Software Engineer",
    "name": "Test User",
    "country": "USA",
    "state": "TX",
    "city": "",
    "allocStartDate": "2019-03-09",
    "allocEndDate": "2020-03-10",
    "allocationHours": [{
            "allocationHoursId": 2250,
            "allocationId": 227,
            "monthYear": "February",
            "year": 2020,
            "workHours": 60,
            "lockStatus": "Y",
            "comments": null
        },
        {
            "allocationHoursId": 2251,
            "allocationId": 227,
            "monthYear": "January",
            "year": 2020,
            "workHours": 10,
            "lockStatus": "N",
            "comments": null
        },
        {
            "allocationHoursId": 2254,
            "allocationId": 227,
            "monthYear": "April",
            "year": 2020,
            "workHours": 40,
            "lockStatus": "N",
            "comments": null
        }
    ],
    "totalHours": 170
}

I need to format the 'allocationHours' against the months of the year such that, For the month which data exists, It is assigned to the month , else we add null values against the month. Please look at the image for clarity :

enter image description here

Making the workhours for the month not present to 0.

What I have tried :

const scrollableTableAttribute = [
  { key: 'January', value: '01' },
  { key: 'February', value: '02' },
  { key: 'March', value: '03' },
  { key: 'April', value: '04' },
  { key: 'May', value: '05' },
  { key: 'June', value: '06' },
  { key: 'July', value: '07' },
  { key: 'August', value: '08' },
  { key: 'September', value: '09' },
  { key: 'October', value: '10' },
  { key: 'November', value: '11' },
  { key: 'December', value: '12' }
];

And in the method -

      item.allocationHours.forEach((element) => {
        scrollableTableAttribute.map((month) => {
          if (element.monthYear === month.key) {
              test[month.key]  = element;
          } else {
            test[month.key]  = {
              workHours: 0, allocationId: item.allocationId,
              // tslint:disable-next-line: no-null-keyword
              monthYear: month.key, lockStatus: 'N', comment: '', allocationHoursId: null, year: null
            };
          }
        });
      });

This is not giving me the required result, Any help would be appreciated. Thanks !

2
  • Could you show the desired result? Commented Mar 10, 2020 at 14:01
  • @StepUp - The desired result is the image. Commented Mar 30, 2020 at 19:00

3 Answers 3

1

So giving the conditions that each month entry is distinct in the object of the values, it's better loop throw your months array. Try this:

const YOUR_OBJECT = {
    "allocationId": 227,
    "role": "Software Engineer",
    "name": "Test User",
    "country": "USA",
    "state": "TX",
    "city": "",
    "allocStartDate": "2019-03-09",
    "allocEndDate": "2020-03-10",
    "allocationHours": [{
            "allocationHoursId": 2250,
            "allocationId": 227,
            "monthYear": "February",
            "year": 2020,
            "workHours": 60,
            "lockStatus": "Y",
            "comments": null
        },
        {
            "allocationHoursId": 2251,
            "allocationId": 227,
            "monthYear": "January",
            "year": 2020,
            "workHours": 10,
            "lockStatus": "N",
            "comments": null
        },
        {
            "allocationHoursId": 2254,
            "allocationId": 227,
            "monthYear": "April",
            "year": 2020,
            "workHours": 40,
            "lockStatus": "N",
            "comments": null
        }
    ],
    "totalHours": 170
};

const scrollableTableAttribute = [
  { key: 'January', value: '01' },
  { key: 'February', value: '02' },
  { key: 'March', value: '03' },
  { key: 'April', value: '04' },
  { key: 'May', value: '05' },
  { key: 'June', value: '06' },
  { key: 'July', value: '07' },
  { key: 'August', value: '08' },
  { key: 'September', value: '09' },
  { key: 'October', value: '10' },
  { key: 'November', value: '11' },
  { key: 'December', value: '12' }
];

const test = {};
scrollableTableAttribute.forEach( (month) => {
test[month.key] = YOUR_OBJECT.allocationHours.find((item) => month.key === item.monthYear) || {
            workHours: 0, allocationId: YOUR_OBJECT.allocationId,
            monthYear: month.key, lockStatus: 'N', comment: '', allocationHoursId: null, 
            year: null
  };
});
console.log(test)

If this works for you, you could make it better depending on your needs.

Sign up to request clarification or add additional context in comments.

Comments

1

We can use map method to project all months to months which are received:

const months = new Map(json.allocationHours.map(s => [s.monthYear, s]));
let fallbackObject = {
    "allocationHoursId": null,
    "allocationId": null,
    "monthYear": null,
    "year": 2020,
    "workHours": 40,
    "lockStatus": "N",
    "comments": null
}

json.allocationHours = scrollableTableAttribute.map(({key}) => 
    ({...months.get(key) || fallbackObject}));

An example:

let json = {
    "allocationId": 227,
    "role": "Software Engineer",
    "name": "Test User",
    "country": "USA",
    "state": "TX",
    "city": "",
    "allocStartDate": "2019-03-09",
    "allocEndDate": "2020-03-10",
    "allocationHours": [{
            "allocationHoursId": 2250,
            "allocationId": 227,
            "monthYear": "February",
            "year": 2020,
            "workHours": 60,
            "lockStatus": "Y",
            "comments": null
        },
        {
            "allocationHoursId": 2251,
            "allocationId": 227,
            "monthYear": "January",
            "year": 2020,
            "workHours": 10,
            "lockStatus": "N",
            "comments": null
        },
        {
            "allocationHoursId": 2254,
            "allocationId": 227,
            "monthYear": "April",
            "year": 2020,
            "workHours": 40,
            "lockStatus": "N",
            "comments": null
        }
    ],
    "totalHours": 170
}

const scrollableTableAttribute = [
    { key: 'January', value: '01' },
    { key: 'February', value: '02' },
    { key: 'March', value: '03' },
    { key: 'April', value: '04' },
    { key: 'May', value: '05' },
    { key: 'June', value: '06' },
    { key: 'July', value: '07' },
    { key: 'August', value: '08' },
    { key: 'September', value: '09' },
    { key: 'October', value: '10' },
    { key: 'November', value: '11' },
    { key: 'December', value: '12' }
  ];

const months = new Map(json.allocationHours.map(s => [s.monthYear, s]));

let fallbackObject = {
    "allocationHoursId": null,
    "allocationId": null,
    "monthYear": null,
    "year": 2020,
    "workHours": 40,
    "lockStatus": "N",
    "comments": null
}

json.allocationHours = scrollableTableAttribute.map(({key}) => ({...months.get(key) || fallbackObject}));
console.log(json);

Comments

1

As your item has a start date and end date, you can actually generate all months that span that period, taking into account that this may cross one or more year-boundaries, and may start/end anywhere within a year.

You could convert year/month combinations to just a single number, representing an absolute number of months.

Here is how that could look:

const item = {"allocationId": 227,"role": "Software Engineer","name": "Test User","country": "USA","state": "TX","city": "","allocStartDate": "2019-03-09","allocEndDate": "2020-03-10","allocationHours": [{"allocationHoursId": 2250,"allocationId": 227,"monthYear": "February","year": 2020,"workHours": 60,"lockStatus": "Y","comments": null},{"allocationHoursId": 2251,"allocationId": 227,"monthYear": "January","year": 2020,"workHours": 10,"lockStatus": "N","comments": null},{"allocationHoursId": 2254,"allocationId": 227,"monthYear": "April","year": 2020,"workHours": 40,"lockStatus": "N","comments": null}],"totalHours": 170};

const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

const toMonths = (dateStr) => dateStr.slice(0, 4) * 12 + +dateStr.slice(5, 7) - 1;

const startMonth = toMonths(item.allocStartDate);

const result = Array.from({length: toMonths(item.allocEndDate) + 1 - startMonth}, (_, i) => ({ 
    allocationHoursId: null,
    allocationId: item.allocationId,
    monthYear: months[(startMonth + i) % 12], 
    year: Math.floor((startMonth + i) / 12),
    workHours: 0, lockStatus: "N", comments: ""
}));

for (const obj of item.allocationHours) {
    result[obj.year * 12 + months.indexOf(obj.monthYear) - startMonth] = obj;
}

console.log(result);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.