Files
caloriethingy.com/common/components/SonarApiComponent.php
2025-02-19 14:51:16 +01:00

469 lines
18 KiB
PHP

<?php
namespace common\components;
use common\jobs\EmailJob;
use common\models\Account;
use common\models\InvoiceItem;
use common\models\SalesAgent;
use common\models\Service;
use Yii;
use yii\helpers\Url;
use yii\httpclient\Client;
use yii\httpclient\Request;
use yii\httpclient\RequestEvent;
class SonarApiComponent extends \yii\base\Component
{
public Client $client;
public string $baseUrl;
public string $bearerToken;
public function init()
{
parent::init();
$this->client = new Client([
'baseUrl' => $this->baseUrl,
'requestConfig' => [
'format' => Client::FORMAT_JSON
],
'responseConfig' => [
'format' => Client::FORMAT_JSON
],
]);
// Setup event for auth before each send
$this->client->on(Request::EVENT_BEFORE_SEND, function (RequestEvent $event) {
$event->request->addHeaders(['Authorization' => 'Bearer ' . $this->bearerToken]);
});
}
public function getAccounts(int $page = 1, int $limit = 100)
{
$data = [
'form_params' => [
'query' => 'query accountsWithSalesAgents(
$paginator: Paginator,
$search: [Search],
$sorter: [Sorter]
) {
accounts(
paginator: $paginator
search: $search
sorter: $sorter
reverse_relation_filters: {
relation: "custom_field_data",
search: {
integer_fields: {
attribute: "custom_field_id",
search_value: 12,
operator: EQ
}
}
}
general_search_mode: ROOT_PLUS_RELATIONS
account_status_id: 1
) {
entities {
id
name
account_status {
id
name
}
account_services {
entities {
id
quantity
name_override
price_override
price_override_reason
service {
id
name
amount
enabled
application
type
}
}
page_info {
page
records_per_page
total_count
total_pages
}
}
custom_field_data(custom_field_id:12) {
entities {
id
custom_field_id
value
}
}
}
page_info {
page
records_per_page
total_count
total_pages
}
}
}',
'variables' => [
'paginator' => [
'page' => $page,
'records_per_page' => $limit
],
'search' => [],
'sorter' => [
[
'attribute' => 'updated_at',
'direction' => 'ASC',
]
],
]
]
];
$response = $this->client->createRequest()
->setMethod('POST')
->setData($data)
->send();
$account = json_decode($response->getContent(), true);
return $account['form_params']['data'];
}
public function getInvoices(string $startDate, string $endDate)
{
$page = 1;
$limit = 100;
$invoices = [];
do {
$data = [
'form_params' => [
'query' => 'query accountInvoice($paginator: Paginator, $search: [Search], $sorter: [Sorter]) {
invoices(
paginator: $paginator
search: $search
sorter: $sorter
general_search_mode: ROOT_PLUS_RELATIONS
) {
entities {
id
account_id
total_debits
void
remaining_due
date
due_date
end_date
delinquent
debits {
entities {
id
quantity
service_id
service_name
amount
}
}
credits {
entities {
amount
}
}
}
page_info {
page
records_per_page
total_count
total_pages
}
}
}',
'variables' => [
'paginator' => [
'page' => $page,
'records_per_page' => $limit
],
'search' => [
[
'date_fields' => [
['attribute' => 'date', 'search_value' => $startDate, 'operator' => 'GTE'],
['attribute' => 'date', 'search_value' => $endDate, 'operator' => 'LTE'],
]
]
]
],
'sorter' => [
[
'attribute' => 'updated_at',
'direction' => 'ASC',
]
],
]
];
$response = $this->client->createRequest()
->setMethod('POST')
->setData($data)
->send();
$responseData = json_decode($response->getContent(), true);
$invoices = array_merge($invoices, $responseData['form_params']['data']['invoices']['entities']);
$page++;
} while ($page < ($responseData['form_params']['data']['invoices']['page_info']['total_pages'] + 1));
return $invoices;
}
public function getInvoice(int $invoiceId = 1)
{
$page = 1;
$limit = 100;
$data = [
'form_params' => [
'query' => 'query accountInvoice($paginator: Paginator, $search: [Search], $sorter: [Sorter]) {
invoices(
id: ' . $invoiceId . '
paginator: $paginator
search: $search
sorter: $sorter
general_search_mode: ROOT_PLUS_RELATIONS
) {
entities {
id
account_id
total_debits
void
remaining_due
date
due_date
end_date
delinquent
debits {
entities {
id
quantity
service_id
service_name
amount
}
}
credits {
entities {
amount
}
}
}
page_info {
page
records_per_page
total_count
total_pages
}
}
}',
'variables' => [
'paginator' => [
'page' => $page,
'records_per_page' => $limit
],
'search' => [],
'sorter' => [
[
'attribute' => 'updated_at',
'direction' => 'ASC',
]
],
]
]
];
$response = $this->client->createRequest()
->setMethod('POST')
->setData($data)
->send();
$invoice = json_decode($response->getContent(), true);
return $invoice['form_params']['data']['invoices']['entities'][0];
}
public function storeInvoices($invoices)
{
foreach ($invoices as $invoice) {
$this->storeInvoice($invoice);
}
}
public function storeInvoice($invoice)
{
\Yii::debug($invoice);
// $remainingDue is the Entire Invoice remaining to be paid amount, 0 = everything paid
$remainingDue = $invoice['remaining_due'];
// debits = charges on the account
// credits = payments on the account
foreach ($invoice['debits']['entities'] as $i => $rawItem) {
$invoiceItem = InvoiceItem::find()->where(['sonar_id' => (int)$rawItem['id']])->one();
if (null === $invoiceItem) { // create new invoice item
$account = Account::findOne(['sonar_id' => (int)$invoice['account_id']]);
$service = Service::findOne(['sonar_id' => (int)$rawItem['service_id']]);
\Yii::debug($rawItem);
if ($service && $account) {
\Yii::debug($invoice);
$payment = (isset($invoice['credits']['entities'][$i]['amount'])) ? $invoice['credits']['entities'][$i]['amount'] : 0;
// @todo check payment - i think it is wrong to assume we have the same credits and debits ^ CGS
$invoiceItem = new InvoiceItem([
'sonar_id' => (int)$rawItem['id'],
'account_id' => $account->id,
'service_id' => $service->id,
'name' => $rawItem['service_name'],
'status' => InvoiceItem::STATUS_OPEN,
'charge' => $rawItem['amount'],
'payment' => $payment,
'is_commissionable' => $service->hasCommission(),
]);
$invoiceItem->save();
}
}
// is the invoice item paid?
if ($invoiceItem && $remainingDue == 0) {
$invoiceItem->status = InvoiceItem::STATUS_PAYMENT_RECEIVED;
$invoiceItem->save();
}
}
}
private function mapAccounts($accounts)
{
$mapped = [];
$i = 0;
$db = \Yii::$app->db;
foreach ($accounts as $account) {
$mapped[$i]['sonar_id'] = (int)$account['id'];
$mapped[$i]['name'] = $account['name'];
/**
* [
* 'id' => '132'
* 'quantity' => 1
* 'name_override' => 'Bradley'
* 'price_override' => 0
* 'price_override_reason' => 'testing'
* 'service' => [
* 'id' => '10'
* 'name' => 'Business Giga Speed Internet'
* 'amount' => 18000
* 'enabled' => true
* 'application' => 'DEBIT'
* 'type' => 'DATA'
* ]
* ]
*/
$mapped[$i]['services'] = []; // init empty array
foreach ($account['account_services']['entities'] as $key => $account_service) {
$mapped[$i]['services'][$key]['sonar_id'] = (int)$account_service['service']['id'];
$mapped[$i]['services'][$key]['name'] = (!empty($account_service['name_override'])) ? $account_service['name_override'] : $account_service['service']['name'];
$mapped[$i]['services'][$key]['price'] = (!empty($account_service['price_override'])) ? $account_service['price_override'] : $account_service['service']['amount'];
if ($account_service['service']['application'] === 'CREDIT') {
$mapped[$i]['services'][$key]['price'] = -1 * $mapped[$i]['services'][$key]['price'];// store as a negative
}
// set to 0 if null after credit
if (null === $mapped[$i]['services'][$key]['price']) {
$mapped[$i]['services'][$key]['price'] = 0;
}
}
$name = $account['custom_field_data']['entities'][0]['value'];
$salesAgent = SalesAgent::findOne(['name' => $name]);
if (null === $salesAgent) {
$salesAgent = new SalesAgent(['name' => $name]);
$salesAgent->save();
}
$mapped[$i]['sales_agent_id'] = $salesAgent->id;
$i++;
}
return $mapped;
}
public function storeAccounts()
{
$page = 1;
do {
$batch = $this->getAccounts($page, 100);
$accounts = $this->mapAccounts($batch['accounts']['entities']);
foreach ($accounts as $account) {
$accountModel = Account::findOne(['sonar_id' => $account['sonar_id']]);
if (null === $accountModel) {
$accountModel = new Account([
'sonar_id' => $account['sonar_id'],
'name' => $account['name'],
'sales_agent_id' => $account['sales_agent_id'],
]);
$accountModel->save();
} else {
//$accountModel->sonar_id = $account['sonar_id'];
$accountModel->name = $account['name'];
$accountModel->sales_agent_id = $account['sales_agent_id'];
$accountModel->save();
}
foreach ($account['services'] as $rawServiceData) {
$serviceModel = Service::findOne(['sonar_id' => (int)$rawServiceData['sonar_id']]);
if (null === $serviceModel) {
$serviceModel = new Service([
'sonar_id' => $rawServiceData['sonar_id'],
'name' => $rawServiceData['name'],
'price' => $rawServiceData['price'],
'account_id' => $accountModel->id,
'active' => 1, // @todo pull active state in from sonar api
]);
$serviceModel->save();
} else {
$serviceModel->commission = $serviceModel->getFormattedDollar($serviceModel->commission, false);
$serviceModel->sonar_id = $rawServiceData['sonar_id'];
$serviceModel->name = $rawServiceData['name'];
$serviceModel->price = $rawServiceData['price'];
$serviceModel->account_id = $accountModel->id;
if (!empty($serviceModel->dirtyAttributes)) {
if (isset($serviceModel->dirtyAttributes['price'])) {
//Yii::$app->queue->push(new EmailJob([
// 'templateAlias' => EmailJob::PRICE_CHANGE,
// "email" => Yii::$app->params['adminEmail'],
// 'templateModel' => [
// "action_edit_url" => Yii::$app->urlManager->createAbsoluteUrl(
// ['service/update', 'id' => $serviceModel->id]
// ),
// ]
//]));
}
}
$serviceModel->save();
}
}
}
$page++;
} while ($page < ($batch['accounts']['page_info']['total_pages'] + 1));
}
public function processInvoices(int $invoiceId)
{
dump($this->getInvoice($invoiceId));
}
}