diff --git a/app/Factory/CreditFactory.php b/app/Factory/CreditFactory.php index 3d0003b86fb2..840512dce5fe 100644 --- a/app/Factory/CreditFactory.php +++ b/app/Factory/CreditFactory.php @@ -16,7 +16,7 @@ use App\Models\Credit; class CreditFactory { - public static function create(int $company_id, int $user_id, object $settings = null, Client $client = null): Credit + public static function create(int $company_id, int $user_id): Credit { $credit = new Credit(); $credit->status_id = Credit::STATUS_DRAFT; diff --git a/app/Services/Quickbooks/Jobs/QuickbooksSync.php b/app/Services/Quickbooks/Jobs/QuickbooksSync.php index 0b82e5a3578a..fa94f152ca3c 100644 --- a/app/Services/Quickbooks/Jobs/QuickbooksSync.php +++ b/app/Services/Quickbooks/Jobs/QuickbooksSync.php @@ -119,8 +119,12 @@ class QuickbooksSync implements ShouldQueue foreach($records as $record) { + nlog($record); + $ninja_invoice_data = $invoice_transformer->qbToNinja($record); + nlog($ninja_invoice_data); + $payment_ids = $ninja_invoice_data['payment_ids'] ?? []; $client_id = $ninja_invoice_data['client_id'] ?? null; @@ -140,6 +144,7 @@ class QuickbooksSync implements ShouldQueue { $payment = $this->qbs->sdk->FindById('Payment', $payment_id); + $payment_transformer = new PaymentTransformer($this->company); $transformed = $payment_transformer->qbToNinja($payment); @@ -151,7 +156,8 @@ class QuickbooksSync implements ShouldQueue $paymentable->payment_id = $ninja_payment->id; $paymentable->paymentable_id = $invoice->id; $paymentable->paymentable_type = 'invoices'; - $paymentable->amount = $transformed['applied']; + $paymentable->amount = $transformed['applied'] + $ninja_payment->credits->sum('amount'); + $paymentable->created_at = $ninja_payment->date; $paymentable->save(); $invoice->service()->applyPayment($ninja_payment, $transformed['applied']); diff --git a/app/Services/Quickbooks/QuickbooksService.php b/app/Services/Quickbooks/QuickbooksService.php index 38d5bceae909..9d5b45fdd18f 100644 --- a/app/Services/Quickbooks/QuickbooksService.php +++ b/app/Services/Quickbooks/QuickbooksService.php @@ -27,9 +27,6 @@ use App\Services\Quickbooks\Transformers\InvoiceTransformer; use App\Services\Quickbooks\Transformers\PaymentTransformer; use App\Services\Quickbooks\Transformers\ProductTransformer; -// quickbooks_realm_id -// quickbooks_refresh_token -// quickbooks_refresh_expires class QuickbooksService { public DataService $sdk; @@ -50,7 +47,7 @@ class QuickbooksService 'auth_mode' => 'oauth2', 'scope' => "com.intuit.quickbooks.accounting", // 'RedirectURI' => 'https://developer.intuit.com/v2/OAuth2Playground/RedirectUrl', - 'RedirectURI' => $this->testMode ? 'https://above-distinctly-teal.ngrok-free.app/quickbooks/authorized' : 'https://invoicing.co/quickbooks/authorized', + 'RedirectURI' => $this->testMode ? 'https://grok.romulus.com.au/quickbooks/authorized' : 'https://invoicing.co/quickbooks/authorized', 'baseUrl' => $this->testMode ? CoreConstants::SANDBOX_DEVELOPMENT : CoreConstants::QBO_BASEURL, ]; @@ -67,7 +64,7 @@ class QuickbooksService return $this; } - private function ninjaAccessToken() + private function ninjaAccessToken(): array { return isset($this->company->quickbooks->accessTokenKey) ? [ 'accessTokenKey' => $this->company->quickbooks->accessTokenKey, @@ -82,11 +79,11 @@ class QuickbooksService } /** - * //@todo - refactor to a job + * * * @return void */ - public function syncFromQb() + public function syncFromQb(): void { QuickbooksSync::dispatch($this->company->id, $this->company->db); } diff --git a/app/Services/Quickbooks/Transformers/InvoiceTransformer.php b/app/Services/Quickbooks/Transformers/InvoiceTransformer.php index 4e5273a55c8b..0ab93d0a7c1f 100644 --- a/app/Services/Quickbooks/Transformers/InvoiceTransformer.php +++ b/app/Services/Quickbooks/Transformers/InvoiceTransformer.php @@ -62,8 +62,6 @@ class InvoiceTransformer extends BaseTransformer $qb_payments = data_get($qb_data, 'LinkedTxn', false); - nlog($qb_payments); - if(!$qb_payments) { return []; } @@ -82,6 +80,8 @@ class InvoiceTransformer extends BaseTransformer } } + nlog($payments); + return $payments; } @@ -99,9 +99,11 @@ class InvoiceTransformer extends BaseTransformer $item->cost = data_get($qb_item, 'SalesItemLineDetail.UnitPrice', 0); $item->discount = data_get($item,'DiscountRate', data_get($qb_item,'DiscountAmount', 0)); $item->is_amount_discount = data_get($qb_item,'DiscountAmount', 0) > 0 ? true : false; - $item->type_id = stripos(data_get($qb_item, 'ItemAccountRef.name'), 'Service') !== false ? '2' : '1'; + $item->type_id = stripos(data_get($qb_item, 'ItemAccountRef.name') ?? '', 'Service') !== false ? '2' : '1'; $item->tax_id = data_get($qb_item, 'TaxCodeRef.value', '') == 'NON' ? Product::PRODUCT_TYPE_EXEMPT : $item->type_id; - $item->tax_rate1 = data_get($qb_item,'TaxLineDetail.TaxRateRef.TaxPercent', 0); + $item->tax_rate1 = data_get($qb_item, 'TxnTaxDetail.TaxLine.TaxLineDetail.TaxPercent', 0); + +// $item->tax_rate1 = data_get($qb_item, 'TaxLineDetail.TaxRateRef.TaxPercent', 0); $item->tax_name1 = $item->tax_rate1 > 0 ? "Sales Tax" : ""; $items[] = (object)$item; } diff --git a/app/Services/Quickbooks/Transformers/PaymentTransformer.php b/app/Services/Quickbooks/Transformers/PaymentTransformer.php index 9b1d0a6691ec..e5eb7f38ae28 100644 --- a/app/Services/Quickbooks/Transformers/PaymentTransformer.php +++ b/app/Services/Quickbooks/Transformers/PaymentTransformer.php @@ -14,6 +14,7 @@ namespace App\Services\Quickbooks\Transformers; use App\Models\Company; use App\Models\Payment; use App\Factory\PaymentFactory; +use App\Models\Credit; /** * @@ -56,15 +57,68 @@ class PaymentTransformer extends BaseTransformer $payment->applied = $ninja_payment_data['applied']; $payment->status_id = 4; $payment->fill($ninja_payment_data); - + $payment->save(); + $payment->client->service()->updatePaidToDate($payment->amount); - return $payment; - } + if($payment->amount == 0) { + //this is a credit memo, create a stub credit for this. + $payment = $this->createCredit($payment, $qb_data); + $payment->type_id = \App\Models\PaymentType::CREDIT; + $payment->save(); + } + + return $payment; + + } return null; } + private function createCredit($payment, $qb_data) + { + $credit_line = null; + + foreach($qb_data->Line as $item) { + + if(data_get($item, 'LinkedTxn.TxnType', null) == 'CreditMemo') { + $credit_line = $item; + break; + } + + } + + if(!$credit_line) + return $payment; + + $credit = \App\Factory\CreditFactory::create($this->company->id, $this->company->owner()->id, $payment->client_id); + $credit->client_id = $payment->client_id; + + $line = new \App\DataMapper\InvoiceItem(); + $line->quantity = 1; + $line->cost = $credit_line->Amount; + $line->product_key = 'CREDITMEMO'; + $line->notes = $payment->private_notes; + + $credit->date = $qb_data->TxnDate; + $credit->status_id = 4; + $credit->amount = $credit_line->Amount; + $credit->paid_to_date = $credit_line->Amount; + $credit->balance = 0; + $credit->line_items = [$line]; + $credit->save(); + + $paymentable = new \App\Models\Paymentable(); + $paymentable->payment_id = $payment->id; + $paymentable->paymentable_id = $credit->id; + $paymentable->paymentable_type = \App\Models\Credit::class; + $paymentable->amount = $credit->amount; + $paymentable->created_at = $payment->date; + $paymentable->save(); + + return $payment; + } + public function getLine($data, $field = null) { $invoices = [];