mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Merge branch 'v5-develop' into v5-stable
This commit is contained in:
commit
6370b1f061
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@ -46,7 +46,9 @@ jobs:
|
|||||||
git checkout main
|
git checkout main
|
||||||
npm i
|
npm i
|
||||||
npm run build
|
npm run build
|
||||||
cp -r dist/react/* ../public/react
|
cp -r dist/react/* ../public/react
|
||||||
|
mkdir -p ../public/tinymce_6.4.2/tinymce/js/
|
||||||
|
cp -r node_modules/tinymce ../public/tinymce_6.4.2/tinymce/js/
|
||||||
cd ..
|
cd ..
|
||||||
rm -rf ui
|
rm -rf ui
|
||||||
php artisan ninja:react
|
php artisan ninja:react
|
||||||
|
@ -1 +1 @@
|
|||||||
5.6.4
|
5.6.10
|
@ -154,7 +154,7 @@ class CheckData extends Command
|
|||||||
->subject('Check-Data: '.strtoupper($this->isValid ? Account::RESULT_SUCCESS : Account::RESULT_FAILURE)." [{$database}]");
|
->subject('Check-Data: '.strtoupper($this->isValid ? Account::RESULT_SUCCESS : Account::RESULT_FAILURE)." [{$database}]");
|
||||||
});
|
});
|
||||||
} elseif (! $this->isValid) {
|
} elseif (! $this->isValid) {
|
||||||
new Exception("Check data failed!!\n".$this->log);
|
new \Exception("Check data failed!!".$this->log);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ class ImportMigrations extends Command
|
|||||||
$import_file = public_path("storage/migrations/$filename/migration.json");
|
$import_file = public_path("storage/migrations/$filename/migration.json");
|
||||||
|
|
||||||
Import::dispatch($import_file, $this->getUser()->companies()->first(), $this->getUser());
|
Import::dispatch($import_file, $this->getUser()->companies()->first(), $this->getUser());
|
||||||
// StartMigration::dispatch($file->getRealPath(), $this->getUser(), $this->getUser()->companies()->first());
|
|
||||||
} catch (NonExistingMigrationFile | ProcessingMigrationArchiveFailed | ResourceNotAvailableForMigration | MigrationValidatorFailed | ResourceDependencyMissing $e) {
|
} catch (NonExistingMigrationFile | ProcessingMigrationArchiveFailed | ResourceNotAvailableForMigration | MigrationValidatorFailed | ResourceDependencyMissing $e) {
|
||||||
\Mail::to($user)->send(new MigrationFailed($e, $company));
|
\Mail::to($user)->send(new MigrationFailed($e, $company));
|
||||||
|
|
||||||
|
@ -133,11 +133,9 @@ class TranslationsExport extends Command
|
|||||||
Storage::disk('local')->makeDirectory('lang');
|
Storage::disk('local')->makeDirectory('lang');
|
||||||
|
|
||||||
foreach ($this->langs as $lang) {
|
foreach ($this->langs as $lang) {
|
||||||
nlog($lang);
|
|
||||||
Storage::disk('local')->makeDirectory("lang/{$lang}");
|
Storage::disk('local')->makeDirectory("lang/{$lang}");
|
||||||
|
|
||||||
$translations = Lang::getLoader()->load($lang, 'texts');
|
$translations = Lang::getLoader()->load($lang, 'texts');
|
||||||
nlog($translations);
|
|
||||||
Storage::disk('local')->put("lang/{$lang}/{$lang}.json", json_encode(Arr::dot($translations), JSON_UNESCAPED_UNICODE));
|
Storage::disk('local')->put("lang/{$lang}/{$lang}.json", json_encode(Arr::dot($translations), JSON_UNESCAPED_UNICODE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,7 @@ class BaseRule implements RuleInterface
|
|||||||
$this->client_region = $this->region_codes[$this->client->country->iso_3166_2];
|
$this->client_region = $this->region_codes[$this->client->country->iso_3166_2];
|
||||||
|
|
||||||
match($this->client_region){
|
match($this->client_region){
|
||||||
'US' => $this->client_subregion = strlen($this->invoice?->client?->tax_data?->geoState) > 1 ? $this->invoice->client->tax_data->geoState : $this->getUSState(),
|
'US' => $this->client_subregion = isset($this->invoice?->client?->tax_data?->geoState) ? $this->invoice->client->tax_data->geoState : $this->getUSState(),
|
||||||
'EU' => $this->client_subregion = $this->client->country->iso_3166_2,
|
'EU' => $this->client_subregion = $this->client->country->iso_3166_2,
|
||||||
'AU' => $this->client_subregion = 'AU',
|
'AU' => $this->client_subregion = 'AU',
|
||||||
default => $this->client_subregion = $this->client->country->iso_3166_2,
|
default => $this->client_subregion = $this->client->country->iso_3166_2,
|
||||||
|
@ -48,7 +48,6 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
{
|
{
|
||||||
|
|
||||||
$this->tax_rate1 = $item->tax_rate1;
|
$this->tax_rate1 = $item->tax_rate1;
|
||||||
|
|
||||||
$this->tax_name1 = $item->tax_name1;
|
$this->tax_name1 = $item->tax_name1;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -117,6 +116,9 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
if(in_array($this->tax_data?->txbService,['Y','L'])) {
|
if(in_array($this->tax_data?->txbService,['Y','L'])) {
|
||||||
$this->default($item);
|
$this->default($item);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
$this->taxExempt($item);
|
||||||
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -162,14 +164,13 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
|
|
||||||
if($this->tax_data?->stateSalesTax == 0) {
|
if($this->tax_data?->stateSalesTax == 0) {
|
||||||
|
|
||||||
$this->tax_rate1 = $this->invoice->client->company->tax_data->regions->{$this->client_region}->subregions->{$this->client_subregion}->tax_rate;
|
$this->tax_rate1 = 0;
|
||||||
$this->tax_name1 = "Sales Tax";
|
$this->tax_name1 = '';
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->tax_rate1 = $this->tax_data->taxSales * 100;
|
$this->tax_rate1 = $this->tax_data->taxSales * 100;
|
||||||
// $this->tax_name1 = "{$this->tax_data->geoState} Sales Tax";
|
|
||||||
$this->tax_name1 = "Sales Tax";
|
$this->tax_name1 = "Sales Tax";
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -13,9 +13,10 @@ namespace App\Events\Payment;
|
|||||||
|
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
use App\Models\ClientContact;
|
||||||
use Illuminate\Foundation\Events\Dispatchable;
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class PaymentWasEmailed.
|
* Class PaymentWasEmailed.
|
||||||
@ -24,26 +25,15 @@ class PaymentWasEmailed
|
|||||||
{
|
{
|
||||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Payment
|
|
||||||
*/
|
|
||||||
public $payment;
|
|
||||||
|
|
||||||
public $company;
|
|
||||||
|
|
||||||
public $event_vars;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new event instance.
|
* Create a new event instance.
|
||||||
*
|
*
|
||||||
* @param Payment $payment
|
* @param Payment $payment
|
||||||
* @param Company $company
|
* @param Company $company
|
||||||
|
* @param ClientContact $contact
|
||||||
* @param array $event_vars
|
* @param array $event_vars
|
||||||
*/
|
*/
|
||||||
public function __construct(Payment $payment, Company $company, array $event_vars)
|
public function __construct(public Payment $payment, public Company $company, public ClientContact $contact, public array $event_vars)
|
||||||
{
|
{
|
||||||
$this->payment = $payment;
|
|
||||||
$this->company = $company;
|
|
||||||
$this->event_vars = $event_vars;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ class Handler extends ExceptionHandler
|
|||||||
|
|
||||||
if($exception instanceof ThrottleRequestsException && class_exists(\Modules\Admin\Events\ThrottledExceptionRaised::class)) {
|
if($exception instanceof ThrottleRequestsException && class_exists(\Modules\Admin\Events\ThrottledExceptionRaised::class)) {
|
||||||
$uri = urldecode(request()->getRequestUri());
|
$uri = urldecode(request()->getRequestUri());
|
||||||
event(new \Modules\Admin\Events\ThrottledExceptionRaised(auth()->user()?->account?->key, $uri, request()->ip()));
|
// event(new \Modules\Admin\Events\ThrottledExceptionRaised(auth()->user()?->account?->key, $uri, request()->ip()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Integration::configureScope(function (Scope $scope): void {
|
Integration::configureScope(function (Scope $scope): void {
|
||||||
|
41
app/Exceptions/QuoteConversion.php
Normal file
41
app/Exceptions/QuoteConversion.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace App\Exceptions;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
|
||||||
|
class QuoteConversion extends Exception
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Report the exception.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function report()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the exception into an HTTP response.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function render($request)
|
||||||
|
{
|
||||||
|
return response()->json(['message' => 'This quote has already been converted. Cannot convert again.'], 400);
|
||||||
|
}
|
||||||
|
}
|
@ -11,11 +11,18 @@
|
|||||||
|
|
||||||
namespace App\Export\CSV;
|
namespace App\Export\CSV;
|
||||||
|
|
||||||
|
use App\Utils\Number;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
|
use App\Models\GatewayType;
|
||||||
|
use App\Models\Payment;
|
||||||
|
use League\Fractal\Manager;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use App\Transformers\ClientTransformer;
|
||||||
|
use App\Transformers\PaymentTransformer;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use League\Fractal\Serializer\ArraySerializer;
|
||||||
|
|
||||||
class BaseExport
|
class BaseExport
|
||||||
{
|
{
|
||||||
@ -35,6 +42,161 @@ class BaseExport
|
|||||||
|
|
||||||
public array $forced_keys = [];
|
public array $forced_keys = [];
|
||||||
|
|
||||||
|
protected array $client_report_keys = [
|
||||||
|
"name" => "client.name",
|
||||||
|
"user" => "client.user_id",
|
||||||
|
"balance" => "client.balance",
|
||||||
|
"paid_to_date" => "client.paid_to_date",
|
||||||
|
"currency" => "client.currency_id",
|
||||||
|
"website" => "client.website",
|
||||||
|
"private_notes" => "client.private_notes",
|
||||||
|
"industry" => "client.industry_id",
|
||||||
|
"size" => "client.size_id",
|
||||||
|
"work_phone" => "client.phone",
|
||||||
|
"address1" => "client.address1",
|
||||||
|
"address2" => "client.address2",
|
||||||
|
"city" => "client.city",
|
||||||
|
"state" => "client.state",
|
||||||
|
"postal_code" => "client.postal_code",
|
||||||
|
"country" => "client.country_id",
|
||||||
|
"custom_value4" => "contact.custom_value4",
|
||||||
|
"shipping_address1" => "client.shipping_address1",
|
||||||
|
"shipping_address2" => "client.shipping_address2",
|
||||||
|
"shipping_city" => "client.shipping_city",
|
||||||
|
"shipping_state" => "client.shipping_state",
|
||||||
|
"shipping_postal_code" => "client.shipping_postal_code",
|
||||||
|
"shipping_country" => "client.shipping_country_id",
|
||||||
|
"payment_terms" => "client.payment_terms",
|
||||||
|
"vat_number" => "client.vat_number",
|
||||||
|
"id_number" => "client.id_number",
|
||||||
|
"public_notes" => "client.public_notes",
|
||||||
|
"phone" => "contact.phone",
|
||||||
|
"first_name" => "contact.first_name",
|
||||||
|
"last_name" => "contact.last_name",
|
||||||
|
"email" => "contact.email",
|
||||||
|
];
|
||||||
|
|
||||||
|
protected array $invoice_report_keys = [
|
||||||
|
"invoice_number" => "invoice.number",
|
||||||
|
"amount" => "invoice.amount",
|
||||||
|
"balance" => "invoice.balance",
|
||||||
|
"paid_to_date" => "invoice.paid_to_date",
|
||||||
|
"po_number" => "invoice.po_number",
|
||||||
|
"date" => "invoice.date",
|
||||||
|
"due_date" => "invoice.due_date",
|
||||||
|
"terms" => "invoice.terms",
|
||||||
|
"footer" => "invoice.footer",
|
||||||
|
"status" => "invoice.status",
|
||||||
|
"public_notes" => "invoice.public_notes",
|
||||||
|
"private_notes" => "invoice.private_notes",
|
||||||
|
"uses_inclusive_taxes" => "invoice.uses_inclusive_taxes",
|
||||||
|
"is_amount_discount" => "invoice.is_amount_discount",
|
||||||
|
"partial" => "invoice.partial",
|
||||||
|
"partial_due_date" => "invoice.partial_due_date",
|
||||||
|
"surcharge1" => "invoice.custom_surcharge1",
|
||||||
|
"surcharge2" => "invoice.custom_surcharge2",
|
||||||
|
"surcharge3" => "invoice.custom_surcharge3",
|
||||||
|
"surcharge4" => "invoice.custom_surcharge4",
|
||||||
|
"exchange_rate" => "invoice.exchange_rate",
|
||||||
|
"tax_amount" => "invoice.total_taxes",
|
||||||
|
"assigned_user" => "invoice.assigned_user_id",
|
||||||
|
"user" => "invoice.user_id",
|
||||||
|
];
|
||||||
|
|
||||||
|
protected array $item_report_keys = [
|
||||||
|
"quantity" => "item.quantity",
|
||||||
|
"cost" => "item.cost",
|
||||||
|
"product_key" => "item.product_key",
|
||||||
|
"notes" => "item.notes",
|
||||||
|
"item_tax1" => "item.tax_name1",
|
||||||
|
"item_tax_rate1" => "item.tax_rate1",
|
||||||
|
"item_tax2" => "item.tax_name2",
|
||||||
|
"item_tax_rate2" => "item.tax_rate2",
|
||||||
|
"item_tax3" => "item.tax_name3",
|
||||||
|
"item_tax_rate3" => "item.tax_rate3",
|
||||||
|
"custom_value1" => "item.custom_value1",
|
||||||
|
"custom_value2" => "item.custom_value2",
|
||||||
|
"custom_value3" => "item.custom_value3",
|
||||||
|
"custom_value4" => "item.custom_value4",
|
||||||
|
"discount" => "item.discount",
|
||||||
|
"type" => "item.type_id",
|
||||||
|
"tax_category" => "item.tax_id",
|
||||||
|
];
|
||||||
|
|
||||||
|
protected array $quote_report_keys = [
|
||||||
|
"quote_number" => "quote.number",
|
||||||
|
"amount" => "quote.amount",
|
||||||
|
"balance" => "quote.balance",
|
||||||
|
"paid_to_date" => "quote.paid_to_date",
|
||||||
|
"po_number" => "quote.po_number",
|
||||||
|
"date" => "quote.date",
|
||||||
|
"due_date" => "quote.due_date",
|
||||||
|
"terms" => "quote.terms",
|
||||||
|
"footer" => "quote.footer",
|
||||||
|
"status" => "quote.status",
|
||||||
|
"public_notes" => "quote.public_notes",
|
||||||
|
"private_notes" => "quote.private_notes",
|
||||||
|
"uses_inclusive_taxes" => "quote.uses_inclusive_taxes",
|
||||||
|
"is_amount_discount" => "quote.is_amount_discount",
|
||||||
|
"partial" => "quote.partial",
|
||||||
|
"partial_due_date" => "quote.partial_due_date",
|
||||||
|
"surcharge1" => "quote.custom_surcharge1",
|
||||||
|
"surcharge2" => "quote.custom_surcharge2",
|
||||||
|
"surcharge3" => "quote.custom_surcharge3",
|
||||||
|
"surcharge4" => "quote.custom_surcharge4",
|
||||||
|
"exchange_rate" => "quote.exchange_rate",
|
||||||
|
"tax_amount" => "quote.total_taxes",
|
||||||
|
"assigned_user" => "quote.assigned_user_id",
|
||||||
|
"user" => "quote.user_id",
|
||||||
|
];
|
||||||
|
|
||||||
|
protected array $credit_report_keys = [
|
||||||
|
"credit_number" => "credit.number",
|
||||||
|
"amount" => "credit.amount",
|
||||||
|
"balance" => "credit.balance",
|
||||||
|
"paid_to_date" => "credit.paid_to_date",
|
||||||
|
"po_number" => "credit.po_number",
|
||||||
|
"date" => "credit.date",
|
||||||
|
"due_date" => "credit.due_date",
|
||||||
|
"terms" => "credit.terms",
|
||||||
|
"footer" => "credit.footer",
|
||||||
|
"status" => "credit.status",
|
||||||
|
"public_notes" => "credit.public_notes",
|
||||||
|
"private_notes" => "credit.private_notes",
|
||||||
|
"uses_inclusive_taxes" => "credit.uses_inclusive_taxes",
|
||||||
|
"is_amount_discount" => "credit.is_amount_discount",
|
||||||
|
"partial" => "credit.partial",
|
||||||
|
"partial_due_date" => "credit.partial_due_date",
|
||||||
|
"surcharge1" => "credit.custom_surcharge1",
|
||||||
|
"surcharge2" => "credit.custom_surcharge2",
|
||||||
|
"surcharge3" => "credit.custom_surcharge3",
|
||||||
|
"surcharge4" => "credit.custom_surcharge4",
|
||||||
|
"exchange_rate" => "credit.exchange_rate",
|
||||||
|
"tax_amount" => "credit.total_taxes",
|
||||||
|
"assigned_user" => "credit.assigned_user_id",
|
||||||
|
"user" => "credit.user_id",
|
||||||
|
];
|
||||||
|
|
||||||
|
protected array $payment_report_keys = [
|
||||||
|
"date" => "payment.date",
|
||||||
|
"amount" => "payment.amount",
|
||||||
|
"refunded" => "payment.refunded",
|
||||||
|
"applied" => "payment.applied",
|
||||||
|
"transaction_reference" => "payment.transaction_reference",
|
||||||
|
"currency" => "payment.currency",
|
||||||
|
"exchange_rate" => "payment.exchange_rate",
|
||||||
|
"number" => "payment.number",
|
||||||
|
"method" => "payment.method",
|
||||||
|
"status" => "payment.status",
|
||||||
|
"private_notes" => "payment.private_notes",
|
||||||
|
"custom_value1" => "payment.custom_value1",
|
||||||
|
"custom_value2" => "payment.custom_value2",
|
||||||
|
"custom_value3" => "payment.custom_value3",
|
||||||
|
"custom_value4" => "payment.custom_value4",
|
||||||
|
"user" => "payment.user_id",
|
||||||
|
"assigned_user" => "payment.assigned_user_id",
|
||||||
|
];
|
||||||
|
|
||||||
protected function filterByClients($query)
|
protected function filterByClients($query)
|
||||||
{
|
{
|
||||||
if (isset($this->input['client_id']) && $this->input['client_id'] != 'all') {
|
if (isset($this->input['client_id']) && $this->input['client_id'] != 'all') {
|
||||||
@ -50,6 +212,167 @@ class BaseExport
|
|||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function resolveKey($key, $entity, $transformer) :string
|
||||||
|
{
|
||||||
|
$parts = explode(".", $key);
|
||||||
|
|
||||||
|
if(!is_array($parts) || count($parts) < 2)
|
||||||
|
return '';
|
||||||
|
|
||||||
|
match($parts[0]) {
|
||||||
|
'contact' => $value = $this->resolveClientContactKey($parts[1], $entity, $transformer),
|
||||||
|
'client' => $value = $this->resolveClientKey($parts[1], $entity, $transformer),
|
||||||
|
'invoice' => $value = $this->resolveInvoiceKey($parts[1], $entity, $transformer),
|
||||||
|
'payment' => $value = $this->resolvePaymentKey($parts[1], $entity, $transformer),
|
||||||
|
default => $value = ''
|
||||||
|
};
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resolveClientContactKey($column, $entity, $transformer)
|
||||||
|
{
|
||||||
|
|
||||||
|
$primary_contact = $entity->client->primary_contact()->first() ?? $entity->client->contacts()->first();
|
||||||
|
|
||||||
|
return $primary_contact?->{$column} ?? '';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resolveClientKey($column, $entity, $transformer)
|
||||||
|
{
|
||||||
|
$transformed_client = $transformer->includeClient($entity);
|
||||||
|
|
||||||
|
$manager = new Manager();
|
||||||
|
$manager->setSerializer(new ArraySerializer());
|
||||||
|
$transformed_client = $manager->createData($transformed_client)->toArray();
|
||||||
|
|
||||||
|
if($column == 'name')
|
||||||
|
return $transformed_client['display_name'];
|
||||||
|
|
||||||
|
if($column == 'user_id')
|
||||||
|
return $entity->client->user->present()->name();
|
||||||
|
|
||||||
|
if($column == 'country_id')
|
||||||
|
return $entity->client->country ? ctrans("texts.country_{$entity->client->country->name}") : '';
|
||||||
|
|
||||||
|
if($column == 'shipping_country_id')
|
||||||
|
return $entity->client->shipping_country ? ctrans("texts.country_{$entity->client->shipping_country->name}") : '';
|
||||||
|
|
||||||
|
if($column == 'size_id')
|
||||||
|
return $entity->client->size?->name ?? '';
|
||||||
|
|
||||||
|
if($column == 'industry_id')
|
||||||
|
return $entity->client->industry?->name ?? '';
|
||||||
|
|
||||||
|
if ($column == 'currency_id') {
|
||||||
|
return $entity->client->currency() ? $entity->client->currency()->code : $entity->company->currency()->code;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($column == 'client.payment_terms') {
|
||||||
|
return $entity->client->getSetting('payment_terms');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(array_key_exists($column, $transformed_client))
|
||||||
|
return $transformed_client[$column];
|
||||||
|
|
||||||
|
nlog("export: Could not resolve client key: {$column}");
|
||||||
|
|
||||||
|
return '';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resolveInvoiceKey($column, $entity, $transformer)
|
||||||
|
{
|
||||||
|
nlog("searching for {$column}");
|
||||||
|
|
||||||
|
if($transformer instanceof PaymentTransformer) {
|
||||||
|
$transformed_invoices = $transformer->includeInvoices($entity);
|
||||||
|
|
||||||
|
$manager = new Manager();
|
||||||
|
$manager->setSerializer(new ArraySerializer());
|
||||||
|
$transformed_invoices = $manager->createData($transformed_invoices)->toArray();
|
||||||
|
|
||||||
|
if(!isset($transformed_invoices['App\\Models\\Invoice']))
|
||||||
|
return '';
|
||||||
|
|
||||||
|
$transformed_invoices = $transformed_invoices['App\\Models\\Invoice'];
|
||||||
|
|
||||||
|
if(count($transformed_invoices) == 1 && array_key_exists($column, $transformed_invoices[0]))
|
||||||
|
return $transformed_invoices[0][$column];
|
||||||
|
|
||||||
|
if(count($transformed_invoices) > 1 && array_key_exists($column, $transformed_invoices[0]))
|
||||||
|
return implode(', ', array_column($transformed_invoices, $column));
|
||||||
|
|
||||||
|
return "";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$transformed_invoice = $transformer->transform($entity);
|
||||||
|
|
||||||
|
if($column == 'status')
|
||||||
|
return $entity->stringStatus($entity->status_id);
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resolvePaymentKey($column, $entity, $transformer)
|
||||||
|
{
|
||||||
|
if($entity instanceof Payment){
|
||||||
|
|
||||||
|
$transformed_payment = $transformer->transform($entity);
|
||||||
|
|
||||||
|
if(array_key_exists($column, $transformed_payment)) {
|
||||||
|
return $transformed_payment[$column];
|
||||||
|
} elseif (array_key_exists(str_replace("payment.", "", $column), $transformed_payment)) {
|
||||||
|
return $transformed_payment[$column];
|
||||||
|
}
|
||||||
|
|
||||||
|
nlog("export: Could not resolve payment key: {$column}");
|
||||||
|
|
||||||
|
return '';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if($column == 'amount')
|
||||||
|
return $entity->payments()->exists() ? Number::formatMoney($entity->payments()->sum('paymentables.amount'), $entity->company) : ctrans('texts.unpaid');
|
||||||
|
|
||||||
|
if($column == 'refunded') {
|
||||||
|
return $entity->payments()->exists() ? Number::formatMoney($entity->payments()->sum('paymentables.refunded'), $entity->company) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($column == 'applied') {
|
||||||
|
$refunded = $entity->payments()->sum('paymentables.refunded');
|
||||||
|
$amount = $entity->payments()->sum('paymentables.amount');
|
||||||
|
|
||||||
|
return $entity->payments()->exists() ? Number::formatMoney(($amount - $refunded), $entity->company) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$payment = $entity->payments()->first();
|
||||||
|
|
||||||
|
if(!$payment)
|
||||||
|
return '';
|
||||||
|
|
||||||
|
if($column == 'method')
|
||||||
|
return $payment->translatedType();
|
||||||
|
|
||||||
|
if($column == 'currency')
|
||||||
|
return $payment?->currency?->code ?? '';
|
||||||
|
|
||||||
|
$payment_transformer = new PaymentTransformer();
|
||||||
|
$transformed_payment = $payment_transformer->transform($payment);
|
||||||
|
|
||||||
|
if($column == 'status'){
|
||||||
|
return $payment->stringStatus($transformed_payment['status_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(array_key_exists($column, $transformed_payment))
|
||||||
|
return $transformed_payment[$column];
|
||||||
|
|
||||||
|
return '';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
protected function addInvoiceStatusFilter($query, $status): Builder
|
protected function addInvoiceStatusFilter($query, $status): Builder
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -173,14 +496,53 @@ class BaseExport
|
|||||||
$header = [];
|
$header = [];
|
||||||
|
|
||||||
foreach (array_merge($this->input['report_keys'], $this->forced_keys) as $value) {
|
foreach (array_merge($this->input['report_keys'], $this->forced_keys) as $value) {
|
||||||
|
|
||||||
$key = array_search($value, $this->entity_keys);
|
$key = array_search($value, $this->entity_keys);
|
||||||
|
|
||||||
|
$prefix = '';
|
||||||
|
|
||||||
|
if(!$key) {
|
||||||
|
$prefix = stripos($value, 'client.') !== false ? ctrans('texts.client') : ctrans('texts.contact');
|
||||||
|
$key = array_search($value, $this->client_report_keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$key) {
|
||||||
|
$prefix = ctrans('texts.invoice');
|
||||||
|
$key = array_search($value, $this->invoice_report_keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$key) {
|
||||||
|
$prefix = ctrans('texts.payment');
|
||||||
|
$key = array_search($value, $this->payment_report_keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(!$key) {
|
||||||
|
$prefix = ctrans('texts.quote');
|
||||||
|
$key = array_search($value, $this->quote_report_keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$key) {
|
||||||
|
$prefix = ctrans('texts.credit');
|
||||||
|
$key = array_search($value, $this->credit_report_keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$key) {
|
||||||
|
$prefix = ctrans('texts.item');
|
||||||
|
$key = array_search($value, $this->item_report_keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$key) {
|
||||||
|
$prefix = '';
|
||||||
|
}
|
||||||
|
|
||||||
$key = str_replace('item.', '', $key);
|
$key = str_replace('item.', '', $key);
|
||||||
$key = str_replace('invoice.', '', $key);
|
$key = str_replace('invoice.', '', $key);
|
||||||
$key = str_replace('client.', '', $key);
|
$key = str_replace('client.', '', $key);
|
||||||
$key = str_replace('contact.', '', $key);
|
$key = str_replace('contact.', '', $key);
|
||||||
|
$key = str_replace('payment.', '', $key);
|
||||||
|
|
||||||
$header[] = ctrans("texts.{$key}");
|
$header[] = "{$prefix} " . ctrans("texts.{$key}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $header;
|
return $header;
|
||||||
|
@ -143,9 +143,9 @@ class ClientExport extends BaseExport
|
|||||||
|
|
||||||
$keyval = array_search($key, $this->entity_keys);
|
$keyval = array_search($key, $this->entity_keys);
|
||||||
|
|
||||||
if ($parts[0] == 'client' && array_key_exists($parts[1], $transformed_client)) {
|
if (is_array($parts) && $parts[0] == 'client' && array_key_exists($parts[1], $transformed_client)) {
|
||||||
$entity[$keyval] = $transformed_client[$parts[1]];
|
$entity[$keyval] = $transformed_client[$parts[1]];
|
||||||
} elseif ($parts[0] == 'contact' && array_key_exists($parts[1], $transformed_contact)) {
|
} elseif (is_array($parts) && $parts[0] == 'contact' && array_key_exists($parts[1], $transformed_contact)) {
|
||||||
$entity[$keyval] = $transformed_contact[$parts[1]];
|
$entity[$keyval] = $transformed_contact[$parts[1]];
|
||||||
} else {
|
} else {
|
||||||
$entity[$keyval] = '';
|
$entity[$keyval] = '';
|
||||||
|
@ -123,10 +123,19 @@ class CreditExport extends BaseExport
|
|||||||
foreach (array_values($this->input['report_keys']) as $key) {
|
foreach (array_values($this->input['report_keys']) as $key) {
|
||||||
$keyval = array_search($key, $this->entity_keys);
|
$keyval = array_search($key, $this->entity_keys);
|
||||||
|
|
||||||
|
if(!$keyval)
|
||||||
|
$keyval = array_search(str_replace("credit.", "", $key), $this->entity_keys) ?? $key;
|
||||||
|
|
||||||
|
if(!$keyval)
|
||||||
|
$keyval = $key;
|
||||||
|
|
||||||
if (array_key_exists($key, $transformed_credit)) {
|
if (array_key_exists($key, $transformed_credit)) {
|
||||||
$entity[$keyval] = $transformed_credit[$key];
|
$entity[$keyval] = $transformed_credit[$key];
|
||||||
} else {
|
} elseif (array_key_exists($keyval, $transformed_credit)) {
|
||||||
$entity[$keyval] = '';
|
$entity[$keyval] = $transformed_credit[$keyval];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$entity[$keyval] = $this->resolveKey($keyval, $credit, $this->credit_transformer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,9 +147,9 @@ class CreditExport extends BaseExport
|
|||||||
if (in_array('country_id', $this->input['report_keys'])) {
|
if (in_array('country_id', $this->input['report_keys'])) {
|
||||||
$entity['country'] = $credit->client->country ? ctrans("texts.country_{$credit->client->country->name}") : '';
|
$entity['country'] = $credit->client->country ? ctrans("texts.country_{$credit->client->country->name}") : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_array('currency_id', $this->input['report_keys'])) {
|
if (in_array('currency_id', $this->input['report_keys'])) {
|
||||||
$entity['currency_id'] = $credit->client->currency() ? $credit->client->currency()->code : $invoice->company->currency()->code;
|
$entity['currency_id'] = $credit->client->currency() ? $credit->client->currency()->code : $credit->company->currency()->code;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_array('invoice_id', $this->input['report_keys'])) {
|
if (in_array('invoice_id', $this->input['report_keys'])) {
|
||||||
@ -155,6 +164,10 @@ class CreditExport extends BaseExport
|
|||||||
$entity['status'] = $credit->stringStatus($credit->status_id);
|
$entity['status'] = $credit->stringStatus($credit->status_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(in_array('credit.status', $this->input['report_keys'])) {
|
||||||
|
$entity['credit.status'] = $credit->stringStatus($credit->status_id);
|
||||||
|
}
|
||||||
|
|
||||||
return $entity;
|
return $entity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,7 @@ class InvoiceExport extends BaseExport
|
|||||||
'project',
|
'project',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
public function __construct(Company $company, array $input)
|
public function __construct(Company $company, array $input)
|
||||||
{
|
{
|
||||||
$this->company = $company;
|
$this->company = $company;
|
||||||
@ -134,10 +135,21 @@ class InvoiceExport extends BaseExport
|
|||||||
foreach (array_values($this->input['report_keys']) as $key) {
|
foreach (array_values($this->input['report_keys']) as $key) {
|
||||||
$keyval = array_search($key, $this->entity_keys);
|
$keyval = array_search($key, $this->entity_keys);
|
||||||
|
|
||||||
|
if(!$keyval) {
|
||||||
|
$keyval = array_search(str_replace("invoice.", "", $key), $this->entity_keys) ?? $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$keyval) {
|
||||||
|
$keyval = $key;
|
||||||
|
}
|
||||||
|
|
||||||
if (array_key_exists($key, $transformed_invoice)) {
|
if (array_key_exists($key, $transformed_invoice)) {
|
||||||
$entity[$keyval] = $transformed_invoice[$key];
|
$entity[$keyval] = $transformed_invoice[$key];
|
||||||
} else {
|
} elseif (array_key_exists($keyval, $transformed_invoice)) {
|
||||||
$entity[$keyval] = '';
|
$entity[$keyval] = $transformed_invoice[$keyval];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$entity[$keyval] = $this->resolveKey($keyval, $invoice, $this->invoice_transformer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,15 +174,15 @@ class InvoiceExport extends BaseExport
|
|||||||
$entity['status'] = $invoice->stringStatus($invoice->status_id);
|
$entity['status'] = $invoice->stringStatus($invoice->status_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
$payment_exists = $invoice->payments()->exists();
|
// $payment_exists = $invoice->payments()->exists();
|
||||||
|
|
||||||
$entity['payment_number'] = $payment_exists ? $invoice->payments()->pluck('number')->implode(',') : '';
|
// $entity['payment_number'] = $payment_exists ? $invoice->payments()->pluck('number')->implode(',') : '';
|
||||||
|
|
||||||
$entity['payment_date'] = $payment_exists ? $invoice->payments()->pluck('date')->implode(',') : '';
|
// $entity['payment_date'] = $payment_exists ? $invoice->payments()->pluck('date')->implode(',') : '';
|
||||||
|
|
||||||
$entity['payment_amount'] = $payment_exists ? Number::formatMoney($invoice->payments()->sum('paymentables.amount'), $invoice->company) : ctrans('texts.unpaid');
|
// $entity['payment_amount'] = $payment_exists ? Number::formatMoney($invoice->payments()->sum('paymentables.amount'), $invoice->company) : ctrans('texts.unpaid');
|
||||||
|
|
||||||
$entity['method'] = $payment_exists ? $invoice->payments()->first()->translatedType() : "";
|
// $entity['method'] = $payment_exists ? $invoice->payments()->first()->translatedType() : "";
|
||||||
|
|
||||||
return $entity;
|
return $entity;
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,8 @@ class InvoiceItemExport extends BaseExport
|
|||||||
|
|
||||||
public Writer $csv;
|
public Writer $csv;
|
||||||
|
|
||||||
|
private bool $force_keys = false;
|
||||||
|
|
||||||
public array $entity_keys = [
|
public array $entity_keys = [
|
||||||
'amount' => 'amount',
|
'amount' => 'amount',
|
||||||
'balance' => 'balance',
|
'balance' => 'balance',
|
||||||
@ -67,9 +69,9 @@ class InvoiceItemExport extends BaseExport
|
|||||||
'total_taxes' => 'total_taxes',
|
'total_taxes' => 'total_taxes',
|
||||||
'currency' => 'currency_id',
|
'currency' => 'currency_id',
|
||||||
'quantity' => 'item.quantity',
|
'quantity' => 'item.quantity',
|
||||||
'unit_cost' => 'item.cost',
|
'cost' => 'item.cost',
|
||||||
'product_key' => 'item.product_key',
|
'product_key' => 'item.product_key',
|
||||||
'cost' => 'item.product_cost',
|
'buy_price' => 'item.product_cost',
|
||||||
'notes' => 'item.notes',
|
'notes' => 'item.notes',
|
||||||
'discount' => 'item.discount',
|
'discount' => 'item.discount',
|
||||||
'is_amount_discount' => 'item.is_amount_discount',
|
'is_amount_discount' => 'item.is_amount_discount',
|
||||||
@ -85,6 +87,8 @@ class InvoiceItemExport extends BaseExport
|
|||||||
'invoice2' => 'item.custom_value2',
|
'invoice2' => 'item.custom_value2',
|
||||||
'invoice3' => 'item.custom_value3',
|
'invoice3' => 'item.custom_value3',
|
||||||
'invoice4' => 'item.custom_value4',
|
'invoice4' => 'item.custom_value4',
|
||||||
|
'tax_category' => 'item.tax_id',
|
||||||
|
'type' => 'item.type_id',
|
||||||
];
|
];
|
||||||
|
|
||||||
private array $decorate_keys = [
|
private array $decorate_keys = [
|
||||||
@ -112,6 +116,7 @@ class InvoiceItemExport extends BaseExport
|
|||||||
$this->csv = Writer::createFromString();
|
$this->csv = Writer::createFromString();
|
||||||
|
|
||||||
if (count($this->input['report_keys']) == 0) {
|
if (count($this->input['report_keys']) == 0) {
|
||||||
|
$this->force_keys = true;
|
||||||
$this->input['report_keys'] = array_values($this->entity_keys);
|
$this->input['report_keys'] = array_values($this->entity_keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,24 +145,36 @@ class InvoiceItemExport extends BaseExport
|
|||||||
$transformed_items = [];
|
$transformed_items = [];
|
||||||
|
|
||||||
foreach ($invoice->line_items as $item) {
|
foreach ($invoice->line_items as $item) {
|
||||||
$item_array = [];
|
$item_array = [];
|
||||||
|
|
||||||
foreach (array_values($this->input['report_keys']) as $key) {
|
foreach (array_values($this->input['report_keys']) as $key) { //items iterator produces item array
|
||||||
|
|
||||||
if (str_contains($key, "item.")) {
|
if (str_contains($key, "item.")) {
|
||||||
|
|
||||||
$key = str_replace("item.", "", $key);
|
$key = str_replace("item.", "", $key);
|
||||||
|
|
||||||
|
$keyval = $key;
|
||||||
|
|
||||||
|
$keyval = str_replace("custom_value", "invoice", $key);
|
||||||
|
|
||||||
|
if($key == 'type_id')
|
||||||
|
$keyval = 'type';
|
||||||
|
|
||||||
|
if($key == 'tax_id')
|
||||||
|
$keyval = 'tax_category';
|
||||||
|
|
||||||
if (property_exists($item, $key)) {
|
if (property_exists($item, $key)) {
|
||||||
$item_array[$key] = $item->{$key};
|
$item_array[$keyval] = $item->{$key};
|
||||||
} else {
|
} else {
|
||||||
$item_array[$key] = '';
|
$item_array[$keyval] = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$entity = [];
|
$entity = [];
|
||||||
|
|
||||||
foreach (array_values($this->input['report_keys']) as $key) {
|
foreach (array_values($this->input['report_keys']) as $key) { //create an array of report keys only
|
||||||
$keyval = array_search($key, $this->entity_keys);
|
$keyval = array_search($key, $this->entity_keys);
|
||||||
|
|
||||||
if (array_key_exists($key, $transformed_items)) {
|
if (array_key_exists($key, $transformed_items)) {
|
||||||
$entity[$keyval] = $transformed_items[$key];
|
$entity[$keyval] = $transformed_items[$key];
|
||||||
@ -182,10 +199,21 @@ class InvoiceItemExport extends BaseExport
|
|||||||
foreach (array_values($this->input['report_keys']) as $key) {
|
foreach (array_values($this->input['report_keys']) as $key) {
|
||||||
$keyval = array_search($key, $this->entity_keys);
|
$keyval = array_search($key, $this->entity_keys);
|
||||||
|
|
||||||
|
if(!$keyval) {
|
||||||
|
$keyval = array_search(str_replace("invoice.", "", $key), $this->entity_keys) ?? $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$keyval) {
|
||||||
|
$keyval = $key;
|
||||||
|
}
|
||||||
|
|
||||||
if (array_key_exists($key, $transformed_invoice)) {
|
if (array_key_exists($key, $transformed_invoice)) {
|
||||||
$entity[$keyval] = $transformed_invoice[$key];
|
$entity[$keyval] = $transformed_invoice[$key];
|
||||||
} else {
|
} elseif (array_key_exists($keyval, $transformed_invoice)) {
|
||||||
$entity[$keyval] = "";
|
$entity[$keyval] = $transformed_invoice[$keyval];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$entity[$keyval] = $this->resolveKey($keyval, $invoice, $this->invoice_transformer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,13 +226,20 @@ class InvoiceItemExport extends BaseExport
|
|||||||
$entity['currency'] = $invoice->client->currency() ? $invoice->client->currency()->code : $invoice->company->currency()->code;
|
$entity['currency'] = $invoice->client->currency() ? $invoice->client->currency()->code : $invoice->company->currency()->code;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if(in_array('client_id', $this->input['report_keys']))
|
if(array_key_exists('type', $entity)) {
|
||||||
$entity['client'] = $invoice->client->present()->name();
|
$entity['type'] = $invoice->typeIdString($entity['type']);
|
||||||
$entity['client_id_number'] = $invoice->client->id_number;
|
}
|
||||||
$entity['client_number'] = $invoice->client->number;
|
|
||||||
|
|
||||||
// if(in_array('status_id', $this->input['report_keys']))
|
if(array_key_exists('tax_category', $entity)) {
|
||||||
$entity['status'] = $invoice->stringStatus($invoice->status_id);
|
$entity['tax_category'] = $invoice->taxTypeString($entity['tax_category']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->force_keys) {
|
||||||
|
$entity['client'] = $invoice->client->present()->name();
|
||||||
|
$entity['client_id_number'] = $invoice->client->id_number;
|
||||||
|
$entity['client_number'] = $invoice->client->number;
|
||||||
|
$entity['status'] = $invoice->stringStatus($invoice->status_id);
|
||||||
|
}
|
||||||
|
|
||||||
return $entity;
|
return $entity;
|
||||||
}
|
}
|
||||||
|
@ -112,10 +112,21 @@ class PaymentExport extends BaseExport
|
|||||||
foreach (array_values($this->input['report_keys']) as $key) {
|
foreach (array_values($this->input['report_keys']) as $key) {
|
||||||
$keyval = array_search($key, $this->entity_keys);
|
$keyval = array_search($key, $this->entity_keys);
|
||||||
|
|
||||||
|
if(!$keyval) {
|
||||||
|
$keyval = array_search(str_replace("payment.", "", $key), $this->entity_keys) ?? $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$keyval) {
|
||||||
|
$keyval = $key;
|
||||||
|
}
|
||||||
|
|
||||||
if (array_key_exists($key, $transformed_entity)) {
|
if (array_key_exists($key, $transformed_entity)) {
|
||||||
$entity[$keyval] = $transformed_entity[$key];
|
$entity[$keyval] = $transformed_entity[$key];
|
||||||
} else {
|
} elseif (array_key_exists($keyval, $transformed_entity)) {
|
||||||
$entity[$keyval] = '';
|
$entity[$keyval] = $transformed_entity[$keyval];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$entity[$keyval] = $this->resolveKey($keyval, $payment, $this->entity_transformer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,6 +151,10 @@ class PaymentExport extends BaseExport
|
|||||||
$entity['currency'] = $payment->currency()->exists() ? $payment->currency->code : '';
|
$entity['currency'] = $payment->currency()->exists() ? $payment->currency->code : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (in_array('payment.currency', $this->input['report_keys'])) {
|
||||||
|
$entity['payment.currency'] = $payment->currency()->exists() ? $payment->currency->code : '';
|
||||||
|
}
|
||||||
|
|
||||||
if (in_array('exchange_currency_id', $this->input['report_keys'])) {
|
if (in_array('exchange_currency_id', $this->input['report_keys'])) {
|
||||||
$entity['exchange_currency'] = $payment->exchange_currency()->exists() ? $payment->exchange_currency->code : '';
|
$entity['exchange_currency'] = $payment->exchange_currency()->exists() ? $payment->exchange_currency->code : '';
|
||||||
}
|
}
|
||||||
@ -152,11 +167,19 @@ class PaymentExport extends BaseExport
|
|||||||
$entity['type'] = $payment->translatedType();
|
$entity['type'] = $payment->translatedType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (in_array('payment.method', $this->input['report_keys'])) {
|
||||||
|
$entity['payment.method'] = $payment->translatedType();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array('payment.status', $this->input['report_keys'])) {
|
||||||
|
$entity['payment.status'] = $payment->stringStatus($payment->status_id);
|
||||||
|
}
|
||||||
|
|
||||||
if (in_array('gateway_type_id', $this->input['report_keys'])) {
|
if (in_array('gateway_type_id', $this->input['report_keys'])) {
|
||||||
$entity['gateway'] = $payment->gateway_type ? $payment->gateway_type->name : 'Unknown Type';
|
$entity['gateway'] = $payment->gateway_type ? $payment->gateway_type->name : 'Unknown Type';
|
||||||
}
|
}
|
||||||
|
|
||||||
$entity['invoices'] = $payment->invoices()->exists() ? $payment->invoices->pluck('number')->implode(',') : '';
|
// $entity['invoices'] = $payment->invoices()->exists() ? $payment->invoices->pluck('number')->implode(',') : '';
|
||||||
|
|
||||||
return $entity;
|
return $entity;
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,11 @@ class RecurringExpenseToExpenseFactory
|
|||||||
|
|
||||||
$replacements = [
|
$replacements = [
|
||||||
'literal' => [
|
'literal' => [
|
||||||
|
':MONTHYEAR' => \sprintf(
|
||||||
|
'%s %s',
|
||||||
|
Carbon::createFromDate(now()->year, now()->month)->translatedFormat('F'),
|
||||||
|
now()->year,
|
||||||
|
),
|
||||||
':MONTH' => Carbon::createFromDate(now()->year, now()->month)->translatedFormat('F'),
|
':MONTH' => Carbon::createFromDate(now()->year, now()->month)->translatedFormat('F'),
|
||||||
':YEAR' => now()->year,
|
':YEAR' => now()->year,
|
||||||
':QUARTER' => 'Q'.now()->quarter,
|
':QUARTER' => 'Q'.now()->quarter,
|
||||||
@ -240,6 +245,17 @@ class RecurringExpenseToExpenseFactory
|
|||||||
$output = \Carbon\Carbon::create()->month($output)->translatedFormat('F');
|
$output = \Carbon\Carbon::create()->month($output)->translatedFormat('F');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($matches->keys()->first() == ':MONTHYEAR') {
|
||||||
|
|
||||||
|
$final_date = now()->addMonths($output-now()->month);
|
||||||
|
|
||||||
|
$output = \sprintf(
|
||||||
|
'%s %s',
|
||||||
|
$final_date->translatedFormat('F'),
|
||||||
|
$final_date->year,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$value = preg_replace(
|
$value = preg_replace(
|
||||||
$target,
|
$target,
|
||||||
$output,
|
$output,
|
||||||
|
@ -115,6 +115,11 @@ class CreditFilters extends QueryFilters
|
|||||||
return $this->builder;
|
return $this->builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($sort_col[0] == 'client_id') {
|
||||||
|
return $this->builder->orderBy(\App\Models\Client::select('name')
|
||||||
|
->whereColumn('clients.id', 'credits.client_id'), $sort_col[1]);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +106,29 @@ class ExpenseFilters extends QueryFilters
|
|||||||
return $this->builder;
|
return $this->builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter expenses that only have invoices
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return Builder
|
||||||
|
*/
|
||||||
|
public function has_invoices(string $value = ''): Builder
|
||||||
|
{
|
||||||
|
$split = explode(",", $value);
|
||||||
|
|
||||||
|
if (is_array($split) && in_array($split[0], ['client', 'project'])) {
|
||||||
|
|
||||||
|
$search_key = $split[0] == 'client' ? 'client_id' : 'project_id';
|
||||||
|
|
||||||
|
return $this->builder->whereHas('invoice', function ($query) use ($search_key, $split){
|
||||||
|
$query->where($search_key, $this->decodePrimaryKey($split[1]))
|
||||||
|
->whereIn('status_id', [\App\Models\Invoice::STATUS_DRAFT, \App\Models\Invoice::STATUS_SENT, \App\Models\Invoice::STATUS_PARTIAL]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of expenses that can be matched to bank transactions
|
* Returns a list of expenses that can be matched to bank transactions
|
||||||
*/
|
*/
|
||||||
|
@ -11,12 +11,14 @@
|
|||||||
|
|
||||||
namespace App\Filters;
|
namespace App\Filters;
|
||||||
|
|
||||||
|
use RuntimeException;
|
||||||
|
use App\Models\Client;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
|
use App\Filters\QueryFilters;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Support\Carbon;
|
|
||||||
use InvalidArgumentException;
|
|
||||||
use RuntimeException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* InvoiceFilters.
|
* InvoiceFilters.
|
||||||
@ -205,10 +207,9 @@ class InvoiceFilters extends QueryFilters
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($sort_col[0] == 'client_id') {
|
if ($sort_col[0] == 'client_id') {
|
||||||
|
|
||||||
$this->builder->with(['client' => function($q) use($sort_col){
|
return $this->builder->orderBy(\App\Models\Client::select('name')
|
||||||
$q->orderBy('name', $sort_col[1]);
|
->whereColumn('clients.id', 'invoices.client_id'), $sort_col[1]);
|
||||||
}]);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +158,13 @@ class PaymentFilters extends QueryFilters
|
|||||||
return $this->builder;
|
return $this->builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ($sort_col[0] == 'client_id') {
|
||||||
|
return $this->builder->orderBy(\App\Models\Client::select('name')
|
||||||
|
->whereColumn('clients.id', 'payments.client_id'), $sort_col[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +135,13 @@ class QuoteFilters extends QueryFilters
|
|||||||
return $this->builder;
|
return $this->builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($sort_col[0] == 'client_id'){
|
||||||
|
|
||||||
|
return $this->builder->orderBy(\App\Models\Client::select('name')
|
||||||
|
->whereColumn('clients.id', 'quotes.client_id'), $sort_col[1]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if ($sort_col[0] == 'valid_until') {
|
if ($sort_col[0] == 'valid_until') {
|
||||||
$sort_col[0] = 'due_date';
|
$sort_col[0] = 'due_date';
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,13 @@ class RecurringInvoiceFilters extends QueryFilters
|
|||||||
return $this->builder;
|
return $this->builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ($sort_col[0] == 'client_id') {
|
||||||
|
return $this->builder->orderBy(\App\Models\Client::select('name')
|
||||||
|
->whereColumn('clients.id', 'recurring_invoices.client_id'), $sort_col[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,9 +110,34 @@ class TaskFilters extends QueryFilters
|
|||||||
return $this->builder;
|
return $this->builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($sort_col[0] == 'client_id') {
|
||||||
|
return $this->builder->orderBy(\App\Models\Client::select('name')
|
||||||
|
->whereColumn('clients.id', 'tasks.client_id'), $sort_col[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($sort_col[0] == 'user_id') {
|
||||||
|
return $this->builder->orderBy(\App\Models\User::select('first_name')
|
||||||
|
->whereColumn('users.id', 'tasks.user_id'), $sort_col[1]);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function task_status(string $value = ''): Builder
|
||||||
|
{
|
||||||
|
if (strlen($value) == 0) {
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
$status_parameters = explode(',', $value);
|
||||||
|
|
||||||
|
if(count($status_parameters) > 0)
|
||||||
|
return $this->builder->whereIn('status_id', $this->transformKeys($status_parameters));
|
||||||
|
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters the query by the users company ID.
|
* Filters the query by the users company ID.
|
||||||
*
|
*
|
||||||
|
@ -36,6 +36,12 @@ class TokenFilters extends QueryFilters
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function is_system(bool $value = false): Builder
|
||||||
|
{
|
||||||
|
return $this->builder->where('is_system', $value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorts the list based on $sort.
|
* Sorts the list based on $sort.
|
||||||
*
|
*
|
||||||
|
@ -89,6 +89,15 @@ class UserFilters extends QueryFilters
|
|||||||
->where('account_id', auth()->user()->account_id);
|
->where('account_id', auth()->user()->account_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function sending_users(string $value = ''): Builder
|
||||||
|
{
|
||||||
|
if (strlen($value) == 0 || $value != 'true') {
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->builder->whereNotNull('oauth_user_refresh_token');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exclude a list of user_ids, can pass multiple
|
* Exclude a list of user_ids, can pass multiple
|
||||||
* user IDs by separating them with a comma.
|
* user IDs by separating them with a comma.
|
||||||
|
@ -127,9 +127,12 @@ class IncomeTransformer implements BankRevenueInterface
|
|||||||
|
|
||||||
foreach ($transaction->transaction as $transaction) {
|
foreach ($transaction->transaction as $transaction) {
|
||||||
//do not store duplicate / pending transactions
|
//do not store duplicate / pending transactions
|
||||||
if (property_exists($transaction, 'status') && $transaction->status == 'PENDING') {
|
if (property_exists($transaction, 'status') && $transaction->status == 'PENDING')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//some object do no store amounts ignore these
|
||||||
|
if(!property_exists($transaction, 'amount'))
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
$data[] = $this->transformTransaction($transaction);
|
$data[] = $this->transformTransaction($transaction);
|
||||||
}
|
}
|
||||||
@ -148,7 +151,7 @@ class IncomeTransformer implements BankRevenueInterface
|
|||||||
'category_type' => $transaction->categoryType,
|
'category_type' => $transaction->categoryType,
|
||||||
'date' => $transaction->date,
|
'date' => $transaction->date,
|
||||||
'bank_account_id' => $transaction->accountId,
|
'bank_account_id' => $transaction->accountId,
|
||||||
'description' => $transaction->description->original,
|
'description' => $transaction?->description?->original ?? '',
|
||||||
'base_type' => property_exists($transaction, 'baseType') ? $transaction->baseType : $this->calculateBaseType($transaction),
|
'base_type' => property_exists($transaction, 'baseType') ? $transaction->baseType : $this->calculateBaseType($transaction),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -85,42 +85,68 @@ class ActivityController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$default_activities = $request->has('rows') ? $request->input('rows') : 50;
|
$default_activities = $request->has('rows') ? $request->input('rows') : 75;
|
||||||
|
|
||||||
$activities = Activity::with('user')
|
$activities = Activity::with('user')
|
||||||
->orderBy('created_at', 'DESC')
|
->orderBy('created_at', 'DESC')
|
||||||
->company()
|
->company()
|
||||||
->take($default_activities);
|
->take($default_activities);
|
||||||
|
|
||||||
if ($request->has('react')) {
|
// if ($request->has('react')) {
|
||||||
if (!auth()->user()->isAdmin()) {
|
|
||||||
|
// /** @var \App\Models\User auth()->user() */
|
||||||
|
// $user = auth()->user();
|
||||||
|
|
||||||
|
// if (!$user->isAdmin()) {
|
||||||
|
// $activities->where('user_id', auth()->user()->id);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// $system = ctrans('texts.system');
|
||||||
|
|
||||||
|
// $data = $activities->cursor()->map(function ($activity) {
|
||||||
|
|
||||||
|
// $arr =
|
||||||
|
// [
|
||||||
|
// 'client' => $activity->client ? $activity->client : '',
|
||||||
|
// 'contact' => $activity->client ? $activity->contact : '',
|
||||||
|
// 'quote' => $activity->quote ? $activity->quote : '',
|
||||||
|
// 'user' => $activity->user ? $activity->user : '',
|
||||||
|
// 'expense' => $activity->expense ? $activity->expense : '',
|
||||||
|
// 'invoice' => $activity->invoice ? $activity->invoice : '',
|
||||||
|
// 'recurring_invoice' => $activity->recurring_invoice ? $activity->recurring_invoice : '',
|
||||||
|
// 'payment' => $activity->payment ? $activity->payment : '',
|
||||||
|
// 'credit' => $activity->credit ? $activity->credit : '',
|
||||||
|
// 'task' => $activity->task ? $activity->task : '',
|
||||||
|
// 'vendor' => $activity->vendor ? $activity->vendor : '',
|
||||||
|
// 'purchase_order' => $activity->purchase_order ? $activity->purchase_order : '',
|
||||||
|
// 'subscription' => $activity->subscription ? $activity->subscription : '',
|
||||||
|
// 'vendor_contact' => $activity->vendor_contact ? $activity->vendor_contact : '',
|
||||||
|
// 'recurring_expense' => $activity->recurring_expense ? $activity->recurring_expense : '',
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// $activity_array = $activity->toArray();
|
||||||
|
|
||||||
|
// return array_merge($arr, $activity_array);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// return response()->json(['data' => $data->toArray()], 200);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
if($request->has('reactv2')) {
|
||||||
|
|
||||||
|
/** @var \App\Models\User auth()->user() */
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
if (!$user->isAdmin()) {
|
||||||
$activities->where('user_id', auth()->user()->id);
|
$activities->where('user_id', auth()->user()->id);
|
||||||
}
|
}
|
||||||
// return response()->json(['data' => []], 200);
|
|
||||||
|
|
||||||
$system = ctrans('texts.system');
|
$system = ctrans('texts.system');
|
||||||
|
|
||||||
$data = $activities->cursor()->map(function ($activity) use ($system) {
|
$data = $activities->cursor()->map(function ($activity) use ($system) {
|
||||||
$arr =
|
|
||||||
[
|
|
||||||
'client' => $activity->client ? $activity->client : '',
|
|
||||||
'contact' => $activity->contact ? $activity->contact : '',
|
|
||||||
'quote' => $activity->quote ? $activity->quote : '',
|
|
||||||
'user' => $activity->user ? $activity->user : '',
|
|
||||||
'expense' => $activity->expense ? $activity->expense : '',
|
|
||||||
'invoice' => $activity->invoice ? $activity->invoice : '',
|
|
||||||
'recurring_invoice' => $activity->recurring_invoice ? $activity->recurring_invoice : '',
|
|
||||||
'payment' => $activity->payment ? $activity->payment : '',
|
|
||||||
'credit' => $activity->credit ? $activity->credit : '',
|
|
||||||
'task' => $activity->task ? $activity->task : '',
|
|
||||||
'vendor' => $activity->vendor ? $activity->vendor : '',
|
|
||||||
'purchase_order' => $activity->purchase_order ? $activity->purchase_order : '',
|
|
||||||
'subscription' => $activity->subscription ? $activity->subscription : '',
|
|
||||||
'vendor_contact' => $activity->vendor_contact ? $activity->vendor_contact : '',
|
|
||||||
'recurring_expense' => $activity->recurring_expense ? $activity->recurring_expense : '',
|
|
||||||
];
|
|
||||||
|
|
||||||
return array_merge($arr, $activity->toArray());
|
return $activity->activity_string();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return response()->json(['data' => $data->toArray()], 200);
|
return response()->json(['data' => $data->toArray()], 200);
|
||||||
|
@ -682,8 +682,6 @@ class LoginController extends BaseController
|
|||||||
'email' => $socialite_user->getEmail(),
|
'email' => $socialite_user->getEmail(),
|
||||||
'oauth_user_id' => $socialite_user->getId(),
|
'oauth_user_id' => $socialite_user->getId(),
|
||||||
'oauth_provider_id' => $provider,
|
'oauth_provider_id' => $provider,
|
||||||
// 'oauth_user_token' => $oauth_user_token,
|
|
||||||
// 'oauth_user_refresh_token' => $socialite_user->refreshToken,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$user->update($update_user);
|
$user->update($update_user);
|
||||||
@ -699,7 +697,7 @@ class LoginController extends BaseController
|
|||||||
|
|
||||||
$request_from_react = Cache::pull("react_redir:".auth()->user()?->account?->key);
|
$request_from_react = Cache::pull("react_redir:".auth()->user()?->account?->key);
|
||||||
|
|
||||||
if($request_from_react)
|
// if($request_from_react)
|
||||||
$redirect_url = config('ninja.react_url')."/#/settings/user_details/connect";
|
$redirect_url = config('ninja.react_url')."/#/settings/user_details/connect";
|
||||||
|
|
||||||
return redirect($redirect_url);
|
return redirect($redirect_url);
|
||||||
@ -735,6 +733,10 @@ class LoginController extends BaseController
|
|||||||
nlog('user not found for oauth');
|
nlog('user not found for oauth');
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect('/#/');
|
$redirect_url = config('ninja.react_url')."/#/settings/user_details/connect";
|
||||||
|
|
||||||
|
return redirect($redirect_url);
|
||||||
|
|
||||||
|
// return redirect('/#/');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ class ChartController extends BaseController
|
|||||||
/** @var \App\Models\User auth()->user() */
|
/** @var \App\Models\User auth()->user() */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$cs = new ChartService($user->company(), $user, $user->isAdmin());
|
$cs = new ChartService($user->company(), $user, $user->isAdmin());
|
||||||
|
|
||||||
return response()->json($cs->chart_summary($request->input('start_date'), $request->input('end_date')), 200);
|
return response()->json($cs->chart_summary($request->input('start_date'), $request->input('end_date')), 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ namespace App\Http\Controllers;
|
|||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\CompanyUser;
|
use App\Models\CompanyUser;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
|
use App\Transformers\UserTransformer;
|
||||||
use App\Transformers\CompanyUserTransformer;
|
use App\Transformers\CompanyUserTransformer;
|
||||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||||
use App\Http\Requests\CompanyUser\UpdateCompanyUserRequest;
|
use App\Http\Requests\CompanyUser\UpdateCompanyUserRequest;
|
||||||
@ -134,6 +135,7 @@ class CompanyUserController extends BaseController
|
|||||||
|
|
||||||
public function updatePreferences(UpdateCompanyUserPreferencesRequest $request, User $user)
|
public function updatePreferences(UpdateCompanyUserPreferencesRequest $request, User $user)
|
||||||
{
|
{
|
||||||
|
/** @var \App\Models\User $logged_in_user */
|
||||||
$company = auth()->user()->company();
|
$company = auth()->user()->company();
|
||||||
|
|
||||||
$company_user = CompanyUser::whereUserId($user->id)->whereCompanyId($company->id)->first();
|
$company_user = CompanyUser::whereUserId($user->id)->whereCompanyId($company->id)->first();
|
||||||
@ -143,10 +145,14 @@ class CompanyUserController extends BaseController
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->entity_type = User::class;
|
||||||
|
|
||||||
|
$this->entity_transformer = UserTransformer::class;
|
||||||
|
|
||||||
$company_user->react_settings = $request->react_settings;
|
$company_user->react_settings = $request->react_settings;
|
||||||
$company_user->save();
|
$company_user->save();
|
||||||
|
|
||||||
return $this->itemResponse($company_user->fresh());
|
return $this->itemResponse($user->fresh());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ class ConnectedAccountController extends BaseController
|
|||||||
* Connect an OAuth account to a regular email/password combination account
|
* Connect an OAuth account to a regular email/password combination account
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @return User Refresh Feed.
|
* @return JsonResponse.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @OA\Post(
|
* @OA\Post(
|
||||||
@ -90,14 +90,15 @@ class ConnectedAccountController extends BaseController
|
|||||||
|
|
||||||
private function handleMicrosoftOauth($request)
|
private function handleMicrosoftOauth($request)
|
||||||
{
|
{
|
||||||
nlog($request->all());
|
$access_token = false;
|
||||||
|
$access_token = $request->has('access_token') ? $request->input('access_token') : $request->input('accessToken');
|
||||||
|
|
||||||
if (!$request->has('access_token')) {
|
if (!$access_token) {
|
||||||
return response()->json(['message' => 'No access_token parameter found!'], 400);
|
return response()->json(['message' => 'No access_token parameter found!'], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$graph = new \Microsoft\Graph\Graph();
|
$graph = new \Microsoft\Graph\Graph();
|
||||||
$graph->setAccessToken($request->input('access_token'));
|
$graph->setAccessToken($access_token);
|
||||||
|
|
||||||
$user = $graph->createRequest("GET", "/me")
|
$user = $graph->createRequest("GET", "/me")
|
||||||
->setReturnType(Model\User::class)
|
->setReturnType(Model\User::class)
|
||||||
|
@ -162,16 +162,14 @@ class ImportController extends Controller
|
|||||||
$delimiters = [',', '.', ';'];
|
$delimiters = [',', '.', ';'];
|
||||||
$bestDelimiter = ' ';
|
$bestDelimiter = ' ';
|
||||||
$count = 0;
|
$count = 0;
|
||||||
|
|
||||||
foreach ($delimiters as $delimiter) {
|
foreach ($delimiters as $delimiter) {
|
||||||
// if (substr_count($csvfile, $delimiter) > $count) {
|
|
||||||
// $count = substr_count($csvfile, $delimiter);
|
|
||||||
// $bestDelimiter = $delimiter;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (substr_count(strstr($csvfile, "\n", true), $delimiter) > $count) {
|
if (substr_count(strstr($csvfile, "\n", true), $delimiter) >= $count) {
|
||||||
$count = substr_count($csvfile, $delimiter);
|
$count = substr_count($csvfile, $delimiter);
|
||||||
$bestDelimiter = $delimiter;
|
$bestDelimiter = $delimiter;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return $bestDelimiter;
|
return $bestDelimiter;
|
||||||
}
|
}
|
||||||
|
@ -408,7 +408,7 @@ class InvoiceController extends BaseController
|
|||||||
|
|
||||||
$invoice->service()
|
$invoice->service()
|
||||||
->triggeredActions($request)
|
->triggeredActions($request)
|
||||||
->touchPdf()
|
->deletePdf()
|
||||||
->adjustInventory($old_invoice);
|
->adjustInventory($old_invoice);
|
||||||
|
|
||||||
event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||||
@ -740,7 +740,8 @@ class InvoiceController extends BaseController
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'cancel':
|
case 'cancel':
|
||||||
$invoice = $invoice->service()->handleCancellation()->touchPdf()->save();
|
$invoice = $invoice->service()->handleCancellation()->deletePdf()->save();
|
||||||
|
// $invoice = $invoice->service()->handleCancellation()->touchPdf()->save();
|
||||||
|
|
||||||
if (! $bulk) {
|
if (! $bulk) {
|
||||||
$this->itemResponse($invoice);
|
$this->itemResponse($invoice);
|
||||||
@ -818,17 +819,11 @@ class InvoiceController extends BaseController
|
|||||||
return response()->json(['message' => 'no record found'], 400);
|
return response()->json(['message' => 'no record found'], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$contact = $invitation->contact;
|
|
||||||
$invoice = $invitation->invoice;
|
$invoice = $invitation->invoice;
|
||||||
|
|
||||||
// $file = $invoice->service()->getInvoicePdf($contact);
|
$file_name = $invoice->numberFormatter().'.pdf';
|
||||||
|
|
||||||
/************** */
|
$file = (new \App\Jobs\Entity\CreateRawPdf($invitation, $invitation->company->db))->handle();
|
||||||
$file_name = $invoice->numberFormatter().'.pdf';
|
|
||||||
|
|
||||||
$file = (new \App\Jobs\Entity\CreateRawPdf($invitation, $invitation->company->db))->handle();
|
|
||||||
|
|
||||||
/************* */
|
|
||||||
|
|
||||||
$headers = ['Content-Type' => 'application/pdf'];
|
$headers = ['Content-Type' => 'application/pdf'];
|
||||||
|
|
||||||
|
@ -565,10 +565,11 @@ class RecurringInvoiceController extends BaseController
|
|||||||
return response()->json(['message' => 'no record found'], 400);
|
return response()->json(['message' => 'no record found'], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$contact = $invitation->contact;
|
|
||||||
$invoice = $invitation->recurring_invoice;
|
$invoice = $invitation->recurring_invoice;
|
||||||
|
|
||||||
$file = $invoice->service()->getInvoicePdf($contact);
|
$file_name = $invoice->numberFormatter().'.pdf';
|
||||||
|
|
||||||
|
$file = (new \App\Jobs\Entity\CreateRawPdf($invitation, $invitation->company->db))->handle();
|
||||||
|
|
||||||
$headers = ['Content-Type' => 'application/pdf'];
|
$headers = ['Content-Type' => 'application/pdf'];
|
||||||
|
|
||||||
@ -577,8 +578,9 @@ class RecurringInvoiceController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
return response()->streamDownload(function () use ($file) {
|
return response()->streamDownload(function () use ($file) {
|
||||||
echo Storage::get($file);
|
echo $file;
|
||||||
}, basename($file), $headers);
|
}, $file_name, $headers);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -175,6 +175,7 @@ class UserController extends BaseController
|
|||||||
$user->oauth_user_refresh_token = null;
|
$user->oauth_user_refresh_token = null;
|
||||||
$user->oauth_user_token = null;
|
$user->oauth_user_token = null;
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
UserEmailChanged::dispatch($new_user, json_decode($old_user), $logged_in_user->company());
|
UserEmailChanged::dispatch($new_user, json_decode($old_user), $logged_in_user->company());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,9 +12,12 @@
|
|||||||
namespace App\Http\Requests\Chart;
|
namespace App\Http\Requests\Chart;
|
||||||
|
|
||||||
use App\Http\Requests\Request;
|
use App\Http\Requests\Request;
|
||||||
|
use App\Utils\Traits\MakesDates;
|
||||||
|
|
||||||
class ShowChartRequest extends Request
|
class ShowChartRequest extends Request
|
||||||
{
|
{
|
||||||
|
use MakesDates;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the user is authorized to make this request.
|
* Determine if the user is authorized to make this request.
|
||||||
*
|
*
|
||||||
@ -22,14 +25,18 @@ class ShowChartRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function authorize() : bool
|
public function authorize() : bool
|
||||||
{
|
{
|
||||||
return auth()->user()->isAdmin();
|
/**@var \App\Models\User auth()->user */
|
||||||
|
$user = auth()->user();
|
||||||
|
|
||||||
|
return $user->isAdmin();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function rules()
|
public function rules()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'start_date' => 'date',
|
'date_range' => 'bail|sometimes|string|in:last7_days,last30_days,last365_days,this_month,last_month,this_quarter,last_quarter,this_year,last_year,all_time,custom',
|
||||||
'end_date' => 'date',
|
'start_date' => 'bail|sometimes|date',
|
||||||
|
'end_date' => 'bail|sometimes|date',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,12 +44,18 @@ class ShowChartRequest extends Request
|
|||||||
{
|
{
|
||||||
$input = $this->all();
|
$input = $this->all();
|
||||||
|
|
||||||
if (! array_key_exists('start_date', $input)) {
|
if(isset($input['date_range'])) {
|
||||||
$input['start_date'] = now()->subDays(20);
|
$dates = $this->calculateStartAndEndDates($input);
|
||||||
|
$input['start_date'] = $dates[0];
|
||||||
|
$input['end_date'] = $dates[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! array_key_exists('end_date', $input)) {
|
if (! isset($input['start_date'])) {
|
||||||
$input['end_date'] = now();
|
$input['start_date'] = now()->subDays(20)->format('Y-m-d');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! isset($input['end_date'])) {
|
||||||
|
$input['end_date'] = now()->format('Y-m-d');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->replace($input);
|
$this->replace($input);
|
||||||
|
@ -48,7 +48,7 @@ class PreviewInvoiceRequest extends Request
|
|||||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||||
$input['amount'] = 0;
|
$input['amount'] = 0;
|
||||||
$input['balance'] = 0;
|
$input['balance'] = 0;
|
||||||
$input['number'] = ctrans('texts.live_preview').' #'.rand(0, 1000);
|
$input['number'] = isset($input['number']) ? $input['number'] : ctrans('texts.live_preview').' #'.rand(0, 1000);
|
||||||
|
|
||||||
$this->replace($input);
|
$this->replace($input);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ class PreviewPurchaseOrderRequest extends Request
|
|||||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||||
$input['amount'] = 0;
|
$input['amount'] = 0;
|
||||||
$input['balance'] = 0;
|
$input['balance'] = 0;
|
||||||
$input['number'] = ctrans('texts.live_preview') . " #". rand(0, 1000);
|
$input['number'] = isset($input['number']) ? $input['number'] : ctrans('texts.live_preview').' #'.rand(0, 1000); //30-06-2023
|
||||||
|
|
||||||
$this->replace($input);
|
$this->replace($input);
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ class GenericReportRequest extends Request
|
|||||||
'start_date' => 'bail|required_if:date_range,custom|nullable|date',
|
'start_date' => 'bail|required_if:date_range,custom|nullable|date',
|
||||||
'report_keys' => 'present|array',
|
'report_keys' => 'present|array',
|
||||||
'send_email' => 'required|bool',
|
'send_email' => 'required|bool',
|
||||||
'status' => 'sometimes|string|nullable|in:all,draft,sent,viewed,paid,unpaid,overdue',
|
// 'status' => 'sometimes|string|nullable|in:all,draft,sent,viewed,paid,unpaid,overdue',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ class StoreSchedulerRequest extends Request
|
|||||||
$input = $this->all();
|
$input = $this->all();
|
||||||
|
|
||||||
if (array_key_exists('next_run', $input) && is_string($input['next_run'])) {
|
if (array_key_exists('next_run', $input) && is_string($input['next_run'])) {
|
||||||
$this->merge(['next_run_client' => $input['next_run']]);
|
$input['next_run_client'] = $input['next_run'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if($input['template'] == 'email_record'){
|
if($input['template'] == 'email_record'){
|
||||||
|
@ -54,7 +54,7 @@ class UpdateSchedulerRequest extends Request
|
|||||||
$input = $this->all();
|
$input = $this->all();
|
||||||
|
|
||||||
if (array_key_exists('next_run', $input) && is_string($input['next_run'])) {
|
if (array_key_exists('next_run', $input) && is_string($input['next_run'])) {
|
||||||
$this->merge(['next_run_client' => $input['next_run']]);
|
$input['next_run_client'] = $input['next_run'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if($input['template'] == 'email_record') {
|
if($input['template'] == 'email_record') {
|
||||||
|
@ -20,12 +20,14 @@ class BankTransactionMap
|
|||||||
1 => 'transaction.amount',
|
1 => 'transaction.amount',
|
||||||
2 => 'transaction.currency',
|
2 => 'transaction.currency',
|
||||||
3 => 'transaction.account_type',
|
3 => 'transaction.account_type',
|
||||||
4 => 'transaction.category_id',
|
4 => 'transaction.category',
|
||||||
5 => 'transaction.category_type',
|
5 => 'transaction.category_type',
|
||||||
6 => 'transaction.date',
|
6 => 'transaction.date',
|
||||||
7 => 'transaction.bank_account_id',
|
7 => 'transaction.bank_account',
|
||||||
8 => 'transaction.description',
|
8 => 'transaction.description',
|
||||||
9 => 'transaction.base_type',
|
9 => 'transaction.base_type',
|
||||||
|
10 => 'transaction.payment_type_Credit',
|
||||||
|
11 => 'transaction.payment_type_Debit',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,6 +44,8 @@ class BankTransactionMap
|
|||||||
7 => 'texts.bank_account_id',
|
7 => 'texts.bank_account_id',
|
||||||
8 => 'texts.description',
|
8 => 'texts.description',
|
||||||
9 => 'texts.type',
|
9 => 'texts.type',
|
||||||
|
10 => 'transaction.credit',
|
||||||
|
11 => 'transaction.debit',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,10 @@ class BaseImport
|
|||||||
|
|
||||||
public function getCsvData($entity_type)
|
public function getCsvData($entity_type)
|
||||||
{
|
{
|
||||||
|
if (! ini_get('auto_detect_line_endings')) {
|
||||||
|
ini_set('auto_detect_line_endings', '1');
|
||||||
|
}
|
||||||
|
|
||||||
$base64_encoded_csv = Cache::pull($this->hash.'-'.$entity_type);
|
$base64_encoded_csv = Cache::pull($this->hash.'-'.$entity_type);
|
||||||
|
|
||||||
if (empty($base64_encoded_csv)) {
|
if (empty($base64_encoded_csv)) {
|
||||||
@ -132,14 +136,12 @@ class BaseImport
|
|||||||
$bestDelimiter = ',';
|
$bestDelimiter = ',';
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($delimiters as $delimiter) {
|
foreach ($delimiters as $delimiter) {
|
||||||
// if (substr_count($csvfile, $delimiter) > $count) {
|
|
||||||
// $count = substr_count($csvfile, $delimiter);
|
if (substr_count(strstr($csvfile, "\n", true), $delimiter) >= $count) {
|
||||||
// $bestDelimiter = $delimiter;
|
|
||||||
// }
|
|
||||||
if (substr_count(strstr($csvfile, "\n", true), $delimiter) > $count) {
|
|
||||||
$count = substr_count($csvfile, $delimiter);
|
$count = substr_count($csvfile, $delimiter);
|
||||||
$bestDelimiter = $delimiter;
|
$bestDelimiter = $delimiter;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return $bestDelimiter;
|
return $bestDelimiter;
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ class BankTransformer extends BaseTransformer
|
|||||||
$transformed = [
|
$transformed = [
|
||||||
'bank_integration_id' => $transaction['transaction.bank_integration_id'],
|
'bank_integration_id' => $transaction['transaction.bank_integration_id'],
|
||||||
'transaction_id' => $this->getNumber($transaction, 'transaction.transaction_id'),
|
'transaction_id' => $this->getNumber($transaction, 'transaction.transaction_id'),
|
||||||
'amount' => abs($this->getFloat($transaction, 'transaction.amount')),
|
'amount' => $this->calculateAmount($transaction),
|
||||||
'currency_id' => $this->getCurrencyByCode($transaction, 'transaction.currency'),
|
'currency_id' => $this->getCurrencyByCode($transaction, 'transaction.currency'),
|
||||||
'account_type' => strlen($this->getString($transaction, 'transaction.account_type')) > 1 ? $this->getString($transaction, 'transaction.account_type') : 'bank',
|
'account_type' => strlen($this->getString($transaction, 'transaction.account_type')) > 1 ? $this->getString($transaction, 'transaction.account_type') : 'bank',
|
||||||
'category_id' => $this->getNumber($transaction, 'transaction.category_id') > 0 ? $this->getNumber($transaction, 'transaction.category_id') : null,
|
'category_id' => $this->getNumber($transaction, 'transaction.category_id') > 0 ? $this->getNumber($transaction, 'transaction.category_id') : null,
|
||||||
@ -49,13 +49,35 @@ class BankTransformer extends BaseTransformer
|
|||||||
return $transformed;
|
return $transformed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function calculateAmount(array $transaction):float
|
||||||
|
{
|
||||||
|
|
||||||
|
if (array_key_exists('transaction.amount', $transaction) && is_numeric($transaction['transaction.amount'])) {
|
||||||
|
return abs($this->getFloat($transaction, 'transaction.amount'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('transaction.payment_type_Credit', $transaction) && is_numeric($transaction['transaction.payment_type_Credit'])) {
|
||||||
|
return abs($this->getFloat($transaction, 'transaction.payment_type_Credit'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('transaction.payment_type_Debit', $transaction) && is_numeric($transaction['transaction.payment_type_Debit'])) {
|
||||||
|
return abs($this->getFloat($transaction, 'transaction.payment_type_Debit'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
private function calculateType($transaction)
|
private function calculateType($transaction)
|
||||||
{
|
{
|
||||||
if (array_key_exists('transaction.base_type', $transaction) && (($transaction['transaction.base_type'] == 'CREDIT') || strtolower($transaction['transaction.base_type']) == 'deposit')) {
|
|
||||||
|
if (array_key_exists('transaction.payment_type_Credit', $transaction) && is_numeric($transaction['transaction.payment_type_Credit'])) {
|
||||||
return 'CREDIT';
|
return 'CREDIT';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('transaction.transaction.payment_type_Debit', $transaction) && is_numeric($transaction['transaction.payment_type_Debit'])) {
|
||||||
|
return 'DEBIT';
|
||||||
|
}
|
||||||
|
|
||||||
if (array_key_exists('transaction.base_type', $transaction) && (($transaction['transaction.base_type'] == 'DEBIT') || strtolower($transaction['transaction.base_type']) == 'withdrawal')) {
|
if (array_key_exists('transaction.base_type', $transaction) && (($transaction['transaction.base_type'] == 'DEBIT') || strtolower($transaction['transaction.base_type']) == 'withdrawal')) {
|
||||||
return 'DEBIT';
|
return 'DEBIT';
|
||||||
}
|
}
|
||||||
|
@ -362,7 +362,7 @@ class MatchBankTransactions implements ShouldQueue
|
|||||||
$this->invoice
|
$this->invoice
|
||||||
->service()
|
->service()
|
||||||
->applyNumber()
|
->applyNumber()
|
||||||
->touchPdf()
|
->deletePdf()
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
$payment->ledger()
|
$payment->ledger()
|
||||||
|
@ -11,17 +11,19 @@
|
|||||||
|
|
||||||
namespace App\Jobs\Bank;
|
namespace App\Jobs\Bank;
|
||||||
|
|
||||||
use App\Helpers\Bank\Yodlee\Yodlee;
|
use App\Models\Company;
|
||||||
use App\Libraries\MultiDB;
|
use App\Libraries\MultiDB;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
use App\Models\BankIntegration;
|
use App\Models\BankIntegration;
|
||||||
use App\Models\BankTransaction;
|
use App\Models\BankTransaction;
|
||||||
use App\Models\Company;
|
use App\Helpers\Bank\Yodlee\Yodlee;
|
||||||
use App\Services\Bank\BankMatchingService;
|
|
||||||
use Illuminate\Bus\Queueable;
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use App\Services\Bank\BankMatchingService;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||||
|
use App\Notifications\Ninja\GenericNinjaAdminNotification;
|
||||||
|
|
||||||
class ProcessBankTransactions implements ShouldQueue
|
class ProcessBankTransactions implements ShouldQueue
|
||||||
{
|
{
|
||||||
@ -70,6 +72,14 @@ class ProcessBankTransactions implements ShouldQueue
|
|||||||
$this->processTransactions();
|
$this->processTransactions();
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
nlog("{$this->bank_integration_account_id} - exited abnormally => ". $e->getMessage());
|
nlog("{$this->bank_integration_account_id} - exited abnormally => ". $e->getMessage());
|
||||||
|
|
||||||
|
$content = [
|
||||||
|
"Processing transactions for account: {$this->bank_integration->account->key} failed",
|
||||||
|
"Exception Details => ",
|
||||||
|
$e->getMessage(),
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->bank_integration->company->notification(new GenericNinjaAdminNotification($content))->ninja();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} while ($this->stop_loop);
|
} while ($this->stop_loop);
|
||||||
@ -152,4 +162,15 @@ class ProcessBankTransactions implements ShouldQueue
|
|||||||
$this->bank_integration->save();
|
$this->bank_integration->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function middleware()
|
||||||
|
{
|
||||||
|
return [new WithoutOverlapping($this->bank_integration_account_id)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function backoff()
|
||||||
|
{
|
||||||
|
return [rand(10, 15), rand(30, 40), rand(60, 79), rand(160, 200), rand(3000, 5000)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,12 +73,11 @@ class UpdateTaxData implements ShouldQueue
|
|||||||
nlog("problem getting tax data => ".$e->getMessage());
|
nlog("problem getting tax data => ".$e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set static tax information */
|
/*
|
||||||
if(!$tax_provider->updatedTaxStatus() && $this->client->country_id == 840){
|
if(!$tax_provider->updatedTaxStatus() && $this->client->country_id == 840){
|
||||||
|
|
||||||
$calculated_state = false;
|
$calculated_state = false;
|
||||||
|
|
||||||
/** State must be calculated else default to the company state for taxes */
|
|
||||||
if(array_key_exists($this->client->shipping_state, USStates::get())) {
|
if(array_key_exists($this->client->shipping_state, USStates::get())) {
|
||||||
$calculated_state = $this->client->shipping_state;
|
$calculated_state = $this->client->shipping_state;
|
||||||
$calculated_postal_code = $this->client->shipping_postal_code;
|
$calculated_postal_code = $this->client->shipping_postal_code;
|
||||||
@ -136,7 +135,7 @@ class UpdateTaxData implements ShouldQueue
|
|||||||
$this->client->saveQuietly();
|
$this->client->saveQuietly();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public function middleware()
|
public function middleware()
|
||||||
@ -147,6 +146,8 @@ class UpdateTaxData implements ShouldQueue
|
|||||||
public function failed($exception)
|
public function failed($exception)
|
||||||
{
|
{
|
||||||
nlog("UpdateTaxData failed => ".$exception->getMessage());
|
nlog("UpdateTaxData failed => ".$exception->getMessage());
|
||||||
|
config(['queue.failed.driver' => null]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -243,19 +243,20 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
case 'gmail':
|
case 'gmail':
|
||||||
$this->mailer = 'gmail';
|
$this->mailer = 'gmail';
|
||||||
$this->setGmailMailer();
|
$this->setGmailMailer();
|
||||||
return;
|
return $this;
|
||||||
case 'office365':
|
case 'office365':
|
||||||
|
case 'microsoft':
|
||||||
$this->mailer = 'office365';
|
$this->mailer = 'office365';
|
||||||
$this->setOfficeMailer();
|
$this->setOfficeMailer();
|
||||||
return;
|
return $this;
|
||||||
case 'client_postmark':
|
case 'client_postmark':
|
||||||
$this->mailer = 'postmark';
|
$this->mailer = 'postmark';
|
||||||
$this->setPostmarkMailer();
|
$this->setPostmarkMailer();
|
||||||
return;
|
return $this;
|
||||||
case 'client_mailgun':
|
case 'client_mailgun':
|
||||||
$this->mailer = 'mailgun';
|
$this->mailer = 'mailgun';
|
||||||
$this->setMailgunMailer();
|
$this->setMailgunMailer();
|
||||||
return;
|
return $this;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -264,6 +265,8 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
if (Ninja::isSelfHost()) {
|
if (Ninja::isSelfHost()) {
|
||||||
$this->setSelfHostMultiMailer();
|
$this->setSelfHostMultiMailer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -65,7 +65,7 @@ class EmailPayment implements ShouldQueue
|
|||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
if ($this->company->is_disabled) {
|
if ($this->company->is_disabled) {
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->contact->email) {
|
if ($this->contact->email) {
|
||||||
@ -96,7 +96,7 @@ class EmailPayment implements ShouldQueue
|
|||||||
|
|
||||||
(new NinjaMailerJob($nmo))->handle();
|
(new NinjaMailerJob($nmo))->handle();
|
||||||
|
|
||||||
event(new PaymentWasEmailed($this->payment, $this->payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
event(new PaymentWasEmailed($this->payment, $this->payment->company, $this->contact, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ class EmailRefundPayment implements ShouldQueue
|
|||||||
|
|
||||||
(new NinjaMailerJob($nmo))->handle();
|
(new NinjaMailerJob($nmo))->handle();
|
||||||
|
|
||||||
event(new PaymentWasEmailed($this->payment, $this->payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
event(new PaymentWasEmailed($this->payment, $this->payment->company, $this->contact, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,85 +11,89 @@
|
|||||||
|
|
||||||
namespace App\Jobs\Util;
|
namespace App\Jobs\Util;
|
||||||
|
|
||||||
use App\DataMapper\Analytics\MigrationFailure;
|
use Exception;
|
||||||
use App\DataMapper\CompanySettings;
|
use App\Models\Task;
|
||||||
use App\Exceptions\ClientHostedMigrationException;
|
use App\Models\User;
|
||||||
use App\Exceptions\MigrationValidatorFailed;
|
use App\Utils\Ninja;
|
||||||
use App\Exceptions\ResourceDependencyMissing;
|
use App\Models\Quote;
|
||||||
|
use App\Models\Client;
|
||||||
|
use App\Models\Credit;
|
||||||
|
use App\Models\Vendor;
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\Expense;
|
||||||
|
use App\Models\Invoice;
|
||||||
|
use App\Models\Payment;
|
||||||
|
use App\Models\Product;
|
||||||
|
use App\Models\Project;
|
||||||
|
use App\Models\TaxRate;
|
||||||
|
use App\Models\Activity;
|
||||||
|
use App\Models\Document;
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
|
use App\Models\TaskStatus;
|
||||||
|
use App\Models\PaymentTerm;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use App\Factory\UserFactory;
|
||||||
|
use App\Factory\QuoteFactory;
|
||||||
|
use App\Models\ClientContact;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
use App\Factory\ClientFactory;
|
use App\Factory\ClientFactory;
|
||||||
use App\Factory\CompanyLedgerFactory;
|
|
||||||
use App\Factory\CreditFactory;
|
use App\Factory\CreditFactory;
|
||||||
|
use App\Factory\VendorFactory;
|
||||||
|
use App\Models\CompanyGateway;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
use App\Factory\InvoiceFactory;
|
use App\Factory\InvoiceFactory;
|
||||||
use App\Factory\PaymentFactory;
|
use App\Factory\PaymentFactory;
|
||||||
use App\Factory\ProductFactory;
|
use App\Factory\ProductFactory;
|
||||||
use App\Factory\QuoteFactory;
|
|
||||||
use App\Factory\RecurringInvoiceFactory;
|
|
||||||
use App\Factory\TaxRateFactory;
|
use App\Factory\TaxRateFactory;
|
||||||
use App\Factory\UserFactory;
|
use App\Jobs\Util\VersionCheck;
|
||||||
use App\Factory\VendorFactory;
|
|
||||||
use App\Http\Requests\Company\UpdateCompanyRequest;
|
|
||||||
use App\Http\ValidationRules\ValidCompanyGatewayFeesAndLimitsRule;
|
|
||||||
use App\Http\ValidationRules\ValidUserForCompany;
|
|
||||||
use App\Jobs\Company\CreateCompanyToken;
|
|
||||||
use App\Jobs\Mail\NinjaMailerJob;
|
|
||||||
use App\Jobs\Mail\NinjaMailerObject;
|
|
||||||
use App\Jobs\Ninja\CheckCompanyData;
|
|
||||||
use App\Libraries\MultiDB;
|
|
||||||
use App\Mail\Migration\StripeConnectMigration;
|
|
||||||
use App\Mail\MigrationCompleted;
|
|
||||||
use App\Models\Activity;
|
|
||||||
use App\Models\Client;
|
|
||||||
use App\Models\ClientContact;
|
|
||||||
use App\Models\ClientGatewayToken;
|
|
||||||
use App\Models\Company;
|
|
||||||
use App\Models\CompanyGateway;
|
|
||||||
use App\Models\Credit;
|
|
||||||
use App\Models\Document;
|
|
||||||
use App\Models\Expense;
|
|
||||||
use App\Models\ExpenseCategory;
|
use App\Models\ExpenseCategory;
|
||||||
use App\Models\Invoice;
|
use App\Utils\Traits\MakesHash;
|
||||||
use App\Models\Payment;
|
use App\Mail\MigrationCompleted;
|
||||||
use App\Models\PaymentTerm;
|
|
||||||
use App\Models\Product;
|
|
||||||
use App\Models\Project;
|
|
||||||
use App\Models\Quote;
|
|
||||||
use App\Models\RecurringExpense;
|
use App\Models\RecurringExpense;
|
||||||
use App\Models\RecurringInvoice;
|
use App\Models\RecurringInvoice;
|
||||||
use App\Models\Task;
|
|
||||||
use App\Models\TaskStatus;
|
|
||||||
use App\Models\TaxRate;
|
|
||||||
use App\Models\User;
|
|
||||||
use App\Models\Vendor;
|
|
||||||
use App\Repositories\ClientContactRepository;
|
|
||||||
use App\Repositories\ClientRepository;
|
|
||||||
use App\Repositories\CompanyRepository;
|
|
||||||
use App\Repositories\CreditRepository;
|
|
||||||
use App\Repositories\Migration\InvoiceMigrationRepository;
|
|
||||||
use App\Repositories\Migration\PaymentMigrationRepository;
|
|
||||||
use App\Repositories\ProductRepository;
|
|
||||||
use App\Repositories\UserRepository;
|
|
||||||
use App\Repositories\VendorContactRepository;
|
|
||||||
use App\Repositories\VendorRepository;
|
|
||||||
use App\Utils\Ninja;
|
|
||||||
use App\Utils\Traits\CleanLineItems;
|
|
||||||
use App\Utils\Traits\CompanyGatewayFeesAndLimitsSaver;
|
|
||||||
use App\Utils\Traits\MakesHash;
|
|
||||||
use App\Utils\Traits\SavesDocuments;
|
|
||||||
use App\Utils\Traits\Uploadable;
|
use App\Utils\Traits\Uploadable;
|
||||||
use Exception;
|
use App\Jobs\Mail\NinjaMailerJob;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Http\UploadedFile;
|
||||||
|
use App\Models\ClientGatewayToken;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use App\DataMapper\CompanySettings;
|
||||||
|
use Illuminate\Support\Facades\App;
|
||||||
|
use App\Jobs\Mail\NinjaMailerObject;
|
||||||
|
use App\Jobs\Ninja\CheckCompanyData;
|
||||||
|
use App\Repositories\UserRepository;
|
||||||
|
use App\Utils\Traits\CleanLineItems;
|
||||||
|
use App\Utils\Traits\SavesDocuments;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
use App\Factory\CompanyLedgerFactory;
|
||||||
|
use App\Repositories\ClientRepository;
|
||||||
|
use App\Repositories\CreditRepository;
|
||||||
|
use App\Repositories\VendorRepository;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Turbo124\Beacon\Facades\LightLogs;
|
||||||
|
use App\Repositories\CompanyRepository;
|
||||||
|
use App\Repositories\ProductRepository;
|
||||||
|
use App\Factory\RecurringInvoiceFactory;
|
||||||
|
use App\Jobs\Company\CreateCompanyToken;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Modules\Admin\Jobs\Account\NinjaUser;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
use Illuminate\Http\UploadedFile;
|
use App\DataMapper\ClientRegistrationFields;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use App\Exceptions\MigrationValidatorFailed;
|
||||||
|
use App\Exceptions\ResourceDependencyMissing;
|
||||||
|
use App\Repositories\ClientContactRepository;
|
||||||
|
use App\Repositories\VendorContactRepository;
|
||||||
|
use App\DataMapper\Analytics\MigrationFailure;
|
||||||
|
use App\Mail\Migration\StripeConnectMigration;
|
||||||
|
use App\Http\ValidationRules\ValidUserForCompany;
|
||||||
|
use App\Exceptions\ClientHostedMigrationException;
|
||||||
|
use App\Http\Requests\Company\UpdateCompanyRequest;
|
||||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use App\Utils\Traits\CompanyGatewayFeesAndLimitsSaver;
|
||||||
use Illuminate\Support\Carbon;
|
use App\Repositories\Migration\InvoiceMigrationRepository;
|
||||||
use Illuminate\Support\Facades\App;
|
use App\Repositories\Migration\PaymentMigrationRepository;
|
||||||
use Illuminate\Support\Facades\Mail;
|
use App\Http\ValidationRules\ValidCompanyGatewayFeesAndLimitsRule;
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
use Illuminate\Support\Str;
|
|
||||||
use Turbo124\Beacon\Facades\LightLogs;
|
|
||||||
|
|
||||||
class Import implements ShouldQueue
|
class Import implements ShouldQueue
|
||||||
{
|
{
|
||||||
@ -135,6 +139,7 @@ class Import implements ShouldQueue
|
|||||||
'recurring_expenses',
|
'recurring_expenses',
|
||||||
'tasks',
|
'tasks',
|
||||||
'documents',
|
'documents',
|
||||||
|
'activities',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -181,7 +186,7 @@ class Import implements ShouldQueue
|
|||||||
|
|
||||||
public function middleware()
|
public function middleware()
|
||||||
{
|
{
|
||||||
return [(new WithoutOverlapping($this->user->account_id))];
|
return [(new WithoutOverlapping($this->company->company_key))];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -303,7 +308,7 @@ class Import implements ShouldQueue
|
|||||||
|
|
||||||
if (round($total_invoice_payments, 2) != round($client->paid_to_date, 2)) {
|
if (round($total_invoice_payments, 2) != round($client->paid_to_date, 2)) {
|
||||||
$client->paid_to_date = $total_invoice_payments;
|
$client->paid_to_date = $total_invoice_payments;
|
||||||
$client->save();
|
$client->saveQuietly();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -319,12 +324,12 @@ class Import implements ShouldQueue
|
|||||||
$company_ledger->notes = 'Migrated Client Balance';
|
$company_ledger->notes = 'Migrated Client Balance';
|
||||||
$company_ledger->balance = $invoice_balances;
|
$company_ledger->balance = $invoice_balances;
|
||||||
$company_ledger->activity_id = Activity::CREATE_CLIENT;
|
$company_ledger->activity_id = Activity::CREATE_CLIENT;
|
||||||
$company_ledger->save();
|
$company_ledger->saveQuietly();
|
||||||
|
|
||||||
$client->company_ledger()->save($company_ledger);
|
$client->company_ledger()->save($company_ledger);
|
||||||
|
|
||||||
$client->balance = $invoice_balances;
|
$client->balance = $invoice_balances;
|
||||||
$client->save();
|
$client->saveQuietly();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1504,7 +1509,19 @@ class Import implements ShouldQueue
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->saveDocument($uploaded_file, $entity, $is_public = true);
|
// $this->saveDocument($uploaded_file, $entity, $is_public = true);
|
||||||
|
|
||||||
|
$document = (new \App\Jobs\Util\UploadFile(
|
||||||
|
$uploaded_file,
|
||||||
|
\App\Jobs\Util\UploadFile::DOCUMENT,
|
||||||
|
$this->user,
|
||||||
|
$this->company,
|
||||||
|
$entity,
|
||||||
|
null,
|
||||||
|
true
|
||||||
|
))->handle();
|
||||||
|
|
||||||
|
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
//do nothing, gracefully :)
|
//do nothing, gracefully :)
|
||||||
}
|
}
|
||||||
@ -1776,6 +1793,78 @@ class Import implements ShouldQueue
|
|||||||
$data = null;
|
$data = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function processActivities(array $data): void
|
||||||
|
{
|
||||||
|
Activity::where('company_id', $this->company->id)->cursor()->each(function ($a){
|
||||||
|
$a->forceDelete();
|
||||||
|
nlog("deleting {$a->id}");
|
||||||
|
});
|
||||||
|
|
||||||
|
Activity::unguard();
|
||||||
|
|
||||||
|
foreach ($data as $resource) {
|
||||||
|
$modified = $resource;
|
||||||
|
|
||||||
|
$modified['company_id'] = $this->company->id;
|
||||||
|
$modified['user_id'] = $this->processUserId($resource);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (isset($modified['client_id'])) {
|
||||||
|
$modified['client_id'] = $this->transformId('clients', $resource['client_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($modified['invoice_id'])) {
|
||||||
|
$modified['invoice_id'] = $this->transformId('invoices', $resource['invoice_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($modified['quote_id'])) {
|
||||||
|
$modified['quote_id'] = $this->transformId('quotes', $resource['quote_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($modified['recurring_invoice_id'])) {
|
||||||
|
$modified['recurring_invoice_id'] = $this->transformId('recurring_invoices', $resource['recurring_invoice_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($modified['payment_id'])) {
|
||||||
|
$modified['payment_id'] = $this->transformId('payments', $resource['payment_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($modified['credit_id'])) {
|
||||||
|
$modified['credit_id'] = $this->transformId('credits', $resource['credit_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($modified['expense_id'])) {
|
||||||
|
$modified['expense_id'] = $this->transformId('expenses', $resource['expense_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($modified['task_id'])) {
|
||||||
|
$modified['task_id'] = $this->transformId('tasks', $resource['task_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($modified['client_contact_id'])) {
|
||||||
|
$modified['client_contact_id'] = $this->transformId('client_contacts', $resource['client_contact_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$modified['updated_at'] = $modified['created_at'];
|
||||||
|
|
||||||
|
$act = Activity::make($modified);
|
||||||
|
|
||||||
|
$act->save(['timestamps' => false]);
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
|
||||||
|
nlog("could not import activity: {$e->getMessage()}");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Activity::reguard();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private function processExpenses(array $data) :void
|
private function processExpenses(array $data) :void
|
||||||
{
|
{
|
||||||
Expense::unguard();
|
Expense::unguard();
|
||||||
|
@ -126,7 +126,7 @@ class ReminderJob implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
$reminder_template = $invoice->calculateTemplate('invoice');
|
$reminder_template = $invoice->calculateTemplate('invoice');
|
||||||
nlog("reminder template = {$reminder_template}");
|
// nlog("reminder template = {$reminder_template}");
|
||||||
$invoice->service()->touchReminder($reminder_template)->save();
|
$invoice->service()->touchReminder($reminder_template)->save();
|
||||||
$fees = $this->calcLateFee($invoice, $reminder_template);
|
$fees = $this->calcLateFee($invoice, $reminder_template);
|
||||||
|
|
||||||
@ -208,7 +208,8 @@ class ReminderJob implements ShouldQueue
|
|||||||
->markSent()
|
->markSent()
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
$invoice->service()->touchPdf(true);
|
//30-6-2023 - fix for duplicate touching
|
||||||
|
// $invoice->service()->touchPdf(true);
|
||||||
|
|
||||||
$enabled_reminder = 'enable_'.$reminder_template;
|
$enabled_reminder = 'enable_'.$reminder_template;
|
||||||
if ($reminder_template == 'endless_reminder') {
|
if ($reminder_template == 'endless_reminder') {
|
||||||
@ -268,7 +269,6 @@ class ReminderJob implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [$late_fee_amount, $late_fee_percent];
|
return [$late_fee_amount, $late_fee_percent];
|
||||||
// return $this->setLateFee($invoice, $late_fee_amount, $late_fee_percent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,10 +60,6 @@ class StartMigration implements ShouldQueue
|
|||||||
|
|
||||||
public $timeout = 0;
|
public $timeout = 0;
|
||||||
|
|
||||||
// public $maxExceptions = 2;
|
|
||||||
|
|
||||||
//public $backoff = 86430;
|
|
||||||
|
|
||||||
public function __construct($filepath, User $user, Company $company)
|
public function __construct($filepath, User $user, Company $company)
|
||||||
{
|
{
|
||||||
$this->filepath = $filepath;
|
$this->filepath = $filepath;
|
||||||
@ -159,8 +155,6 @@ class StartMigration implements ShouldQueue
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//always make sure we unset the migration as running
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,9 @@ class WebhookSingle implements ShouldQueue
|
|||||||
$client = new Client(['headers' => array_merge($base_headers, $headers)]);
|
$client = new Client(['headers' => array_merge($base_headers, $headers)]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$response = $client->post($subscription->target_url, [
|
$verb = $subscription->rest_method ?? 'post';
|
||||||
|
|
||||||
|
$response = $client->{$verb}($subscription->target_url, [
|
||||||
RequestOptions::JSON => $data, // or 'json' => [...]
|
RequestOptions::JSON => $data, // or 'json' => [...]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -38,25 +38,28 @@ class PaymentCreatedActivity implements ShouldQueue
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function handle($event)
|
public function handle($event)
|
||||||
{
|
{
|
||||||
|
|
||||||
MultiDB::setDb($event->company->db);
|
MultiDB::setDb($event->company->db);
|
||||||
|
|
||||||
$payment = $event->payment;
|
$payment = $event->payment;
|
||||||
|
$invoice_id = null;
|
||||||
|
|
||||||
|
if($payment->invoices()->exists())
|
||||||
|
$invoice_id = $payment->invoices()->first()->id;
|
||||||
|
|
||||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->payment->user_id;
|
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->payment->user_id;
|
||||||
|
|
||||||
$invoices = $payment->invoices;
|
|
||||||
|
|
||||||
$fields = new stdClass;
|
$fields = new stdClass;
|
||||||
|
|
||||||
$fields->payment_id = $payment->id;
|
$fields->payment_id = $payment->id;
|
||||||
|
$fields->invoice_id = $invoice_id;
|
||||||
$fields->client_id = $payment->client_id;
|
$fields->client_id = $payment->client_id;
|
||||||
$fields->user_id = $user_id;
|
$fields->user_id = $user_id;
|
||||||
$fields->company_id = $payment->company_id;
|
$fields->company_id = $payment->company_id;
|
||||||
$fields->activity_type_id = Activity::CREATE_PAYMENT;
|
$fields->activity_type_id = Activity::CREATE_PAYMENT;
|
||||||
|
|
||||||
if (count($invoices) == 0) {
|
$this->activity_repo->save($fields, $payment, $event->event_vars);
|
||||||
$this->activity_repo->save($fields, $payment, $event->event_vars);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,6 @@ class InvoiceEmailFailedActivity implements ShouldQueue
|
|||||||
$fields->client_contact_id = $event->invitation->client_contact_id;
|
$fields->client_contact_id = $event->invitation->client_contact_id;
|
||||||
$fields->company_id = $event->invitation->invoice->company_id;
|
$fields->company_id = $event->invitation->invoice->company_id;
|
||||||
$fields->activity_type_id = Activity::EMAIL_INVOICE_FAILED;
|
$fields->activity_type_id = Activity::EMAIL_INVOICE_FAILED;
|
||||||
$fields->notes = $event->message;
|
|
||||||
|
|
||||||
$this->activity_repo->save($fields, $event->invitation->invoice, $event->event_vars);
|
$this->activity_repo->save($fields, $event->invitation->invoice, $event->event_vars);
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ class PaymentEmailedActivity implements ShouldQueue
|
|||||||
|
|
||||||
$fields->user_id = $user_id;
|
$fields->user_id = $user_id;
|
||||||
$fields->client_id = $event->payment->client_id;
|
$fields->client_id = $event->payment->client_id;
|
||||||
|
$fields->client_contact_id = $event->contact->id;
|
||||||
$fields->company_id = $event->payment->company_id;
|
$fields->company_id = $event->payment->company_id;
|
||||||
$fields->activity_type_id = Activity::PAYMENT_EMAILED;
|
$fields->activity_type_id = Activity::PAYMENT_EMAILED;
|
||||||
$fields->payment_id = $event->payment->id;
|
$fields->payment_id = $event->payment->id;
|
||||||
|
@ -46,7 +46,6 @@ class ArchivedUserActivity implements ShouldQueue
|
|||||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->creating_user->id;
|
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->creating_user->id;
|
||||||
|
|
||||||
$fields->user_id = $user_id;
|
$fields->user_id = $user_id;
|
||||||
$fields->notes = $event->creating_user->present()->name.' Archived User '.$event->user->present()->name();
|
|
||||||
|
|
||||||
$fields->company_id = $event->company->id;
|
$fields->company_id = $event->company->id;
|
||||||
$fields->activity_type_id = Activity::ARCHIVE_USER;
|
$fields->activity_type_id = Activity::ARCHIVE_USER;
|
||||||
|
@ -46,7 +46,6 @@ class CreatedUserActivity implements ShouldQueue
|
|||||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->creating_user->id;
|
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->creating_user->id;
|
||||||
|
|
||||||
$fields->user_id = $user_id;
|
$fields->user_id = $user_id;
|
||||||
$fields->notes = $event->creating_user->present()->name().' Created the user '.$event->user->present()->name();
|
|
||||||
$fields->company_id = $event->company->id;
|
$fields->company_id = $event->company->id;
|
||||||
$fields->activity_type_id = Activity::CREATE_USER;
|
$fields->activity_type_id = Activity::CREATE_USER;
|
||||||
|
|
||||||
|
@ -51,8 +51,6 @@ class DeletedUserActivity implements ShouldQueue
|
|||||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->creating_user->id;
|
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->creating_user->id;
|
||||||
|
|
||||||
$fields->user_id = $user_id;
|
$fields->user_id = $user_id;
|
||||||
|
|
||||||
$fields->notes = $event->creating_user->present()->name().' Deleted the user '.$event->user->present()->name();
|
|
||||||
$fields->company_id = $event->company->id;
|
$fields->company_id = $event->company->id;
|
||||||
$fields->activity_type_id = Activity::DELETE_USER;
|
$fields->activity_type_id = Activity::DELETE_USER;
|
||||||
|
|
||||||
|
@ -45,7 +45,6 @@ class RestoredUserActivity implements ShouldQueue
|
|||||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->creating_user->id;
|
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->creating_user->id;
|
||||||
|
|
||||||
$fields->user_id = $user_id;
|
$fields->user_id = $user_id;
|
||||||
$fields->notes = $event->creating_user->present()->name().' Restored user '.$event->user->present()->name();
|
|
||||||
|
|
||||||
$fields->company_id = $event->company->id;
|
$fields->company_id = $event->company->id;
|
||||||
$fields->activity_type_id = Activity::RESTORE_USER;
|
$fields->activity_type_id = Activity::RESTORE_USER;
|
||||||
|
@ -45,7 +45,6 @@ class UpdatedUserActivity implements ShouldQueue
|
|||||||
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->creating_user->id;
|
$user_id = array_key_exists('user_id', $event->event_vars) ? $event->event_vars['user_id'] : $event->creating_user->id;
|
||||||
|
|
||||||
$fields->user_id = $user_id;
|
$fields->user_id = $user_id;
|
||||||
$fields->notes = $event->creating_user->present()->name().' Updated user '.$event->user->present()->name();
|
|
||||||
|
|
||||||
$fields->company_id = $event->company->id;
|
$fields->company_id = $event->company->id;
|
||||||
$fields->activity_type_id = Activity::UPDATE_USER;
|
$fields->activity_type_id = Activity::UPDATE_USER;
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Utils\Number;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -346,7 +347,7 @@ class Activity extends StaticModel
|
|||||||
*/
|
*/
|
||||||
public function contact()
|
public function contact()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(ClientContact::class)->withTrashed();
|
return $this->belongsTo(ClientContact::class, 'client_contact_id', 'id')->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -460,4 +461,90 @@ class Activity extends StaticModel
|
|||||||
{
|
{
|
||||||
return $this->belongsTo(Company::class);
|
return $this->belongsTo(Company::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function activity_string()
|
||||||
|
{
|
||||||
|
$intersect = [
|
||||||
|
':invoice',
|
||||||
|
':client',
|
||||||
|
':contact',
|
||||||
|
':user',
|
||||||
|
':vendor',
|
||||||
|
':quote',
|
||||||
|
':credit',
|
||||||
|
':payment',
|
||||||
|
':task',
|
||||||
|
':expense',
|
||||||
|
':purchase_order',
|
||||||
|
':subscription',
|
||||||
|
':recurring_invoice',
|
||||||
|
':recurring_expense',
|
||||||
|
':amount',
|
||||||
|
':balance',
|
||||||
|
':number',
|
||||||
|
':payment_amount',
|
||||||
|
':gateway',
|
||||||
|
':adjustment'
|
||||||
|
];
|
||||||
|
|
||||||
|
$found_variables = array_intersect(explode(" ",trans("texts.activity_{$this->activity_type_id}")), $intersect);
|
||||||
|
|
||||||
|
$replacements = [];
|
||||||
|
|
||||||
|
foreach($found_variables as $var)
|
||||||
|
$replacements = array_merge($replacements, $this->matchVar($var));
|
||||||
|
|
||||||
|
if($this->client)
|
||||||
|
$replacements['client'] = ['label' => $this?->client?->present()->name() ?? '', 'hashed_id' => $this->client->hashed_id ?? ''];
|
||||||
|
|
||||||
|
if($this->vendor)
|
||||||
|
$replacements['vendor'] = ['label' => $this?->vendor?->present()->name() ?? '', 'hashed_id' => $this->vendor->hashed_id ?? ''];
|
||||||
|
|
||||||
|
$replacements['activity_type_id'] = $this->activity_type_id;
|
||||||
|
$replacements['id'] = $this->id;
|
||||||
|
$replacements['hashed_id'] = $this->hashed_id;
|
||||||
|
$replacements['notes'] = $this->notes ?? '';
|
||||||
|
$replacements['created_at'] = $this->created_at ?? '';
|
||||||
|
$replacements['ip'] = $this->ip ?? '';
|
||||||
|
|
||||||
|
return $replacements;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function matchVar(string $variable)
|
||||||
|
{
|
||||||
|
$system = ctrans('texts.system');
|
||||||
|
|
||||||
|
match($variable) {
|
||||||
|
':invoice' => $translation = [substr($variable, 1) => [ 'label' => $this?->invoice?->number ?? '', 'hashed_id' => $this->invoice?->hashed_id ?? '']],
|
||||||
|
':user' => $translation = [substr($variable, 1) => [ 'label' => $this?->user?->present()->name() ?? $system, 'hashed_id' => $this->user->hashed_id ?? '']],
|
||||||
|
':quote' => $translation = [substr($variable, 1) => [ 'label' => $this?->quote?->number ?? '', 'hashed_id' => $this->quote->hashed_id ?? '']],
|
||||||
|
':credit' => $translation = [substr($variable, 1) => [ 'label' => $this?->credit?->number ?? '', 'hashed_id' => $this->credit->hashed_id ?? '']],
|
||||||
|
':payment' => $translation = [substr($variable, 1) => [ 'label' => $this?->payment?->number ?? '', 'hashed_id' => $this->payment->hashed_id ?? '']],
|
||||||
|
':task' => $translation = [substr($variable, 1) => [ 'label' => $this?->task?->number ?? '', 'hashed_id' => $this->task->hashed_id ?? '']],
|
||||||
|
':expense' => $translation = [substr($variable, 1) => [ 'label' => $this?->expense?->number ?? '', 'hashed_id' => $this->expense->hashed_id ?? '']],
|
||||||
|
':purchase_order' => $translation = [substr($variable, 1) => [ 'label' => $this?->purchase_order?->number ?? '', 'hashed_id' => $this->purchase_order->hashed_id ?? '']],
|
||||||
|
':subscription' => $translation = [substr($variable, 1) => [ 'label' => $this?->subscription?->number ?? '', 'hashed_id' => $this->subscription->hashed_id ?? '' ]],
|
||||||
|
':recurring_invoice' => $translation = [substr($variable, 1) =>[ 'label' => $this?->recurring_invoice?->number ??'', 'hashed_id' => $this->recurring_invoice->hashed_id ?? '']],
|
||||||
|
':recurring_expense' => $translation = [substr($variable, 1) => [ 'label' => $this?->recurring_expense?->number ??'', 'hashed_id' => $this->recurring_expense->hashed_id ?? '']],
|
||||||
|
':payment_amount' => $translation = [substr($variable, 1) =>[ 'label' => Number::formatMoney($this?->payment?->amount, $this?->payment?->client) ?? '', 'hashed_id' => '']],
|
||||||
|
':adjustment' => $translation = [substr($variable, 1) =>[ 'label' => Number::formatMoney($this?->payment?->refunded, $this?->payment?->client) ?? '', 'hashed_id' => '']],
|
||||||
|
':ip' => $translation = [ 'ip' => $this->ip ?? ''],
|
||||||
|
':contact' => $translation = $this->resolveContact(),
|
||||||
|
default => $translation = [],
|
||||||
|
};
|
||||||
|
|
||||||
|
return $translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resolveContact() : array
|
||||||
|
{
|
||||||
|
$contact = $this->contact ? $this->contact : $this->vendor_contact;
|
||||||
|
|
||||||
|
$entity = $this->contact ? $this->client : $this->vendor;
|
||||||
|
|
||||||
|
$contact_entity = $this->contact ? 'clients' : 'vendors';
|
||||||
|
|
||||||
|
return ['contact' => [ 'label' => $contact?->present()->name() ?? '', 'hashed_id' => $entity->hashed_id ?? '', 'contact_entity' => $contact_entity]];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,15 +11,17 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use App\Jobs\Entity\CreateRawPdf;
|
||||||
use App\Jobs\Util\WebhookHandler;
|
use App\Jobs\Util\WebhookHandler;
|
||||||
use App\Models\Traits\Excludable;
|
use App\Models\Traits\Excludable;
|
||||||
use App\Utils\Traits\MakesHash;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use App\Jobs\Vendor\CreatePurchaseOrderPdf;
|
||||||
use App\Utils\Traits\UserSessionAttributes;
|
use App\Utils\Traits\UserSessionAttributes;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException;
|
use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException;
|
||||||
use Illuminate\Support\Carbon;
|
|
||||||
use Illuminate\Support\Str;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BaseModel
|
* Class BaseModel
|
||||||
@ -45,8 +47,11 @@ use Illuminate\Support\Str;
|
|||||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel count()
|
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel count()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel create()
|
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel create()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel insert()
|
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel insert()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel service()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel whereHas()
|
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel whereHas()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel withTrashed()
|
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel withTrashed()
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\InvoiceInvitation | \App\Models\CreditInvitation | \App\Models\QuoteInvitation | \App\Models\RecurringInvoiceInvitation> $invitations
|
||||||
|
* @property-read int|null $invitations_count
|
||||||
*
|
*
|
||||||
* @method \App\Models\Company company()
|
* @method \App\Models\Company company()
|
||||||
* @method int companyId()
|
* @method int companyId()
|
||||||
@ -255,4 +260,30 @@ class BaseModel extends Model
|
|||||||
WebhookHandler::dispatch($event_id, $this, $this->company, $additional_data);
|
WebhookHandler::dispatch($event_id, $this, $this->company, $additional_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the base64 encoded PDF string of the entity
|
||||||
|
*/
|
||||||
|
public function fullscreenPdfViewer($invitation = null): string
|
||||||
|
{
|
||||||
|
|
||||||
|
if (! $invitation) {
|
||||||
|
if ($this->invitations()->exists()) {
|
||||||
|
$invitation = $this->invitations()->first();
|
||||||
|
} else {
|
||||||
|
$this->service()->createInvitations();
|
||||||
|
$invitation = $this->invitations()->first();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $invitation) {
|
||||||
|
throw new \Exception('Hard fail, could not create an invitation.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this instanceof \App\Models\PurchaseOrder)
|
||||||
|
return "data:application/pdf;base64,".base64_encode((new CreatePurchaseOrderPdf($invitation, $invitation->company->db))->rawPdf());
|
||||||
|
|
||||||
|
return "data:application/pdf;base64,".base64_encode((new CreateRawPdf($invitation, $invitation->company->db))->handle());
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,6 @@ use Laracasts\Presenter\PresentableTrait;
|
|||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientGatewayToken> $gateway_tokens
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientGatewayToken> $gateway_tokens
|
||||||
* @property-read int|null $gateway_tokens_count
|
* @property-read int|null $gateway_tokens_count
|
||||||
* @property-read mixed $hashed_id
|
* @property-read mixed $hashed_id
|
||||||
* @property-read \App\Models\GroupSetting|null $group_settings
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
|
||||||
* @property-read int|null $invoices_count
|
* @property-read int|null $invoices_count
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $ledger
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $ledger
|
||||||
@ -112,6 +111,7 @@ use Laracasts\Presenter\PresentableTrait;
|
|||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\SystemLog> $system_logs
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\SystemLog> $system_logs
|
||||||
* @property-read int|null $system_logs_count
|
* @property-read int|null $system_logs_count
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Task> $tasks
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Task> $tasks
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoice> $recurring_invoices
|
||||||
* @property-read int|null $tasks_count
|
* @property-read int|null $tasks_count
|
||||||
* @property-read \App\Models\User $user
|
* @property-read \App\Models\User $user
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel company()
|
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel company()
|
||||||
@ -175,26 +175,7 @@ use Laracasts\Presenter\PresentableTrait;
|
|||||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereTaxData($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|Client whereTaxData($value)
|
||||||
* @property int $is_tax_exempt
|
* @property int $is_tax_exempt
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereIsTaxExempt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|Client whereIsTaxExempt($value)
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientContact> $contacts
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Credit> $credits
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Expense> $expenses
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\GroupSetting> $group_settings
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientGatewayToken> $gateway_tokens
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $ledger
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Payment> $payments
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientContact> $primary_contact
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Project> $projects
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Quote> $quotes
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringExpense> $recurring_expenses
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoice> $recurring_invoices
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\SystemLog> $system_logs
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Task> $tasks
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
|
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientContact> $contacts
|
|
||||||
* @property int $has_valid_vat_number
|
* @property int $has_valid_vat_number
|
||||||
* @mixin \Eloquent
|
* @mixin \Eloquent
|
||||||
*/
|
*/
|
||||||
@ -464,6 +445,11 @@ class Client extends BaseModel implements HasLocalePreference
|
|||||||
return $this->belongsTo(Industry::class);
|
return $this->belongsTo(Industry::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function size()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Size::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function locale()
|
public function locale()
|
||||||
{
|
{
|
||||||
if (! $this->language()) {
|
if (! $this->language()) {
|
||||||
@ -544,9 +530,9 @@ class Client extends BaseModel implements HasLocalePreference
|
|||||||
return $this->settings->{$setting};
|
return $this->settings->{$setting};
|
||||||
} elseif (is_bool($this->settings->{$setting})) {
|
} elseif (is_bool($this->settings->{$setting})) {
|
||||||
return $this->settings->{$setting};
|
return $this->settings->{$setting};
|
||||||
} elseif (is_int($this->settings->{$setting})) { //10-08-2022 integer client values are not being passed back! This resolves it.
|
} elseif (is_int($this->settings->{$setting})) {
|
||||||
return $this->settings->{$setting};
|
return $this->settings->{$setting};
|
||||||
} elseif(is_float($this->settings->{$setting})) { //10-08-2022 integer client values are not being passed back! This resolves it.
|
} elseif(is_float($this->settings->{$setting})) {
|
||||||
return $this->settings->{$setting};
|
return $this->settings->{$setting};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,29 +212,29 @@ class Company extends BaseModel
|
|||||||
use AppSetup;
|
use AppSetup;
|
||||||
use \Awobaz\Compoships\Compoships;
|
use \Awobaz\Compoships\Compoships;
|
||||||
|
|
||||||
const ENTITY_RECURRING_INVOICE = 'recurring_invoice';
|
// const ENTITY_RECURRING_INVOICE = 'recurring_invoice';
|
||||||
|
|
||||||
const ENTITY_CREDIT = 'credit';
|
// const ENTITY_CREDIT = 'credit';
|
||||||
|
|
||||||
const ENTITY_QUOTE = 'quote';
|
// const ENTITY_QUOTE = 'quote';
|
||||||
|
|
||||||
const ENTITY_TASK = 'task';
|
// const ENTITY_TASK = 'task';
|
||||||
|
|
||||||
const ENTITY_EXPENSE = 'expense';
|
// const ENTITY_EXPENSE = 'expense';
|
||||||
|
|
||||||
const ENTITY_PROJECT = 'project';
|
// const ENTITY_PROJECT = 'project';
|
||||||
|
|
||||||
const ENTITY_VENDOR = 'vendor';
|
// const ENTITY_VENDOR = 'vendor';
|
||||||
|
|
||||||
const ENTITY_TICKET = 'ticket';
|
// const ENTITY_TICKET = 'ticket';
|
||||||
|
|
||||||
const ENTITY_PROPOSAL = 'proposal';
|
// const ENTITY_PROPOSAL = 'proposal';
|
||||||
|
|
||||||
const ENTITY_RECURRING_EXPENSE = 'recurring_expense';
|
// const ENTITY_RECURRING_EXPENSE = 'recurring_expense';
|
||||||
|
|
||||||
const ENTITY_RECURRING_TASK = 'task';
|
// const ENTITY_RECURRING_TASK = 'task';
|
||||||
|
|
||||||
const ENTITY_RECURRING_QUOTE = 'recurring_quote';
|
// const ENTITY_RECURRING_QUOTE = 'recurring_quote';
|
||||||
|
|
||||||
protected $presenter = CompanyPresenter::class;
|
protected $presenter = CompanyPresenter::class;
|
||||||
|
|
||||||
@ -309,7 +309,6 @@ class Company extends BaseModel
|
|||||||
'google_analytics_key',
|
'google_analytics_key',
|
||||||
'matomo_url',
|
'matomo_url',
|
||||||
'matomo_id',
|
'matomo_id',
|
||||||
'enable_e_invoice',
|
|
||||||
'client_can_register',
|
'client_can_register',
|
||||||
'enable_shop_api',
|
'enable_shop_api',
|
||||||
'invoice_task_timelog',
|
'invoice_task_timelog',
|
||||||
@ -368,31 +367,26 @@ class Company extends BaseModel
|
|||||||
|
|
||||||
protected $with = [];
|
protected $with = [];
|
||||||
|
|
||||||
public static $modules = [
|
// public static $modules = [
|
||||||
self::ENTITY_RECURRING_INVOICE => 1,
|
// self::ENTITY_RECURRING_INVOICE => 1,
|
||||||
self::ENTITY_CREDIT => 2,
|
// self::ENTITY_CREDIT => 2,
|
||||||
self::ENTITY_QUOTE => 4,
|
// self::ENTITY_QUOTE => 4,
|
||||||
self::ENTITY_TASK => 8,
|
// self::ENTITY_TASK => 8,
|
||||||
self::ENTITY_EXPENSE => 16,
|
// self::ENTITY_EXPENSE => 16,
|
||||||
self::ENTITY_PROJECT => 32,
|
// self::ENTITY_PROJECT => 32,
|
||||||
self::ENTITY_VENDOR => 64,
|
// self::ENTITY_VENDOR => 64,
|
||||||
self::ENTITY_TICKET => 128,
|
// self::ENTITY_TICKET => 128,
|
||||||
self::ENTITY_PROPOSAL => 256,
|
// self::ENTITY_PROPOSAL => 256,
|
||||||
self::ENTITY_RECURRING_EXPENSE => 512,
|
// self::ENTITY_RECURRING_EXPENSE => 512,
|
||||||
self::ENTITY_RECURRING_TASK => 1024,
|
// self::ENTITY_RECURRING_TASK => 1024,
|
||||||
self::ENTITY_RECURRING_QUOTE => 2048,
|
// self::ENTITY_RECURRING_QUOTE => 2048,
|
||||||
];
|
// ];
|
||||||
|
|
||||||
public function shouldCalculateTax()
|
public function shouldCalculateTax()
|
||||||
{
|
{
|
||||||
return $this->calculate_taxes && in_array($this->getSetting('country_id'), $this->tax_coverage_countries);
|
return $this->calculate_taxes && in_array($this->getSetting('country_id'), $this->tax_coverage_countries);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function refreshTaxData()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function documents()
|
public function documents()
|
||||||
{
|
{
|
||||||
return $this->morphMany(Document::class, 'documentable');
|
return $this->morphMany(Document::class, 'documentable');
|
||||||
|
@ -225,6 +225,11 @@ class Expense extends BaseModel
|
|||||||
return $this->belongsTo(Company::class);
|
return $this->belongsTo(Company::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function invoice()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Invoice::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function vendor()
|
public function vendor()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Vendor::class);
|
return $this->belongsTo(Vendor::class);
|
||||||
|
@ -14,6 +14,7 @@ namespace App\Models;
|
|||||||
use App\Utils\Ninja;
|
use App\Utils\Ninja;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use App\Utils\Traits\MakesDates;
|
use App\Utils\Traits\MakesDates;
|
||||||
|
use App\Jobs\Entity\CreateRawPdf;
|
||||||
use App\Helpers\Invoice\InvoiceSum;
|
use App\Helpers\Invoice\InvoiceSum;
|
||||||
use App\Jobs\Entity\CreateEntityPdf;
|
use App\Jobs\Entity\CreateEntityPdf;
|
||||||
use App\Utils\Traits\MakesReminders;
|
use App\Utils\Traits\MakesReminders;
|
||||||
@ -683,6 +684,7 @@ class Invoice extends BaseModel
|
|||||||
|
|
||||||
public function pdf_file_path($invitation = null, string $type = 'path', bool $portal = false)
|
public function pdf_file_path($invitation = null, string $type = 'path', bool $portal = false)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (! $invitation) {
|
if (! $invitation) {
|
||||||
if ($this->invitations()->exists()) {
|
if ($this->invitations()->exists()) {
|
||||||
$invitation = $this->invitations()->first();
|
$invitation = $this->invitations()->first();
|
||||||
@ -725,7 +727,6 @@ class Invoice extends BaseModel
|
|||||||
return Storage::disk(config('filesystems.default'))->{$type}($file_path);
|
return Storage::disk(config('filesystems.default'))->{$type}($file_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$file_exists = Storage::disk('public')->exists($file_path);
|
$file_exists = Storage::disk('public')->exists($file_path);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
@ -888,4 +889,38 @@ class Invoice extends BaseModel
|
|||||||
{
|
{
|
||||||
return ctrans('texts.invoice');
|
return ctrans('texts.invoice');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function taxTypeString($id)
|
||||||
|
{
|
||||||
|
match(intval($id)){
|
||||||
|
Product::PRODUCT_TYPE_PHYSICAL => $tax_type = ctrans('texts.physical_goods'),
|
||||||
|
Product::PRODUCT_TYPE_SERVICE => $tax_type = ctrans('texts.services'),
|
||||||
|
Product::PRODUCT_TYPE_DIGITAL => $tax_type = ctrans('texts.digital_products'),
|
||||||
|
Product::PRODUCT_TYPE_SHIPPING => $tax_type = ctrans('texts.shipping'),
|
||||||
|
Product::PRODUCT_TYPE_EXEMPT => $tax_type = ctrans('texts.tax_exempt'),
|
||||||
|
Product::PRODUCT_TYPE_REDUCED_TAX => $tax_type = ctrans('texts.reduced_tax'),
|
||||||
|
Product::PRODUCT_TYPE_OVERRIDE_TAX => $tax_type = ctrans('texts.override_tax'),
|
||||||
|
Product::PRODUCT_TYPE_ZERO_RATED => $tax_type = ctrans('texts.zero_rated'),
|
||||||
|
Product::PRODUCT_TYPE_REVERSE_TAX => $tax_type = ctrans('texts.reverse_tax'),
|
||||||
|
default => $tax_type = ctrans('texts.physical_goods'),
|
||||||
|
};
|
||||||
|
|
||||||
|
return $tax_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function typeIdString($id)
|
||||||
|
{
|
||||||
|
match($id) {
|
||||||
|
'1' => $type = ctrans('texts.product'),
|
||||||
|
'2' => $type = ctrans('texts.service'),
|
||||||
|
'3' => $type = ctrans('texts.gateway_fees'),
|
||||||
|
'4' => $type = ctrans('texts.gateway_fees'),
|
||||||
|
'5' => $type = ctrans('texts.late_fees'),
|
||||||
|
'6' => $type = ctrans('texts.expense'),
|
||||||
|
default => $type = ctrans('texts.product'),
|
||||||
|
};
|
||||||
|
|
||||||
|
return $type;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -522,17 +522,18 @@ class Payment extends BaseModel
|
|||||||
event(new PaymentWasVoided($this, $this->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
event(new PaymentWasVoided($this, $this->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// public function getLink()
|
|
||||||
// {
|
|
||||||
// return route('client.payments.show', $this->hashed_id);
|
|
||||||
// }
|
|
||||||
|
|
||||||
public function getLink() :string
|
public function getLink() :string
|
||||||
{
|
{
|
||||||
|
// if (Ninja::isHosted()) {
|
||||||
|
// $domain = isset($this->company->portal_domain) ? $this->company->portal_domain : $this->company->domain();
|
||||||
|
// } else {
|
||||||
|
// $domain = config('ninja.app_url');
|
||||||
|
// }
|
||||||
|
|
||||||
if (Ninja::isHosted()) {
|
if (Ninja::isHosted()) {
|
||||||
$domain = isset($this->company->portal_domain) ? $this->company->portal_domain : $this->company->domain();
|
$domain = $this->company->domain();
|
||||||
} else {
|
} else {
|
||||||
$domain = config('ninja.app_url');
|
$domain = strlen($this->company->portal_domain) > 5 ? $this->company->portal_domain : config('ninja.app_url');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $domain.'/client/payment/'.$this->client->contacts()->first()->contact_key.'/'.$this->hashed_id.'?next=/client/payments/'.$this->hashed_id;
|
return $domain.'/client/payment/'.$this->client->contacts()->first()->contact_key.'/'.$this->hashed_id.'?next=/client/payments/'.$this->hashed_id;
|
||||||
|
@ -34,7 +34,8 @@ class PaymentType extends StaticModel
|
|||||||
*/
|
*/
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
const CREDIT = 32;
|
const BANK_TRANSFER = 1;
|
||||||
|
const CASH = 2;
|
||||||
const ACH = 4;
|
const ACH = 4;
|
||||||
const VISA = 5;
|
const VISA = 5;
|
||||||
const MASTERCARD = 6;
|
const MASTERCARD = 6;
|
||||||
@ -53,11 +54,14 @@ class PaymentType extends StaticModel
|
|||||||
const MAESTRO = 20;
|
const MAESTRO = 20;
|
||||||
const SOLO = 21;
|
const SOLO = 21;
|
||||||
const SWITCH = 22;
|
const SWITCH = 22;
|
||||||
|
const VENMO = 24;
|
||||||
const ALIPAY = 27;
|
const ALIPAY = 27;
|
||||||
const SOFORT = 28;
|
const SOFORT = 28;
|
||||||
const SEPA = 29;
|
const SEPA = 29;
|
||||||
const GOCARDLESS = 30;
|
const GOCARDLESS = 30;
|
||||||
const CRYPTO = 31;
|
const CRYPTO = 31;
|
||||||
|
const CREDIT = 32;
|
||||||
|
const ZELLE = 33;
|
||||||
const MOLLIE_BANK_TRANSFER = 34;
|
const MOLLIE_BANK_TRANSFER = 34;
|
||||||
const KBC = 35;
|
const KBC = 35;
|
||||||
const BANCONTACT = 36;
|
const BANCONTACT = 36;
|
||||||
@ -76,10 +80,12 @@ class PaymentType extends StaticModel
|
|||||||
const BACS = 49;
|
const BACS = 49;
|
||||||
const STRIPE_BANK_TRANSFER = 50;
|
const STRIPE_BANK_TRANSFER = 50;
|
||||||
const CASH_APP = 51;
|
const CASH_APP = 51;
|
||||||
const VENMO = 24;
|
|
||||||
|
|
||||||
public array $type_names = [
|
public array $type_names = [
|
||||||
|
self::BANK_TRANSFER => 'payment_type_Bank Transfer',
|
||||||
|
self::CASH => 'payment_type_Cash',
|
||||||
self::CREDIT => 'payment_type_Credit',
|
self::CREDIT => 'payment_type_Credit',
|
||||||
|
self::ZELLE => 'payment_type_Zelle',
|
||||||
self::ACH => 'payment_type_ACH',
|
self::ACH => 'payment_type_ACH',
|
||||||
self::VISA => 'payment_type_Visa Card',
|
self::VISA => 'payment_type_Visa Card',
|
||||||
self::MASTERCARD => 'payment_type_MasterCard',
|
self::MASTERCARD => 'payment_type_MasterCard',
|
||||||
|
@ -202,5 +202,16 @@ class Scheduler extends BaseModel
|
|||||||
$this->save();
|
$this->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function adjustOffset(): void
|
||||||
|
{
|
||||||
|
if (! $this->next_run) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$offset = $this->company->timezone_offset();
|
||||||
|
|
||||||
|
$this->next_run = $this->next_run->copy()->addSeconds($offset);
|
||||||
|
$this->save();
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,8 @@ use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundExceptio
|
|||||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel newQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel newQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel query()
|
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel query()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel find()
|
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel find()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel with()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel withTrashed()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel findOrFail()
|
* @method static \Illuminate\Database\Eloquent\Builder|StaticModel findOrFail()
|
||||||
* @mixin \Eloquent
|
* @mixin \Eloquent
|
||||||
*/
|
*/
|
||||||
|
71
app/Notifications/Ninja/GenericNinjaAdminNotification.php
Normal file
71
app/Notifications/Ninja/GenericNinjaAdminNotification.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Notifications\Ninja;
|
||||||
|
|
||||||
|
use Illuminate\Notifications\Messages\SlackMessage;
|
||||||
|
use Illuminate\Notifications\Notification;
|
||||||
|
|
||||||
|
class GenericNinjaAdminNotification extends Notification
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct(protected array $message_array)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the notification's delivery channels.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function via($notifiable)
|
||||||
|
{
|
||||||
|
return ['slack'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the mail representation of the notification.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
*/
|
||||||
|
public function toMail($notifiable)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the array representation of the notification.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($notifiable)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toSlack($notifiable)
|
||||||
|
{
|
||||||
|
$content = '';
|
||||||
|
|
||||||
|
foreach($this->message_array as $message) {
|
||||||
|
$content .= $message . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return (new SlackMessage)
|
||||||
|
->success()
|
||||||
|
->from(ctrans('texts.notification_bot'))
|
||||||
|
->image('https://app.invoiceninja.com/favicon.png')
|
||||||
|
->content($content);
|
||||||
|
}
|
||||||
|
}
|
@ -525,7 +525,7 @@ class BaseDriver extends AbstractPaymentDriver
|
|||||||
$invoices = Invoice::whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->withTrashed()->get();
|
$invoices = Invoice::whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->withTrashed()->get();
|
||||||
|
|
||||||
$invoices->each(function ($invoice) {
|
$invoices->each(function ($invoice) {
|
||||||
$invoice->service()->touchPdf();
|
$invoice->service()->deletePdf();
|
||||||
});
|
});
|
||||||
|
|
||||||
$invoices->first()->invitations->each(function ($invitation) use ($nmo) {
|
$invoices->first()->invitations->each(function ($invitation) use ($nmo) {
|
||||||
@ -570,7 +570,7 @@ class BaseDriver extends AbstractPaymentDriver
|
|||||||
$invoices = Invoice::whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->withTrashed()->get();
|
$invoices = Invoice::whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->withTrashed()->get();
|
||||||
|
|
||||||
$invoices->each(function ($invoice) {
|
$invoices->each(function ($invoice) {
|
||||||
$invoice->service()->touchPdf();
|
$invoice->service()->deletePdf();
|
||||||
});
|
});
|
||||||
|
|
||||||
$invoices->first()->invitations->each(function ($invitation) use ($nmo) {
|
$invoices->first()->invitations->each(function ($invitation) use ($nmo) {
|
||||||
@ -732,6 +732,9 @@ class BaseDriver extends AbstractPaymentDriver
|
|||||||
|
|
||||||
$invoices_string = \implode(', ', collect($this->payment_hash->invoices())->pluck('invoice_number')->toArray()) ?: null;
|
$invoices_string = \implode(', ', collect($this->payment_hash->invoices())->pluck('invoice_number')->toArray()) ?: null;
|
||||||
|
|
||||||
|
if (!$invoices_string)
|
||||||
|
return str_replace(["*","<",">","'",'"'], "", $this->client->company->present()->name());
|
||||||
|
|
||||||
$invoices_string = str_replace(["*","<",">","'",'"'], "-", $invoices_string);
|
$invoices_string = str_replace(["*","<",">","'",'"'], "-", $invoices_string);
|
||||||
|
|
||||||
$invoices_string = "I-".$invoices_string;
|
$invoices_string = "I-".$invoices_string;
|
||||||
|
@ -70,12 +70,15 @@ class CreditCard
|
|||||||
|
|
||||||
$response = $this->eway_driver->init()->eway->createCustomer(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction);
|
$response = $this->eway_driver->init()->eway->createCustomer(\Eway\Rapid\Enum\ApiMethod::DIRECT, $transaction);
|
||||||
|
|
||||||
$response_status = ErrorCode::getStatus($response->ResponseMessage);
|
if($response->getErrors()) {
|
||||||
|
|
||||||
|
$response_status['message'] = \Eway\Rapid::getMessage($response->getErrors()[0]);
|
||||||
|
|
||||||
if (! $response_status['success']) {
|
|
||||||
$this->eway_driver->sendFailureMail($response_status['message']);
|
$this->eway_driver->sendFailureMail($response_status['message']);
|
||||||
|
|
||||||
throw new PaymentFailed($response_status['message'], 400);
|
$this->logResponse($response);
|
||||||
|
|
||||||
|
throw new PaymentFailed($response_status['message'] ?? 'Unknown response from gateway, please contact you merchant.', 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
//success
|
//success
|
||||||
@ -94,6 +97,8 @@ class CreditCard
|
|||||||
|
|
||||||
$token = $this->eway_driver->storeGatewayToken($cgt, []);
|
$token = $this->eway_driver->storeGatewayToken($cgt, []);
|
||||||
|
|
||||||
|
$this->logResponse($response);
|
||||||
|
|
||||||
return $token;
|
return $token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +140,7 @@ class CreditCard
|
|||||||
|
|
||||||
$amount = array_sum(array_column($this->eway_driver->payment_hash->invoices(), 'amount')) + $this->eway_driver->payment_hash->fee_total;
|
$amount = array_sum(array_column($this->eway_driver->payment_hash->invoices(), 'amount')) + $this->eway_driver->payment_hash->fee_total;
|
||||||
|
|
||||||
$description = "Invoices: {$invoice_numbers} for {$amount} for client {$this->eway_driver->client->present()->name()}";
|
// $description = "Invoices: {$invoice_numbers} for {$amount} for client {$this->eway_driver->client->present()->name()}";
|
||||||
|
|
||||||
$transaction = [
|
$transaction = [
|
||||||
'Payment' => [
|
'Payment' => [
|
||||||
@ -152,29 +157,6 @@ class CreditCard
|
|||||||
|
|
||||||
$this->logResponse($response);
|
$this->logResponse($response);
|
||||||
|
|
||||||
// if(!$response || !property_exists($response, 'ResponseMessage'))
|
|
||||||
// throw new PaymentFailed('The gateway did not return a valid response. Please check your gateway credentials.', 400);
|
|
||||||
|
|
||||||
// $response_status = ErrorCode::getStatus($response->ResponseMessage);
|
|
||||||
|
|
||||||
// if(!$response_status['success']){
|
|
||||||
|
|
||||||
// if($response->getErrors())
|
|
||||||
// {
|
|
||||||
// $message = false;
|
|
||||||
|
|
||||||
// foreach ($response->getErrors() as $error) {
|
|
||||||
// $message = \Eway\Rapid::getMessage($error);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// $return_message = $message ?: $response_status['message'];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// $this->eway_driver->sendFailureMail($response_status['message']);
|
|
||||||
|
|
||||||
// throw new PaymentFailed($response_status['message'], 400);
|
|
||||||
// }
|
|
||||||
|
|
||||||
if ($response->TransactionStatus) {
|
if ($response->TransactionStatus) {
|
||||||
$payment = $this->storePayment($response);
|
$payment = $this->storePayment($response);
|
||||||
} else {
|
} else {
|
||||||
|
@ -123,6 +123,7 @@ class CreditCard
|
|||||||
'city' => $this->paytrace->client->city,
|
'city' => $this->paytrace->client->city,
|
||||||
'state' => $this->paytrace->client->state,
|
'state' => $this->paytrace->client->state,
|
||||||
'zip' => $this->paytrace->client->postal_code,
|
'zip' => $this->paytrace->client->postal_code,
|
||||||
|
'country' => $this->paytrace->client->country->iso_3166_2
|
||||||
];
|
];
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
@ -177,6 +178,7 @@ class CreditCard
|
|||||||
'customer_id' => $token,
|
'customer_id' => $token,
|
||||||
'integrator_id' => $this->paytrace->company_gateway->getConfigField('integratorId'),
|
'integrator_id' => $this->paytrace->company_gateway->getConfigField('integratorId'),
|
||||||
'amount' => $request->input('amount_with_fee'),
|
'amount' => $request->input('amount_with_fee'),
|
||||||
|
'invoice_id' => $this->harvestInvoiceId(),
|
||||||
];
|
];
|
||||||
|
|
||||||
$response = $this->paytrace->gatewayRequest('/v1/transactions/sale/by_customer', $data);
|
$response = $this->paytrace->gatewayRequest('/v1/transactions/sale/by_customer', $data);
|
||||||
|
@ -106,7 +106,7 @@ class iDeal
|
|||||||
'gateway_type_id' => GatewayType::IDEAL,
|
'gateway_type_id' => GatewayType::IDEAL,
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->stripe->createPayment($data, Payment::STATUS_PENDING);
|
$this->stripe->createPayment($data, Payment::STATUS_COMPLETED);
|
||||||
|
|
||||||
SystemLogger::dispatch(
|
SystemLogger::dispatch(
|
||||||
['response' => $this->stripe->payment_hash->data, 'data' => $data],
|
['response' => $this->stripe->payment_hash->data, 'data' => $data],
|
||||||
|
@ -122,7 +122,7 @@ class PaymentMigrationRepository extends BaseRepository
|
|||||||
|
|
||||||
$invoices = Invoice::whereIn('id', array_column($data['invoices'], 'invoice_id'))->withTrashed()->get();
|
$invoices = Invoice::whereIn('id', array_column($data['invoices'], 'invoice_id'))->withTrashed()->get();
|
||||||
|
|
||||||
$payment->invoices()->saveMany($invoices);
|
$payment->invoices()->saveMany($invoices); // 1:1 relationship so this is ok
|
||||||
|
|
||||||
$payment->invoices->each(function ($inv) use ($invoice_totals, $refund_totals, $payment) {
|
$payment->invoices->each(function ($inv) use ($invoice_totals, $refund_totals, $payment) {
|
||||||
if ($payment->status_id != Payment::STATUS_CANCELLED || ! $payment->is_deleted) {
|
if ($payment->status_id != Payment::STATUS_CANCELLED || ! $payment->is_deleted) {
|
||||||
|
@ -11,19 +11,20 @@
|
|||||||
|
|
||||||
namespace App\Repositories;
|
namespace App\Repositories;
|
||||||
|
|
||||||
use App\Events\Payment\PaymentWasCreated;
|
use App\Utils\Ninja;
|
||||||
use App\Events\Payment\PaymentWasDeleted;
|
|
||||||
use App\Jobs\Credit\ApplyCreditPayment;
|
|
||||||
use App\Libraries\Currency\Conversion\CurrencyApi;
|
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\Credit;
|
use App\Models\Credit;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
use App\Utils\Ninja;
|
use App\Models\Paymentable;
|
||||||
use App\Utils\Traits\MakesHash;
|
|
||||||
use App\Utils\Traits\SavesDocuments;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use App\Utils\Traits\SavesDocuments;
|
||||||
|
use App\Jobs\Credit\ApplyCreditPayment;
|
||||||
|
use App\Events\Payment\PaymentWasCreated;
|
||||||
|
use App\Events\Payment\PaymentWasDeleted;
|
||||||
|
use App\Libraries\Currency\Conversion\CurrencyApi;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PaymentRepository.
|
* PaymentRepository.
|
||||||
@ -138,7 +139,7 @@ class PaymentRepository extends BaseRepository
|
|||||||
|
|
||||||
$invoices = Invoice::withTrashed()->whereIn('id', array_column($data['invoices'], 'invoice_id'))->get();
|
$invoices = Invoice::withTrashed()->whereIn('id', array_column($data['invoices'], 'invoice_id'))->get();
|
||||||
|
|
||||||
$payment->invoices()->saveMany($invoices);
|
// $payment->invoices()->saveMany($invoices); //25-06-2023
|
||||||
|
|
||||||
//todo optimize this into a single query
|
//todo optimize this into a single query
|
||||||
foreach ($data['invoices'] as $paid_invoice) {
|
foreach ($data['invoices'] as $paid_invoice) {
|
||||||
@ -146,6 +147,16 @@ class PaymentRepository extends BaseRepository
|
|||||||
$invoice = $invoices->firstWhere('id', $paid_invoice['invoice_id']);
|
$invoice = $invoices->firstWhere('id', $paid_invoice['invoice_id']);
|
||||||
|
|
||||||
if ($invoice) {
|
if ($invoice) {
|
||||||
|
|
||||||
|
//25-06-2023
|
||||||
|
|
||||||
|
$paymentable = new Paymentable();
|
||||||
|
$paymentable->payment_id = $payment->id;
|
||||||
|
$paymentable->paymentable_id = $invoice->id;
|
||||||
|
$paymentable->paymentable_type = 'invoices';
|
||||||
|
$paymentable->amount = $paid_invoice['amount'];
|
||||||
|
$paymentable->save();
|
||||||
|
|
||||||
$invoice = $invoice->service()
|
$invoice = $invoice->service()
|
||||||
->markSent()
|
->markSent()
|
||||||
->applyPayment($payment, $paid_invoice['amount'])
|
->applyPayment($payment, $paid_invoice['amount'])
|
||||||
@ -153,26 +164,30 @@ class PaymentRepository extends BaseRepository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//payment is made, but not to any invoice, therefore we are applying the payment to the clients paid_to_date only
|
|
||||||
//01-07-2020 i think we were duplicating the paid to date here.
|
|
||||||
//$payment->client->service()->updatePaidToDate($payment->amount)->save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array_key_exists('credits', $data) && is_array($data['credits'])) {
|
if (array_key_exists('credits', $data) && is_array($data['credits'])) {
|
||||||
$credit_totals = array_sum(array_column($data['credits'], 'amount'));
|
$credit_totals = array_sum(array_column($data['credits'], 'amount'));
|
||||||
|
|
||||||
// $credits = Credit::whereIn('id', $this->transformKeys(array_column($data['credits'], 'credit_id')))->get();
|
|
||||||
|
|
||||||
$credits = Credit::whereIn('id', array_column($data['credits'], 'credit_id'))->get();
|
$credits = Credit::whereIn('id', array_column($data['credits'], 'credit_id'))->get();
|
||||||
|
|
||||||
$payment->credits()->saveMany($credits);
|
// $payment->credits()->saveMany($credits);
|
||||||
|
|
||||||
//todo optimize into a single query
|
//todo optimize into a single query
|
||||||
foreach ($data['credits'] as $paid_credit) {
|
foreach ($data['credits'] as $paid_credit) {
|
||||||
// $credit = Credit::withTrashed()->find($paid_credit['credit_id']);
|
|
||||||
$credit = $credits->firstWhere('id', $paid_credit['credit_id']);
|
$credit = $credits->firstWhere('id', $paid_credit['credit_id']);
|
||||||
|
|
||||||
if ($credit) {
|
if ($credit) {
|
||||||
|
|
||||||
|
$paymentable = new Paymentable();
|
||||||
|
$paymentable->payment_id = $payment->id;
|
||||||
|
$paymentable->paymentable_id = $credit->id;
|
||||||
|
$paymentable->paymentable_type = Credit::class;
|
||||||
|
$paymentable->amount = $paid_credit['amount'];
|
||||||
|
$paymentable->save();
|
||||||
|
|
||||||
$credit = $credit->service()->markSent()->save();
|
$credit = $credit->service()->markSent()->save();
|
||||||
(new ApplyCreditPayment($credit, $payment, $paid_credit['amount'], $credit->company))->handle();
|
(new ApplyCreditPayment($credit, $payment, $paid_credit['amount'], $credit->company))->handle();
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,7 @@ class SchedulerRepository extends BaseRepository
|
|||||||
|
|
||||||
$scheduler->save();
|
$scheduler->save();
|
||||||
|
|
||||||
/** 18-5-2023 set client specific send times. */
|
$scheduler->adjustOffset();
|
||||||
$scheduler->calculateNextRun();
|
|
||||||
|
|
||||||
return $scheduler->fresh();
|
return $scheduler->fresh();
|
||||||
}
|
}
|
||||||
|
@ -38,13 +38,15 @@ class TaskStatusRepository extends BaseRepository
|
|||||||
|
|
||||||
public function archive($task_status)
|
public function archive($task_status)
|
||||||
{
|
{
|
||||||
$task_status = TaskStatus::where('id', $task_status->id)
|
$task_status = TaskStatus::withTrashed()
|
||||||
|
->where('id', $task_status->id)
|
||||||
->where('company_id', $task_status->company_id)
|
->where('company_id', $task_status->company_id)
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
$new_status = $task_status ? $task_status->id : null;
|
$new_status = $task_status ? $task_status->id : null;
|
||||||
|
|
||||||
Task::where('status_id', $task_status->id)
|
Task::withTrashed()
|
||||||
|
->where('status_id', $task_status->id)
|
||||||
->where('company_id', $task_status->company_id)
|
->where('company_id', $task_status->company_id)
|
||||||
->update(['status_id' => $new_status]);
|
->update(['status_id' => $new_status]);
|
||||||
|
|
||||||
|
@ -76,6 +76,8 @@ class ChartService
|
|||||||
$currencies = $this->getCurrencyCodes();
|
$currencies = $this->getCurrencyCodes();
|
||||||
|
|
||||||
$data = [];
|
$data = [];
|
||||||
|
$data['start_date'] = $start_date;
|
||||||
|
$data['end_date'] = $end_date;
|
||||||
|
|
||||||
foreach ($currencies as $key => $value) {
|
foreach ($currencies as $key => $value) {
|
||||||
$data[$key]['invoices'] = $this->getInvoiceChartQuery($start_date, $end_date, $key);
|
$data[$key]['invoices'] = $this->getInvoiceChartQuery($start_date, $end_date, $key);
|
||||||
@ -97,6 +99,9 @@ class ChartService
|
|||||||
|
|
||||||
$data['currencies'] = $this->getCurrencyCodes();
|
$data['currencies'] = $this->getCurrencyCodes();
|
||||||
|
|
||||||
|
$data['start_date'] = $start_date;
|
||||||
|
$data['end_date'] = $end_date;
|
||||||
|
|
||||||
$revenue = $this->getRevenue($start_date, $end_date);
|
$revenue = $this->getRevenue($start_date, $end_date);
|
||||||
$outstanding = $this->getOutstanding($start_date, $end_date);
|
$outstanding = $this->getOutstanding($start_date, $end_date);
|
||||||
$expenses = $this->getExpenses($start_date, $end_date);
|
$expenses = $this->getExpenses($start_date, $end_date);
|
||||||
|
@ -137,7 +137,7 @@ class ApplyPayment
|
|||||||
->updateBalance($this->amount_applied * -1)
|
->updateBalance($this->amount_applied * -1)
|
||||||
->updatePaidToDate($this->amount_applied)
|
->updatePaidToDate($this->amount_applied)
|
||||||
->updateStatus()
|
->updateStatus()
|
||||||
->touchPdf()
|
->deletePdf()
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
$this->credit
|
$this->credit
|
||||||
@ -147,7 +147,7 @@ class ApplyPayment
|
|||||||
event(new InvoiceWasUpdated($this->invoice, $this->invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
event(new InvoiceWasUpdated($this->invoice, $this->invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||||
|
|
||||||
if ((int) $this->invoice->balance == 0) {
|
if ((int) $this->invoice->balance == 0) {
|
||||||
$this->invoice->service()->touchPdf();
|
$this->invoice->service()->deletePdf();
|
||||||
$this->invoice = $this->invoice->fresh();
|
$this->invoice = $this->invoice->fresh();
|
||||||
event(new InvoiceWasPaid($this->invoice, $this->payment, $this->payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
event(new InvoiceWasPaid($this->invoice, $this->payment, $this->payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||||
}
|
}
|
||||||
|
@ -11,15 +11,17 @@
|
|||||||
|
|
||||||
namespace App\Services\Credit;
|
namespace App\Services\Credit;
|
||||||
|
|
||||||
use App\Factory\PaymentFactory;
|
use App\Utils\Ninja;
|
||||||
use App\Jobs\Entity\CreateEntityPdf;
|
|
||||||
use App\Jobs\Util\UnlinkFile;
|
|
||||||
use App\Models\Credit;
|
use App\Models\Credit;
|
||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
use App\Models\PaymentType;
|
use App\Models\PaymentType;
|
||||||
|
use App\Jobs\Util\UnlinkFile;
|
||||||
|
use App\Factory\PaymentFactory;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use App\Jobs\Entity\CreateEntityPdf;
|
||||||
use App\Repositories\CreditRepository;
|
use App\Repositories\CreditRepository;
|
||||||
use App\Repositories\PaymentRepository;
|
use App\Repositories\PaymentRepository;
|
||||||
use App\Utils\Traits\MakesHash;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
class CreditService
|
class CreditService
|
||||||
{
|
{
|
||||||
@ -235,7 +237,24 @@ class CreditService
|
|||||||
public function deletePdf()
|
public function deletePdf()
|
||||||
{
|
{
|
||||||
$this->credit->invitations->each(function ($invitation) {
|
$this->credit->invitations->each(function ($invitation) {
|
||||||
(new UnlinkFile(config('filesystems.default'), $this->credit->client->credit_filepath($invitation).$this->credit->numberFormatter().'.pdf'))->handle();
|
// (new UnlinkFile(config('filesystems.default'), $this->credit->client->credit_filepath($invitation).$this->credit->numberFormatter().'.pdf'))->handle();
|
||||||
|
|
||||||
|
//30-06-2023
|
||||||
|
try {
|
||||||
|
// if (Storage::disk(config('filesystems.default'))->exists($this->invoice->client->invoice_filepath($invitation).$this->invoice->numberFormatter().'.pdf')) {
|
||||||
|
Storage::disk(config('filesystems.default'))->delete($this->credit->client->credit_filepath($invitation).$this->credit->numberFormatter().'.pdf');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (Ninja::isHosted() && Storage::disk('public')->exists($this->invoice->client->invoice_filepath($invitation).$this->invoice->numberFormatter().'.pdf')) {
|
||||||
|
if (Ninja::isHosted()) {
|
||||||
|
Storage::disk('public')->delete($this->credit->client->credit_filepath($invitation).$this->credit->numberFormatter().'.pdf');
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
nlog($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -42,7 +42,7 @@ class MarkSent
|
|||||||
->setStatus(Credit::STATUS_SENT)
|
->setStatus(Credit::STATUS_SENT)
|
||||||
->applyNumber()
|
->applyNumber()
|
||||||
->adjustBalance($this->credit->amount)
|
->adjustBalance($this->credit->amount)
|
||||||
->touchPdf()
|
->deletePdf()
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
$this->client
|
$this->client
|
||||||
|
@ -432,6 +432,7 @@ class Email implements ShouldQueue
|
|||||||
$this->setGmailMailer();
|
$this->setGmailMailer();
|
||||||
return $this;
|
return $this;
|
||||||
case 'office365':
|
case 'office365':
|
||||||
|
case 'microsoft':
|
||||||
$this->mailer = 'office365';
|
$this->mailer = 'office365';
|
||||||
$this->setOfficeMailer();
|
$this->setOfficeMailer();
|
||||||
return $this;
|
return $this;
|
||||||
@ -445,7 +446,8 @@ class Email implements ShouldQueue
|
|||||||
return $this;
|
return $this;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
$this->mailer = config('mail.default');
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Ninja::isSelfHost()) {
|
if (Ninja::isSelfHost()) {
|
||||||
|
@ -168,7 +168,7 @@ class EmailDefaults
|
|||||||
*/
|
*/
|
||||||
private function setBody(): self
|
private function setBody(): self
|
||||||
{
|
{
|
||||||
|
|
||||||
if (strlen($this->email->email_object->body) > 3) {
|
if (strlen($this->email->email_object->body) > 3) {
|
||||||
// A Custom Message has been set in the email screen.
|
// A Custom Message has been set in the email screen.
|
||||||
// return $this;
|
// return $this;
|
||||||
@ -181,7 +181,7 @@ class EmailDefaults
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->email->email_object->text_body = strip_tags($this->email->email_object->body);
|
$this->email->email_object->text_body = strip_tags($this->email->email_object->body);
|
||||||
|
|
||||||
if ($this->template == 'email.template.custom') {
|
if ($this->template == 'email.template.custom') {
|
||||||
$this->email->email_object->body = (str_replace('$body', $this->email->email_object->body, str_replace(["\r","\n"], "", $this->email->email_object->settings->email_style_custom)));
|
$this->email->email_object->body = (str_replace('$body', $this->email->email_object->body, str_replace(["\r","\n"], "", $this->email->email_object->settings->email_style_custom)));
|
||||||
}
|
}
|
||||||
@ -230,7 +230,7 @@ class EmailDefaults
|
|||||||
|
|
||||||
$this->email->email_object->subject = strtr($this->email->email_object->subject, $this->email->email_object->variables);
|
$this->email->email_object->subject = strtr($this->email->email_object->subject, $this->email->email_object->variables);
|
||||||
|
|
||||||
|
|
||||||
//06-06-2023 ensure we do not parse markdown in custom templates
|
//06-06-2023 ensure we do not parse markdown in custom templates
|
||||||
if ($this->template != 'custom' && $this->template != 'email.template.custom') {
|
if ($this->template != 'custom' && $this->template != 'email.template.custom') {
|
||||||
$this->email->email_object->body = $this->parseMarkdownToHtml($this->email->email_object->body);
|
$this->email->email_object->body = $this->parseMarkdownToHtml($this->email->email_object->body);
|
||||||
@ -303,20 +303,6 @@ class EmailDefaults
|
|||||||
$this->email->email_object->entity instanceof Quote ||
|
$this->email->email_object->entity instanceof Quote ||
|
||||||
$this->email->email_object->entity instanceof Credit)) {
|
$this->email->email_object->entity instanceof Credit)) {
|
||||||
$pdf = ((new CreateRawPdf($this->email->email_object->invitation, $this->email->company->db))->handle());
|
$pdf = ((new CreateRawPdf($this->email->email_object->invitation, $this->email->company->db))->handle());
|
||||||
if ($this->email->email_object->settings->enable_e_invoice && $this->email->email_object->entity instanceof Invoice) {
|
|
||||||
|
|
||||||
$xinvoice_path = $this->email->email_object->entity->service()->getEInvoice();
|
|
||||||
|
|
||||||
// $xinvoice_path = (new CreateEInvoice($this->email->email_object->entity, true, stream_get_meta_data($tempfile)['uri']))->handle();
|
|
||||||
// $this->email->email_object->attachments = array_merge($this->email->email_object->attachments, [['file' => base64_encode($pdf), 'name' => $this->email->email_object->entity->numberFormatter().'.pdf']]);
|
|
||||||
|
|
||||||
if(Storage::disk(config('filesystems.default'))->exists($xinvoice_path))
|
|
||||||
$this->email->email_object->attachments = array_merge($this->email->email_object->attachments, [['file' => base64_encode(Storage::get($xinvoice_path)), 'name' => explode(".", $this->email->email_object->entity->getFileName('xml'))[0]."-xinvoice.xml"]]);
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->email->email_object->attachments = array_merge($this->email->email_object->attachments, [['file' => base64_encode($pdf), 'name' => $this->email->email_object->entity->numberFormatter().'.pdf']]);
|
|
||||||
}
|
|
||||||
$this->email->email_object->attachments = array_merge($this->email->email_object->attachments, [['file' => base64_encode($pdf), 'name' => $this->email->email_object->entity->numberFormatter().'.pdf']]);
|
$this->email->email_object->attachments = array_merge($this->email->email_object->attachments, [['file' => base64_encode($pdf), 'name' => $this->email->email_object->entity->numberFormatter().'.pdf']]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,15 +84,15 @@ class ApplyPayment extends AbstractService
|
|||||||
/* Update Pivot Record amount */
|
/* Update Pivot Record amount */
|
||||||
$this->payment->invoices->each(function ($inv) use ($amount_paid) {
|
$this->payment->invoices->each(function ($inv) use ($amount_paid) {
|
||||||
if ($inv->id == $this->invoice->id) {
|
if ($inv->id == $this->invoice->id) {
|
||||||
$inv->pivot->amount = ($amount_paid * -1);
|
// $inv->pivot->amount = ($amount_paid * -1);
|
||||||
$inv->pivot->save();
|
// $inv->pivot->save();
|
||||||
|
//25-06-2023
|
||||||
$inv->paid_to_date += floatval($amount_paid * -1);
|
$inv->paid_to_date += floatval($amount_paid * -1);
|
||||||
$inv->save();
|
$inv->save();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->invoice->service()->applyNumber()->workFlow()->touchPdf()->save();
|
$this->invoice->service()->applyNumber()->workFlow()->deletePdf()->save();
|
||||||
|
|
||||||
return $this->invoice;
|
return $this->invoice;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,9 @@ class ZugferdEInvoice extends AbstractService
|
|||||||
if (!empty($item->notes)){
|
if (!empty($item->notes)){
|
||||||
$xrechnung->setDocumentPositionProductDetails($item->product_key, $item->notes);
|
$xrechnung->setDocumentPositionProductDetails($item->product_key, $item->notes);
|
||||||
}
|
}
|
||||||
$xrechnung->setDocumentPositionProductDetails($item->product_key);
|
else {
|
||||||
|
$xrechnung->setDocumentPositionProductDetails($item->product_key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!empty($item->notes)){
|
if (!empty($item->notes)){
|
||||||
@ -159,13 +161,7 @@ class ZugferdEInvoice extends AbstractService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$xrechnung->setDocumentSummation($this->invoice->amount, $this->invoice->balance, $invoicing_data->getSubTotal(), $invoicing_data->getTotalSurcharges(), $invoicing_data->getTotalDiscount(), $invoicing_data->getSubTotal(), $invoicing_data->getItemTotalTaxes(), 0.0, $this->invoice->amount-$this->invoice->balance);
|
||||||
if ($this->invoice->isPartial()) {
|
|
||||||
$xrechnung->setDocumentSummation($this->invoice->amount, $this->invoice->balance, $invoicing_data->getSubTotal(), $invoicing_data->getTotalSurcharges(), $invoicing_data->getTotalDiscount(), $invoicing_data->getSubTotal(), $invoicing_data->getItemTotalTaxes(), null, $this->invoice->partial);
|
|
||||||
} else {
|
|
||||||
$xrechnung->setDocumentSummation($this->invoice->amount, $this->invoice->balance, $invoicing_data->getSubTotal(), $invoicing_data->getTotalSurcharges(), $invoicing_data->getTotalDiscount(), $invoicing_data->getSubTotal(), $invoicing_data->getItemTotalTaxes(), null, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
foreach ($this->tax_map as $item){
|
foreach ($this->tax_map as $item){
|
||||||
$xrechnung->addDocumentTax($item["tax_type"], "VAT", $item["net_amount"], $item["tax_rate"]*$item["net_amount"], $item["tax_rate"]*100);
|
$xrechnung->addDocumentTax($item["tax_type"], "VAT", $item["net_amount"], $item["tax_rate"]*$item["net_amount"], $item["tax_rate"]*100);
|
||||||
@ -236,7 +232,8 @@ class ZugferdEInvoice extends AbstractService
|
|||||||
}
|
}
|
||||||
return $tax_type;
|
return $tax_type;
|
||||||
}
|
}
|
||||||
private function addtoTaxMap(string $tax_type, float $net_amount, float $tax_rate){
|
private function addtoTaxMap(string $tax_type, float $net_amount, float $tax_rate): void
|
||||||
|
{
|
||||||
$hash = hash("md5", $tax_type."-".$tax_rate);
|
$hash = hash("md5", $tax_type."-".$tax_rate);
|
||||||
if (array_key_exists($hash, $this->tax_map)){
|
if (array_key_exists($hash, $this->tax_map)){
|
||||||
$this->tax_map[$hash]["net_amount"] += $net_amount;
|
$this->tax_map[$hash]["net_amount"] += $net_amount;
|
||||||
|
@ -44,9 +44,7 @@ class HandleCancellation extends AbstractService
|
|||||||
$this->invoice->balance = 0;
|
$this->invoice->balance = 0;
|
||||||
$this->invoice = $this->invoice->service()->setStatus(Invoice::STATUS_CANCELLED)->save();
|
$this->invoice = $this->invoice->service()->setStatus(Invoice::STATUS_CANCELLED)->save();
|
||||||
|
|
||||||
//adjust client balance
|
|
||||||
$this->invoice->client->service()->updateBalance($adjustment)->save();
|
$this->invoice->client->service()->updateBalance($adjustment)->save();
|
||||||
// $this->invoice->fresh();
|
|
||||||
|
|
||||||
$this->invoice->service()->workFlow()->save();
|
$this->invoice->service()->workFlow()->save();
|
||||||
|
|
||||||
@ -54,16 +52,6 @@ class HandleCancellation extends AbstractService
|
|||||||
|
|
||||||
event('eloquent.updated: App\Models\Invoice', $this->invoice);
|
event('eloquent.updated: App\Models\Invoice', $this->invoice);
|
||||||
|
|
||||||
$transaction = [
|
|
||||||
'invoice' => $this->invoice->transaction_event(),
|
|
||||||
'payment' => [],
|
|
||||||
'client' => $this->invoice->client->transaction_event(),
|
|
||||||
'credit' => [],
|
|
||||||
'metadata' => [],
|
|
||||||
];
|
|
||||||
|
|
||||||
// TransactionLog::dispatch(TransactionEvent::INVOICE_CANCELLED, $transaction, $this->invoice->company->db);
|
|
||||||
|
|
||||||
return $this->invoice;
|
return $this->invoice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,6 @@ class InvoiceService
|
|||||||
*/
|
*/
|
||||||
public function applyPayment(Payment $payment, float $payment_amount)
|
public function applyPayment(Payment $payment, float $payment_amount)
|
||||||
{
|
{
|
||||||
// $this->deletePdf();
|
|
||||||
$this->invoice = $this->markSent()->save();
|
$this->invoice = $this->markSent()->save();
|
||||||
|
|
||||||
$this->invoice = (new ApplyPayment($this->invoice, $payment, $payment_amount))->run();
|
$this->invoice = (new ApplyPayment($this->invoice, $payment, $payment_amount))->run();
|
||||||
@ -339,7 +338,7 @@ class InvoiceService
|
|||||||
return $item;
|
return $item;
|
||||||
})->toArray();
|
})->toArray();
|
||||||
|
|
||||||
$this->touchPdf();
|
$this->deletePdf();
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -348,13 +347,15 @@ class InvoiceService
|
|||||||
{
|
{
|
||||||
$this->invoice->load('invitations');
|
$this->invoice->load('invitations');
|
||||||
|
|
||||||
|
//30-06-2023
|
||||||
$this->invoice->invitations->each(function ($invitation) {
|
$this->invoice->invitations->each(function ($invitation) {
|
||||||
try {
|
try {
|
||||||
if (Storage::disk(config('filesystems.default'))->exists($this->invoice->client->invoice_filepath($invitation).$this->invoice->numberFormatter().'.pdf')) {
|
// if (Storage::disk(config('filesystems.default'))->exists($this->invoice->client->invoice_filepath($invitation).$this->invoice->numberFormatter().'.pdf')) {
|
||||||
Storage::disk(config('filesystems.default'))->delete($this->invoice->client->invoice_filepath($invitation).$this->invoice->numberFormatter().'.pdf');
|
Storage::disk(config('filesystems.default'))->delete($this->invoice->client->invoice_filepath($invitation).$this->invoice->numberFormatter().'.pdf');
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (Ninja::isHosted() && Storage::disk('public')->exists($this->invoice->client->invoice_filepath($invitation).$this->invoice->numberFormatter().'.pdf')) {
|
// if (Ninja::isHosted() && Storage::disk('public')->exists($this->invoice->client->invoice_filepath($invitation).$this->invoice->numberFormatter().'.pdf')) {
|
||||||
|
if (Ninja::isHosted()) {
|
||||||
Storage::disk('public')->delete($this->invoice->client->invoice_filepath($invitation).$this->invoice->numberFormatter().'.pdf');
|
Storage::disk('public')->delete($this->invoice->client->invoice_filepath($invitation).$this->invoice->numberFormatter().'.pdf');
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
@ -371,11 +372,12 @@ class InvoiceService
|
|||||||
|
|
||||||
$this->invoice->invitations->each(function ($invitation) {
|
$this->invoice->invitations->each(function ($invitation) {
|
||||||
try {
|
try {
|
||||||
if (Storage::disk(config('filesystems.default'))->exists($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"))) {
|
// if (Storage::disk(config('filesystems.default'))->exists($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"))) {
|
||||||
Storage::disk(config('filesystems.default'))->delete($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"));
|
Storage::disk(config('filesystems.default'))->delete($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"));
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (Ninja::isHosted() && Storage::disk('public')->exists($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"))) {
|
// if (Ninja::isHosted() && Storage::disk('public')->exists($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"))) {
|
||||||
|
if (Ninja::isHosted()) {
|
||||||
Storage::disk('public')->delete($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"));
|
Storage::disk('public')->delete($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"));
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
@ -403,7 +405,7 @@ class InvoiceService
|
|||||||
})->toArray();
|
})->toArray();
|
||||||
|
|
||||||
$this->invoice = $this->invoice->calc()->getInvoice();
|
$this->invoice = $this->invoice->calc()->getInvoice();
|
||||||
$this->touchPdf();
|
$this->deletePdf();
|
||||||
|
|
||||||
/* 24-03-2022 */
|
/* 24-03-2022 */
|
||||||
$new_balance = $this->invoice->balance;
|
$new_balance = $this->invoice->balance;
|
||||||
|
@ -102,7 +102,7 @@ class MarkPaid extends AbstractService
|
|||||||
$this->invoice
|
$this->invoice
|
||||||
->service()
|
->service()
|
||||||
->applyNumber()
|
->applyNumber()
|
||||||
->touchPdf()
|
->deletePdf()
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
$payment->ledger()
|
$payment->ledger()
|
||||||
|
@ -54,7 +54,7 @@ class TriggeredActions extends AbstractService
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->request->has('send_email') && $this->request->input('send_email') == 'true') {
|
if ($this->request->has('send_email') && $this->request->input('send_email') == 'true') {
|
||||||
$this->invoice->service()->markSent()->touchPdf()->save();
|
$this->invoice->service()->markSent()->save();
|
||||||
$this->sendEmail();
|
$this->sendEmail();
|
||||||
$this->updated = false;
|
$this->updated = false;
|
||||||
}
|
}
|
||||||
|
@ -33,14 +33,7 @@ class SendEmail
|
|||||||
$this->contact = $this->payment->client->contacts()->first();
|
$this->contact = $this->payment->client->contacts()->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
// $this->payment->invoices->sortByDesc('id')->first(function ($invoice) {
|
|
||||||
// $invoice->invitations->each(function ($invitation) {
|
|
||||||
// if (!$invitation->contact->trashed() && $invitation->contact->email) {
|
|
||||||
EmailPayment::dispatch($this->payment, $this->payment->company, $this->contact);
|
EmailPayment::dispatch($this->payment, $this->payment->company, $this->contact);
|
||||||
|
|
||||||
// event(new PaymentWasEmailed($this->payment, $this->payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ class UpdateInvoicePayment
|
|||||||
$invoice = $invoice->service()
|
$invoice = $invoice->service()
|
||||||
->clearPartial()
|
->clearPartial()
|
||||||
->updateStatus()
|
->updateStatus()
|
||||||
->touchPdf()
|
->deletePdf()
|
||||||
->workFlow()
|
->workFlow()
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
|
@ -653,7 +653,7 @@ class PdfBuilder
|
|||||||
$data[$key][$table_type.".{$_table_type}4"] = strlen($item->custom_value4) >= 1 ? $helpers->formatCustomFieldValue($this->service->company->custom_fields, "{$_table_type}4", $item->custom_value4, $this->service->config->currency_entity) : '';
|
$data[$key][$table_type.".{$_table_type}4"] = strlen($item->custom_value4) >= 1 ? $helpers->formatCustomFieldValue($this->service->company->custom_fields, "{$_table_type}4", $item->custom_value4, $this->service->config->currency_entity) : '';
|
||||||
|
|
||||||
if ($item->quantity > 0 || $item->cost > 0) {
|
if ($item->quantity > 0 || $item->cost > 0) {
|
||||||
$data[$key][$table_type.'.quantity'] = $this->service->config->formatMoney($item->quantity);
|
$data[$key][$table_type.'.quantity'] = $item->quantity;
|
||||||
|
|
||||||
$data[$key][$table_type.'.unit_cost'] = $this->service->config->formatMoney($item->cost);
|
$data[$key][$table_type.'.unit_cost'] = $this->service->config->formatMoney($item->cost);
|
||||||
|
|
||||||
|
@ -232,6 +232,9 @@ class PdfMock
|
|||||||
'$secondary_font_url' => 'https://fonts.googleapis.com/css2?family=Roboto&display=swap',
|
'$secondary_font_url' => 'https://fonts.googleapis.com/css2?family=Roboto&display=swap',
|
||||||
'$contact.signature' => '',
|
'$contact.signature' => '',
|
||||||
'$company_logo_size' => $this->settings->company_logo_size ?: '65%',
|
'$company_logo_size' => $this->settings->company_logo_size ?: '65%',
|
||||||
|
'$product.tax_rate1' => ctrans('texts.tax'),
|
||||||
|
'$product.tax_rate2' => ctrans('texts.tax'),
|
||||||
|
'$product.tax_rate3' => ctrans('texts.tax'),
|
||||||
'$product.tax_name1' => '',
|
'$product.tax_name1' => '',
|
||||||
'$product.tax_name2' => '',
|
'$product.tax_name2' => '',
|
||||||
'$product.tax_name3' => '',
|
'$product.tax_name3' => '',
|
||||||
@ -688,8 +691,11 @@ class PdfMock
|
|||||||
'$net_subtotal_label' => ctrans('texts.net_subtotal'),
|
'$net_subtotal_label' => ctrans('texts.net_subtotal'),
|
||||||
'$credit.total_label' => ctrans('texts.total'),
|
'$credit.total_label' => ctrans('texts.total'),
|
||||||
'$quote.amount_label' => ctrans('texts.amount'),
|
'$quote.amount_label' => ctrans('texts.amount'),
|
||||||
'$description_label' => ctrans('texts.description'),
|
'$product.tax_rate1_label' => ctrans('texts.tax'),
|
||||||
|
'$product.tax_rate2_label' => ctrans('texts.tax'),
|
||||||
|
'$product.tax_rate3_label' => ctrans('texts.tax'),
|
||||||
'$product.tax_label' => ctrans('texts.tax'),
|
'$product.tax_label' => ctrans('texts.tax'),
|
||||||
|
'$description_label' => ctrans('texts.description'),
|
||||||
'$your_entity_label' => ctrans("texts.your_{$this->entity_string}"),
|
'$your_entity_label' => ctrans("texts.your_{$this->entity_string}"),
|
||||||
'$view_button_label' => ctrans('texts.view'),
|
'$view_button_label' => ctrans('texts.view'),
|
||||||
'$status_logo_label' => ctrans('texts.logo'),
|
'$status_logo_label' => ctrans('texts.logo'),
|
||||||
@ -782,9 +788,9 @@ class PdfMock
|
|||||||
'$amount_label' => ctrans('texts.amount'),
|
'$amount_label' => ctrans('texts.amount'),
|
||||||
'$notes_label' => ctrans('texts.notes'),
|
'$notes_label' => ctrans('texts.notes'),
|
||||||
'$terms_label' => ctrans('texts.terms'),
|
'$terms_label' => ctrans('texts.terms'),
|
||||||
'tax_rate1_label' => ctrans('texts.tax_rate1'),
|
'$tax_rate1_label' => ctrans('texts.tax_rate1'),
|
||||||
'tax_rate2_label' => ctrans('texts.tax_rate2'),
|
'$tax_rate2_label' => ctrans('texts.tax_rate2'),
|
||||||
'tax_rate3_label' => ctrans('texts.tax_rate3'),
|
'$tax_rate3_label' => ctrans('texts.tax_rate3'),
|
||||||
'$phone_label' => ctrans('texts.phone'),
|
'$phone_label' => ctrans('texts.phone'),
|
||||||
'$email_label' => ctrans('texts.email'),
|
'$email_label' => ctrans('texts.email'),
|
||||||
'$taxes_label' => ctrans('texts.taxes'),
|
'$taxes_label' => ctrans('texts.taxes'),
|
||||||
|
@ -19,11 +19,8 @@ use Illuminate\Support\Facades\Storage;
|
|||||||
|
|
||||||
class GetPurchaseOrderPdf extends AbstractService
|
class GetPurchaseOrderPdf extends AbstractService
|
||||||
{
|
{
|
||||||
public function __construct(PurchaseOrder $purchase_order, VendorContact $contact = null)
|
public function __construct(public PurchaseOrder $purchase_order, public ?VendorContact $contact = null)
|
||||||
{
|
{
|
||||||
$this->purchase_order = $purchase_order;
|
|
||||||
|
|
||||||
$this->contact = $contact;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run()
|
public function run()
|
||||||
|
@ -43,10 +43,6 @@ class TriggeredActions extends AbstractService
|
|||||||
$this->purchase_order = $this->purchase_order->service()->markSent()->touchPdf()->save();
|
$this->purchase_order = $this->purchase_order->service()->markSent()->touchPdf()->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if ($this->request->has('cancel') && $this->request->input('cancel') == 'true') {
|
|
||||||
// $this->purchase_order = $this->purchase_order->service()->handleCancellation()->save();
|
|
||||||
// }
|
|
||||||
|
|
||||||
if ($this->request->has('save_default_footer') && $this->request->input('save_default_footer') == 'true') {
|
if ($this->request->has('save_default_footer') && $this->request->input('save_default_footer') == 'true') {
|
||||||
$company = $this->purchase_order->company;
|
$company = $this->purchase_order->company;
|
||||||
$settings = $company->settings;
|
$settings = $company->settings;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user