|
|
|
@@ -0,0 +1,712 @@ |
|
|
|
<?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; |
|
|
|
} |
|
|
|
|
|
|
|
} |