|
- <?php
-
- /* xero integration oauth 2 */
-
- /* required by XeroOauth1 in 2021 */
-
- namespace Biukop;
- require_once(dirname(__FILE__) . '/vendor/autoload.php');
- // require_once(ABSPATH . 'wp-includes/pluggable.php');
- require_once(dirname(__FILE__) . '/Storage.php');
-
- use \Carbon_Fields\Container;
- use \Carbon_Fields\Field;
- use \Carbon_Fields\Carbon_Fields;
- use phpDocumentor\Reflection\DocBlock\Tags\Method;
-
- class XeroOAuth2
- {
- private $office; // parent
- private $clientID = '83CC79EEC6A54B4E8C2CA7AD61D1BF69';
- private $clientSecret = 'axgKF-Ri60D89conDFhqZsi1wu7uLdQFGvMpino9nI-nfO3f';
- private $clientContactGroupID="48646f3d-cf5e-4fea-8c8b-5812bd540e1b";
-
- public $provider;
- public $options = [
- 'scope' => ['openid email profile offline_access assets projects accounting.settings accounting.transactions accounting.contacts accounting.journals.read accounting.reports.read accounting.attachments payroll.employees payroll.payruns payroll.payslip payroll.timesheets payroll.settings files'],
- 'scope1' => [
- 'openid',
- 'email',
- 'profile',
- 'offline_access',
- 'assets',
- 'projects',
- 'accounting.settings',
- 'accounting.transactions',
- 'accounting.contacts',
- 'accounting.journals.read',
- 'accounting.reports.read',
- 'accounting.attachments',
- 'payroll.employees',
- 'payroll.payruns',
- 'payroll.payslip',
- 'payroll.timesheets',
- 'payroll.settings'
- ]
- ];
- public $storage;
- public $config;
- public $apiAccountingInstance; //accounting instance
- public $apiPayrollInstance; // payroll au instance
- public $xeroTenantId;
-
-
- public function __construct($office)
- {
- $this->office = $office;
- add_action('init', array($this, 'init_wp'));
- add_action('after_setup_theme', array($this, 'boot_carbon'));
- // add_action('init', array('Carbon_Fields\\Carbon_Fields', 'boot'));
- add_action( 'plugins_loaded', array( '\\Carbon_Fields\\Carbon_Fields', 'boot' ) );
- add_action('carbon_fields_register_fields', array($this, 'build_settings_page'));
- add_action('carbon_fields_container_activated', array($this, 'field_activated'));
- add_action('parse_request', array($this, 'xero_callback'));
-
- add_shortcode('xero_org_name', array($this, 'xero_org_name'));
- add_shortcode('xero_org_contacts', array($this, 'xero_org_contacts'));
- add_shortcode('xero_org_invoices', array($this, 'xero_org_invoices'));
- add_shortcode('xero_org_pay_items', array($this, 'xero_org_pay_items'));
- add_shortcode('xero_org_employees', array($this, 'xero_org_employees'));
- add_shortcode('xero_org_clients', array($this, 'xero_org_clients'));
- add_shortcode('xero_org_payroll_calendar', array($this, 'xero_org_payroll_calendar'));
-
-
-
- add_action('init', array($this, "xero_init"));
- add_action('plugins_loaded', array($this, "load_storage"));
- // $this->xero_init();
- $this->storage = new StorageClass();
- }
-
- public function __call($method, $args) {
- if ( method_exists($this->XeroOauth1, $method) ) {
- syslog(LOG_INFO,"Calling $method");
- $this->XeroOauth1->$method($args);
- } else {
- error_log("$method is not defined" );
- }
- }
-
- public function xero_init()
- {
- $this->provider = $this->create_provider();
-
- }
-
- private function create_provider() {
- $provider = new \League\OAuth2\Client\Provider\GenericProvider([
- 'clientId' => $this->clientID,
- 'clientSecret' => $this->clientSecret,
- 'redirectUri' => $this->getRedirectURL(),
- 'urlAuthorize' => 'https://login.xero.com/identity/connect/authorize',
- 'urlAccessToken' => 'https://identity.xero.com/connect/token',
- 'urlResourceOwnerDetails' => 'https://api.xero.com/api.xro/2.0/Organisation'
- ]);
- return $provider;
- }
-
- public function load_storage()
- {
- //$this->storage->read_value();
- }
-
- public function boot_carbon()
- {
- \Carbon_Fields\Carbon_Fields::boot();
- }
-
-
- function build_settings_page()
- {
- Container::make('theme_options', __('Xero Integration'))
- ->set_page_parent('options-general.php')
- ->add_fields(array(
- Field::make('text', 'xero_oauth2state', 'Xero Oauth2 State')
- ->set_attribute('maxLength', 2048)
- ->set_attribute('readOnly', true)
- ->set_default_value($this->storage->getOauth2State()),
- Field::make('text', 'xero_token', 'Xero Token')
- ->set_attribute('maxLength', 2048)
- ->set_attribute('readOnly', true)
- ->set_default_value($this->storage->getSession()['token']),
- Field::make('text', 'xero_refresh_token', 'RefreshToken')
- ->set_attribute('readOnly', true)
- ->set_default_value($this->storage->getSession()['refresh_token']),
- Field::make('text', 'xero_id_token', 'ID Token')
- ->set_attribute('readOnly', true)
- ->set_default_value($this->storage->getSession()['id_token']),
- Field::make('text', 'xero_tenant_id', 'Tenant ID')
- ->set_attribute('readOnly', true)
- ->set_default_value($this->storage->getSession()['tenant_id']),
- Field::make('text', 'xero_expires', 'Expires')
- ->set_attribute('readOnly', true)
- ->set_default_value($this->storage->getSession()['expires']),
- Field::make('text', 'xero_expires_human', 'Expires')
- ->set_attribute('readOnly', true)
- ->set_default_value($this->storage->getSession()['expires_human']),
-
- Field::make('html', 'crb_information_text')
- ->set_html('<h1>Connect/Reconnect</h2><p>if the above field is empty,
- or the expire date looks suspicous, please reconnect to XeroOauth1 </p>
- <form action="/">
- <input type="hidden" name="xero_reauth" value="1" />
- <input type="submit" class="button button-primary button-large" value="Xero Connect" />
- </form>')
- ));
-
- $this->storage->read_value();
- }
-
-
- function field_activated()
- {
- $this->storage->read_value();
- $xeroTenantId = (string)$this->storage->getSession()['tenant_id'];
- if ($xeroTenantId == "") {
- $this->startAuthorization();
- } else {
- $this->refresh_token();
- }
- }
-
- public function startAuthorization()
- {
- // This returns the authorizeUrl with necessary parameters applied (e.g. state).
- $authorizationUrl = $this->provider->getAuthorizationUrl($this->options);
-
- // Save the state generated for you and store it to the session.
- // For security, on callback we compare the saved state with the one returned to ensure they match.
- $this->storage->setOauth2State($this->provider->getState());
-
- // Redirect the user to the authorization URL.
- header('Location: ' . $authorizationUrl);
- exit();
- }
-
-
- function xero_callback()
- {
- if (isset($_GET['xero_reauth'])) {
- $this->startAuthorization();
- return;
- }
- if (!isset($_GET['xero_callback'])) {
- return;
- }
- // If we don't have an authorization code then get one
- if (!isset($_GET['code'])) {
- echo "Something went wrong, no authorization code found";
- exit("Something went wrong, no authorization code found");
-
- // Check given state against previously stored one to mitigate CSRF attack
- } elseif (empty($_GET['state']) || ($_GET['state'] !== $this->storage->getOauth2State())) {
- echo "Invalid State";
- $this->storage->setOauth2State("");
- exit('Invalid state');
- } else {
-
- try {
- // Try to get an access token using the authorization code grant.
- $accessToken = $this->provider->getAccessToken('authorization_code', [
- 'code' => $_GET['code']
- ]);
-
- $config = \XeroAPI\XeroPHP\Configuration::getDefaultConfiguration()->setAccessToken((string)$accessToken->getToken());
- $identityInstance = new \XeroAPI\XeroPHP\Api\IdentityApi(
- new \GuzzleHttp\Client(),
- $config
- );
-
- $result = $identityInstance->getConnections();
-
- // Save my tokens, expiration tenant_id
- $this->storage->setToken(
- $accessToken->getToken(),
- $accessToken->getExpires(),
- $result[0]->getTenantId(),
- $accessToken->getRefreshToken(),
- $accessToken->getValues()["id_token"]
- );
-
- // related to $this->build_settings_page
- $url = "/wp-admin/options-general.php?page=crb_carbon_fields_container_xero_integration.php";
- header('Location: ' . $url);
- exit();
-
- } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
- echo "Xero Callback failed";
- exit();
- }
- }
- }
-
- private function getRedirectURL() {
- return get_site_url() . "/?xero_callback";
- }
-
- function refresh_token($enforced=false)
- {
- $this->storage->read_value();
- $this->xeroTenantId = (string)$this->storage->getSession()['tenant_id'];
-
- if ($this->storage->getHasExpired() || $enforced) {
- $this->provider = $this->create_provider();
-
- try {
- $newAccessToken = $this->provider->getAccessToken('refresh_token', [
- 'refresh_token' => $this->storage->getRefreshToken()
- ]);
-
- } catch (\Exception $e) {
- $this->startAuthorization();
- return;
- }
-
- // Save my token, expiration and refresh token
- $this->storage->setToken(
- $newAccessToken->getToken(),
- $newAccessToken->getExpires(),
- $this->xeroTenantId,
- $newAccessToken->getRefreshToken(),
- $newAccessToken->getValues()["id_token"]);
- }
- }
-
- private function get_accounting_instance() {
- $this->refresh_token();
- if ($this->apiAccountingInstance == null) {
- $this->config = \XeroAPI\XeroPHP\Configuration::getDefaultConfiguration()->setAccessToken(
- (string)$this->storage->getSession()['token']);
- $this->apiAccountingInstance = new \XeroAPI\XeroPHP\Api\AccountingApi(
- new \GuzzleHttp\Client(),
- $this->config
- );
- }
- return $this->apiAccountingInstance;
- }
-
- private function get_payroll_au_instance() {
- $this->refresh_token();
- if ($this->apiPayrollInstance == null) {
- $this->config = \XeroAPI\XeroPHP\Configuration::getDefaultConfiguration()->setAccessToken(
- (string)$this->storage->getSession()['token']);
- $this->config->setDebug(true);
- $this->config->setDebugFile("/home/acaresydneycom/public_html/wp-content/plugins/ts/debug.log");
- $this->apiPayrollInstance = new \XeroAPI\XeroPHP\Api\PayrollAuApi(
- new \GuzzleHttp\Client(),
- $this->config
- );
- }
- return $this->apiPayrollInstance;
- }
-
- public function xero_org_name()
- {
- ini_set('display_errors', 'On');
- $apiInstance = $this->get_accounting_instance();
- $apiResponse = $apiInstance->getOrganisations($this->xeroTenantId);
- return 'Organisation Name: <b> ' . $apiResponse->getOrganisations()[0]->getName() . "</b> ";
- }
-
- public function xero_org_contacts()
- {
- ini_set('display_errors', 'On');
- $apiInstance = $this->get_accounting_instance();
-
- $apiResponse = $apiInstance->getContacts($this->xeroTenantId);
- $contacts = $apiResponse->getContacts();
- $message = "<table> ";
- $message .= "<tr> <td> # </td>
- <td> unique-id </td>
- <td> name </td>
- <td> Supplier </td>
- <td> Customer </td>
- <td> Group </td>
- <td> Status </td> </tr> ";
- $count = 1;
- foreach ($contacts as $c) {
-
- $group = "";
- foreach ($c->getContactGroups() as $g) {
- $group .= $g->getName() . " - " . $g->getStatus() . "<br>";
- }
-
- $message .= "<tr> <td>" . $count++ . "</td> " .
- "<td> " . $c->getContactId() . "</td> " .
- "<td> " . $c->getName() . "</td> " .
- "<td> " . ($c->getIsSupplier() ? "yes" : " - ") . "</td> " .
- "<td> " . ($c->getIsCustomer() ? "yes" : " - ") . "</td> " .
- "<td> " . $group . "</td> " .
- "<td> " . $c->getContactStatus() . "</td> " .
- "</tr>";
- }
- $message .= "</table>";
- return $message;
-
- }
-
- public function xero_org_invoices() {
- ini_set('display_errors', 'On');
- $apiInstance = $this->get_accounting_instance();
-
- $apiResponse = $apiInstance->getInvoices($this->xeroTenantId);
- $invoices = $apiResponse->getInvoices();
-
- $message = "<table> ";
- $message .= "<tr> <td> # </td>
- <td> invoice num</td>
- <td> date </td>
- <td> contact </td>
- <td> amount </td>
- <td> Type </td>
- <td> Status </td> </tr> ";
- $count = 1;
-
- foreach ( $invoices as $c) {
- $strDate = "";
- $d = $c->getDate();
- if ( $d != null) {
- $da = $c->getDateAsDate();
- $strDate = $da->format("Y-m-d");
- } else {
- $strDate = $d;
- }
-
- $message .= "<tr> <td>" . $count ++ . "</td> " .
- "<td> " . $c->getInvoiceNumber() . "</td> " .
- "<td> " . $strDate . "</td> " .
- "<td> " . $c->getContact()->getName() . "</td> " .
- "<td> " . $c->getTotal() . "</td> " .
- "<td> " . $c->getType() . "</td> " .
- "<td> " . $c->getStatus() . "</td> " .
- "</tr>";
- }
- $message .= "</table>";
- return $message;
-
- }
-
- public function xero_org_pay_items(){
- ini_set('display_errors', 'On');
- $api = $this->get_payroll_au_instance();
-
- $xeroTenantId = $this->xeroTenantId;
- //$xeroTenantId = "e23fd416-3b66-43e9-b908-97fbefa24eb8"; // demo company;
- //$xeroTenantId = "4e2521ae-83e6-4895-aa90-b20aa0825ce1"; // Acaresydney ;
-
- $ifModifiedSince = null;
- $where = null; // "Status==\"ACTIVE\"";
- $order = null; // "EmailAddress%20DESC";
- $page = 1;
- // $result = null;
- try {
- $result = $api->getPayItems ($xeroTenantId, $ifModifiedSince, $where, $order, $page);
- $rates = $result->getPayItems()->getEarningsRates();
- $message = "<table> ";
- $message .= "<tr> <td> # </td>
- <td> Name </td>
- <td> EarningsType </td>
- <td> RateType </td>
- <td> AccountCode </td>
- <td> Multiplier </td>
- <td> IsExemptFromTax </td>
- <td> IsExemptFromSuper </td>
- <td> AccrueLeave </td>
- <td> IsReportableAsW1 </td>
- <td> UpdatedDateUTC </td>
- <td> CurrentRecord </td> </tr> ";
- $count = 1;
-
- foreach ( $rates as $r) {
- $message .= "<tr> <td>" . $r->getEarningsRateId() . "</td> " .
- "<td> " . $r->getName() . "</td> " .
- "<td> " . $r->getEarningsType() . "</td> " .
- "<td> " . $r->getRateType() . "</td> " .
- "<td> " . $r->getAccountCode() . "</td> " .
- "<td> " . $r->getTypeOfUnits() . "</td> " .
- "<td> " . $r->getRatePerUnit() . "</td> " .
- "<td> " . $r->getIsExemptFromTax() . "</td> " .
- "<td> " . $r->getIsExemptFromSuper() . "</td> " .
- "<td> " . $r->getIsReportableAsW1() . "</td> " .
- "<td> " . $r->getUpdatedDateUtc() . "</td> " .
- "<td> " . $r->getCurrentRecord() . "</td> " .
- "</tr>";
- }
- $message .= "</table>";
- return $message;
- } catch (\Exception $e) {
- echo 'Exception when calling PayrollAuApi->getPayItems: ', $e->getMessage(), PHP_EOL;
- return;
- }
- }
-
- public function xero_org_employees(){
- ini_set('display_errors', 'On');
- $api = $this->get_payroll_au_instance();
-
- $xeroTenantId = $this->xeroTenantId;
- //$xeroTenantId = "e23fd416-3b66-43e9-b908-97fbefa24eb8"; // demo company;
- //$xeroTenantId = "4e2521ae-83e6-4895-aa90-b20aa0825ce1"; // Acaresydney ;
-
- $ifModifiedSince = date("M d Y H:i:s", strtotime("-30 days"));
- $where = "Status==\"ACTIVE\"";
- $order = null; // "EmailAddress%20DESC";
- $page = 1;
- // $result = null;
- try {
- $result = $api->getEmployees($xeroTenantId,$ifModifiedSince,$where,$order,$page);
- $employees = $result->getEmployees();
- $message = "<table> ";
- $message .= "<tr> <td> # </td>
- <td> First </td>
- <td> Last </td>
- <td> Status </td>
- <td> Email </td>
- <td> DOB </td>
- <td> Gender </td>
- <td> Phone </td>
- <td> Mobile </td>
- <td> Start </td>
- <td> Group </td>
- </tr> ";
- $count = 1;
- foreach ($employees as $r){
-
- $message .= "<tr> <td>" . $count . "</td> " .
- "<td> " . $r->getFirstName() . "</td> " .
- "<td> " . $r->getLastName() . "</td> " .
- "<td> " . $r->getStatus() . "</td> " .
- "<td> " . $r->getEmail() . "</td> " .
- "<td> " . $r->getDateOfBirthAsDate()->format("M d Y") . "</td> " .
- "<td> " . $r->getGender() . "</td> " .
- "<td> " . $r->getPhone() . "</td> " .
- "<td> " . $r->getMobile() . "</td> " .
- "<td> " . $r->getStartDateAsDate()->format("M d Y") . "</td> " .
- "<td> " . $r->getEmployeeGroupName() . "</td> " .
- "</tr>";
- $count ++;
- }
- $message .= "</table>";
- return $message;
- } catch (\Exception $e) {
- echo 'Exception when calling PayrollAuApi->getPayItems: ', $e->getMessage(), PHP_EOL;
- return;
- }
- }
-
- public function xero_org_clients(){
- ini_set('display_errors', 'On');
- try {
- $contacts = $this->getClients();
- $message = "<table> ";
- $message .= "<tr> <td> # </td>
- <td> Name </td>
- <td> Last </td>
- <td> Status </td>
- <td> Email </td>
- <td> AccountNumber </td>
- <td> Addresses </td>
- </tr> ";
- $count = 1;
- foreach ($contacts as $r){
-
- $message .= "<tr> <td>" . $count . " - ". $r->getContactID() . "</td> " .
- "<td> " . $r->getFirstName() . "</td> " .
- "<td> " . $r->getLastName() . "</td> " .
- "<td> " . $r->getContactStatus() . "</td> " .
- "<td> " . $r->getEmailAddress() . "</td> " .
- "<td> " . $r->getAccountNumber() . "</td> " .
- "<td> " . $r->getAddresses() . "</td> " .
- "</tr>";
- $count ++;
- }
- $message .= "</table>";
- return $message;
- } catch (\Exception $e) {
- echo 'Exception when calling PayrollAuApi->getPayContacts: ', $e->getMessage(), PHP_EOL;
- return;
- }
- }
-
-
- public function xero_org_payroll_calendar()
- {
- // update_option('bts_pay_roll_calendar_last_sync', time());
- try {
- $result = $this->get_payroll_calendar();
- $pc = $result->getPayrollCalendars()[0];
- $start = $pc->getStartDateAsDate()->format('Y-m-d');
- $finish = new \DateTime($start);
- $finish = $finish->modify("+13 days")->format('Y-m-d');
- $paydate = $pc->getPaymentDateAsDate()->format('Y-m-d');
- $calendar["start"] = $start;
- $calendar["finish"] = $finish;
- $calendar["paydate"] = $paydate;
-
- return print_r ($calendar);
- }catch (\Exception $e) {
- echo 'Exception when calling PayrollAuApi->getPayrollCalendar: ', $e->getMessage(), PHP_EOL;
- }
- //update_option('bts_pay_roll_calendar', $calendar);
- }
-
- //
- //TS implementation
- //
-
- /* sync xero to wp options */
- public function init_wp(){
- try{
- error_log("init_wp is empty");
- $this->sync_pay_item();
- // $this->add_new_client();
- // $this->add_new_employee();
- // $this->sync_payroll_calendar();
- }catch(\Exception $e){
-
- }
- }
-
- private function sync_pay_item() {
- if ($this->too_close_to_sync_payitem()){
- //return;
- }
-
- $api = $this->get_payroll_au_instance();
- $xeroTenantId = $this->xeroTenantId;
- $page = 1;
- try {
- $result = $api->getPayItems($xeroTenantId, $ifModifiedSince, $where, $order, $page);
-
-
-
- foreach ($result->getPayItems()->getEarningsRates() as $e){
- // "EarningsRateID": "34e17d08-237a-4ae2-8115-375d1ff8a9ed",
- // "Name": "Overtime Hours (exempt from super)",
- // "EarningsType": "OVERTIMEEARNINGS",
- // "RateType": "MULTIPLE",
- // "AccountCode": "477",
- // "Multiplier": 1.5,
- // "IsExemptFromTax": true,
- // "IsExemptFromSuper": true,
- // "AccrueLeave": false,
- // "IsReportableAsW1": true,
- // "UpdatedDateUTC": "2019-03-16T13:18:19+00:00",
- // "CurrentRecord": false
- if ($e->getCurrentRecord() == "true"){
- $payitem_options[]= array(
- 'EarningsRateID' => $e->getEarningsRateID(),
- 'Name'=> $e->getName(),
- 'EarningsType'=> $e->getEarningstype(),
- 'RatePerUnit' => $e->getRatePerUnit(),
- 'RateType' => $e->getRateType(),
- 'AccountCode' => $e->getAccountCode(),
- "Multiplier"=> $e->getMultiplier(),
- "IsExemptFromTax" => $e->getIsExemptFromTax(),
- "IsExemptFromSuper"=> $e->getIsExemptFromSuper(),
- "AccrueLeave" => $e->getAccrueLeave(),
- "TypeOfUnits" => $e->getTypeOfUnits(),
- "CurrentRecord"=> $e->getCurrentRecord(),
- );
- }
- }
- update_option('bts_payitem_earnings_rate', $payitem_options);
- update_option('bts_payitem_last_sync', time());
-
-
- } catch (Exception $e) {
- echo 'Exception when calling PayrollAuApi->getPayItems: ', $e->getMessage(), PHP_EOL;
- }
- }
-
- public function sync_users($mininterval, $employeeonly, $clientsonly){
- echo "not implemented "; //TODO;
- }
-
- public function sync_payroll_calendar() {
-
- }
-
- private function too_close_to_sync_payitem(){
- $lastsync = get_option('bts_payitem_last_sync', 0);
- $now = time();
- $diff = $now - (int) $lastsync;
- return $diff < $this->minimum_sync_interval_in_seconds; //default 10 minutes
- }
-
- private function sync_payitem(){
-
-
- }
-
-
- private function too_close_to_add_employee(){
- $lastsync = get_option('bts_add_employee_last_sync', 0);
- $now = time();
- $diff = $now - (int) $lastsync;
- return $diff < 1.5 * $this->minimum_sync_interval_in_seconds; //default 1.1 * 10 minutes
- }
- private function too_close_to_add_client(){
- $lastsync = get_option('bts_add_client_last_sync', 0);
- $now = time();
- $diff = $now - (int) $lastsync;
- return $diff < 2.0 * $this->minimum_sync_interval_in_seconds; //default 1.2 * 10 minutes
- }
- private function too_close_to_sync_payroll_calendar(){
- $lastsync = get_option('bts_pay_roll_calendar_last_sync', 0);
- $now = time();
- $diff = $now - (int) $lastsync;
- return $diff < 3.0 * $this->minimum_sync_interval_in_seconds; //default 1.3 * 10 minutes
- }
-
-
-
-
-
-
- public function getClients($contact_group_id = null) {
- if ( $contact_group_id == null ){
- $contact_group_id = $this->clientContactGroupID;
- }
- $apiAcc = $this->get_accounting_instance();
- $result = $apiAcc->getContactGroup($this->xeroTenantId, $contact_group_id);
- $cg = $result->getContactGroups();
- $allClients = $cg[0]->getContacts();
-
- $ifModifiedSince = new \DateTime();
- $recent = new \DateInterval("P30D");
- $ifModifiedSince->sub($recent);
-
-
- $allContacts = $apiAcc->getContacts($this->xeroTenantId, $ifModifiedSince);
- $ret = [];
- foreach ( $allContacts as $ac ) {
- //search from within the group
- $found = false;
- $id = $ac->getContactID();
- foreach ($allClients as $client) {
- $clientID = $client->getContactID();
- if ( $clientID == $id ) {
- $found = true;
- break;
- }
- }
-
- if ( $found ) {
- $ret[] = $ac;
- }
-
- }
- return $ret;
- }
-
- public function get_payroll_calendar()
- {
- $id = "33dc7df5-3060-4d76-b4da-57c20685d77d"; //fortnightly
- $api = $this->get_payroll_au_instance();
-
- $pc = $api->getPayrollCalendar($this->xeroTenantId, $id);
- return $pc;
- }
-
- }
|