0

I'm using the Xero API php wrapper to post timesheets and there's no detail coming back except for "An error occurred" and Status 500.

I'm authenticating ok, it's included in the scopes and as far as I can tell it's valid json in the format requested...

[{"EmployeeID":"a valid employee id","StartDate":"2020-08-03","EndDate":"2020-08-09","Status":"Draft","TimesheetLines":{"TimesheetLine":[{"EarningsRateID":"a valid pay item id","NumberOfUnits":{"NumberOfUnit":["0.00","0.00","8","0.00","0.00","0.00","0.00"]}},{"EarningsRateID":"a valid pay item id","NumberOfUnits":{"NumberOfUnit":["0.00","0.00","0.00","8.5","0.00","0.00","0.00"]}},{"EarningsRateID":"a valid pay item id","NumberOfUnits":{"NumberOfUnit":["0.00","0.00","0.00","0.00","8","0.00","0.00"]}},{"EarningsRateID":"a valid pay item id","NumberOfUnits":{"NumberOfUnit":["0.00","0.00","0.00","0.00","0.00","8","0.00"]}},{"EarningsRateID":"a valid pay item id","NumberOfUnits":{"NumberOfUnit":["0.00","0.00","0.00","0.00","0.00","0.00","8.5"]}}]}}]

That's getting sent via...

try {
      $result = $payrollAuApi->createTimesheet($xeroTenantId, $timesheet);
      print_r($result);
  } catch (Exception $e) {
      echo 'Exception when calling PayrollAuApi->createTimesheet: ', $e->getMessage(), PHP_EOL;
  }

And the tenantID is ok.

I'm grateful for any guidance on where I'm going wrong.

Craig
  • 79
  • 8

2 Answers2

0

It looks like your TimesheetLines is an object containing a property called TimesheetLine, which is a collection - but according to the docs, TimesheetLines itself should be the collection of timesheet lines.

i.e. you should have something like:

[{ EmployeeID : 4fd71c0f-8612-4fd8-99d0-b3a2e8272b02 , StartDate : 2020-08-03 , EndDate : 2020-08-09 , Status : Draft , TimesheetLines :[{ EarningsRateID : 0e30f933-04ed-4b96-9357-9747209c306f , NumberOfUnits :{ NumberOfUnit :[ 0.00 , 0.00 , 8 , 0.00 , 0.00 , 0.00 , 0.00 ]}},{ EarningsRateID : 0e30f933-04ed-4b96-9357-9747209c306f , NumberOfUnits :{ NumberOfUnit :[ 0.00 , 0.00 , 0.00 , 8.5 , 0.00 , 0.00 , 0.00 ]}},{ EarningsRateID : 0e30f933-04ed-4b96-9357-9747209c306f , NumberOfUnits :{ NumberOfUnit :[ 0.00 , 0.00 , 0.00 , 0.00 , 8 , 0.00 , 0.00 ]}},{ EarningsRateID : 0e30f933-04ed-4b96-9357-9747209c306f , NumberOfUnits :{ NumberOfUnit :[ 0.00 , 0.00 , 0.00 , 0.00 , 0.00 , 8 , 0.00 ]}},{ EarningsRateID : 0e30f933-04ed-4b96-9357-9747209c306f , NumberOfUnits :{ NumberOfUnit :[ 0.00 , 0.00 , 0.00 , 0.00 , 0.00 , 0.00 , 8.5 ]}}]}]

...instead of...

[{ EmployeeID : 4fd71c0f-8612-4fd8-99d0-b3a2e8272b02 , StartDate : 2020-08-03 , EndDate : 2020-08-09 , Status : Draft , TimesheetLines :{ TimesheetLine :[{ EarningsRateID : 0e30f933-04ed-4b96-9357-9747209c306f , NumberOfUnits :{ NumberOfUnit :[ 0.00 , 0.00 , 8 , 0.00 , 0.00 , 0.00 , 0.00 ]}},{ EarningsRateID : 0e30f933-04ed-4b96-9357-9747209c306f , NumberOfUnits :{ NumberOfUnit :[ 0.00 , 0.00 , 0.00 , 8.5 , 0.00 , 0.00 , 0.00 ]}},{ EarningsRateID : 0e30f933-04ed-4b96-9357-9747209c306f , NumberOfUnits :{ NumberOfUnit :[ 0.00 , 0.00 , 0.00 , 0.00 , 8 , 0.00 , 0.00 ]}},{ EarningsRateID : 0e30f933-04ed-4b96-9357-9747209c306f , NumberOfUnits :{ NumberOfUnit :[ 0.00 , 0.00 , 0.00 , 0.00 , 0.00 , 8 , 0.00 ]}},{ EarningsRateID : 0e30f933-04ed-4b96-9357-9747209c306f , NumberOfUnits :{ NumberOfUnit :[ 0.00 , 0.00 , 0.00 , 0.00 , 0.00 , 0.00 , 8.5 ]}}]}}]

