Invoice Sync

This commit is contained in:
David Bomba 2024-09-24 12:46:16 +10:00
parent 6f3e56a2a2
commit 8fadba5545
4 changed files with 104 additions and 26 deletions

View File

@ -53,10 +53,10 @@ class QuickbooksImport implements ShouldQueue
'product' => 'Item',
'client' => 'Customer',
'invoice' => 'Invoice',
'sales' => 'SalesReceipt',
// 'quote' => 'Estimate',
// 'purchase_order' => 'PurchaseOrder',
// 'payment' => 'Payment',
'sales' => 'SalesReceipt',
// 'vendor' => 'Vendor',
// 'expense' => 'Purchase',
];

View File

@ -11,23 +11,29 @@
namespace App\Services\Quickbooks\Models;
use Carbon\Carbon;
use App\Models\Invoice;
use App\DataMapper\InvoiceSync;
use App\Factory\InvoiceFactory;
use App\Interfaces\SyncInterface;
use App\Repositories\InvoiceRepository;
use App\Services\Quickbooks\QuickbooksService;
use App\Services\Quickbooks\Transformers\InvoiceTransformer;
use App\Services\Quickbooks\Transformers\PaymentTransformer;
class QbInvoice implements SyncInterface
{
protected InvoiceTransformer $transformer;
protected InvoiceTransformer $invoice_transformer;
protected InvoiceRepository $invoice_repository;
public function __construct(public QuickbooksService $service)
{
$this->transformer = new InvoiceTransformer($this->service->company);
$this->invoice_transformer = new InvoiceTransformer($this->service->company);
$this->invoice_repository = new InvoiceRepository();
}
public function find(int $id): mixed
public function find(string $id): mixed
{
return $this->service->sdk->FindById('Invoice', $id);
}
@ -37,7 +43,7 @@ class QbInvoice implements SyncInterface
foreach ($records as $record) {
$ninja_invoice_data = $this->transformer->qbToNinja($record);
$ninja_invoice_data = $this->invoice_transformer->qbToNinja($record);
$payment_ids = $ninja_invoice_data['payment_ids'] ?? [];
@ -49,7 +55,11 @@ class QbInvoice implements SyncInterface
unset($ninja_invoice_data['payment_ids']);
if ($invoice = $this->findInvoice($ninja_invoice_data)) {
if ($invoice = $this->findInvoice($ninja_invoice_data['id'], $ninja_invoice_data['client_id'])) {
if($invoice->id)
$this->processQbToNinjaInvoiceUpdate($ninja_invoice_data, $invoice);
$invoice->fill($ninja_invoice_data);
$invoice->saveQuietly();
@ -95,17 +105,38 @@ class QbInvoice implements SyncInterface
}
private function processQbToNinjaInvoiceUpdate(array $ninja_invoice_data, Invoice $invoice): void
{
$current_ninja_invoice_balance = $invoice->balance;
$qb_invoice_balance = $ninja_invoice_data['balance'];
private function findInvoice(array $ninja_invoice_data): ?Invoice
if(floatval($current_ninja_invoice_balance) == floatval($qb_invoice_balance))
{
nlog('Invoice balance is the same, skipping update of line items');
unset($ninja_invoice_data['line_items']);
$invoice->fill($ninja_invoice_data);
$invoice->saveQuietly();
}
else{
nlog('Invoice balance is different, updating line items');
$this->invoice_repository->save($ninja_invoice_data, $invoice);
}
}
private function findInvoice(string $id, ?string $client_id = null): ?Invoice
{
$search = Invoice::query()
->withTrashed()
->where('company_id', $this->service->company->id)
->where('sync->qb_id', $ninja_invoice_data['id']);
->where('sync->qb_id', $id);
if($search->count() == 0) {
if($search->count() == 0 && $client_id) {
$invoice = InvoiceFactory::create($this->service->company->id, $this->service->company->owner()->id);
$invoice->client_id = $ninja_invoice_data['client_id'];
$invoice->client_id = $client_id;
$sync = new InvoiceSync();
$sync->qb_id = $id;
$invoice->sync = $sync;
return $invoice;
} elseif($search->count() == 1) {
@ -116,4 +147,25 @@ class QbInvoice implements SyncInterface
}
public function sync(string $id, string $last_updated): void
{
$qb_record = $this->find($id);
if($this->service->updateGate('invoice') && $invoice = $this->findInvoice($id))
{
//logic here to determine if we should update the record
if(Carbon::parse($last_updated)->gt(Carbon::parse($invoice->updated_at)))
{
$ninja_invoice_data = $this->invoice_transformer->qbToNinja($qb_record);
$this->invoice_repository->save($ninja_invoice_data, $invoice);
}
// }
}
}
}

View File

@ -90,11 +90,14 @@ class QuickbooksService
private function checkToken(): self
{
nlog($this->company->quickbooks->accessTokenExpiresAt);
nlog(time());
if($this->company->quickbooks->accessTokenKey > time())
if($this->company->quickbooks->accessTokenExpiresAt > time())
return $this;
if($this->company->quickbooks->accessTokenExpiresAt < time() && $this->try_refresh){
nlog('Refreshing token');
$this->sdk()->refreshToken($this->company->quickbooks->refresh_token);
$this->company = $this->company->fresh();
$this->try_refresh = false;
@ -145,7 +148,10 @@ class QuickbooksService
*/
public function updateGate(string $entity): bool
{
return (bool) $this->service->settings->{$entity}->sync && $this->service->settings->{$entity}->update_record;
nlog($this->settings->{$entity}->sync);
nlog($this->settings->{$entity}->update_record);
return $this->settings->{$entity}->sync && $this->settings->{$entity}->update_record;
}
/**

View File

@ -87,6 +87,9 @@ class InvoiceTransformer extends BaseTransformer
$items = [];
foreach($qb_items as $qb_item)
{
if(data_get($qb_item, 'DetailType.value') == 'SalesItemLineDetail')
{
$item = new InvoiceItem;
$item->product_key = data_get($qb_item, 'SalesItemLineDetail.ItemRef.name', '');
@ -102,6 +105,23 @@ class InvoiceTransformer extends BaseTransformer
$items[] = (object)$item;
}
if(data_get($qb_item, 'DetailType.value') == 'DiscountLineDetail')
{
$item = new InvoiceItem();
$item->product_key = ctrans('texts.discount');
$item->notes = ctrans('texts.discount');
$item->quantity = 1;
$item->cost = data_get($qb_item, 'Amount', 0) * -1;
$item->discount = 0;
$item->is_amount_discount = true;
$item->type_id = '1';
$item->tax_id = Product::PRODUCT_TYPE_PHYSICAL;
$items[] = (object)$item;
}
}
nlog($items);
return $items;