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.
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);