Does changing that help?

rustyskates
  • 856
  • 4
  • 10
  • Hey thanks for taking a look. It got to the point where I copied exactly the example from the docs ('Example of adding a timesheet with lines'), just substituting the employee and pay item id's and the pay period and it still throws the same really unhelpful error. Driving me nuts. – Craig Aug 12 '20 at 02:56
  • Seems to me that a few of the examples in the developers section don't work. I'm currently having issues using the createEmployee sample code, very frustrating – DeanO May 15 '22 at 22:45
0

For anyone that comes across this, the problem is that unlike the old wrapper I was using in a private app where I was constructing a complete XML timesheet and sending that, the oauth2 wrapper fro Xero doesn't take a completed timesheet. Rather you create an instance of the timesheet and set the properties for it.

Code credit goes to @wobinb from the repo

$config = XeroAPI\XeroPHP\Configuration::getDefaultConfiguration()- 
>setAccessToken( (string)$storage->getAccessToken() );
$payrollApi = new XeroAPI\XeroPHP\Api\PayrollAuApi(
  new GuzzleHttp\Client(),
  $config
);

//first retrieve a list of active employees
$apiResponse = $payrollApi->getEmployees($tenantId, null, "Status==\"ACTIVE\"");
$employees = $apiResponse->getEmployees();
foreach ($employees AS $employee) {
  print $employee->getFirstName()." ".$employee->getLastName()." - ".$employee->getPayrollCalendarID();
   if ($employee->getPayrollCalendarID() != null) {
     $employeeID = $employee->getEmployeeID();
     $payrollCalendarID = $employee->getPayrollCalendarID();
     $ordinaryEarningsRateID = $employee->getOrdinaryEarningsRateID();
   }
   print "<br />";
}
print "<br />";
//and now the payroll calendar
$apiResponse = $payrollApi->getPayrollCalendar($tenantId,$payrollCalendarID);
$calendar = $apiResponse->getPayrollCalendars()[0];
print $calendar->getName()." - ".$calendar->getCalendarType();
print "<br />";

//finally create the timesheet
$timesheet = new XeroAPI\XeroPHP\Models\PayrollAu\Timesheet();
$timesheet->setEmployeeID($employeeID);
$timesheet->setStartDateAsDate($calendar->getStartDateAsDate());
//need to calculate how many days the timesheet will cover
switch ($calendar->getCalendarType()) {
  case "WEEKLY":
    $lengthofCalendar = 7;
    break;
  case "FORTNIGHTLY":
    $lengthofCalendar = 14;
    break;
  case "FOURWEEKLY":
    $lengthofCalendar = 28;
    break;
//monthly pay runs will be more complicated to calculate  
}
$endDate = $calendar->getStartDateAsDate();
//end date will be start date plus the length and minus one day
$period = "P". ($lengthofCalendar - 1) . "D";
$endDate->add(new DateInterval($period));
$timesheet->setEndDateAsDate($endDate);
$timesheet->setStatus("DRAFT");
$timesheetLine = new XeroAPI\XeroPHP\Models\PayrollAu\TimesheetLine();
$timesheetLine->setEarningsRateId($ordinaryEarningsRateID);
for ($day = 1; $day <= $lengthofCalendar; $day++) { 
  $numberOfUnits[] = $day;
}
$timesheetLine->setNumberOfUnits($numberOfUnits);
$timesheetLines[] = $timesheetLine;
$timesheet->setTimeSheetLines($timesheetLines);
$timesheets[] = $timesheet;
$apiResponse = $payrollApi->createTimesheet($tenantId,$timesheets);
Craig
  • 79
  • 8