mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-03 22:07:33 -05:00 
			
		
		
		
	Merge branch 'v5-develop' into v5-stable
This commit is contained in:
		
						commit
						319f2e78dc
					
				@ -1 +1 @@
 | 
				
			|||||||
5.6.19
 | 
					5.6.21
 | 
				
			||||||
@ -24,8 +24,7 @@ use App\Transformers\ActivityTransformer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class ActivityExport extends BaseExport
 | 
					class ActivityExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Company $company;
 | 
					    
 | 
				
			||||||
 | 
					 | 
				
			||||||
    private $entity_transformer;
 | 
					    private $entity_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public string $date_key = 'created_at';
 | 
					    public string $date_key = 'created_at';
 | 
				
			||||||
 | 
				
			|||||||
@ -13,14 +13,14 @@ namespace App\Export\CSV;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use App\Utils\Number;
 | 
					use App\Utils\Number;
 | 
				
			||||||
use App\Models\Client;
 | 
					use App\Models\Client;
 | 
				
			||||||
 | 
					use App\Models\Company;
 | 
				
			||||||
use App\Models\Expense;
 | 
					use App\Models\Expense;
 | 
				
			||||||
use App\Models\Invoice;
 | 
					use App\Models\Invoice;
 | 
				
			||||||
use App\Models\GatewayType;
 | 
					 | 
				
			||||||
use App\Models\Payment;
 | 
					use App\Models\Payment;
 | 
				
			||||||
use League\Fractal\Manager;
 | 
					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\TaskTransformer;
 | 
				
			||||||
use App\Transformers\PaymentTransformer;
 | 
					use App\Transformers\PaymentTransformer;
 | 
				
			||||||
use Illuminate\Database\Eloquent\Builder;
 | 
					use Illuminate\Database\Eloquent\Builder;
 | 
				
			||||||
use League\Fractal\Serializer\ArraySerializer;
 | 
					use League\Fractal\Serializer\ArraySerializer;
 | 
				
			||||||
@ -29,6 +29,8 @@ class BaseExport
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    use MakesHash;
 | 
					    use MakesHash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Company $company;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    public array $input;
 | 
					    public array $input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public string $date_key = '';
 | 
					    public string $date_key = '';
 | 
				
			||||||
@ -136,6 +138,35 @@ class BaseExport
 | 
				
			|||||||
        "user" => "invoice.user_id",
 | 
					        "user" => "invoice.user_id",
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected array $recurring_invoice_report_keys = [    
 | 
				
			||||||
 | 
					        "invoice_number" => "recurring_invoice.number",
 | 
				
			||||||
 | 
					        "amount" => "recurring_invoice.amount",
 | 
				
			||||||
 | 
					        "balance" => "recurring_invoice.balance",
 | 
				
			||||||
 | 
					        "paid_to_date" => "recurring_invoice.paid_to_date",
 | 
				
			||||||
 | 
					        "po_number" => "recurring_invoice.po_number",
 | 
				
			||||||
 | 
					        "date" => "recurring_invoice.date",
 | 
				
			||||||
 | 
					        "due_date" => "recurring_invoice.due_date",
 | 
				
			||||||
 | 
					        "terms" => "recurring_invoice.terms",
 | 
				
			||||||
 | 
					        "footer" => "recurring_invoice.footer",
 | 
				
			||||||
 | 
					        "status" => "recurring_invoice.status",
 | 
				
			||||||
 | 
					        "public_notes" => "recurring_invoice.public_notes",
 | 
				
			||||||
 | 
					        "private_notes" => "recurring_invoice.private_notes",
 | 
				
			||||||
 | 
					        "uses_inclusive_taxes" => "recurring_invoice.uses_inclusive_taxes",
 | 
				
			||||||
 | 
					        "is_amount_discount" => "recurring_invoice.is_amount_discount",
 | 
				
			||||||
 | 
					        "partial" => "recurring_invoice.partial",
 | 
				
			||||||
 | 
					        "partial_due_date" => "recurring_invoice.partial_due_date",
 | 
				
			||||||
 | 
					        "surcharge1" => "recurring_invoice.custom_surcharge1",
 | 
				
			||||||
 | 
					        "surcharge2" => "recurring_invoice.custom_surcharge2",
 | 
				
			||||||
 | 
					        "surcharge3" => "recurring_invoice.custom_surcharge3",
 | 
				
			||||||
 | 
					        "surcharge4" => "recurring_invoice.custom_surcharge4",
 | 
				
			||||||
 | 
					        "exchange_rate" => "recurring_invoice.exchange_rate",
 | 
				
			||||||
 | 
					        "tax_amount" => "recurring_invoice.total_taxes",
 | 
				
			||||||
 | 
					        "assigned_user" => "recurring_invoice.assigned_user_id",
 | 
				
			||||||
 | 
					        "user" => "recurring_invoice.user_id",
 | 
				
			||||||
 | 
					        "frequency_id" => "recurring_invoice.frequency_id",
 | 
				
			||||||
 | 
					        "next_send_date" => "recurring_invoice.next_send_date"
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected array $purchase_order_report_keys = [
 | 
					    protected array $purchase_order_report_keys = [
 | 
				
			||||||
        'amount' => 'purchase_order.amount',
 | 
					        'amount' => 'purchase_order.amount',
 | 
				
			||||||
        'balance' => 'purchase_order.balance',
 | 
					        'balance' => 'purchase_order.balance',
 | 
				
			||||||
@ -193,13 +224,17 @@ class BaseExport
 | 
				
			|||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected array $quote_report_keys = [
 | 
					    protected array $quote_report_keys = [
 | 
				
			||||||
        "quote_number" => "quote.number",
 | 
					        'custom_value1' => 'quote.custom_value1',
 | 
				
			||||||
 | 
					        'custom_value2' => 'quote.custom_value2',
 | 
				
			||||||
 | 
					        'custom_value3' => 'quote.custom_value3',
 | 
				
			||||||
 | 
					        'custom_value4' => 'quote.custom_value4',
 | 
				
			||||||
 | 
					        "number" => "quote.number",
 | 
				
			||||||
        "amount" => "quote.amount",
 | 
					        "amount" => "quote.amount",
 | 
				
			||||||
        "balance" => "quote.balance",
 | 
					        "balance" => "quote.balance",
 | 
				
			||||||
        "paid_to_date" => "quote.paid_to_date",
 | 
					        "paid_to_date" => "quote.paid_to_date",
 | 
				
			||||||
        "po_number" => "quote.po_number",
 | 
					        "po_number" => "quote.po_number",
 | 
				
			||||||
        "date" => "quote.date",
 | 
					        "date" => "quote.date",
 | 
				
			||||||
        "due_date" => "quote.due_date",
 | 
					        "valid_until" => "quote.due_date",
 | 
				
			||||||
        "terms" => "quote.terms",
 | 
					        "terms" => "quote.terms",
 | 
				
			||||||
        "footer" => "quote.footer",
 | 
					        "footer" => "quote.footer",
 | 
				
			||||||
        "status" => "quote.status",
 | 
					        "status" => "quote.status",
 | 
				
			||||||
@ -314,8 +349,6 @@ class BaseExport
 | 
				
			|||||||
        'custom_value4' => 'task.custom_value4',
 | 
					        'custom_value4' => 'task.custom_value4',
 | 
				
			||||||
        'status' => 'task.status_id',
 | 
					        'status' => 'task.status_id',
 | 
				
			||||||
        'project' => 'task.project_id',
 | 
					        'project' => 'task.project_id',
 | 
				
			||||||
        'invoice' => 'task.invoice_id',
 | 
					 | 
				
			||||||
        'client' => 'task.client_id',
 | 
					 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected function filterByClients($query)
 | 
					    protected function filterByClients($query)
 | 
				
			||||||
@ -347,8 +380,11 @@ class BaseExport
 | 
				
			|||||||
            'vendor' => $value = $this->resolveVendorKey($parts[1], $entity, $transformer),
 | 
					            'vendor' => $value = $this->resolveVendorKey($parts[1], $entity, $transformer),
 | 
				
			||||||
            'vendor_contact' => $value = $this->resolveVendorContactKey($parts[1], $entity, $transformer),
 | 
					            'vendor_contact' => $value = $this->resolveVendorContactKey($parts[1], $entity, $transformer),
 | 
				
			||||||
            'invoice' => $value = $this->resolveInvoiceKey($parts[1], $entity, $transformer),
 | 
					            'invoice' => $value = $this->resolveInvoiceKey($parts[1], $entity, $transformer),
 | 
				
			||||||
 | 
					            'recurring_invoice' => $value = $this->resolveInvoiceKey($parts[1], $entity, $transformer),
 | 
				
			||||||
 | 
					            'quote' => $value = $this->resolveQuoteKey($parts[1], $entity, $transformer),
 | 
				
			||||||
            'purchase_order' => $value = $this->resolvePurchaseOrderKey($parts[1], $entity, $transformer),
 | 
					            'purchase_order' => $value = $this->resolvePurchaseOrderKey($parts[1], $entity, $transformer),
 | 
				
			||||||
            'payment' => $value = $this->resolvePaymentKey($parts[1], $entity, $transformer),
 | 
					            'payment' => $value = $this->resolvePaymentKey($parts[1], $entity, $transformer),
 | 
				
			||||||
 | 
					            'task' => $value = $this->resolveTaskKey($parts[1], $entity, $transformer),
 | 
				
			||||||
            default => $value = ''
 | 
					            default => $value = ''
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
@ -414,6 +450,22 @@ class BaseExport
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function resolveTaskKey($column, $entity, $transformer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        nlog("searching for {$column}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $transformed_entity = $transformer->transform($entity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(array_key_exists($column, $transformed_entity)) {
 | 
				
			||||||
 | 
					            return $transformed_entity[$column];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function resolveVendorKey($column, $entity, $transformer)
 | 
					    private function resolveVendorKey($column, $entity, $transformer)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -511,6 +563,20 @@ class BaseExport
 | 
				
			|||||||
        return '';
 | 
					        return '';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function resolveQuoteKey($column, $entity, $transformer)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        nlog("searching for {$column}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $transformed_entity = $transformer->transform($entity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(array_key_exists($column, $transformed_entity)) {
 | 
				
			||||||
 | 
					            return $transformed_entity[$column];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function resolveInvoiceKey($column, $entity, $transformer)
 | 
					    private function resolveInvoiceKey($column, $entity, $transformer)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        nlog("searching for {$column}");
 | 
					        nlog("searching for {$column}");
 | 
				
			||||||
@ -537,7 +603,23 @@ class BaseExport
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $transformed_invoice = $transformer->transform($entity);
 | 
					        if($transformer instanceof TaskTransformer) {
 | 
				
			||||||
 | 
					            $transformed_invoice = $transformer->includeInvoice($entity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(!$transformed_invoice)
 | 
				
			||||||
 | 
					                return '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $manager = new Manager();
 | 
				
			||||||
 | 
					            $manager->setSerializer(new ArraySerializer());
 | 
				
			||||||
 | 
					            $transformed_invoice = $manager->createData($transformed_invoice)->toArray();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if(array_key_exists($column, $transformed_invoice)) {
 | 
				
			||||||
 | 
					            return $transformed_invoice[$column];
 | 
				
			||||||
 | 
					        } elseif (array_key_exists(str_replace("invoice.", "", $column), $transformed_invoice)) {
 | 
				
			||||||
 | 
					            return $transformed_invoice[$column];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if($column == 'status')
 | 
					        if($column == 'status')
 | 
				
			||||||
            return $entity->stringStatus($entity->status_id);
 | 
					            return $entity->stringStatus($entity->status_id);
 | 
				
			||||||
@ -707,8 +789,27 @@ class BaseExport
 | 
				
			|||||||
                $this->end_date = now()->startOfDay()->format('Y-m-d');
 | 
					                $this->end_date = now()->startOfDay()->format('Y-m-d');
 | 
				
			||||||
                return $query->whereBetween($this->date_key, [now()->subDays(365), now()])->orderBy($this->date_key, 'ASC');
 | 
					                return $query->whereBetween($this->date_key, [now()->subDays(365), now()])->orderBy($this->date_key, 'ASC');
 | 
				
			||||||
            case 'this_year':
 | 
					            case 'this_year':
 | 
				
			||||||
                $this->start_date = now()->startOfYear()->format('Y-m-d');
 | 
					
 | 
				
			||||||
                $this->end_date = now()->format('Y-m-d');
 | 
					                $first_month_of_year = $this->company->getSetting('first_month_of_year') ?? 1;
 | 
				
			||||||
 | 
					                $fin_year_start = now()->createFromDate(now()->year, $first_month_of_year, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if(now()->lt($fin_year_start))
 | 
				
			||||||
 | 
					                    $fin_year_start->subYearNoOverflow();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $this->start_date = $fin_year_start->format('Y-m-d');
 | 
				
			||||||
 | 
					                $this->end_date = $fin_year_start->copy()->addYear()->subDay()->format('Y-m-d');
 | 
				
			||||||
 | 
					                return $query->whereBetween($this->date_key, [now()->startOfYear(), now()])->orderBy($this->date_key, 'ASC');
 | 
				
			||||||
 | 
					            case 'last_year':
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $first_month_of_year = $this->company->getSetting('first_month_of_year') ?? 1;
 | 
				
			||||||
 | 
					                $fin_year_start = now()->createFromDate(now()->year, $first_month_of_year, 1);
 | 
				
			||||||
 | 
					                $fin_year_start->subYearNoOverflow();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if(now()->subYear()->lt($fin_year_start)) 
 | 
				
			||||||
 | 
					                    $fin_year_start->subYearNoOverflow();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $this->start_date = $fin_year_start->format('Y-m-d');
 | 
				
			||||||
 | 
					                $this->end_date = $fin_year_start->copy()->addYear()->subDay()->format('Y-m-d');
 | 
				
			||||||
                return $query->whereBetween($this->date_key, [now()->startOfYear(), now()])->orderBy($this->date_key, 'ASC');
 | 
					                return $query->whereBetween($this->date_key, [now()->startOfYear(), now()])->orderBy($this->date_key, 'ASC');
 | 
				
			||||||
            case 'custom':
 | 
					            case 'custom':
 | 
				
			||||||
                $this->start_date = $custom_start_date->format('Y-m-d');
 | 
					                $this->start_date = $custom_start_date->format('Y-m-d');
 | 
				
			||||||
@ -743,6 +844,11 @@ class BaseExport
 | 
				
			|||||||
                $key = array_search($value, $this->invoice_report_keys);
 | 
					                $key = array_search($value, $this->invoice_report_keys);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(!$key) {
 | 
				
			||||||
 | 
					                $prefix = ctrans('texts.recurring_invoice')." ";
 | 
				
			||||||
 | 
					                $key = array_search($value, $this->recurring_invoice_report_keys);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!$key) {
 | 
					            if(!$key) {
 | 
				
			||||||
                $prefix = ctrans('texts.payment')." ";
 | 
					                $prefix = ctrans('texts.payment')." ";
 | 
				
			||||||
                $key = array_search($value, $this->payment_report_keys);
 | 
					                $key = array_search($value, $this->payment_report_keys);
 | 
				
			||||||
@ -790,6 +896,7 @@ class BaseExport
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            $key = str_replace('item.', '', $key);
 | 
					            $key = str_replace('item.', '', $key);
 | 
				
			||||||
            $key = str_replace('recurring_invoice.', '', $key);
 | 
					            $key = str_replace('recurring_invoice.', '', $key);
 | 
				
			||||||
 | 
					            $key = str_replace('purchase_order.', '', $key);
 | 
				
			||||||
            $key = str_replace('invoice.', '', $key);
 | 
					            $key = str_replace('invoice.', '', $key);
 | 
				
			||||||
            $key = str_replace('quote.', '', $key);
 | 
					            $key = str_replace('quote.', '', $key);
 | 
				
			||||||
            $key = str_replace('credit.', '', $key);
 | 
					            $key = str_replace('credit.', '', $key);
 | 
				
			||||||
@ -800,9 +907,18 @@ class BaseExport
 | 
				
			|||||||
            $key = str_replace('payment.', '', $key);
 | 
					            $key = str_replace('payment.', '', $key);
 | 
				
			||||||
            $key = str_replace('expense.', '', $key);
 | 
					            $key = str_replace('expense.', '', $key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $header[] = "{$prefix}" . ctrans("texts.{$key}");
 | 
					            if(in_array($key, ['quote1','quote2','quote3','quote4','credit1','credit2','credit3','credit4','purchase_order1','purchase_order2','purchase_order3','purchase_order4']))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                $number = substr($key, -1);
 | 
				
			||||||
 | 
					                $header[] = ctrans('texts.item') . " ". ctrans("texts.custom_value{$number}"); 
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                $header[] = "{$prefix}" . ctrans("texts.{$key}");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
// nlog($header);
 | 
					
 | 
				
			||||||
 | 
					        // nlog($header);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $header;
 | 
					        return $header;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -22,8 +22,6 @@ use League\Csv\Writer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class ClientExport extends BaseExport
 | 
					class ClientExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private $company;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private $client_transformer;
 | 
					    private $client_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private $contact_transformer;
 | 
					    private $contact_transformer;
 | 
				
			||||||
@ -172,8 +170,8 @@ class ClientExport extends BaseExport
 | 
				
			|||||||
            $entity['shipping_country'] = $client->shipping_country ? ctrans("texts.country_{$client->shipping_country->name}") : '';
 | 
					            $entity['shipping_country'] = $client->shipping_country ? ctrans("texts.country_{$client->shipping_country->name}") : '';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (in_array('client.currency', $this->input['report_keys'])) {
 | 
					        if (in_array('client.currency_id', $this->input['report_keys'])) {
 | 
				
			||||||
            $entity['currency'] = $client->currency() ? $client->currency()->code : $client->company->currency()->code;
 | 
					            $entity['client.currency_id'] = $client->currency() ? $client->currency()->code : $client->company->currency()->code;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (in_array('client.industry_id', $this->input['report_keys'])) {
 | 
					        if (in_array('client.industry_id', $this->input['report_keys'])) {
 | 
				
			||||||
 | 
				
			|||||||
@ -23,7 +23,6 @@ use League\Csv\Writer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class ContactExport extends BaseExport
 | 
					class ContactExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Company $company;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private ClientTransformer $client_transformer;
 | 
					    private ClientTransformer $client_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,6 @@ use League\Csv\Writer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class CreditExport extends BaseExport
 | 
					class CreditExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Company $company;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private CreditTransformer $credit_transformer;
 | 
					    private CreditTransformer $credit_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,6 @@ use League\Csv\Writer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class DocumentExport extends BaseExport
 | 
					class DocumentExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Company $company;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private $entity_transformer;
 | 
					    private $entity_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,6 @@ use League\Csv\Writer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class ExpenseExport extends BaseExport
 | 
					class ExpenseExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Company $company;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private $expense_transformer;
 | 
					    private $expense_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -23,8 +23,6 @@ use App\Transformers\InvoiceTransformer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class InvoiceExport extends BaseExport
 | 
					class InvoiceExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Company $company;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private $invoice_transformer;
 | 
					    private $invoice_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public string $date_key = 'date';
 | 
					    public string $date_key = 'date';
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,6 @@ use League\Csv\Writer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class InvoiceItemExport extends BaseExport
 | 
					class InvoiceItemExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Company $company;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private $invoice_transformer;
 | 
					    private $invoice_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -21,8 +21,6 @@ use League\Csv\Writer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class PaymentExport extends BaseExport
 | 
					class PaymentExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Company $company;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private $entity_transformer;
 | 
					    private $entity_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public string $date_key = 'date';
 | 
					    public string $date_key = 'date';
 | 
				
			||||||
 | 
				
			|||||||
@ -22,8 +22,6 @@ use League\Csv\Writer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class ProductExport extends BaseExport
 | 
					class ProductExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Company $company;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private $entity_transformer;
 | 
					    private $entity_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public string $date_key = 'created_at';
 | 
					    public string $date_key = 'created_at';
 | 
				
			||||||
 | 
				
			|||||||
@ -23,8 +23,6 @@ use League\Csv\Writer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class ProductSalesExport extends BaseExport
 | 
					class ProductSalesExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Company $company;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public string $date_key = 'created_at';
 | 
					    public string $date_key = 'created_at';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected Collection $products;
 | 
					    protected Collection $products;
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,6 @@ use League\Csv\Writer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class PurchaseOrderExport extends BaseExport
 | 
					class PurchaseOrderExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Company $company;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private $purchase_order_transformer;
 | 
					    private $purchase_order_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -31,39 +30,39 @@ class PurchaseOrderExport extends BaseExport
 | 
				
			|||||||
    public Writer $csv;
 | 
					    public Writer $csv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public array $entity_keys = [
 | 
					    public array $entity_keys = [
 | 
				
			||||||
        'amount' => 'amount',
 | 
					        'amount' => 'purchase_order.amount',
 | 
				
			||||||
        'balance' => 'balance',
 | 
					        'balance' => 'purchase_order.balance',
 | 
				
			||||||
        'vendor' => 'vendor_id',
 | 
					        'vendor' => 'purchase_order.vendor_id',
 | 
				
			||||||
        'custom_surcharge1' => 'custom_surcharge1',
 | 
					        // 'custom_surcharge1' => 'purchase_order.custom_surcharge1',
 | 
				
			||||||
        'custom_surcharge2' => 'custom_surcharge2',
 | 
					        // 'custom_surcharge2' => 'purchase_order.custom_surcharge2',
 | 
				
			||||||
        'custom_surcharge3' => 'custom_surcharge3',
 | 
					        // 'custom_surcharge3' => 'purchase_order.custom_surcharge3',
 | 
				
			||||||
        'custom_surcharge4' => 'custom_surcharge4',
 | 
					        // 'custom_surcharge4' => 'purchase_order.custom_surcharge4',
 | 
				
			||||||
        'custom_value1' => 'custom_value1',
 | 
					        'custom_value1' => 'purchase_order.custom_value1',
 | 
				
			||||||
        'custom_value2' => 'custom_value2',
 | 
					        'custom_value2' => 'purchase_order.custom_value2',
 | 
				
			||||||
        'custom_value3' => 'custom_value3',
 | 
					        'custom_value3' => 'purchase_order.custom_value3',
 | 
				
			||||||
        'custom_value4' => 'custom_value4',
 | 
					        'custom_value4' => 'purchase_order.custom_value4',
 | 
				
			||||||
        'date' => 'date',
 | 
					        'date' => 'purchase_order.date',
 | 
				
			||||||
        'discount' => 'discount',
 | 
					        'discount' => 'purchase_order.discount',
 | 
				
			||||||
        'due_date' => 'due_date',
 | 
					        'due_date' => 'purchase_order.due_date',
 | 
				
			||||||
        'exchange_rate' => 'exchange_rate',
 | 
					        'exchange_rate' => 'purchase_order.exchange_rate',
 | 
				
			||||||
        'footer' => 'footer',
 | 
					        'footer' => 'purchase_order.footer',
 | 
				
			||||||
        'number' => 'number',
 | 
					        'number' => 'purchase_order.number',
 | 
				
			||||||
        'paid_to_date' => 'paid_to_date',
 | 
					        'paid_to_date' => 'purchase_order.paid_to_date',
 | 
				
			||||||
        'partial' => 'partial',
 | 
					        'partial' => 'purchase_order.partial',
 | 
				
			||||||
        'partial_due_date' => 'partial_due_date',
 | 
					        'partial_due_date' => 'purchase_order.partial_due_date',
 | 
				
			||||||
        'po_number' => 'po_number',
 | 
					        'po_number' => 'purchase_order.po_number',
 | 
				
			||||||
        'private_notes' => 'private_notes',
 | 
					        'private_notes' => 'purchase_order.private_notes',
 | 
				
			||||||
        'public_notes' => 'public_notes',
 | 
					        'public_notes' => 'purchase_order.public_notes',
 | 
				
			||||||
        'status' => 'status_id',
 | 
					        'status' => 'purchase_order.status_id',
 | 
				
			||||||
        'tax_name1' => 'tax_name1',
 | 
					        'tax_name1' => 'purchase_order.tax_name1',
 | 
				
			||||||
        'tax_name2' => 'tax_name2',
 | 
					        'tax_name2' => 'purchase_order.tax_name2',
 | 
				
			||||||
        'tax_name3' => 'tax_name3',
 | 
					        'tax_name3' => 'purchase_order.tax_name3',
 | 
				
			||||||
        'tax_rate1' => 'tax_rate1',
 | 
					        'tax_rate1' => 'purchase_order.tax_rate1',
 | 
				
			||||||
        'tax_rate2' => 'tax_rate2',
 | 
					        'tax_rate2' => 'purchase_order.tax_rate2',
 | 
				
			||||||
        'tax_rate3' => 'tax_rate3',
 | 
					        'tax_rate3' => 'purchase_order.tax_rate3',
 | 
				
			||||||
        'terms' => 'terms',
 | 
					        'terms' => 'purchase_order.terms',
 | 
				
			||||||
        'total_taxes' => 'total_taxes',
 | 
					        'total_taxes' => 'purchase_order.total_taxes',
 | 
				
			||||||
        'currency_id' => 'currency_id',
 | 
					        'currency_id' => 'purchase_order.currency_id',
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private array $decorate_keys = [
 | 
					    private array $decorate_keys = [
 | 
				
			||||||
@ -130,7 +129,7 @@ class PurchaseOrderExport extends BaseExport
 | 
				
			|||||||
            $keyval = array_search($key, $this->entity_keys);
 | 
					            $keyval = array_search($key, $this->entity_keys);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!$keyval) {
 | 
					            if(!$keyval) {
 | 
				
			||||||
                $keyval = array_search(str_replace("invoice.", "", $key), $this->entity_keys) ?? $key;
 | 
					                $keyval = array_search(str_replace("purchase_order.", "", $key), $this->entity_keys) ?? $key;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!$keyval) {
 | 
					            if(!$keyval) {
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,6 @@ use League\Csv\Writer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class PurchaseOrderItemExport extends BaseExport
 | 
					class PurchaseOrderItemExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Company $company;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private $purchase_order_transformer;
 | 
					    private $purchase_order_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -37,10 +36,10 @@ class PurchaseOrderItemExport extends BaseExport
 | 
				
			|||||||
        'vendor' => 'vendor_id',
 | 
					        'vendor' => 'vendor_id',
 | 
				
			||||||
        'vendor_number' => 'vendor.number',
 | 
					        'vendor_number' => 'vendor.number',
 | 
				
			||||||
        'vendor_id_number' => 'vendor.id_number',
 | 
					        'vendor_id_number' => 'vendor.id_number',
 | 
				
			||||||
        'custom_surcharge1' => 'custom_surcharge1',
 | 
					        // 'custom_surcharge1' => 'custom_surcharge1',
 | 
				
			||||||
        'custom_surcharge2' => 'custom_surcharge2',
 | 
					        // 'custom_surcharge2' => 'custom_surcharge2',
 | 
				
			||||||
        'custom_surcharge3' => 'custom_surcharge3',
 | 
					        // 'custom_surcharge3' => 'custom_surcharge3',
 | 
				
			||||||
        'custom_surcharge4' => 'custom_surcharge4',
 | 
					        // 'custom_surcharge4' => 'custom_surcharge4',
 | 
				
			||||||
        // 'custom_value1' => 'custom_value1',
 | 
					        // 'custom_value1' => 'custom_value1',
 | 
				
			||||||
        // 'custom_value2' => 'custom_value2',
 | 
					        // 'custom_value2' => 'custom_value2',
 | 
				
			||||||
        // 'custom_value3' => 'custom_value3',
 | 
					        // 'custom_value3' => 'custom_value3',
 | 
				
			||||||
@ -82,10 +81,10 @@ class PurchaseOrderItemExport extends BaseExport
 | 
				
			|||||||
        'tax_name3' => 'item.tax_name3',
 | 
					        'tax_name3' => 'item.tax_name3',
 | 
				
			||||||
        'line_total' => 'item.line_total',
 | 
					        'line_total' => 'item.line_total',
 | 
				
			||||||
        'gross_line_total' => 'item.gross_line_total',
 | 
					        'gross_line_total' => 'item.gross_line_total',
 | 
				
			||||||
        // 'invoice1' => 'item.custom_value1',
 | 
					        'purchase_order1' => 'item.custom_value1',
 | 
				
			||||||
        // 'invoice2' => 'item.custom_value2',
 | 
					        'purchase_order2' => 'item.custom_value2',
 | 
				
			||||||
        // 'invoice3' => 'item.custom_value3',
 | 
					        'purchase_order3' => 'item.custom_value3',
 | 
				
			||||||
        // 'invoice4' => 'item.custom_value4',
 | 
					        'purchase_order4' => 'item.custom_value4',
 | 
				
			||||||
        'tax_category' => 'item.tax_id',
 | 
					        'tax_category' => 'item.tax_id',
 | 
				
			||||||
        'type' => 'item.type_id',
 | 
					        'type' => 'item.type_id',
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
@ -139,7 +138,7 @@ class PurchaseOrderItemExport extends BaseExport
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private function iterateItems(PurchaseOrder $purchase_order)
 | 
					    private function iterateItems(PurchaseOrder $purchase_order)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $transformed_invoice = $this->buildRow($purchase_order);
 | 
					        $transformed_purchase_order = $this->buildRow($purchase_order);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $transformed_items = [];
 | 
					        $transformed_items = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -154,7 +153,7 @@ class PurchaseOrderItemExport extends BaseExport
 | 
				
			|||||||
                    
 | 
					                    
 | 
				
			||||||
                    $keyval = $key;
 | 
					                    $keyval = $key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    $keyval = str_replace("custom_value", "invoice", $key);
 | 
					                    $keyval = str_replace("custom_value", "purchase_order", $key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if($key == 'type_id') {
 | 
					                    if($key == 'type_id') {
 | 
				
			||||||
                        $keyval = 'type';
 | 
					                        $keyval = 'type';
 | 
				
			||||||
@ -184,7 +183,7 @@ class PurchaseOrderItemExport extends BaseExport
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $transformed_items = array_merge($transformed_invoice, $item_array);
 | 
					            $transformed_items = array_merge($transformed_purchase_order, $item_array);
 | 
				
			||||||
            $entity = $this->decorateAdvancedFields($purchase_order, $transformed_items);
 | 
					            $entity = $this->decorateAdvancedFields($purchase_order, $transformed_items);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $this->csv->insertOne($entity);
 | 
					            $this->csv->insertOne($entity);
 | 
				
			||||||
@ -193,7 +192,7 @@ class PurchaseOrderItemExport extends BaseExport
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private function buildRow(PurchaseOrder $purchase_order) :array
 | 
					    private function buildRow(PurchaseOrder $purchase_order) :array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $transformed_invoice = $this->purchase_order_transformer->transform($purchase_order);
 | 
					        $transformed_purchase_order = $this->purchase_order_transformer->transform($purchase_order);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $entity = [];
 | 
					        $entity = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -201,17 +200,17 @@ class PurchaseOrderItemExport extends BaseExport
 | 
				
			|||||||
            $keyval = array_search($key, $this->entity_keys);
 | 
					            $keyval = array_search($key, $this->entity_keys);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!$keyval) {
 | 
					            if(!$keyval) {
 | 
				
			||||||
                $keyval = array_search(str_replace("invoice.", "", $key), $this->entity_keys) ?? $key;
 | 
					                $keyval = array_search(str_replace("purchase_order.", "", $key), $this->entity_keys) ?? $key;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!$keyval) {
 | 
					            if(!$keyval) {
 | 
				
			||||||
                $keyval = $key;
 | 
					                $keyval = $key;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (array_key_exists($key, $transformed_invoice)) {
 | 
					            if (array_key_exists($key, $transformed_purchase_order)) {
 | 
				
			||||||
                $entity[$keyval] = $transformed_invoice[$key];
 | 
					                $entity[$keyval] = $transformed_purchase_order[$key];
 | 
				
			||||||
            } elseif (array_key_exists($keyval, $transformed_invoice)) {
 | 
					            } elseif (array_key_exists($keyval, $transformed_purchase_order)) {
 | 
				
			||||||
                $entity[$keyval] = $transformed_invoice[$keyval];
 | 
					                $entity[$keyval] = $transformed_purchase_order[$keyval];
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                $entity[$keyval] = $this->resolveKey($keyval, $purchase_order, $this->purchase_order_transformer);
 | 
					                $entity[$keyval] = $this->resolveKey($keyval, $purchase_order, $this->purchase_order_transformer);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,6 @@ use League\Csv\Writer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class QuoteExport extends BaseExport
 | 
					class QuoteExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Company $company;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private $quote_transformer;
 | 
					    private $quote_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -43,7 +42,7 @@ class QuoteExport extends BaseExport
 | 
				
			|||||||
        'custom_value4' => 'custom_value4',
 | 
					        'custom_value4' => 'custom_value4',
 | 
				
			||||||
        'date' => 'date',
 | 
					        'date' => 'date',
 | 
				
			||||||
        'discount' => 'discount',
 | 
					        'discount' => 'discount',
 | 
				
			||||||
        'due_date' => 'due_date',
 | 
					        'valid_until' => 'due_date',
 | 
				
			||||||
        'exchange_rate' => 'exchange_rate',
 | 
					        'exchange_rate' => 'exchange_rate',
 | 
				
			||||||
        'footer' => 'footer',
 | 
					        'footer' => 'footer',
 | 
				
			||||||
        'number' => 'number',
 | 
					        'number' => 'number',
 | 
				
			||||||
@ -115,17 +114,28 @@ class QuoteExport extends BaseExport
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private function buildRow(Quote $quote) :array
 | 
					    private function buildRow(Quote $quote) :array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $transformed_quote = $this->quote_transformer->transform($quote);
 | 
					        $transformed_entity = $this->quote_transformer->transform($quote);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $entity = [];
 | 
					        $entity = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        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 (array_key_exists($key, $transformed_quote)) {
 | 
					            if(!$keyval) {
 | 
				
			||||||
                $entity[$keyval] = $transformed_quote[$key];
 | 
					                $keyval = array_search(str_replace("invoice.", "", $key), $this->entity_keys) ?? $key;
 | 
				
			||||||
            } else {
 | 
					            }
 | 
				
			||||||
                $entity[$keyval] = '';
 | 
					
 | 
				
			||||||
 | 
					            if(!$keyval) {
 | 
				
			||||||
 | 
					                $keyval = $key;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (array_key_exists($key, $transformed_entity)) {
 | 
				
			||||||
 | 
					                $entity[$keyval] = $transformed_entity[$key];
 | 
				
			||||||
 | 
					            } elseif (array_key_exists($keyval, $transformed_entity)) {
 | 
				
			||||||
 | 
					                $entity[$keyval] = $transformed_entity[$keyval];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                $entity[$keyval] = $this->resolveKey($keyval, $quote, $this->quote_transformer);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,6 @@ use League\Csv\Writer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class QuoteItemExport extends BaseExport
 | 
					class QuoteItemExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Company $company;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private $quote_transformer;
 | 
					    private $quote_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -63,10 +62,11 @@ class QuoteItemExport extends BaseExport
 | 
				
			|||||||
        'terms' => 'terms',
 | 
					        'terms' => 'terms',
 | 
				
			||||||
        'total_taxes' => 'total_taxes',
 | 
					        'total_taxes' => 'total_taxes',
 | 
				
			||||||
        'currency' => 'currency_id',
 | 
					        'currency' => 'currency_id',
 | 
				
			||||||
        'qty' => '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',
 | 
				
			||||||
 | 
					        'cost' => 'item.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',
 | 
				
			||||||
@ -77,11 +77,13 @@ class QuoteItemExport extends BaseExport
 | 
				
			|||||||
        'tax_name2' => 'item.tax_name2',
 | 
					        'tax_name2' => 'item.tax_name2',
 | 
				
			||||||
        'tax_name3' => 'item.tax_name3',
 | 
					        'tax_name3' => 'item.tax_name3',
 | 
				
			||||||
        'line_total' => 'item.line_total',
 | 
					        'line_total' => 'item.line_total',
 | 
				
			||||||
        // 'gross_line_total' => 'item.gross_line_total',
 | 
					        'gross_line_total' => 'item.gross_line_total',
 | 
				
			||||||
        'custom_value1' => 'item.custom_value1',
 | 
					        'quote1' => 'item.custom_value1',
 | 
				
			||||||
        'custom_value2' => 'item.custom_value2',
 | 
					        'quote2' => 'item.custom_value2',
 | 
				
			||||||
        'custom_value3' => 'item.custom_value3',
 | 
					        'quote3' => 'item.custom_value3',
 | 
				
			||||||
        'custom_value4' => 'item.custom_value4',
 | 
					        'quote4' => 'item.custom_value4',
 | 
				
			||||||
 | 
					        'tax_category' => 'item.tax_id',
 | 
				
			||||||
 | 
					        'type' => 'item.type_id',
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private array $decorate_keys = [
 | 
					    private array $decorate_keys = [
 | 
				
			||||||
@ -135,25 +137,44 @@ class QuoteItemExport extends BaseExport
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $transformed_items = [];
 | 
					        $transformed_items = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($quote->line_items as $item) {
 | 
					        $transformed_items = [];
 | 
				
			||||||
            $item_array = [];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            foreach (array_values($this->input['report_keys']) as $key) {
 | 
					        foreach ($quote->line_items as $item) {
 | 
				
			||||||
                if (str_contains($key, 'item.')) {
 | 
					            $item_array = [];      
 | 
				
			||||||
                    $key = str_replace('item.', '', $key);
 | 
					
 | 
				
			||||||
                    $item_array[$key] = $item->{$key};
 | 
					            foreach (array_values($this->input['report_keys']) as $key) { //items iterator produces item array
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                if (str_contains($key, "item.")) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    $key = str_replace("item.", "", $key);
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    $keyval = $key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    $keyval = str_replace("custom_value", "quote", $key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if($key == 'type_id')
 | 
				
			||||||
 | 
					                        $keyval = 'type';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if($key == 'tax_id')
 | 
				
			||||||
 | 
					                        $keyval = 'tax_category';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (property_exists($item, $key)) {
 | 
				
			||||||
 | 
					                        $item_array[$keyval] = $item->{$key};
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        $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];
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    $entity[$keyval] = '';
 | 
					                    $entity[$keyval] = "";
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -173,16 +194,26 @@ class QuoteItemExport 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("quote.", "", $key), $this->entity_keys) ?? $key;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(!$keyval) {
 | 
				
			||||||
 | 
					                $keyval = $key;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (array_key_exists($key, $transformed_quote)) {
 | 
					            if (array_key_exists($key, $transformed_quote)) {
 | 
				
			||||||
                $entity[$keyval] = $transformed_quote[$key];
 | 
					                $entity[$keyval] = $transformed_quote[$key];
 | 
				
			||||||
            } else {
 | 
					            } elseif (array_key_exists($keyval, $transformed_quote)) {
 | 
				
			||||||
                $entity[$keyval] = '';
 | 
					                $entity[$keyval] = $transformed_quote[$keyval];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					             else {
 | 
				
			||||||
 | 
					                $entity[$keyval] = $this->resolveKey($keyval, $quote, $this->quote_transformer);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this->decorateAdvancedFields($quote, $entity);
 | 
					        return $this->decorateAdvancedFields($quote, $entity);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    private function decorateAdvancedFields(Quote $quote, array $entity) :array
 | 
					    private function decorateAdvancedFields(Quote $quote, array $entity) :array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (in_array('currency_id', $this->input['report_keys'])) {
 | 
					        if (in_array('currency_id', $this->input['report_keys'])) {
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,6 @@ use League\Csv\Writer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class RecurringInvoiceExport extends BaseExport
 | 
					class RecurringInvoiceExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Company $company;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private $invoice_transformer;
 | 
					    private $invoice_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -33,10 +32,10 @@ class RecurringInvoiceExport extends BaseExport
 | 
				
			|||||||
        'amount' => 'amount',
 | 
					        'amount' => 'amount',
 | 
				
			||||||
        'balance' => 'balance',
 | 
					        'balance' => 'balance',
 | 
				
			||||||
        'client' => 'client_id',
 | 
					        'client' => 'client_id',
 | 
				
			||||||
        'custom_surcharge1' => 'custom_surcharge1',
 | 
					        // 'custom_surcharge1' => 'custom_surcharge1',
 | 
				
			||||||
        'custom_surcharge2' => 'custom_surcharge2',
 | 
					        // 'custom_surcharge2' => 'custom_surcharge2',
 | 
				
			||||||
        'custom_surcharge3' => 'custom_surcharge3',
 | 
					        // 'custom_surcharge3' => 'custom_surcharge3',
 | 
				
			||||||
        'custom_surcharge4' => 'custom_surcharge4',
 | 
					        // 'custom_surcharge4' => 'custom_surcharge4',
 | 
				
			||||||
        'custom_value1' => 'custom_value1',
 | 
					        'custom_value1' => 'custom_value1',
 | 
				
			||||||
        'custom_value2' => 'custom_value2',
 | 
					        'custom_value2' => 'custom_value2',
 | 
				
			||||||
        'custom_value3' => 'custom_value3',
 | 
					        'custom_value3' => 'custom_value3',
 | 
				
			||||||
@ -66,7 +65,8 @@ class RecurringInvoiceExport extends BaseExport
 | 
				
			|||||||
        'currency' => 'currency_id',
 | 
					        'currency' => 'currency_id',
 | 
				
			||||||
        'vendor' => 'vendor_id',
 | 
					        'vendor' => 'vendor_id',
 | 
				
			||||||
        'project' => 'project_id',
 | 
					        'project' => 'project_id',
 | 
				
			||||||
        'frequency' => 'frequency_id'
 | 
					        'frequency_id' => 'frequency_id',
 | 
				
			||||||
 | 
					        'next_send_date' => 'next_send_date'
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private array $decorate_keys = [
 | 
					    private array $decorate_keys = [
 | 
				
			||||||
@ -127,11 +127,22 @@ class RecurringInvoiceExport 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("recurring_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];
 | 
				
			||||||
 | 
					            } elseif (array_key_exists($keyval, $transformed_invoice)) {
 | 
				
			||||||
 | 
					                $entity[$keyval] = $transformed_invoice[$keyval];
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                $entity[$keyval] = '';
 | 
					                $entity[$keyval] = $this->resolveKey($keyval, $invoice, $this->invoice_transformer);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this->decorateAdvancedFields($invoice, $entity);
 | 
					        return $this->decorateAdvancedFields($invoice, $entity);
 | 
				
			||||||
@ -163,7 +174,9 @@ class RecurringInvoiceExport extends BaseExport
 | 
				
			|||||||
            $entity['vendor'] = $invoice->vendor ? $invoice->vendor->name : '';
 | 
					            $entity['vendor'] = $invoice->vendor ? $invoice->vendor->name : '';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $entity['frequency'] = $invoice->frequencyForKey($invoice->frequency_id);
 | 
					        if (in_array('recurring_invoice.frequency_id', $this->input['report_keys']) || in_array('frequency_id', $this->input['report_keys'])) {
 | 
				
			||||||
 | 
					            $entity['frequency_id'] = $invoice->frequencyForKey($invoice->frequency_id);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $entity;
 | 
					        return $entity;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,6 @@ use League\Csv\Writer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class TaskExport extends BaseExport
 | 
					class TaskExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private Company $company;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private $entity_transformer;
 | 
					    private $entity_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -47,9 +46,7 @@ class TaskExport extends BaseExport
 | 
				
			|||||||
        'custom_value4' => 'custom_value4',
 | 
					        'custom_value4' => 'custom_value4',
 | 
				
			||||||
        'status' => 'status_id',
 | 
					        'status' => 'status_id',
 | 
				
			||||||
        'project' => 'project_id',
 | 
					        'project' => 'project_id',
 | 
				
			||||||
        'invoice' => 'invoice_id',
 | 
					     ];
 | 
				
			||||||
        'client' => 'client_id',
 | 
					 | 
				
			||||||
    ];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private array $decorate_keys = [
 | 
					    private array $decorate_keys = [
 | 
				
			||||||
        'status',
 | 
					        'status',
 | 
				
			||||||
@ -110,38 +107,39 @@ class TaskExport extends BaseExport
 | 
				
			|||||||
        $entity = [];
 | 
					        $entity = [];
 | 
				
			||||||
        $transformed_entity = $this->entity_transformer->transform($task);
 | 
					        $transformed_entity = $this->entity_transformer->transform($task);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach (array_values($this->input['report_keys']) as $key) {
 | 
				
			||||||
 | 
					            $keyval = array_search($key, $this->entity_keys);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(!$keyval) {
 | 
				
			||||||
 | 
					                $keyval = array_search(str_replace("task.", "", $key), $this->entity_keys) ?? $key;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(!$keyval) {
 | 
				
			||||||
 | 
					                $keyval = $key;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (array_key_exists($key, $transformed_entity)) {
 | 
				
			||||||
 | 
					                $entity[$keyval] = $transformed_entity[$key];
 | 
				
			||||||
 | 
					            } elseif (array_key_exists($keyval, $transformed_entity)) {
 | 
				
			||||||
 | 
					                $entity[$keyval] = $transformed_entity[$keyval];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                $entity[$keyval] = $this->resolveKey($keyval, $task, $this->entity_transformer);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $entity['start_date'] = '';
 | 
				
			||||||
 | 
					        $entity['end_date'] = '';
 | 
				
			||||||
 | 
					        $entity['duration'] = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (is_null($task->time_log) || (is_array(json_decode($task->time_log, 1)) && count(json_decode($task->time_log, 1)) == 0)) {
 | 
					        if (is_null($task->time_log) || (is_array(json_decode($task->time_log, 1)) && count(json_decode($task->time_log, 1)) == 0)) {
 | 
				
			||||||
            foreach (array_values($this->input['report_keys']) as $key) {
 | 
					 | 
				
			||||||
                $keyval = array_search($key, $this->entity_keys);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (array_key_exists($key, $transformed_entity)) {
 | 
					 | 
				
			||||||
                    $entity[$keyval] = $transformed_entity[$key];
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    $entity[$keyval] = '';
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $entity['start_date'] = '';
 | 
					 | 
				
			||||||
            $entity['end_date'] = '';
 | 
					 | 
				
			||||||
            $entity['duration'] = '';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $entity = $this->decorateAdvancedFields($task, $entity);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            ksort($entity);
 | 
					 | 
				
			||||||
            $this->csv->insertOne($entity);
 | 
					            $this->csv->insertOne($entity);
 | 
				
			||||||
        } elseif (is_array(json_decode($task->time_log, 1)) && count(json_decode($task->time_log, 1)) > 0) {
 | 
					        } else {
 | 
				
			||||||
            foreach (array_values($this->input['report_keys']) as $key) {
 | 
					 | 
				
			||||||
                $keyval = array_search($key, $this->entity_keys);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (array_key_exists($key, $transformed_entity)) {
 | 
					 | 
				
			||||||
                    $entity[$keyval] = $transformed_entity[$key];
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    $entity[$keyval] = '';
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $this->iterateLogs($task, $entity);
 | 
					            $this->iterateLogs($task, $entity);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function iterateLogs(Task $task, array $entity)
 | 
					    private function iterateLogs(Task $task, array $entity)
 | 
				
			||||||
@ -164,39 +162,26 @@ class TaskExport extends BaseExport
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($logs as $key => $item) {
 | 
					        foreach ($logs as $key => $item) {
 | 
				
			||||||
            if (in_array('start_date', $this->input['report_keys'])) {
 | 
					            if (in_array('task.start_date', $this->input['report_keys']) || in_array('start_date', $this->input['report_keys'])) {
 | 
				
			||||||
                $entity['start_date'] = Carbon::createFromTimeStamp($item[0])->setTimezone($timezone_name)->format($date_format_default);
 | 
					                $entity['start_date'] = Carbon::createFromTimeStamp($item[0])->setTimezone($timezone_name)->format($date_format_default);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (in_array('end_date', $this->input['report_keys']) && $item[1] > 0) {
 | 
					            if ((in_array('task.end_date', $this->input['report_keys']) || in_array('end_date', $this->input['report_keys'])) && $item[1] > 0) {
 | 
				
			||||||
                $entity['end_date'] = Carbon::createFromTimeStamp($item[1])->setTimezone($timezone_name)->format($date_format_default);
 | 
					                $entity['end_date'] = Carbon::createFromTimeStamp($item[1])->setTimezone($timezone_name)->format($date_format_default);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (in_array('end_date', $this->input['report_keys']) && $item[1] == 0) {
 | 
					            if ((in_array('task.end_date', $this->input['report_keys']) || in_array('end_date', $this->input['report_keys'])) && $item[1] == 0) {
 | 
				
			||||||
                $entity['end_date'] = ctrans('texts.is_running');
 | 
					                $entity['end_date'] = ctrans('texts.is_running');
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (in_array('duration', $this->input['report_keys'])) {
 | 
					            if (in_array('task.duration', $this->input['report_keys']) || in_array('duration', $this->input['report_keys'])) {
 | 
				
			||||||
                $entity['duration'] = $task->calcDuration();
 | 
					                $entity['duration'] = $task->calcDuration();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            if (! array_key_exists('duration', $entity)) {
 | 
					 | 
				
			||||||
                $entity['duration'] = '';
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (! array_key_exists('start_date', $entity)) {
 | 
					 | 
				
			||||||
                $entity['start_date'] = '';
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (! array_key_exists('end_date', $entity)) {
 | 
					 | 
				
			||||||
                $entity['end_date'] = '';
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $entity = $this->decorateAdvancedFields($task, $entity);
 | 
					            $entity = $this->decorateAdvancedFields($task, $entity);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            ksort($entity);
 | 
					 | 
				
			||||||
            $this->csv->insertOne($entity);
 | 
					            $this->csv->insertOne($entity);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            unset($entity['start_date']);
 | 
					            unset($entity['start_date']);
 | 
				
			||||||
            unset($entity['end_date']);
 | 
					            unset($entity['end_date']);
 | 
				
			||||||
            unset($entity['duration']);
 | 
					            unset($entity['duration']);
 | 
				
			||||||
@ -213,14 +198,6 @@ class TaskExport extends BaseExport
 | 
				
			|||||||
            $entity['project'] = $task->project()->exists() ? $task->project->name : '';
 | 
					            $entity['project'] = $task->project()->exists() ? $task->project->name : '';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (in_array('client_id', $this->input['report_keys'])) {
 | 
					 | 
				
			||||||
            $entity['client'] = $task->client ? $task->client->present()->name() : '';
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (in_array('invoice_id', $this->input['report_keys'])) {
 | 
					 | 
				
			||||||
            $entity['invoice'] = $task->invoice ? $task->invoice->number : '';
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return $entity;
 | 
					        return $entity;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,6 @@ use League\Csv\Writer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class VendorExport extends BaseExport
 | 
					class VendorExport extends BaseExport
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private $company;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private $vendor_transformer;
 | 
					    private $vendor_transformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -115,7 +114,7 @@ class VendorExport extends BaseExport
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private function buildRow(Vendor $vendor) :array
 | 
					    private function buildRow(Vendor $vendor) :array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $transformed_contact = false;
 | 
					        $transformed_contact = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $transformed_vendor = $this->vendor_transformer->transform($vendor);
 | 
					        $transformed_vendor = $this->vendor_transformer->transform($vendor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -49,7 +49,7 @@ class CreditFactory
 | 
				
			|||||||
        $credit->user_id = $user_id;
 | 
					        $credit->user_id = $user_id;
 | 
				
			||||||
        $credit->company_id = $company_id;
 | 
					        $credit->company_id = $company_id;
 | 
				
			||||||
        $credit->recurring_id = null;
 | 
					        $credit->recurring_id = null;
 | 
				
			||||||
 | 
					        $credit->exchange_rate = 1;
 | 
				
			||||||
        return $credit;
 | 
					        return $credit;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -49,7 +49,8 @@ class PurchaseOrderFactory
 | 
				
			|||||||
        $purchase_order->user_id = $user_id;
 | 
					        $purchase_order->user_id = $user_id;
 | 
				
			||||||
        $purchase_order->company_id = $company_id;
 | 
					        $purchase_order->company_id = $company_id;
 | 
				
			||||||
        $purchase_order->recurring_id = null;
 | 
					        $purchase_order->recurring_id = null;
 | 
				
			||||||
 | 
					        $purchase_order->exchange_rate = 1;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        return $purchase_order;
 | 
					        return $purchase_order;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -46,6 +46,7 @@ class QuoteFactory
 | 
				
			|||||||
        $quote->user_id = $user_id;
 | 
					        $quote->user_id = $user_id;
 | 
				
			||||||
        $quote->company_id = $company_id;
 | 
					        $quote->company_id = $company_id;
 | 
				
			||||||
        $quote->paid_to_date = 0;
 | 
					        $quote->paid_to_date = 0;
 | 
				
			||||||
 | 
					        $quote->exchange_rate = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $quote;
 | 
					        return $quote;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -32,11 +32,12 @@ class ExpenseFilters extends QueryFilters
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return  $this->builder->where(function ($query) use ($filter) {
 | 
					        return  $this->builder->where(function ($query) use ($filter) {
 | 
				
			||||||
            $query->where('public_notes', 'like', '%'.$filter.'%')
 | 
					            $query->where('number', 'like', '%'.$filter.'%')
 | 
				
			||||||
                          ->orWhere('custom_value1', 'like', '%'.$filter.'%')
 | 
					                ->orWhere('public_notes', 'like', '%'.$filter.'%')
 | 
				
			||||||
                          ->orWhere('custom_value2', 'like', '%'.$filter.'%')
 | 
					                ->orWhere('custom_value1', 'like', '%'.$filter.'%')
 | 
				
			||||||
                          ->orWhere('custom_value3', 'like', '%'.$filter.'%')
 | 
					                ->orWhere('custom_value2', 'like', '%'.$filter.'%')
 | 
				
			||||||
                          ->orWhere('custom_value4', 'like', '%'.$filter.'%');
 | 
					                ->orWhere('custom_value3', 'like', '%'.$filter.'%')
 | 
				
			||||||
 | 
					                ->orWhere('custom_value4', 'like', '%'.$filter.'%');
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -164,6 +165,17 @@ class ExpenseFilters 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', 'expenses.client_id'), $sort_col[1]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($sort_col[0] == 'vendor_id') {
 | 
				
			||||||
 | 
					            return $this->builder->orderBy(\App\Models\Vendor::select('name')
 | 
				
			||||||
 | 
					                    ->whereColumn('vendors.id', 'expenses.vendor_id'), $sort_col[1]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (is_array($sort_col) && in_array($sort_col[1], ['asc', 'desc']) && in_array($sort_col[0], ['public_notes', 'date', 'id_number', 'custom_value1', 'custom_value2', 'custom_value3', 'custom_value4'])) {
 | 
					        if (is_array($sort_col) && in_array($sort_col[1], ['asc', 'desc']) && in_array($sort_col[0], ['public_notes', 'date', 'id_number', 'custom_value1', 'custom_value2', 'custom_value3', 'custom_value4'])) {
 | 
				
			||||||
            return $this->builder->orderBy($sort_col[0], $sort_col[1]);
 | 
					            return $this->builder->orderBy($sort_col[0], $sort_col[1]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -123,6 +123,11 @@ class PurchaseOrderFilters extends QueryFilters
 | 
				
			|||||||
            return $this->builder;
 | 
					            return $this->builder;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($sort_col[0] == 'vendor_id') {
 | 
				
			||||||
 | 
					            return $this->builder->orderBy(\App\Models\Vendor::select('name')
 | 
				
			||||||
 | 
					                    ->whereColumn('vendors.id', 'purchase_orders.vendor_id'), $sort_col[1]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this->builder->orderBy($sort_col[0], $sort_col[1]);
 | 
					        return $this->builder->orderBy($sort_col[0], $sort_col[1]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -81,6 +81,19 @@ class AccountTransformer implements AccountTransformerInterface
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function transformAccount($account)
 | 
					    public function transformAccount($account)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        $current_balance = 0;
 | 
				
			||||||
 | 
					        $account_currency = '';
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if(property_exists($account, 'currentBalance')) {
 | 
				
			||||||
 | 
					            $current_balance = $account->currentBalance->amount ?? 0;
 | 
				
			||||||
 | 
					            $account_currency = $account->currentBalance->currency ?? '';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        elseif(property_exists($account, 'balance')){
 | 
				
			||||||
 | 
					            $current_balance = $account->balance->amount ?? 0;
 | 
				
			||||||
 | 
					            $account_currency = $account->balance->currency ?? '';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            'id' => $account->id,
 | 
					            'id' => $account->id,
 | 
				
			||||||
            'account_type' => $account->CONTAINER,
 | 
					            'account_type' => $account->CONTAINER,
 | 
				
			||||||
@ -92,8 +105,8 @@ class AccountTransformer implements AccountTransformerInterface
 | 
				
			|||||||
            'provider_id' => $account->providerId,
 | 
					            'provider_id' => $account->providerId,
 | 
				
			||||||
            'provider_name' => $account->providerName,
 | 
					            'provider_name' => $account->providerName,
 | 
				
			||||||
            'nickname' => property_exists($account, 'nickname') ? $account->nickname : '',
 | 
					            'nickname' => property_exists($account, 'nickname') ? $account->nickname : '',
 | 
				
			||||||
            'current_balance' => property_exists($account, 'currentBalance') ? $account->currentBalance->amount : 0,
 | 
					            'current_balance' => $current_balance,
 | 
				
			||||||
            'account_currency' => property_exists($account, 'currency') ? $account->currentBalance->currency : '',
 | 
					            'account_currency' => $account_currency,
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -185,6 +185,21 @@ class Yodlee
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getAccountSummary($account_id)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $token = $this->getAccessToken();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $response = Http::withHeaders($this->getHeaders(["Authorization" => "Bearer {$token}"]))->get($this->getEndpoint(). "/accounts/{$account_id}", []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($response->successful()) {
 | 
				
			||||||
 | 
					            return $response->object();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($response->failed()) {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function deleteAccount($account_id)
 | 
					    public function deleteAccount($account_id)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $token = $this->getAccessToken();
 | 
					        $token = $this->getAccessToken();
 | 
				
			||||||
 | 
				
			|||||||
@ -238,14 +238,20 @@ class InvoiceItemSum
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->rule->tax($this->item);
 | 
					        $this->rule->tax($this->item);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        $precision = strlen(substr(strrchr($this->rule->tax_rate1, "."), 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->item->tax_name1 = $this->rule->tax_name1;
 | 
					        $this->item->tax_name1 = $this->rule->tax_name1;
 | 
				
			||||||
        $this->item->tax_rate1 = $this->rule->tax_rate1;
 | 
					        $this->item->tax_rate1 = round($this->rule->tax_rate1, $precision);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $precision = strlen(substr(strrchr($this->rule->tax_rate2, "."), 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->item->tax_name2 = $this->rule->tax_name2;
 | 
					        $this->item->tax_name2 = $this->rule->tax_name2;
 | 
				
			||||||
        $this->item->tax_rate2 = $this->rule->tax_rate2;
 | 
					        $this->item->tax_rate2 = round($this->rule->tax_rate2, $precision);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $precision = strlen(substr(strrchr($this->rule->tax_rate3, "."), 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->item->tax_name3 = $this->rule->tax_name3;
 | 
					        $this->item->tax_name3 = $this->rule->tax_name3;
 | 
				
			||||||
        $this->item->tax_rate3 = $this->rule->tax_rate3;
 | 
					        $this->item->tax_rate3 = round($this->rule->tax_rate3, $precision);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -11,24 +11,23 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Http\Controllers;
 | 
					namespace App\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Http\Requests\Activity\DownloadHistoricalEntityRequest;
 | 
					 | 
				
			||||||
use App\Models\Activity;
 | 
					 | 
				
			||||||
use App\Transformers\ActivityTransformer;
 | 
					 | 
				
			||||||
use App\Utils\HostedPDF\NinjaPdf;
 | 
					 | 
				
			||||||
use App\Utils\Ninja;
 | 
					 | 
				
			||||||
use App\Utils\PhantomJS\Phantom;
 | 
					 | 
				
			||||||
use App\Utils\Traits\Pdf\PageNumbering;
 | 
					 | 
				
			||||||
use App\Utils\Traits\Pdf\PdfMaker;
 | 
					 | 
				
			||||||
use Illuminate\Http\JsonResponse;
 | 
					 | 
				
			||||||
use Illuminate\Http\Request;
 | 
					 | 
				
			||||||
use Illuminate\Http\Response;
 | 
					 | 
				
			||||||
use Illuminate\Support\Facades\Storage;
 | 
					 | 
				
			||||||
use stdClass;
 | 
					use stdClass;
 | 
				
			||||||
use Symfony\Component\HttpFoundation\StreamedResponse;
 | 
					use App\Utils\Ninja;
 | 
				
			||||||
 | 
					use App\Models\Activity;
 | 
				
			||||||
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
 | 
					use App\Utils\Traits\MakesHash;
 | 
				
			||||||
 | 
					use App\Utils\PhantomJS\Phantom;
 | 
				
			||||||
 | 
					use App\Utils\HostedPDF\NinjaPdf;
 | 
				
			||||||
 | 
					use App\Utils\Traits\Pdf\PdfMaker;
 | 
				
			||||||
 | 
					use App\Utils\Traits\Pdf\PageNumbering;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Storage;
 | 
				
			||||||
 | 
					use App\Transformers\ActivityTransformer;
 | 
				
			||||||
 | 
					use App\Http\Requests\Activity\ShowActivityRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\Activity\DownloadHistoricalEntityRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ActivityController extends BaseController
 | 
					class ActivityController extends BaseController
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    use PdfMaker, PageNumbering;
 | 
					    use PdfMaker, PageNumbering, MakesHash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected $entity_type = Activity::class;
 | 
					    protected $entity_type = Activity::class;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -39,50 +38,6 @@ class ActivityController extends BaseController
 | 
				
			|||||||
        parent::__construct();
 | 
					        parent::__construct();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * @OA\Get(
 | 
					 | 
				
			||||||
     *      path="/api/v1/activities",
 | 
					 | 
				
			||||||
     *      operationId="getActivities",
 | 
					 | 
				
			||||||
     *      tags={"actvities"},
 | 
					 | 
				
			||||||
     *      summary="Gets a list of actvities",
 | 
					 | 
				
			||||||
     *      description="Lists all activities",
 | 
					 | 
				
			||||||
     *      @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"),
 | 
					 | 
				
			||||||
     *      @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
 | 
					 | 
				
			||||||
     *      @OA\Parameter(ref="#/components/parameters/include"),
 | 
					 | 
				
			||||||
     *      @OA\Parameter(ref="#/components/parameters/index"),
 | 
					 | 
				
			||||||
     *      @OA\Parameter(
 | 
					 | 
				
			||||||
     *          name="rows",
 | 
					 | 
				
			||||||
     *          in="query",
 | 
					 | 
				
			||||||
     *          description="The number of activities to return",
 | 
					 | 
				
			||||||
     *          example="50",
 | 
					 | 
				
			||||||
     *          required=false,
 | 
					 | 
				
			||||||
     *          @OA\Schema(
 | 
					 | 
				
			||||||
     *              type="number",
 | 
					 | 
				
			||||||
     *              format="integer",
 | 
					 | 
				
			||||||
     *          ),
 | 
					 | 
				
			||||||
     *      ),
 | 
					 | 
				
			||||||
     *      @OA\Response(
 | 
					 | 
				
			||||||
     *          response=200,
 | 
					 | 
				
			||||||
     *          description="A list of actvities",
 | 
					 | 
				
			||||||
     *          @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
 | 
					 | 
				
			||||||
     *          @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
 | 
					 | 
				
			||||||
     *          @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
 | 
					 | 
				
			||||||
     *          @OA\JsonContent(ref="#/components/schemas/Activity"),
 | 
					 | 
				
			||||||
     *       ),
 | 
					 | 
				
			||||||
     *       @OA\Response(
 | 
					 | 
				
			||||||
     *          response=422,
 | 
					 | 
				
			||||||
     *          description="Validation error",
 | 
					 | 
				
			||||||
     *          @OA\JsonContent(ref="#/components/schemas/ValidationError"),
 | 
					 | 
				
			||||||
     *       ),
 | 
					 | 
				
			||||||
     *       @OA\Response(
 | 
					 | 
				
			||||||
     *           response="default",
 | 
					 | 
				
			||||||
     *           description="Unexpected Error",
 | 
					 | 
				
			||||||
     *           @OA\JsonContent(ref="#/components/schemas/Error"),
 | 
					 | 
				
			||||||
     *       ),
 | 
					 | 
				
			||||||
     *     )
 | 
					 | 
				
			||||||
     * @param Request $request
 | 
					 | 
				
			||||||
     * @return Response|mixed
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function index(Request $request)
 | 
					    public function index(Request $request)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $default_activities = $request->has('rows') ? $request->input('rows') : 75;
 | 
					        $default_activities = $request->has('rows') ? $request->input('rows') : 75;
 | 
				
			||||||
@ -115,47 +70,36 @@ class ActivityController extends BaseController
 | 
				
			|||||||
        return $this->listResponse($activities);
 | 
					        return $this->listResponse($activities);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    public function entityActivity(ShowActivityRequest $request)
 | 
				
			||||||
     * @OA\Get(
 | 
					    {
 | 
				
			||||||
     *      path="/api/v1/actvities/download_entity/{activity_id}",
 | 
					
 | 
				
			||||||
     *      operationId="getActivityHistoricalEntityPdf",
 | 
					        $default_activities = request()->has('rows') ? request()->input('rows') : 75;
 | 
				
			||||||
     *      tags={"actvities"},
 | 
					
 | 
				
			||||||
     *      summary="Gets a PDF for the given activity",
 | 
					        $activities = Activity::with('user')
 | 
				
			||||||
     *      description="Gets a PDF for the given activity",
 | 
					                                ->orderBy('created_at', 'DESC')
 | 
				
			||||||
     *      @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"),
 | 
					                                ->company()
 | 
				
			||||||
     *      @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
 | 
					                                ->where("{$request->entity}_id", $request->entity_id)
 | 
				
			||||||
     *      @OA\Parameter(
 | 
					                                ->take($default_activities);
 | 
				
			||||||
     *          name="activity_id",
 | 
					
 | 
				
			||||||
     *          in="path",
 | 
					        /** @var \App\Models\User auth()->user() */
 | 
				
			||||||
     *          description="The Activity Hashed ID",
 | 
					        $user = auth()->user();
 | 
				
			||||||
     *          example="D2J234DFA",
 | 
					
 | 
				
			||||||
     *          required=true,
 | 
					        if (!$user->isAdmin()) {
 | 
				
			||||||
     *          @OA\Schema(
 | 
					            $activities->where('user_id', auth()->user()->id);
 | 
				
			||||||
     *              type="string",
 | 
					        }
 | 
				
			||||||
     *              format="string",
 | 
					
 | 
				
			||||||
     *          ),
 | 
					        $system = ctrans('texts.system');
 | 
				
			||||||
     *      ),
 | 
					
 | 
				
			||||||
     *      @OA\Response(
 | 
					        $data = $activities->cursor()->map(function ($activity) use ($system) {
 | 
				
			||||||
     *          response=200,
 | 
					
 | 
				
			||||||
     *          description="PDF File",
 | 
					            return $activity->activity_string();
 | 
				
			||||||
     *          @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
 | 
					
 | 
				
			||||||
     *          @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
 | 
					        });
 | 
				
			||||||
     *          @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
 | 
					
 | 
				
			||||||
     *       ),
 | 
					        return response()->json(['data' => $data->toArray()], 200);
 | 
				
			||||||
     *       @OA\Response(
 | 
					
 | 
				
			||||||
     *          response=404,
 | 
					    }
 | 
				
			||||||
     *          description="No file exists for the given record",
 | 
					
 | 
				
			||||||
     *       ),
 | 
					 | 
				
			||||||
     *       @OA\Response(
 | 
					 | 
				
			||||||
     *           response="default",
 | 
					 | 
				
			||||||
     *           description="Unexpected Error",
 | 
					 | 
				
			||||||
     *           @OA\JsonContent(ref="#/components/schemas/Error"),
 | 
					 | 
				
			||||||
     *       ),
 | 
					 | 
				
			||||||
     *     )
 | 
					 | 
				
			||||||
     * @param DownloadHistoricalEntityRequest $request
 | 
					 | 
				
			||||||
     * @param Activity $activity
 | 
					 | 
				
			||||||
     * @return JsonResponse|StreamedResponse
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function downloadHistoricalEntity(DownloadHistoricalEntityRequest $request, Activity $activity)
 | 
					    public function downloadHistoricalEntity(DownloadHistoricalEntityRequest $request, Activity $activity)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $backup = $activity->backup;
 | 
					        $backup = $activity->backup;
 | 
				
			||||||
@ -204,6 +148,8 @@ class ActivityController extends BaseController
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $activity->company->setLocale();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        if (isset($activity->invoice_id)) {
 | 
					        if (isset($activity->invoice_id)) {
 | 
				
			||||||
            $filename = $activity->invoice->numberFormatter().'.pdf';
 | 
					            $filename = $activity->invoice->numberFormatter().'.pdf';
 | 
				
			||||||
        } elseif (isset($activity->quote_id)) {
 | 
					        } elseif (isset($activity->quote_id)) {
 | 
				
			||||||
 | 
				
			|||||||
@ -209,7 +209,12 @@ class BankIntegrationController extends BaseController
 | 
				
			|||||||
        $accounts = $yodlee->getAccounts();
 | 
					        $accounts = $yodlee->getAccounts();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($accounts as $account) {
 | 
					        foreach ($accounts as $account) {
 | 
				
			||||||
            if (!BankIntegration::withTrashed()->where('bank_account_id', $account['id'])->where('company_id', $user->company()->id)->exists()) {
 | 
					            if ($bi = BankIntegration::withTrashed()->where('bank_account_id', $account['id'])->where('company_id', $user->company()->id)->first()){
 | 
				
			||||||
 | 
					                    $bi->balance = $account['current_balance'];
 | 
				
			||||||
 | 
					                    $bi->currency = $account['account_currency'];
 | 
				
			||||||
 | 
					                    $bi->save();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
                $bank_integration = new BankIntegration();
 | 
					                $bank_integration = new BankIntegration();
 | 
				
			||||||
                $bank_integration->company_id = $user->company()->id;
 | 
					                $bank_integration->company_id = $user->company()->id;
 | 
				
			||||||
                $bank_integration->account_id = $user->account_id;
 | 
					                $bank_integration->account_id = $user->account_id;
 | 
				
			||||||
 | 
				
			|||||||
@ -85,23 +85,21 @@ class InvitationController extends Controller
 | 
				
			|||||||
                                    ->with('contact.client')
 | 
					                                    ->with('contact.client')
 | 
				
			||||||
                                    ->firstOrFail();
 | 
					                                    ->firstOrFail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //09-03-2023 do not show entity if the invitation has been trashed.
 | 
					 | 
				
			||||||
        if ($invitation->trashed() || $invitation->{$entity}->is_deleted) {
 | 
					        if ($invitation->trashed() || $invitation->{$entity}->is_deleted) {
 | 
				
			||||||
            return $this->render('generic.not_available', ['account' => $invitation->company->account, 'company' => $invitation->company]);
 | 
					            return $this->render('generic.not_available', ['account' => $invitation->company->account, 'company' => $invitation->company]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* 12/01/2022 Clean up an edge case where if the contact is trashed, restore if a invitation comes back. */
 | 
					 | 
				
			||||||
        if ($invitation->contact->trashed()) {
 | 
					        if ($invitation->contact->trashed()) {
 | 
				
			||||||
            $invitation->contact->restore();
 | 
					            $invitation->contact->restore();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Return early if we have the correct client_hash embedded */
 | 
					 | 
				
			||||||
        $client_contact = $invitation->contact;
 | 
					        $client_contact = $invitation->contact;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (empty($client_contact->email)) {
 | 
					        if (empty($client_contact->email)) {
 | 
				
			||||||
            $client_contact->email = Str::random(15) . "@example.com";
 | 
					            $client_contact->email = Str::random(15) . "@example.com";
 | 
				
			||||||
        } $client_contact->save();
 | 
					            $client_contact->save();
 | 
				
			||||||
 | 
					        } 
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        if (request()->has('client_hash') && request()->input('client_hash') == $invitation->contact->client->client_hash) {
 | 
					        if (request()->has('client_hash') && request()->input('client_hash') == $invitation->contact->client->client_hash) {
 | 
				
			||||||
            request()->session()->invalidate();
 | 
					            request()->session()->invalidate();
 | 
				
			||||||
            auth()->guard('contact')->loginUsingId($client_contact->id, true);
 | 
					            auth()->guard('contact')->loginUsingId($client_contact->id, true);
 | 
				
			||||||
 | 
				
			|||||||
@ -86,7 +86,7 @@ class InvoiceController extends Controller
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function showBlob($hash)
 | 
					    public function showBlob($hash)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $data = Cache::pull($hash);
 | 
					        $data = Cache::get($hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match($data['entity_type']){
 | 
					        match($data['entity_type']){
 | 
				
			||||||
            'invoice' => $invitation = InvoiceInvitation::withTrashed()->find($data['invitation_id']),
 | 
					            'invoice' => $invitation = InvoiceInvitation::withTrashed()->find($data['invitation_id']),
 | 
				
			||||||
 | 
				
			|||||||
@ -24,6 +24,7 @@ use App\Http\Requests\CompanyGateway\UpdateCompanyGatewayRequest;
 | 
				
			|||||||
use App\Jobs\Util\ApplePayDomain;
 | 
					use App\Jobs\Util\ApplePayDomain;
 | 
				
			||||||
use App\Models\Client;
 | 
					use App\Models\Client;
 | 
				
			||||||
use App\Models\CompanyGateway;
 | 
					use App\Models\CompanyGateway;
 | 
				
			||||||
 | 
					use App\PaymentDrivers\CheckoutCom\CheckoutSetupWebhook;
 | 
				
			||||||
use App\PaymentDrivers\Stripe\Jobs\StripeWebhook;
 | 
					use App\PaymentDrivers\Stripe\Jobs\StripeWebhook;
 | 
				
			||||||
use App\Repositories\CompanyRepository;
 | 
					use App\Repositories\CompanyRepository;
 | 
				
			||||||
use App\Transformers\CompanyGatewayTransformer;
 | 
					use App\Transformers\CompanyGatewayTransformer;
 | 
				
			||||||
@ -49,6 +50,8 @@ class CompanyGatewayController extends BaseController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private array $stripe_keys = ['d14dd26a47cecc30fdd65700bfb67b34', 'd14dd26a37cecc30fdd65700bfb55b23'];
 | 
					    private array $stripe_keys = ['d14dd26a47cecc30fdd65700bfb67b34', 'd14dd26a37cecc30fdd65700bfb55b23'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private string $checkout_key = '3758e7f7c6f4cecf0f4f348b9a00f456';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * CompanyGatewayController constructor.
 | 
					     * CompanyGatewayController constructor.
 | 
				
			||||||
     * @param CompanyRepository $company_repo
 | 
					     * @param CompanyRepository $company_repo
 | 
				
			||||||
@ -211,6 +214,9 @@ class CompanyGatewayController extends BaseController
 | 
				
			|||||||
        if (in_array($company_gateway->gateway_key, $this->stripe_keys)) {
 | 
					        if (in_array($company_gateway->gateway_key, $this->stripe_keys)) {
 | 
				
			||||||
            StripeWebhook::dispatch($company_gateway->company->company_key, $company_gateway->id);
 | 
					            StripeWebhook::dispatch($company_gateway->company->company_key, $company_gateway->id);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        elseif($company_gateway->gateway_key == $this->checkout_key) {
 | 
				
			||||||
 | 
					            CheckoutSetupWebhook::dispatch($company_gateway->company->company_key, $company_gateway->id);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this->itemResponse($company_gateway);
 | 
					        return $this->itemResponse($company_gateway);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -382,8 +388,10 @@ class CompanyGatewayController extends BaseController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $company_gateway->save();
 | 
					        $company_gateway->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // ApplePayDomain::dispatch($company_gateway, $company_gateway->company->db);
 | 
					        if($company_gateway->gateway_key == $this->checkout_key) {
 | 
				
			||||||
 | 
					            CheckoutSetupWebhook::dispatch($company_gateway->company->company_key, $company_gateway->fresh()->id);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        return $this->itemResponse($company_gateway);
 | 
					        return $this->itemResponse($company_gateway);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -11,34 +11,35 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Http\Controllers;
 | 
					namespace App\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Events\Credit\CreditWasCreated;
 | 
					use App\Utils\Ninja;
 | 
				
			||||||
use App\Events\Credit\CreditWasUpdated;
 | 
					use App\Models\Client;
 | 
				
			||||||
use App\Factory\CloneCreditFactory;
 | 
					use App\Models\Credit;
 | 
				
			||||||
 | 
					use App\Models\Account;
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					use Illuminate\Http\Response;
 | 
				
			||||||
use App\Factory\CreditFactory;
 | 
					use App\Factory\CreditFactory;
 | 
				
			||||||
use App\Filters\CreditFilters;
 | 
					use App\Filters\CreditFilters;
 | 
				
			||||||
use App\Http\Requests\Credit\ActionCreditRequest;
 | 
					use App\Jobs\Credit\ZipCredits;
 | 
				
			||||||
 | 
					use App\Utils\Traits\MakesHash;
 | 
				
			||||||
 | 
					use App\Jobs\Entity\EmailEntity;
 | 
				
			||||||
 | 
					use App\Factory\CloneCreditFactory;
 | 
				
			||||||
 | 
					use App\Services\PdfMaker\PdfMerge;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\App;
 | 
				
			||||||
 | 
					use App\Utils\Traits\SavesDocuments;
 | 
				
			||||||
 | 
					use App\Repositories\CreditRepository;
 | 
				
			||||||
 | 
					use App\Events\Credit\CreditWasCreated;
 | 
				
			||||||
 | 
					use App\Events\Credit\CreditWasUpdated;
 | 
				
			||||||
 | 
					use App\Transformers\CreditTransformer;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Storage;
 | 
				
			||||||
use App\Http\Requests\Credit\BulkCreditRequest;
 | 
					use App\Http\Requests\Credit\BulkCreditRequest;
 | 
				
			||||||
use App\Http\Requests\Credit\CreateCreditRequest;
 | 
					 | 
				
			||||||
use App\Http\Requests\Credit\DestroyCreditRequest;
 | 
					 | 
				
			||||||
use App\Http\Requests\Credit\EditCreditRequest;
 | 
					use App\Http\Requests\Credit\EditCreditRequest;
 | 
				
			||||||
use App\Http\Requests\Credit\ShowCreditRequest;
 | 
					use App\Http\Requests\Credit\ShowCreditRequest;
 | 
				
			||||||
use App\Http\Requests\Credit\StoreCreditRequest;
 | 
					use App\Http\Requests\Credit\StoreCreditRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\Credit\ActionCreditRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\Credit\CreateCreditRequest;
 | 
				
			||||||
use App\Http\Requests\Credit\UpdateCreditRequest;
 | 
					use App\Http\Requests\Credit\UpdateCreditRequest;
 | 
				
			||||||
use App\Http\Requests\Credit\UploadCreditRequest;
 | 
					use App\Http\Requests\Credit\UploadCreditRequest;
 | 
				
			||||||
use App\Jobs\Credit\ZipCredits;
 | 
					use App\Http\Requests\Credit\DestroyCreditRequest;
 | 
				
			||||||
use App\Jobs\Entity\EmailEntity;
 | 
					 | 
				
			||||||
use App\Models\Account;
 | 
					 | 
				
			||||||
use App\Models\Client;
 | 
					 | 
				
			||||||
use App\Models\Credit;
 | 
					 | 
				
			||||||
use App\Models\Invoice;
 | 
					 | 
				
			||||||
use App\Repositories\CreditRepository;
 | 
					 | 
				
			||||||
use App\Services\PdfMaker\PdfMerge;
 | 
					 | 
				
			||||||
use App\Transformers\CreditTransformer;
 | 
					 | 
				
			||||||
use App\Utils\Ninja;
 | 
					 | 
				
			||||||
use App\Utils\Traits\MakesHash;
 | 
					 | 
				
			||||||
use App\Utils\Traits\SavesDocuments;
 | 
					 | 
				
			||||||
use Illuminate\Http\Response;
 | 
					 | 
				
			||||||
use Illuminate\Support\Facades\Storage;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Class CreditController.
 | 
					 * Class CreditController.
 | 
				
			||||||
@ -691,6 +692,8 @@ class CreditController extends BaseController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $credit = $invitation->credit;
 | 
					        $credit = $invitation->credit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        App::setLocale($invitation->contact->preferredLocale());
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        $file = $credit->service()->getCreditPdf($invitation);
 | 
					        $file = $credit->service()->getCreditPdf($invitation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $headers = ['Content-Type' => 'application/pdf'];
 | 
					        $headers = ['Content-Type' => 'application/pdf'];
 | 
				
			||||||
 | 
				
			|||||||
@ -81,7 +81,8 @@ class ImportController extends Controller
 | 
				
			|||||||
        /** @var UploadedFile $file */
 | 
					        /** @var UploadedFile $file */
 | 
				
			||||||
        foreach ($request->files->get('files') as $entityType => $file) {
 | 
					        foreach ($request->files->get('files') as $entityType => $file) {
 | 
				
			||||||
            $contents = file_get_contents($file->getPathname());
 | 
					            $contents = file_get_contents($file->getPathname());
 | 
				
			||||||
            // $contents = mb_convert_encoding($contents, 'UTF-16LE', 'UTF-8');
 | 
					
 | 
				
			||||||
 | 
					            $contents = $this->convertEncoding($contents);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Store the csv in cache with an expiry of 10 minutes
 | 
					            // Store the csv in cache with an expiry of 10 minutes
 | 
				
			||||||
            Cache::put($hash.'-'.$entityType, base64_encode($contents), 600);
 | 
					            Cache::put($hash.'-'.$entityType, base64_encode($contents), 600);
 | 
				
			||||||
@ -100,6 +101,18 @@ class ImportController extends Controller
 | 
				
			|||||||
        return response()->json($data);
 | 
					        return response()->json($data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function convertEncoding($data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        $enc = mb_detect_encoding($data, mb_list_encodings(), true);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if($enc !== false) {
 | 
				
			||||||
 | 
					            $data = mb_convert_encoding($data, "UTF-8", $enc);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function import(ImportRequest $request)
 | 
					    public function import(ImportRequest $request)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $data = $request->all();
 | 
					        $data = $request->all();
 | 
				
			||||||
 | 
				
			|||||||
@ -12,38 +12,39 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Http\Controllers;
 | 
					namespace App\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Events\Invoice\InvoiceWasCreated;
 | 
					use App\Utils\Ninja;
 | 
				
			||||||
use App\Events\Invoice\InvoiceWasUpdated;
 | 
					use App\Models\Quote;
 | 
				
			||||||
use App\Factory\CloneInvoiceFactory;
 | 
					use App\Models\Account;
 | 
				
			||||||
use App\Factory\CloneInvoiceToQuoteFactory;
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					use App\Jobs\Cron\AutoBill;
 | 
				
			||||||
 | 
					use Illuminate\Http\Response;
 | 
				
			||||||
use App\Factory\InvoiceFactory;
 | 
					use App\Factory\InvoiceFactory;
 | 
				
			||||||
use App\Filters\InvoiceFilters;
 | 
					use App\Filters\InvoiceFilters;
 | 
				
			||||||
use App\Http\Requests\Invoice\ActionInvoiceRequest;
 | 
					use App\Utils\Traits\MakesHash;
 | 
				
			||||||
 | 
					use App\Jobs\Invoice\ZipInvoices;
 | 
				
			||||||
 | 
					use App\Services\PdfMaker\PdfMerge;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\App;
 | 
				
			||||||
 | 
					use App\Factory\CloneInvoiceFactory;
 | 
				
			||||||
 | 
					use App\Jobs\Invoice\BulkInvoiceJob;
 | 
				
			||||||
 | 
					use App\Utils\Traits\SavesDocuments;
 | 
				
			||||||
 | 
					use App\Jobs\Invoice\UpdateReminders;
 | 
				
			||||||
 | 
					use App\Transformers\QuoteTransformer;
 | 
				
			||||||
 | 
					use App\Repositories\InvoiceRepository;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Storage;
 | 
				
			||||||
 | 
					use App\Transformers\InvoiceTransformer;
 | 
				
			||||||
 | 
					use App\Events\Invoice\InvoiceWasCreated;
 | 
				
			||||||
 | 
					use App\Events\Invoice\InvoiceWasUpdated;
 | 
				
			||||||
 | 
					use App\Factory\CloneInvoiceToQuoteFactory;
 | 
				
			||||||
use App\Http\Requests\Invoice\BulkInvoiceRequest;
 | 
					use App\Http\Requests\Invoice\BulkInvoiceRequest;
 | 
				
			||||||
use App\Http\Requests\Invoice\CreateInvoiceRequest;
 | 
					 | 
				
			||||||
use App\Http\Requests\Invoice\DestroyInvoiceRequest;
 | 
					 | 
				
			||||||
use App\Http\Requests\Invoice\EditInvoiceRequest;
 | 
					use App\Http\Requests\Invoice\EditInvoiceRequest;
 | 
				
			||||||
use App\Http\Requests\Invoice\ShowInvoiceRequest;
 | 
					use App\Http\Requests\Invoice\ShowInvoiceRequest;
 | 
				
			||||||
use App\Http\Requests\Invoice\StoreInvoiceRequest;
 | 
					use App\Http\Requests\Invoice\StoreInvoiceRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\Invoice\ActionInvoiceRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\Invoice\CreateInvoiceRequest;
 | 
				
			||||||
use App\Http\Requests\Invoice\UpdateInvoiceRequest;
 | 
					use App\Http\Requests\Invoice\UpdateInvoiceRequest;
 | 
				
			||||||
use App\Http\Requests\Invoice\UpdateReminderRequest;
 | 
					 | 
				
			||||||
use App\Http\Requests\Invoice\UploadInvoiceRequest;
 | 
					use App\Http\Requests\Invoice\UploadInvoiceRequest;
 | 
				
			||||||
use App\Jobs\Cron\AutoBill;
 | 
					use App\Http\Requests\Invoice\DestroyInvoiceRequest;
 | 
				
			||||||
use App\Jobs\Invoice\BulkInvoiceJob;
 | 
					use App\Http\Requests\Invoice\UpdateReminderRequest;
 | 
				
			||||||
use App\Jobs\Invoice\UpdateReminders;
 | 
					 | 
				
			||||||
use App\Jobs\Invoice\ZipInvoices;
 | 
					 | 
				
			||||||
use App\Models\Account;
 | 
					 | 
				
			||||||
use App\Models\Invoice;
 | 
					 | 
				
			||||||
use App\Models\Quote;
 | 
					 | 
				
			||||||
use App\Repositories\InvoiceRepository;
 | 
					 | 
				
			||||||
use App\Services\PdfMaker\PdfMerge;
 | 
					 | 
				
			||||||
use App\Transformers\InvoiceTransformer;
 | 
					 | 
				
			||||||
use App\Transformers\QuoteTransformer;
 | 
					 | 
				
			||||||
use App\Utils\Ninja;
 | 
					 | 
				
			||||||
use App\Utils\Traits\MakesHash;
 | 
					 | 
				
			||||||
use App\Utils\Traits\SavesDocuments;
 | 
					 | 
				
			||||||
use Illuminate\Http\Response;
 | 
					 | 
				
			||||||
use Illuminate\Support\Facades\Storage;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Class InvoiceController.
 | 
					 * Class InvoiceController.
 | 
				
			||||||
@ -821,6 +822,8 @@ class InvoiceController extends BaseController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $invoice = $invitation->invoice;
 | 
					        $invoice = $invitation->invoice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        App::setLocale($invitation->contact->preferredLocale());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $file_name = $invoice->numberFormatter().'.pdf';
 | 
					        $file_name = $invoice->numberFormatter().'.pdf';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $file = (new \App\Jobs\Entity\CreateRawPdf($invitation, $invitation->company->db))->handle();
 | 
					        $file = (new \App\Jobs\Entity\CreateRawPdf($invitation, $invitation->company->db))->handle();
 | 
				
			||||||
 | 
				
			|||||||
@ -285,7 +285,7 @@ class PreviewController extends BaseController
 | 
				
			|||||||
                return $maker->getCompiledHTML();
 | 
					                return $maker->getCompiledHTML();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } catch(\Exception $e) {
 | 
					        } catch(\Exception $e) {
 | 
				
			||||||
            nlog($e->getMessage());
 | 
					            // nlog($e->getMessage());
 | 
				
			||||||
            DB::connection(config('database.default'))->rollBack();
 | 
					            DB::connection(config('database.default'))->rollBack();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Http\Controllers;
 | 
					namespace App\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Utils\Ninja;
 | 
				
			||||||
use Illuminate\Http\Request;
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
use App\Jobs\Util\UnlinkFile;
 | 
					use App\Jobs\Util\UnlinkFile;
 | 
				
			||||||
use App\Exceptions\SystemError;
 | 
					use App\Exceptions\SystemError;
 | 
				
			||||||
@ -29,8 +30,10 @@ class ProtectedDownloadController extends BaseController
 | 
				
			|||||||
            throw new SystemError('File no longer available', 404);
 | 
					            throw new SystemError('File no longer available', 404);
 | 
				
			||||||
            abort(404, 'File no longer available');
 | 
					            abort(404, 'File no longer available');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        return response()->download($hashed_path, basename($hashed_path), [])->deleteFileAfterSend(true);
 | 
					        return response()->streamDownload(function () use ($hashed_path) {
 | 
				
			||||||
 | 
					            echo Storage::get($hashed_path);
 | 
				
			||||||
 | 
					        }, basename($hashed_path), []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -11,32 +11,33 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Http\Controllers;
 | 
					namespace App\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Events\PurchaseOrder\PurchaseOrderWasCreated;
 | 
					use App\Utils\Ninja;
 | 
				
			||||||
use App\Events\PurchaseOrder\PurchaseOrderWasUpdated;
 | 
					use App\Models\Client;
 | 
				
			||||||
 | 
					use App\Models\Account;
 | 
				
			||||||
 | 
					use App\Models\PurchaseOrder;
 | 
				
			||||||
 | 
					use Illuminate\Http\Response;
 | 
				
			||||||
 | 
					use App\Utils\Traits\MakesHash;
 | 
				
			||||||
 | 
					use App\Services\PdfMaker\PdfMerge;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\App;
 | 
				
			||||||
 | 
					use App\Utils\Traits\SavesDocuments;
 | 
				
			||||||
use App\Factory\PurchaseOrderFactory;
 | 
					use App\Factory\PurchaseOrderFactory;
 | 
				
			||||||
use App\Filters\PurchaseOrderFilters;
 | 
					use App\Filters\PurchaseOrderFilters;
 | 
				
			||||||
use App\Http\Requests\PurchaseOrder\ActionPurchaseOrderRequest;
 | 
					use Illuminate\Support\Facades\Storage;
 | 
				
			||||||
 | 
					use App\Jobs\PurchaseOrder\ZipPurchaseOrders;
 | 
				
			||||||
 | 
					use App\Repositories\PurchaseOrderRepository;
 | 
				
			||||||
 | 
					use App\Jobs\PurchaseOrder\PurchaseOrderEmail;
 | 
				
			||||||
 | 
					use App\Transformers\PurchaseOrderTransformer;
 | 
				
			||||||
 | 
					use App\Events\PurchaseOrder\PurchaseOrderWasCreated;
 | 
				
			||||||
 | 
					use App\Events\PurchaseOrder\PurchaseOrderWasUpdated;
 | 
				
			||||||
use App\Http\Requests\PurchaseOrder\BulkPurchaseOrderRequest;
 | 
					use App\Http\Requests\PurchaseOrder\BulkPurchaseOrderRequest;
 | 
				
			||||||
use App\Http\Requests\PurchaseOrder\CreatePurchaseOrderRequest;
 | 
					 | 
				
			||||||
use App\Http\Requests\PurchaseOrder\DestroyPurchaseOrderRequest;
 | 
					 | 
				
			||||||
use App\Http\Requests\PurchaseOrder\EditPurchaseOrderRequest;
 | 
					use App\Http\Requests\PurchaseOrder\EditPurchaseOrderRequest;
 | 
				
			||||||
use App\Http\Requests\PurchaseOrder\ShowPurchaseOrderRequest;
 | 
					use App\Http\Requests\PurchaseOrder\ShowPurchaseOrderRequest;
 | 
				
			||||||
use App\Http\Requests\PurchaseOrder\StorePurchaseOrderRequest;
 | 
					use App\Http\Requests\PurchaseOrder\StorePurchaseOrderRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\PurchaseOrder\ActionPurchaseOrderRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\PurchaseOrder\CreatePurchaseOrderRequest;
 | 
				
			||||||
use App\Http\Requests\PurchaseOrder\UpdatePurchaseOrderRequest;
 | 
					use App\Http\Requests\PurchaseOrder\UpdatePurchaseOrderRequest;
 | 
				
			||||||
use App\Http\Requests\PurchaseOrder\UploadPurchaseOrderRequest;
 | 
					use App\Http\Requests\PurchaseOrder\UploadPurchaseOrderRequest;
 | 
				
			||||||
use App\Jobs\PurchaseOrder\PurchaseOrderEmail;
 | 
					use App\Http\Requests\PurchaseOrder\DestroyPurchaseOrderRequest;
 | 
				
			||||||
use App\Jobs\PurchaseOrder\ZipPurchaseOrders;
 | 
					 | 
				
			||||||
use App\Models\Account;
 | 
					 | 
				
			||||||
use App\Models\Client;
 | 
					 | 
				
			||||||
use App\Models\PurchaseOrder;
 | 
					 | 
				
			||||||
use App\Repositories\PurchaseOrderRepository;
 | 
					 | 
				
			||||||
use App\Services\PdfMaker\PdfMerge;
 | 
					 | 
				
			||||||
use App\Transformers\PurchaseOrderTransformer;
 | 
					 | 
				
			||||||
use App\Utils\Ninja;
 | 
					 | 
				
			||||||
use App\Utils\Traits\MakesHash;
 | 
					 | 
				
			||||||
use App\Utils\Traits\SavesDocuments;
 | 
					 | 
				
			||||||
use Illuminate\Http\Response;
 | 
					 | 
				
			||||||
use Illuminate\Support\Facades\Storage;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PurchaseOrderController extends BaseController
 | 
					class PurchaseOrderController extends BaseController
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
				
			|||||||
@ -11,38 +11,39 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Http\Controllers;
 | 
					namespace App\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Events\Quote\QuoteWasCreated;
 | 
					use App\Utils\Ninja;
 | 
				
			||||||
use App\Events\Quote\QuoteWasUpdated;
 | 
					use App\Models\Quote;
 | 
				
			||||||
use App\Factory\CloneQuoteFactory;
 | 
					use App\Models\Client;
 | 
				
			||||||
use App\Factory\CloneQuoteToInvoiceFactory;
 | 
					use App\Models\Account;
 | 
				
			||||||
use App\Factory\CloneQuoteToProjectFactory;
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
use App\Factory\QuoteFactory;
 | 
					use App\Factory\QuoteFactory;
 | 
				
			||||||
use App\Filters\QuoteFilters;
 | 
					use App\Filters\QuoteFilters;
 | 
				
			||||||
use App\Http\Requests\Quote\ActionQuoteRequest;
 | 
					use App\Jobs\Quote\ZipQuotes;
 | 
				
			||||||
use App\Http\Requests\Quote\BulkActionQuoteRequest;
 | 
					use Illuminate\Http\Response;
 | 
				
			||||||
use App\Http\Requests\Quote\CreateQuoteRequest;
 | 
					use App\Utils\Traits\MakesHash;
 | 
				
			||||||
use App\Http\Requests\Quote\DestroyQuoteRequest;
 | 
					use App\Factory\CloneQuoteFactory;
 | 
				
			||||||
 | 
					use App\Services\PdfMaker\PdfMerge;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\App;
 | 
				
			||||||
 | 
					use App\Utils\Traits\SavesDocuments;
 | 
				
			||||||
 | 
					use App\Events\Quote\QuoteWasCreated;
 | 
				
			||||||
 | 
					use App\Events\Quote\QuoteWasUpdated;
 | 
				
			||||||
 | 
					use App\Repositories\QuoteRepository;
 | 
				
			||||||
 | 
					use App\Transformers\QuoteTransformer;
 | 
				
			||||||
 | 
					use App\Utils\Traits\GeneratesCounter;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Storage;
 | 
				
			||||||
 | 
					use App\Transformers\InvoiceTransformer;
 | 
				
			||||||
 | 
					use App\Factory\CloneQuoteToInvoiceFactory;
 | 
				
			||||||
 | 
					use App\Factory\CloneQuoteToProjectFactory;
 | 
				
			||||||
use App\Http\Requests\Quote\EditQuoteRequest;
 | 
					use App\Http\Requests\Quote\EditQuoteRequest;
 | 
				
			||||||
use App\Http\Requests\Quote\ShowQuoteRequest;
 | 
					use App\Http\Requests\Quote\ShowQuoteRequest;
 | 
				
			||||||
use App\Http\Requests\Quote\StoreQuoteRequest;
 | 
					use App\Http\Requests\Quote\StoreQuoteRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\Quote\ActionQuoteRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\Quote\CreateQuoteRequest;
 | 
				
			||||||
use App\Http\Requests\Quote\UpdateQuoteRequest;
 | 
					use App\Http\Requests\Quote\UpdateQuoteRequest;
 | 
				
			||||||
use App\Http\Requests\Quote\UploadQuoteRequest;
 | 
					use App\Http\Requests\Quote\UploadQuoteRequest;
 | 
				
			||||||
use App\Jobs\Quote\ZipQuotes;
 | 
					use App\Http\Requests\Quote\DestroyQuoteRequest;
 | 
				
			||||||
use App\Models\Account;
 | 
					use App\Http\Requests\Quote\BulkActionQuoteRequest;
 | 
				
			||||||
use App\Models\Client;
 | 
					 | 
				
			||||||
use App\Models\Invoice;
 | 
					 | 
				
			||||||
use App\Models\Quote;
 | 
					 | 
				
			||||||
use App\Repositories\QuoteRepository;
 | 
					 | 
				
			||||||
use App\Services\PdfMaker\PdfMerge;
 | 
					 | 
				
			||||||
use App\Transformers\InvoiceTransformer;
 | 
					 | 
				
			||||||
use App\Transformers\QuoteTransformer;
 | 
					 | 
				
			||||||
use App\Utils\Ninja;
 | 
					 | 
				
			||||||
use App\Utils\Traits\GeneratesCounter;
 | 
					 | 
				
			||||||
use App\Utils\Traits\MakesHash;
 | 
					 | 
				
			||||||
use App\Utils\Traits\SavesDocuments;
 | 
					 | 
				
			||||||
use Illuminate\Http\Request;
 | 
					 | 
				
			||||||
use Illuminate\Http\Response;
 | 
					 | 
				
			||||||
use Illuminate\Support\Facades\Storage;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Class QuoteController.
 | 
					 * Class QuoteController.
 | 
				
			||||||
@ -824,6 +825,8 @@ class QuoteController extends BaseController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $contact = $invitation->contact;
 | 
					        $contact = $invitation->contact;
 | 
				
			||||||
        $quote = $invitation->quote;
 | 
					        $quote = $invitation->quote;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        App::setLocale($invitation->contact->preferredLocale());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $file = $quote->service()->getQuotePdf($contact);
 | 
					        $file = $quote->service()->getQuotePdf($contact);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -11,29 +11,28 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Http\Controllers;
 | 
					namespace App\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Events\RecurringInvoice\RecurringInvoiceWasCreated;
 | 
					use App\Utils\Ninja;
 | 
				
			||||||
use App\Events\RecurringInvoice\RecurringInvoiceWasUpdated;
 | 
					use App\Models\Account;
 | 
				
			||||||
 | 
					use Illuminate\Http\Response;
 | 
				
			||||||
 | 
					use App\Utils\Traits\MakesHash;
 | 
				
			||||||
 | 
					use App\Models\RecurringInvoice;
 | 
				
			||||||
 | 
					use App\Utils\Traits\SavesDocuments;
 | 
				
			||||||
use App\Factory\RecurringInvoiceFactory;
 | 
					use App\Factory\RecurringInvoiceFactory;
 | 
				
			||||||
use App\Filters\RecurringInvoiceFilters;
 | 
					use App\Filters\RecurringInvoiceFilters;
 | 
				
			||||||
use App\Http\Requests\RecurringInvoice\ActionRecurringInvoiceRequest;
 | 
					use App\Jobs\RecurringInvoice\UpdateRecurring;
 | 
				
			||||||
 | 
					use App\Repositories\RecurringInvoiceRepository;
 | 
				
			||||||
 | 
					use App\Transformers\RecurringInvoiceTransformer;
 | 
				
			||||||
 | 
					use App\Events\RecurringInvoice\RecurringInvoiceWasCreated;
 | 
				
			||||||
 | 
					use App\Events\RecurringInvoice\RecurringInvoiceWasUpdated;
 | 
				
			||||||
use App\Http\Requests\RecurringInvoice\BulkRecurringInvoiceRequest;
 | 
					use App\Http\Requests\RecurringInvoice\BulkRecurringInvoiceRequest;
 | 
				
			||||||
use App\Http\Requests\RecurringInvoice\CreateRecurringInvoiceRequest;
 | 
					 | 
				
			||||||
use App\Http\Requests\RecurringInvoice\DestroyRecurringInvoiceRequest;
 | 
					 | 
				
			||||||
use App\Http\Requests\RecurringInvoice\EditRecurringInvoiceRequest;
 | 
					use App\Http\Requests\RecurringInvoice\EditRecurringInvoiceRequest;
 | 
				
			||||||
use App\Http\Requests\RecurringInvoice\ShowRecurringInvoiceRequest;
 | 
					use App\Http\Requests\RecurringInvoice\ShowRecurringInvoiceRequest;
 | 
				
			||||||
use App\Http\Requests\RecurringInvoice\StoreRecurringInvoiceRequest;
 | 
					use App\Http\Requests\RecurringInvoice\StoreRecurringInvoiceRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\RecurringInvoice\ActionRecurringInvoiceRequest;
 | 
				
			||||||
 | 
					use App\Http\Requests\RecurringInvoice\CreateRecurringInvoiceRequest;
 | 
				
			||||||
use App\Http\Requests\RecurringInvoice\UpdateRecurringInvoiceRequest;
 | 
					use App\Http\Requests\RecurringInvoice\UpdateRecurringInvoiceRequest;
 | 
				
			||||||
use App\Http\Requests\RecurringInvoice\UploadRecurringInvoiceRequest;
 | 
					use App\Http\Requests\RecurringInvoice\UploadRecurringInvoiceRequest;
 | 
				
			||||||
use App\Jobs\RecurringInvoice\UpdateRecurring;
 | 
					use App\Http\Requests\RecurringInvoice\DestroyRecurringInvoiceRequest;
 | 
				
			||||||
use App\Models\Account;
 | 
					 | 
				
			||||||
use App\Models\RecurringInvoice;
 | 
					 | 
				
			||||||
use App\Repositories\RecurringInvoiceRepository;
 | 
					 | 
				
			||||||
use App\Transformers\RecurringInvoiceTransformer;
 | 
					 | 
				
			||||||
use App\Utils\Ninja;
 | 
					 | 
				
			||||||
use App\Utils\Traits\MakesHash;
 | 
					 | 
				
			||||||
use App\Utils\Traits\SavesDocuments;
 | 
					 | 
				
			||||||
use Illuminate\Http\Response;
 | 
					 | 
				
			||||||
use Illuminate\Support\Facades\Storage;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Class RecurringInvoiceController.
 | 
					 * Class RecurringInvoiceController.
 | 
				
			||||||
@ -566,6 +565,8 @@ class RecurringInvoiceController extends BaseController
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $invoice = $invitation->recurring_invoice;
 | 
					        $invoice = $invitation->recurring_invoice;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        \Illuminate\Support\Facades\App::setLocale($invitation->contact->preferredLocale());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $file_name = $invoice->numberFormatter().'.pdf';
 | 
					        $file_name = $invoice->numberFormatter().'.pdf';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -53,7 +53,7 @@ class SelfUpdateController extends BaseController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        nlog('Test filesystem is writable');
 | 
					        nlog('Test filesystem is writable');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->testWritable();
 | 
					        // $this->testWritable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        nlog('Clear cache directory');
 | 
					        nlog('Clear cache directory');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -11,16 +11,17 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Http\Controllers\VendorPortal;
 | 
					namespace App\Http\Controllers\VendorPortal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Events\Misc\InvitationWasViewed;
 | 
					 | 
				
			||||||
use App\Events\PurchaseOrder\PurchaseOrderWasViewed;
 | 
					 | 
				
			||||||
use App\Http\Controllers\Controller;
 | 
					 | 
				
			||||||
use App\Jobs\Vendor\CreatePurchaseOrderPdf;
 | 
					 | 
				
			||||||
use App\Models\PurchaseOrderInvitation;
 | 
					 | 
				
			||||||
use App\Utils\Ninja;
 | 
					use App\Utils\Ninja;
 | 
				
			||||||
use App\Utils\Traits\MakesDates;
 | 
					 | 
				
			||||||
use App\Utils\Traits\MakesHash;
 | 
					 | 
				
			||||||
use Illuminate\Support\Facades\Auth;
 | 
					 | 
				
			||||||
use Illuminate\Support\Str;
 | 
					use Illuminate\Support\Str;
 | 
				
			||||||
 | 
					use App\Utils\Traits\MakesHash;
 | 
				
			||||||
 | 
					use App\Utils\Traits\MakesDates;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\App;
 | 
				
			||||||
 | 
					use App\Http\Controllers\Controller;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Auth;
 | 
				
			||||||
 | 
					use App\Models\PurchaseOrderInvitation;
 | 
				
			||||||
 | 
					use App\Events\Misc\InvitationWasViewed;
 | 
				
			||||||
 | 
					use App\Jobs\Vendor\CreatePurchaseOrderPdf;
 | 
				
			||||||
 | 
					use App\Events\PurchaseOrder\PurchaseOrderWasViewed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Class InvitationController.
 | 
					 * Class InvitationController.
 | 
				
			||||||
@ -89,6 +90,8 @@ class InvitationController extends Controller
 | 
				
			|||||||
            return response()->json(["message" => "no record found"], 400);
 | 
					            return response()->json(["message" => "no record found"], 400);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        App::setLocale($invitation->contact->preferredLocale());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $file_name = $invitation->purchase_order->numberFormatter().'.pdf';
 | 
					        $file_name = $invitation->purchase_order->numberFormatter().'.pdf';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $file = (new CreatePurchaseOrderPdf($invitation))->rawPdf();
 | 
					        $file = (new CreatePurchaseOrderPdf($invitation))->rawPdf();
 | 
				
			||||||
 | 
				
			|||||||
@ -20,15 +20,12 @@ use Illuminate\Support\Str;
 | 
				
			|||||||
use App\Models\QuoteInvitation;
 | 
					use App\Models\QuoteInvitation;
 | 
				
			||||||
use App\Utils\VendorHtmlEngine;
 | 
					use App\Utils\VendorHtmlEngine;
 | 
				
			||||||
use App\Models\CreditInvitation;
 | 
					use App\Models\CreditInvitation;
 | 
				
			||||||
use App\Services\Pdf\PdfBuilder;
 | 
					 | 
				
			||||||
use App\Services\Pdf\PdfService;
 | 
					 | 
				
			||||||
use App\Models\InvoiceInvitation;
 | 
					use App\Models\InvoiceInvitation;
 | 
				
			||||||
use App\Services\Pdf\PdfDesigner;
 | 
					 | 
				
			||||||
use Illuminate\Support\Facades\Cache;
 | 
					use Illuminate\Support\Facades\Cache;
 | 
				
			||||||
use App\Services\Pdf\PdfConfiguration;
 | 
					 | 
				
			||||||
use App\Models\PurchaseOrderInvitation;
 | 
					use App\Models\PurchaseOrderInvitation;
 | 
				
			||||||
use App\Models\RecurringInvoiceInvitation;
 | 
					use App\Models\RecurringInvoiceInvitation;
 | 
				
			||||||
use App\Jobs\Vendor\CreatePurchaseOrderPdf;
 | 
					use App\Jobs\Vendor\CreatePurchaseOrderPdf;
 | 
				
			||||||
 | 
					use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PdfSlot extends Component
 | 
					class PdfSlot extends Component
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -48,12 +45,12 @@ class PdfSlot extends Component
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private $entity_type;
 | 
					    private $entity_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected $listeners = ['viewportChanged' => 'getPdf'];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public $show_cost = true;
 | 
					    public $show_cost = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public $show_quantity = true;
 | 
					    public $show_quantity = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $show_line_total = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public $route_entity = 'client';
 | 
					    public $route_entity = 'client';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function mount()
 | 
					    public function mount()
 | 
				
			||||||
@ -106,11 +103,12 @@ class PdfSlot extends Component
 | 
				
			|||||||
        $this->settings = $this->entity->client ? $this->entity->client->getMergedSettings() : $this->entity->company->settings;
 | 
					        $this->settings = $this->entity->client ? $this->entity->client->getMergedSettings() : $this->entity->company->settings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->show_cost = in_array('$product.unit_cost', $this->settings->pdf_variables->product_columns);
 | 
					        $this->show_cost = in_array('$product.unit_cost', $this->settings->pdf_variables->product_columns);
 | 
				
			||||||
        $this->show_quantity = in_array('$product.quantity', $this->settings->pdf_variables->product_columns);
 | 
					        $this->show_line_total = in_array('$product.line_total', $this->settings->pdf_variables->product_columns);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if($this->entity_type == 'quote' && !$this->settings->sync_invoice_quote_columns ){
 | 
					        if($this->entity_type == 'quote' && !$this->settings->sync_invoice_quote_columns ){
 | 
				
			||||||
            $this->show_cost = in_array('$product.unit_cost', $this->settings->pdf_variables->product_quote_columns);
 | 
					            $this->show_cost = in_array('$product.unit_cost', $this->settings->pdf_variables->product_quote_columns);
 | 
				
			||||||
            $this->show_quantity = in_array('$product.quantity', $this->settings->pdf_variables->product_quote_columns);
 | 
					            $this->show_quantity = in_array('$product.quantity', $this->settings->pdf_variables->product_quote_columns);
 | 
				
			||||||
 | 
					            $this->show_line_total = in_array('$product.line_total', $this->settings->pdf_variables->product_quote_columns);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->html_variables = $this->entity->client ?
 | 
					        $this->html_variables = $this->entity->client ?
 | 
				
			||||||
@ -175,20 +173,20 @@ class PdfSlot extends Component
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if($this->entity_type == 'invoice' || $this->entity_type == 'recurring_invoice') {
 | 
					        if($this->entity_type == 'invoice' || $this->entity_type == 'recurring_invoice') {
 | 
				
			||||||
            foreach($this->settings->pdf_variables->invoice_details as $variable) 
 | 
					            foreach($this->settings->pdf_variables->invoice_details as $variable) 
 | 
				
			||||||
                $entity_details .= "<div class='flex px-3 block'><p class= w-36 block'>{$variable}_label</p><p class='pl-1 w-36 block entity-field'>{$variable}</p></div>";
 | 
					                $entity_details .= "<div class='flex px-5 block'><p class= w-36 block'>{$variable}_label</p><p class='pl-5 w-36 block entity-field'>{$variable}</p></div>";
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        elseif($this->entity_type == 'quote'){
 | 
					        elseif($this->entity_type == 'quote'){
 | 
				
			||||||
            foreach($this->settings->pdf_variables->quote_details as $variable)
 | 
					            foreach($this->settings->pdf_variables->quote_details as $variable)
 | 
				
			||||||
                $entity_details .= "<div class='flex px-3 block'><p class= w-36 block'>{$variable}_label</p><p class='pl-1 w-36 block entity-field'>{$variable}</p></div>";
 | 
					                $entity_details .= "<div class='flex px-5 block'><p class= w-36 block'>{$variable}_label</p><p class='pl-5 w-36 block entity-field'>{$variable}</p></div>";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        elseif($this->entity_type == 'credit') {
 | 
					        elseif($this->entity_type == 'credit') {
 | 
				
			||||||
            foreach($this->settings->pdf_variables->credit_details as $variable)
 | 
					            foreach($this->settings->pdf_variables->credit_details as $variable)
 | 
				
			||||||
                $entity_details .= "<div class='flex px-3 block'><p class= w-36 block'>{$variable}_label</p><p class='pl-1 w-36 block entity-field'>{$variable}</p></div>";
 | 
					                $entity_details .= "<div class='flex px-5 block'><p class= w-36 block'>{$variable}_label</p><p class='pl-5 w-36 block entity-field'>{$variable}</p></div>";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        elseif($this->entity_type == 'purchase_order'){
 | 
					        elseif($this->entity_type == 'purchase_order'){
 | 
				
			||||||
            foreach($this->settings->pdf_variables->purchase_order_details as $variable)
 | 
					            foreach($this->settings->pdf_variables->purchase_order_details as $variable)
 | 
				
			||||||
                $entity_details .= "<div class='flex px-3 block'><p class= w-36 block'>{$variable}_label</p><p class='pl-1 w-36 block entity-field'>{$variable}</p></div>";
 | 
					                $entity_details .= "<div class='flex px-5 block'><p class= w-36 block'>{$variable}_label</p><p class='pl-5 w-36 block entity-field'>{$variable}</p></div>";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
        return $this->convertVariables($entity_details);
 | 
					        return $this->convertVariables($entity_details);
 | 
				
			||||||
@ -231,13 +229,16 @@ class PdfSlot extends Component
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private function getProducts()
 | 
					    private function getProducts()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $product_items = collect($this->entity->line_items)->filter(function ($item) {
 | 
					        $product_items = collect($this->entity->line_items)->filter(function ($item) {
 | 
				
			||||||
            return $item->type_id == 1 || $item->type_id == 6 || $item->type_id == 5;
 | 
					            return $item->type_id == 1 || $item->type_id == 6 || $item->type_id == 5;
 | 
				
			||||||
        })->map(function ($item){
 | 
					        })->map(function ($item){
 | 
				
			||||||
            return [
 | 
					            return [
 | 
				
			||||||
                'quantity' => $item->quantity,
 | 
					                'quantity' => $item->quantity,
 | 
				
			||||||
                'cost' => Number::formatMoney($item->cost, $this->entity->client ?: $this->entity->vendor),
 | 
					                'cost' => Number::formatMoney($item->cost, $this->entity->client ?: $this->entity->vendor),
 | 
				
			||||||
                'notes' => $item->notes,
 | 
					                'notes' => $this->invitation->company->markdown_enabled ? DesignHelpers::parseMarkdownToHtml($item->notes) : $item->notes,
 | 
				
			||||||
                'line_total' => Number::formatMoney($item->line_total, $this->entity->client ?: $this->entity->vendor),
 | 
					                'line_total' => Number::formatMoney($item->line_total, $this->entity->client ?: $this->entity->vendor),
 | 
				
			||||||
            ];
 | 
					            ];
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
@ -253,7 +254,7 @@ class PdfSlot extends Component
 | 
				
			|||||||
            return [
 | 
					            return [
 | 
				
			||||||
                'quantity' => $item->quantity,
 | 
					                'quantity' => $item->quantity,
 | 
				
			||||||
                'cost' => Number::formatMoney($item->cost, $this->entity->client ?: $this->entity->vendor),
 | 
					                'cost' => Number::formatMoney($item->cost, $this->entity->client ?: $this->entity->vendor),
 | 
				
			||||||
                'notes' => $item->notes,
 | 
					                'notes' => $this->invitation->company->markdown_enabled ? DesignHelpers::parseMarkdownToHtml($item->notes) : $item->notes,
 | 
				
			||||||
                'line_total' => Number::formatMoney($item->line_total, $this->entity->client ?: $this->entity->vendor),
 | 
					                'line_total' => Number::formatMoney($item->line_total, $this->entity->client ?: $this->entity->vendor),
 | 
				
			||||||
            ];
 | 
					            ];
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
				
			|||||||
@ -53,7 +53,6 @@ class SetInviteDb
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        /* Try and determine the DB from the invitation key STRING*/
 | 
					        /* Try and determine the DB from the invitation key STRING*/
 | 
				
			||||||
        if (config('ninja.db.multi_db_enabled')) {
 | 
					        if (config('ninja.db.multi_db_enabled')) {
 | 
				
			||||||
            // nlog("/ Try and determine the DB from the invitation key /");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $hashids = new Hashids(config('ninja.hash_salt'), 10);
 | 
					            $hashids = new Hashids(config('ninja.hash_salt'), 10);
 | 
				
			||||||
            $segments = explode('-', $request->route('invitation_key'));
 | 
					            $segments = explode('-', $request->route('invitation_key'));
 | 
				
			||||||
 | 
				
			|||||||
@ -12,10 +12,12 @@
 | 
				
			|||||||
namespace App\Http\Requests\Activity;
 | 
					namespace App\Http\Requests\Activity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Http\Requests\Request;
 | 
					use App\Http\Requests\Request;
 | 
				
			||||||
use App\Models\Activity;
 | 
					use App\Utils\Traits\MakesHash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ShowActivityRequest extends Request
 | 
					class ShowActivityRequest extends Request
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    use MakesHash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Determine if the user is authorized to make this request.
 | 
					     * Determine if the user is authorized to make this request.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@ -23,7 +25,25 @@ class ShowActivityRequest extends Request
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function authorize() : bool
 | 
					    public function authorize() : bool
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // return auth()->user()->isAdmin();
 | 
					        return true;
 | 
				
			||||||
        return auth()->user()->can('view', Activity::class);
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function rules()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            'entity' => 'bail|required|in:invoice,quote,credit,purchase_order,payment,client,vendor,expense,task,project,subscription,recurring_invoice,',
 | 
				
			||||||
 | 
					            'entity_id' => 'bail|required|exists:'.$this->entity.'s,id,company_id,'.auth()->user()->company()->id,
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function prepareForValidation()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $input = $this->all();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(isset($input['entity_id']))
 | 
				
			||||||
 | 
					            $input['entity_id'] = $this->decodePrimaryKey($input['entity_id']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->replace($input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -45,7 +45,7 @@ class ShowChartRequest extends Request
 | 
				
			|||||||
        $input = $this->all();
 | 
					        $input = $this->all();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(isset($input['date_range'])) {
 | 
					        if(isset($input['date_range'])) {
 | 
				
			||||||
            $dates = $this->calculateStartAndEndDates($input);
 | 
					            $dates = $this->calculateStartAndEndDates($input, auth()->user()->company());
 | 
				
			||||||
            $input['start_date'] = $dates[0];
 | 
					            $input['start_date'] = $dates[0];
 | 
				
			||||||
            $input['end_date'] = $dates[1];
 | 
					            $input['end_date'] = $dates[1];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -67,7 +67,8 @@ class StoreCreditRequest extends Request
 | 
				
			|||||||
        $rules['tax_name1'] = 'bail|sometimes|string|nullable';
 | 
					        $rules['tax_name1'] = 'bail|sometimes|string|nullable';
 | 
				
			||||||
        $rules['tax_name2'] = 'bail|sometimes|string|nullable';
 | 
					        $rules['tax_name2'] = 'bail|sometimes|string|nullable';
 | 
				
			||||||
        $rules['tax_name3'] = 'bail|sometimes|string|nullable';
 | 
					        $rules['tax_name3'] = 'bail|sometimes|string|nullable';
 | 
				
			||||||
        
 | 
					        $rules['exchange_rate'] = 'bail|sometimes|gt:0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($this->invoice_id) {
 | 
					        if ($this->invoice_id) {
 | 
				
			||||||
            $rules['invoice_id'] = new ValidInvoiceCreditRule();
 | 
					            $rules['invoice_id'] = new ValidInvoiceCreditRule();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -88,7 +89,11 @@ class StoreCreditRequest extends Request
 | 
				
			|||||||
        $input = $this->decodePrimaryKeys($input);
 | 
					        $input = $this->decodePrimaryKeys($input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $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['line_items'] = json_encode($input['line_items']);
 | 
					
 | 
				
			||||||
 | 
					        if (array_key_exists('exchange_rate', $input) && is_null($input['exchange_rate'])) {
 | 
				
			||||||
 | 
					            $input['exchange_rate'] = 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->replace($input);
 | 
					        $this->replace($input);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -67,7 +67,8 @@ class UpdateCreditRequest extends Request
 | 
				
			|||||||
        $rules['tax_name1'] = 'bail|sometimes|string|nullable';
 | 
					        $rules['tax_name1'] = 'bail|sometimes|string|nullable';
 | 
				
			||||||
        $rules['tax_name2'] = 'bail|sometimes|string|nullable';
 | 
					        $rules['tax_name2'] = 'bail|sometimes|string|nullable';
 | 
				
			||||||
        $rules['tax_name3'] = 'bail|sometimes|string|nullable';
 | 
					        $rules['tax_name3'] = 'bail|sometimes|string|nullable';
 | 
				
			||||||
        
 | 
					        $rules['exchange_rate'] = 'bail|sometimes|gt:0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $rules;
 | 
					        return $rules;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -81,6 +82,10 @@ class UpdateCreditRequest 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']) : [];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (array_key_exists('exchange_rate', $input) && is_null($input['exchange_rate'])) {
 | 
				
			||||||
 | 
					            $input['exchange_rate'] = 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $input['id'] = $this->credit->id;
 | 
					        $input['id'] = $this->credit->id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->replace($input);
 | 
					        $this->replace($input);
 | 
				
			||||||
 | 
				
			|||||||
@ -72,7 +72,8 @@ class StoreInvoiceRequest extends Request
 | 
				
			|||||||
        $rules['tax_name1'] = 'bail|sometimes|string|nullable';
 | 
					        $rules['tax_name1'] = 'bail|sometimes|string|nullable';
 | 
				
			||||||
        $rules['tax_name2'] = 'bail|sometimes|string|nullable';
 | 
					        $rules['tax_name2'] = 'bail|sometimes|string|nullable';
 | 
				
			||||||
        $rules['tax_name3'] = 'bail|sometimes|string|nullable';
 | 
					        $rules['tax_name3'] = 'bail|sometimes|string|nullable';
 | 
				
			||||||
        
 | 
					        $rules['exchange_rate'] = 'bail|sometimes|gt:0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $rules;
 | 
					        return $rules;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -72,7 +72,8 @@ class UpdateInvoiceRequest extends Request
 | 
				
			|||||||
        $rules['tax_name2'] = 'bail|sometimes|string|nullable';
 | 
					        $rules['tax_name2'] = 'bail|sometimes|string|nullable';
 | 
				
			||||||
        $rules['tax_name3'] = 'bail|sometimes|string|nullable';
 | 
					        $rules['tax_name3'] = 'bail|sometimes|string|nullable';
 | 
				
			||||||
        $rules['status_id'] = 'bail|sometimes|not_in:5'; //do not all cancelled invoices to be modfified.
 | 
					        $rules['status_id'] = 'bail|sometimes|not_in:5'; //do not all cancelled invoices to be modfified.
 | 
				
			||||||
 | 
					        $rules['exchange_rate'] = 'bail|sometimes|gt:0';
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        // not needed.
 | 
					        // not needed.
 | 
				
			||||||
        // $rules['partial_due_date'] = 'bail|sometimes|required_unless:partial,0,null';
 | 
					        // $rules['partial_due_date'] = 'bail|sometimes|required_unless:partial,0,null';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -95,6 +96,10 @@ class UpdateInvoiceRequest extends Request
 | 
				
			|||||||
            unset($input['documents']);
 | 
					            unset($input['documents']);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (array_key_exists('exchange_rate', $input) && is_null($input['exchange_rate'])) {
 | 
				
			||||||
 | 
					            $input['exchange_rate'] = 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->replace($input);
 | 
					        $this->replace($input);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -60,7 +60,8 @@ class StorePurchaseOrderRequest extends Request
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $rules['status_id'] = 'nullable|integer|in:1,2,3,4,5';
 | 
					        $rules['status_id'] = 'nullable|integer|in:1,2,3,4,5';
 | 
				
			||||||
        
 | 
					        $rules['exchange_rate'] = 'bail|sometimes|gt:0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $rules;
 | 
					        return $rules;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -77,6 +78,10 @@ class StorePurchaseOrderRequest extends Request
 | 
				
			|||||||
        $input['amount'] = 0;
 | 
					        $input['amount'] = 0;
 | 
				
			||||||
        $input['balance'] = 0;
 | 
					        $input['balance'] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (array_key_exists('exchange_rate', $input) && is_null($input['exchange_rate'])) {
 | 
				
			||||||
 | 
					            $input['exchange_rate'] = 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->replace($input);
 | 
					        $this->replace($input);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -63,6 +63,7 @@ class UpdatePurchaseOrderRequest extends Request
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $rules['status_id'] = 'sometimes|integer|in:1,2,3,4,5';
 | 
					        $rules['status_id'] = 'sometimes|integer|in:1,2,3,4,5';
 | 
				
			||||||
 | 
					        $rules['exchange_rate'] = 'bail|sometimes|gt:0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $rules;
 | 
					        return $rules;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -79,6 +80,10 @@ class UpdatePurchaseOrderRequest 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']) : [];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (array_key_exists('exchange_rate', $input) && is_null($input['exchange_rate'])) {
 | 
				
			||||||
 | 
					            $input['exchange_rate'] = 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->replace($input);
 | 
					        $this->replace($input);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -55,6 +55,7 @@ class StoreQuoteRequest extends Request
 | 
				
			|||||||
        $rules['discount'] = 'sometimes|numeric';
 | 
					        $rules['discount'] = 'sometimes|numeric';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $rules['is_amount_discount'] = ['boolean'];
 | 
					        $rules['is_amount_discount'] = ['boolean'];
 | 
				
			||||||
 | 
					        $rules['exchange_rate'] = 'bail|sometimes|gt:0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // $rules['number'] = new UniqueQuoteNumberRule($this->all());
 | 
					        // $rules['number'] = new UniqueQuoteNumberRule($this->all());
 | 
				
			||||||
        $rules['line_items'] = 'array';
 | 
					        $rules['line_items'] = 'array';
 | 
				
			||||||
@ -72,6 +73,10 @@ class StoreQuoteRequest extends Request
 | 
				
			|||||||
        $input['amount'] = 0;
 | 
					        $input['amount'] = 0;
 | 
				
			||||||
        $input['balance'] = 0;
 | 
					        $input['balance'] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (array_key_exists('exchange_rate', $input) && is_null($input['exchange_rate'])) {
 | 
				
			||||||
 | 
					            $input['exchange_rate'] = 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->replace($input);
 | 
					        $this->replace($input);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -57,6 +57,7 @@ class UpdateQuoteRequest extends Request
 | 
				
			|||||||
        $rules['line_items'] = 'array';
 | 
					        $rules['line_items'] = 'array';
 | 
				
			||||||
        $rules['discount'] = 'sometimes|numeric';
 | 
					        $rules['discount'] = 'sometimes|numeric';
 | 
				
			||||||
        $rules['is_amount_discount'] = ['boolean'];
 | 
					        $rules['is_amount_discount'] = ['boolean'];
 | 
				
			||||||
 | 
					        $rules['exchange_rate'] = 'bail|sometimes|gt:0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $rules;
 | 
					        return $rules;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -75,6 +76,10 @@ class UpdateQuoteRequest extends Request
 | 
				
			|||||||
            unset($input['documents']);
 | 
					            unset($input['documents']);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (array_key_exists('exchange_rate', $input) && is_null($input['exchange_rate'])) {
 | 
				
			||||||
 | 
					            $input['exchange_rate'] = 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $input['id'] = $this->quote->id;
 | 
					        $input['id'] = $this->quote->id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->replace($input);
 | 
					        $this->replace($input);
 | 
				
			||||||
 | 
				
			|||||||
@ -67,7 +67,8 @@ class StoreRecurringInvoiceRequest extends Request
 | 
				
			|||||||
        $rules['tax_name2'] = 'bail|sometimes|string|nullable';
 | 
					        $rules['tax_name2'] = 'bail|sometimes|string|nullable';
 | 
				
			||||||
        $rules['tax_name3'] = 'bail|sometimes|string|nullable';
 | 
					        $rules['tax_name3'] = 'bail|sometimes|string|nullable';
 | 
				
			||||||
        $rules['due_date_days'] = 'bail|sometimes|string';
 | 
					        $rules['due_date_days'] = 'bail|sometimes|string';
 | 
				
			||||||
        
 | 
					        $rules['exchange_rate'] = 'bail|sometimes|gt:0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $rules;
 | 
					        return $rules;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -143,6 +144,10 @@ class StoreRecurringInvoiceRequest extends Request
 | 
				
			|||||||
            unset($input['number']);
 | 
					            unset($input['number']);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (array_key_exists('exchange_rate', $input) && (is_null($input['exchange_rate']) || $input['exchange_rate'] == 0)) {
 | 
				
			||||||
 | 
					            $input['exchange_rate'] = 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->replace($input);
 | 
					        $this->replace($input);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -61,7 +61,8 @@ class UpdateRecurringInvoiceRequest extends Request
 | 
				
			|||||||
        $rules['tax_name1'] = 'bail|sometimes|string|nullable';
 | 
					        $rules['tax_name1'] = 'bail|sometimes|string|nullable';
 | 
				
			||||||
        $rules['tax_name2'] = 'bail|sometimes|string|nullable';
 | 
					        $rules['tax_name2'] = 'bail|sometimes|string|nullable';
 | 
				
			||||||
        $rules['tax_name3'] = 'bail|sometimes|string|nullable';
 | 
					        $rules['tax_name3'] = 'bail|sometimes|string|nullable';
 | 
				
			||||||
        
 | 
					        $rules['exchange_rate'] = 'bail|sometimes|gt:0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $rules;
 | 
					        return $rules;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -121,6 +122,10 @@ class UpdateRecurringInvoiceRequest extends Request
 | 
				
			|||||||
            unset($input['documents']);
 | 
					            unset($input['documents']);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (array_key_exists('exchange_rate', $input) && (is_null($input['exchange_rate']) || $input['exchange_rate'] == 0)) {
 | 
				
			||||||
 | 
					            $input['exchange_rate'] = 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->replace($input);
 | 
					        $this->replace($input);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -102,6 +102,8 @@ class BaseImport
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $csv = base64_decode($base64_encoded_csv);
 | 
					        $csv = base64_decode($base64_encoded_csv);
 | 
				
			||||||
 | 
					        $csv = mb_convert_encoding($csv, 'UTF-8', 'UTF-8');
 | 
				
			||||||
 | 
					 nlog($csv);
 | 
				
			||||||
        $csv = Reader::createFromString($csv);
 | 
					        $csv = Reader::createFromString($csv);
 | 
				
			||||||
        $csvdelimiter = self::detectDelimiter($csv);
 | 
					        $csvdelimiter = self::detectDelimiter($csv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -477,8 +479,12 @@ class BaseImport
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
                    nlog($invoice_data);
 | 
					                    nlog($invoice_data);
 | 
				
			||||||
 | 
					                    $saveable_invoice_data = $invoice_data;
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    if(array_key_exists('payments', $saveable_invoice_data))
 | 
				
			||||||
 | 
					                        unset($saveable_invoice_data['payments']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    $invoice_repository->save($invoice_data, $invoice);
 | 
					                    $invoice_repository->save($saveable_invoice_data, $invoice);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    $count++;
 | 
					                    $count++;
 | 
				
			||||||
                    // If we're doing a generic CSV import, only import payment data if we're not importing a payment CSV.
 | 
					                    // If we're doing a generic CSV import, only import payment data if we're not importing a payment CSV.
 | 
				
			||||||
@ -504,7 +510,7 @@ class BaseImport
 | 
				
			|||||||
                                ];
 | 
					                                ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                /* Make sure we don't apply any payments to invoices with a Zero Amount*/
 | 
					                                /* Make sure we don't apply any payments to invoices with a Zero Amount*/
 | 
				
			||||||
                                if ($invoice->amount > 0) {
 | 
					                                if ($invoice->amount > 0 && $payment_data['amount'] > 0) {
 | 
				
			||||||
                                    
 | 
					                                    
 | 
				
			||||||
                                    $payment = $payment_repository->save(
 | 
					                                    $payment = $payment_repository->save(
 | 
				
			||||||
                                        $payment_data,
 | 
					                                        $payment_data,
 | 
				
			||||||
 | 
				
			|||||||
@ -319,6 +319,21 @@ class BaseTransformer
 | 
				
			|||||||
        // return Number::parseFloat($number);
 | 
					        // return Number::parseFloat($number);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param $data
 | 
				
			||||||
 | 
					     * @param $field
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return float
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getFloatOrOne($data, $field)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (array_key_exists($field, $data)) 
 | 
				
			||||||
 | 
					            return Number::parseStringFloat($data[$field]) > 0 ? Number::parseStringFloat($data[$field]) : 1;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					        return 1;    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @param $name
 | 
					     * @param $name
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
 | 
				
			|||||||
@ -114,7 +114,7 @@ class InvoiceTransformer extends BaseTransformer
 | 
				
			|||||||
                $invoice_data,
 | 
					                $invoice_data,
 | 
				
			||||||
                'invoice.custom_surcharge4'
 | 
					                'invoice.custom_surcharge4'
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            'exchange_rate' => $this->getString(
 | 
					            'exchange_rate' => $this->getFloatOrOne(
 | 
				
			||||||
                $invoice_data,
 | 
					                $invoice_data,
 | 
				
			||||||
                'invoice.exchange_rate'
 | 
					                'invoice.exchange_rate'
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 | 
				
			|||||||
@ -46,7 +46,7 @@ class PaymentTransformer extends BaseTransformer
 | 
				
			|||||||
                $data,
 | 
					                $data,
 | 
				
			||||||
                'payment.transaction_reference '
 | 
					                'payment.transaction_reference '
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            'date' => $this->getString($data, 'payment.date'),
 | 
					            'date' => isset($data['payment.date']) ? $this->parseDate($data['payment.date']) : date('y-m-d'),
 | 
				
			||||||
            'private_notes' => $this->getString($data, 'payment.private_notes'),
 | 
					            'private_notes' => $this->getString($data, 'payment.private_notes'),
 | 
				
			||||||
            'custom_value1' => $this->getString($data, 'payment.custom_value1'),
 | 
					            'custom_value1' => $this->getString($data, 'payment.custom_value1'),
 | 
				
			||||||
            'custom_value2' => $this->getString($data, 'payment.custom_value2'),
 | 
					            'custom_value2' => $this->getString($data, 'payment.custom_value2'),
 | 
				
			||||||
 | 
				
			|||||||
@ -114,7 +114,7 @@ class QuoteTransformer extends BaseTransformer
 | 
				
			|||||||
                $quote_data,
 | 
					                $quote_data,
 | 
				
			||||||
                'quote.custom_surcharge4'
 | 
					                'quote.custom_surcharge4'
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            'exchange_rate' => $this->getString(
 | 
					            'exchange_rate' => $this->getFloatOrOne(
 | 
				
			||||||
                $quote_data,
 | 
					                $quote_data,
 | 
				
			||||||
                'quote.exchange_rate'
 | 
					                'quote.exchange_rate'
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 | 
				
			|||||||
@ -122,7 +122,7 @@ class RecurringInvoiceTransformer extends BaseTransformer
 | 
				
			|||||||
                $invoice_data,
 | 
					                $invoice_data,
 | 
				
			||||||
                'invoice.custom_surcharge4'
 | 
					                'invoice.custom_surcharge4'
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            'exchange_rate' => $this->getString(
 | 
					            'exchange_rate' => $this->getFloat(
 | 
				
			||||||
                $invoice_data,
 | 
					                $invoice_data,
 | 
				
			||||||
                'invoice.exchange_rate'
 | 
					                'invoice.exchange_rate'
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 | 
				
			|||||||
@ -24,6 +24,7 @@ use Illuminate\Contracts\Queue\ShouldQueue;
 | 
				
			|||||||
use Illuminate\Foundation\Events\Dispatchable;
 | 
					use Illuminate\Foundation\Events\Dispatchable;
 | 
				
			||||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
 | 
					use Illuminate\Queue\Middleware\WithoutOverlapping;
 | 
				
			||||||
use App\Notifications\Ninja\GenericNinjaAdminNotification;
 | 
					use App\Notifications\Ninja\GenericNinjaAdminNotification;
 | 
				
			||||||
 | 
					use App\Helpers\Bank\Yodlee\Transformer\AccountTransformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ProcessBankTransactions implements ShouldQueue
 | 
					class ProcessBankTransactions implements ShouldQueue
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -99,6 +100,24 @@ class ProcessBankTransactions implements ShouldQueue
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $account_summary = $yodlee->getAccountSummary($this->bank_integration->bank_account_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if($account_summary) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $at = new AccountTransformer();
 | 
				
			||||||
 | 
					                $account = $at->transform($account_summary);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $this->bank_integration->balance = $account['current_balance'];
 | 
				
			||||||
 | 
					                $this->bank_integration->currency = $account['account_currency'];
 | 
				
			||||||
 | 
					                $this->bank_integration->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        catch(\Exception $e) {
 | 
				
			||||||
 | 
					            nlog("YODLEE: unable to update account summary for {$this->bank_integration->bank_account_id} => ". $e->getMessage());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $data = [
 | 
					        $data = [
 | 
				
			||||||
            'top' => 500,
 | 
					            'top' => 500,
 | 
				
			||||||
            'fromDate' => $this->from_date,
 | 
					            'fromDate' => $this->from_date,
 | 
				
			||||||
 | 
				
			|||||||
@ -441,15 +441,15 @@ class CompanyExport implements ShouldQueue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $path = 'backups';
 | 
					        $path = 'backups';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Storage::makeDirectory(public_path('storage/backups/'));
 | 
					        Storage::makeDirectory(storage_path('backups/'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            mkdir(public_path('storage/backups/'));
 | 
					            mkdir(storage_path('backups/'));
 | 
				
			||||||
        } catch(\Exception $e) {
 | 
					        } catch(\Exception $e) {
 | 
				
			||||||
            nlog("could not create directory");
 | 
					            nlog("could not create directory");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $zip_path = public_path('storage/backups/'.$file_name);
 | 
					        $zip_path = storage_path('backups/'.$file_name);
 | 
				
			||||||
        $zip = new \ZipArchive();
 | 
					        $zip = new \ZipArchive();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($zip->open($zip_path, \ZipArchive::CREATE)!==true) {
 | 
					        if ($zip->open($zip_path, \ZipArchive::CREATE)!==true) {
 | 
				
			||||||
@ -459,14 +459,16 @@ class CompanyExport implements ShouldQueue
 | 
				
			|||||||
        $zip->addFromString("backup.json", json_encode($this->export_data));
 | 
					        $zip->addFromString("backup.json", json_encode($this->export_data));
 | 
				
			||||||
        $zip->close();
 | 
					        $zip->close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (Ninja::isHosted()) {
 | 
					        Storage::disk(config('filesystems.default'))->put('backups/'.$file_name, file_get_contents($zip_path));
 | 
				
			||||||
            Storage::disk(config('filesystems.default'))->put('backups/'.$file_name, file_get_contents($zip_path));
 | 
					        unlink($zip_path);        
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $storage_file_path = Storage::disk(config('filesystems.default'))->url('backups/'.$file_name);
 | 
					        if(Ninja::isSelfHost())
 | 
				
			||||||
        $storage_path = Storage::disk(config('filesystems.default'))->path('backups/'.$file_name);
 | 
					            $storage_path = 'backups/'.$file_name;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            $storage_path = Storage::disk(config('filesystems.default'))->path('backups/'.$file_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $url = Cache::get($this->hash);
 | 
					        $url = Cache::get($this->hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Cache::put($this->hash, $storage_path, now()->addHour());
 | 
					        Cache::put($this->hash, $storage_path, now()->addHour());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        App::forgetInstance('translator');
 | 
					        App::forgetInstance('translator');
 | 
				
			||||||
 | 
				
			|||||||
@ -398,6 +398,9 @@ class Import implements ShouldQueue
 | 
				
			|||||||
        $data = $this->transformCompanyData($data);
 | 
					        $data = $this->transformCompanyData($data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (Ninja::isHosted()) {
 | 
					        if (Ninja::isHosted()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $data['subdomain'] = str_replace("_","",$data['subdomain']);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            if (!MultiDB::checkDomainAvailable($data['subdomain'])) {
 | 
					            if (!MultiDB::checkDomainAvailable($data['subdomain'])) {
 | 
				
			||||||
                $data['subdomain'] = MultiDB::randomSubdomainGenerator();
 | 
					                $data['subdomain'] = MultiDB::randomSubdomainGenerator();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -129,12 +129,10 @@ class ReminderJob implements ShouldQueue
 | 
				
			|||||||
            $invoice->service()->touchReminder($reminder_template)->save();
 | 
					            $invoice->service()->touchReminder($reminder_template)->save();
 | 
				
			||||||
            $fees = $this->calcLateFee($invoice, $reminder_template);
 | 
					            $fees = $this->calcLateFee($invoice, $reminder_template);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(in_array($invoice->client->getSetting('lock_invoices'), ['when_sent','when_paid'])) {
 | 
					            if($invoice->isLocked()) 
 | 
				
			||||||
                return $this->addFeeToNewInvoice($invoice, $reminder_template, $fees);
 | 
					                return $this->addFeeToNewInvoice($invoice, $reminder_template, $fees);
 | 
				
			||||||
            }
 | 
					            
 | 
				
			||||||
            else
 | 
					            $invoice = $this->setLateFee($invoice, $fees[0], $fees[1]);
 | 
				
			||||||
                $invoice = $this->setLateFee($invoice, $fees[0], $fees[1]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //20-04-2022 fixes for endless reminders - generic template naming was wrong
 | 
					            //20-04-2022 fixes for endless reminders - generic template naming was wrong
 | 
				
			||||||
            $enabled_reminder = 'enable_'.$reminder_template;
 | 
					            $enabled_reminder = 'enable_'.$reminder_template;
 | 
				
			||||||
 | 
				
			|||||||
@ -43,6 +43,10 @@ class UnlinkFile implements ShouldQueue
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Storage::disk($this->disk)->delete($this->file_path);
 | 
					        try {
 | 
				
			||||||
 | 
					            Storage::disk($this->disk)->delete($this->file_path);
 | 
				
			||||||
 | 
					        } catch (\Exception $e) {
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -554,7 +554,7 @@ class Account extends BaseModel
 | 
				
			|||||||
                    $nmo->to_user = $this->companies()->first()->owner();
 | 
					                    $nmo->to_user = $this->companies()->first()->owner();
 | 
				
			||||||
                    NinjaMailerJob::dispatch($nmo, true);
 | 
					                    NinjaMailerJob::dispatch($nmo, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    Cache::put("throttle_notified:{$this->key}", true, 60 * 24);
 | 
					                    Cache::put("throttle_notified:{$this->key}", true, 60 * 60 * 24);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (config('ninja.notification.slack')) {
 | 
					                    if (config('ninja.notification.slack')) {
 | 
				
			||||||
                        $this->companies()->first()->notification(new EmailQuotaNotification($this))->ninja();
 | 
					                        $this->companies()->first()->notification(new EmailQuotaNotification($this))->ninja();
 | 
				
			||||||
 | 
				
			|||||||
@ -347,6 +347,11 @@ class Client extends BaseModel implements HasLocalePreference
 | 
				
			|||||||
        return $this->hasMany(Credit::class)->withTrashed();
 | 
					        return $this->hasMany(Credit::class)->withTrashed();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function purgeable_activities()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->hasMany(Activity::class);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function activities()
 | 
					    public function activities()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->hasMany(Activity::class)->take(50)->orderBy('id', 'desc');
 | 
					        return $this->hasMany(Activity::class)->take(50)->orderBy('id', 'desc');
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,7 @@ use App\Casts\EncryptedCast;
 | 
				
			|||||||
use App\Utils\Traits\AppSetup;
 | 
					use App\Utils\Traits\AppSetup;
 | 
				
			||||||
use App\Utils\Traits\MakesHash;
 | 
					use App\Utils\Traits\MakesHash;
 | 
				
			||||||
use App\DataMapper\CompanySettings;
 | 
					use App\DataMapper\CompanySettings;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\App;
 | 
				
			||||||
use Illuminate\Support\Facades\Cache;
 | 
					use Illuminate\Support\Facades\Cache;
 | 
				
			||||||
use Laracasts\Presenter\PresentableTrait;
 | 
					use Laracasts\Presenter\PresentableTrait;
 | 
				
			||||||
use App\Utils\Traits\CompanySettingsSaver;
 | 
					use App\Utils\Traits\CompanySettingsSaver;
 | 
				
			||||||
@ -686,6 +687,11 @@ class Company extends BaseModel
 | 
				
			|||||||
        return $this->getLocale();
 | 
					        return $this->getLocale();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function setLocale()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        App::setLocale($this->getLocale());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    public function getSetting($setting)
 | 
					    public function getSetting($setting)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (property_exists($this->settings, $setting) != false) {
 | 
					        if (property_exists($this->settings, $setting) != false) {
 | 
				
			||||||
 | 
				
			|||||||
@ -455,7 +455,7 @@ class Quote extends BaseModel
 | 
				
			|||||||
            case self::STATUS_DRAFT:
 | 
					            case self::STATUS_DRAFT:
 | 
				
			||||||
                return ctrans('texts.draft');
 | 
					                return ctrans('texts.draft');
 | 
				
			||||||
            case self::STATUS_SENT:
 | 
					            case self::STATUS_SENT:
 | 
				
			||||||
                return ctrans('texts.pending');
 | 
					                return ctrans('texts.sent');
 | 
				
			||||||
            case self::STATUS_APPROVED:
 | 
					            case self::STATUS_APPROVED:
 | 
				
			||||||
                return ctrans('texts.approved');
 | 
					                return ctrans('texts.approved');
 | 
				
			||||||
            case self::STATUS_EXPIRED:
 | 
					            case self::STATUS_EXPIRED:
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										122
									
								
								app/PaymentDrivers/CheckoutCom/CheckoutSetupWebhook.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								app/PaymentDrivers/CheckoutCom/CheckoutSetupWebhook.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,122 @@
 | 
				
			|||||||
 | 
					<?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\PaymentDrivers\CheckoutCom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Models\Payment;
 | 
				
			||||||
 | 
					use App\Models\SystemLog;
 | 
				
			||||||
 | 
					use App\Libraries\MultiDB;
 | 
				
			||||||
 | 
					use App\Models\GatewayType;
 | 
				
			||||||
 | 
					use App\Models\PaymentHash;
 | 
				
			||||||
 | 
					use App\Models\PaymentType;
 | 
				
			||||||
 | 
					use Illuminate\Bus\Queueable;
 | 
				
			||||||
 | 
					use App\Models\CompanyGateway;
 | 
				
			||||||
 | 
					use App\Jobs\Util\SystemLogger;
 | 
				
			||||||
 | 
					use Checkout\CheckoutApiException;
 | 
				
			||||||
 | 
					use Illuminate\Queue\SerializesModels;
 | 
				
			||||||
 | 
					use App\PaymentDrivers\Stripe\Utilities;
 | 
				
			||||||
 | 
					use Illuminate\Queue\InteractsWithQueue;
 | 
				
			||||||
 | 
					use App\PaymentDrivers\CheckoutCom\Webhook;
 | 
				
			||||||
 | 
					use Illuminate\Contracts\Queue\ShouldQueue;
 | 
				
			||||||
 | 
					use Illuminate\Foundation\Bus\Dispatchable;
 | 
				
			||||||
 | 
					use Checkout\CheckoutAuthorizationException;
 | 
				
			||||||
 | 
					use Checkout\Workflows\CreateWorkflowRequest;
 | 
				
			||||||
 | 
					use App\PaymentDrivers\CheckoutComPaymentDriver;
 | 
				
			||||||
 | 
					use Checkout\Workflows\Actions\WebhookSignature;
 | 
				
			||||||
 | 
					use Checkout\Workflows\Actions\WebhookWorkflowActionRequest;
 | 
				
			||||||
 | 
					use Checkout\Workflows\Conditions\EventWorkflowConditionRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CheckoutSetupWebhook implements ShouldQueue
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, Utilities;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $tries = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $deleteWhenMissingModels = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private string $authentication_webhook_name = 'Invoice_Ninja_3DS_Workflow';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public CheckoutComPaymentDriver $checkout;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public function __construct(private string $company_key, private int $company_gateway_id)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function handle()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        MultiDB::findAndSetDbByCompanyKey($this->company_key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $company_gateway = CompanyGateway::find($this->company_gateway_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->checkout = $company_gateway->driver()->init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $webhook = new Webhook($this->checkout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $workflows = $webhook->getWorkFlows();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $wf = collect($workflows['data'])->first(function ($workflow) {
 | 
				
			||||||
 | 
					            return $workflow['name'] == $this->authentication_webhook_name;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if($wf)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->createAuthenticationWorkflow();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Creates an authentication workflow for 3DS
 | 
				
			||||||
 | 
					     * and also a registration mechanism for payments that have been approved.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function createAuthenticationWorkflow()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $signature = new WebhookSignature();
 | 
				
			||||||
 | 
					        $signature->key = $this->checkout->company_gateway->company->company_key;
 | 
				
			||||||
 | 
					        $signature->method = "HMACSHA256";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $actionRequest = new WebhookWorkflowActionRequest();
 | 
				
			||||||
 | 
					        $actionRequest->url = $this->checkout->company_gateway->webhookUrl();
 | 
				
			||||||
 | 
					        $actionRequest->signature = $signature;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        $eventWorkflowConditionRequest = new EventWorkflowConditionRequest();
 | 
				
			||||||
 | 
					        $eventWorkflowConditionRequest->events = [
 | 
				
			||||||
 | 
					            "gateway" => ["payment_approved"],
 | 
				
			||||||
 | 
					            "issuing" => ["authorization_approved","authorization_declined"],
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $request = new CreateWorkflowRequest();
 | 
				
			||||||
 | 
					        $request->actions = [$actionRequest];
 | 
				
			||||||
 | 
					        $request->conditions = [$eventWorkflowConditionRequest];
 | 
				
			||||||
 | 
					        $request->name = $this->authentication_webhook_name;
 | 
				
			||||||
 | 
					        $request->active = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $response = $this->checkout->gateway->getWorkflowsClient()->createWorkflow($request);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        } catch (CheckoutApiException $e) {
 | 
				
			||||||
 | 
					            // API error
 | 
				
			||||||
 | 
					            $error_details = $e->error_details;
 | 
				
			||||||
 | 
					            $http_status_code = isset($e->http_metadata) ? $e->http_metadata->getStatusCode() : null;
 | 
				
			||||||
 | 
					            nlog("Checkout WEBHOOK creation error");
 | 
				
			||||||
 | 
					            nlog($error_details);
 | 
				
			||||||
 | 
					        } catch (CheckoutAuthorizationException $e) {
 | 
				
			||||||
 | 
					            // Bad Invalid authorization
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										117
									
								
								app/PaymentDrivers/CheckoutCom/CheckoutWebhook.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								app/PaymentDrivers/CheckoutCom/CheckoutWebhook.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,117 @@
 | 
				
			|||||||
 | 
					<?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\PaymentDrivers\CheckoutCom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Models\Payment;
 | 
				
			||||||
 | 
					use App\Models\SystemLog;
 | 
				
			||||||
 | 
					use App\Libraries\MultiDB;
 | 
				
			||||||
 | 
					use App\Models\GatewayType;
 | 
				
			||||||
 | 
					use App\Models\PaymentHash;
 | 
				
			||||||
 | 
					use App\Models\PaymentType;
 | 
				
			||||||
 | 
					use Illuminate\Bus\Queueable;
 | 
				
			||||||
 | 
					use App\Models\CompanyGateway;
 | 
				
			||||||
 | 
					use App\Jobs\Util\SystemLogger;
 | 
				
			||||||
 | 
					use Illuminate\Queue\SerializesModels;
 | 
				
			||||||
 | 
					use App\PaymentDrivers\Stripe\Utilities;
 | 
				
			||||||
 | 
					use Illuminate\Queue\InteractsWithQueue;
 | 
				
			||||||
 | 
					use Illuminate\Contracts\Queue\ShouldQueue;
 | 
				
			||||||
 | 
					use Illuminate\Foundation\Bus\Dispatchable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CheckoutWebhook implements ShouldQueue
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, Utilities;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $tries = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $deleteWhenMissingModels = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public CompanyGateway $company_gateway;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct(public array $webhook_array, public string $company_key, public int $company_gateway_id)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function handle()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        nlog("Checkout Webhook");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        MultiDB::findAndSetDbByCompanyKey($this->company_key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->company_gateway = CompanyGateway::withTrashed()->find($this->company_gateway_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!isset($this->webhook_array['type']))
 | 
				
			||||||
 | 
					            nlog("Checkout Webhook type not set");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        match($this->webhook_array['type']){
 | 
				
			||||||
 | 
					            'payment_approved' => $this->paymentApproved(),
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * {
 | 
				
			||||||
 | 
					     * "id":"evt_dli6ty4qo5vuxle5wklf5gwbwy","type":"payment_approved","version":"1.0.33","created_on":"2023-07-21T10:03:07.1555904Z",
 | 
				
			||||||
 | 
					     * "data":{"id":"pay_oqwbsd22kvpuvd35y5fhbdawxa","action_id":"act_buviezur7zsurnsorcgfn63e44","reference":"0014","amount":584168,"auth_code":"113059","currency":"USD","customer":{"id":"cus_6n4yt4q5kf4unn36o5qpbevxhe","email":"cypress@example.com"},
 | 
				
			||||||
 | 
					     * "metadata":{"udf1":"Invoice Ninja","udf2":"ofhgiGjyQXbsbUwygURfYFT2C3E7iY7U"},"payment_type":"Regular","processed_on":"2023-07-21T10:02:57.4678165Z","processing":{"acquirer_transaction_id":"645272142084717830381","retrieval_reference_number":"183042259107"},"response_code":"10000","response_summary":"Approved","risk":{"flagged":false,"score":0},"3ds":{"version":"2.2.0","challenged":true,"challenge_indicator":"no_preference","exemption":"none","eci":"05","cavv":"AAABAVIREQAAAAAAAAAAAAAAAAA=","xid":"74afa3ac-25d3-4d95-b815-cefbdd7c8270","downgraded":false,"enrolled":"Y","authentication_response":"Y","flow_type":"challenged"},"scheme_id":"114455763095262",
 | 
				
			||||||
 | 
					     * "source":{"id":"src_ghavmefpetjellmteqwj5jjcli","type":"card","billing_address":{},"expiry_month":10,"expiry_year":2025,"scheme":"VISA","last_4":"4242","fingerprint":"BD864B08D0B098DD83052A038FD2BA967DF2D48E375AAEEF54E37BC36B385E9A","bin":"424242","card_type":"CREDIT","card_category":"CONSUMER","issuer_country":"GB","product_id":"F","product_type":"Visa Classic","avs_check":"G","cvv_check":"Y"},"balances":{"total_authorized":584168,"total_voided":0,"available_to_void":584168,"total_captured":0,"available_to_capture":584168,"total_refunded":0,"available_to_refund":0},"event_links":{"payment":"https://api.sandbox.checkout.com/payments/pay_oqwbsd22kvpuvd35y5fhbdawxa","payment_actions":"https://api.sandbox.checkout.com/payments/pay_oqwbsd22kvpuvd35y5fhbdawxa/actions","capture":"https://api.sandbox.checkout.com/payments/pay_oqwbsd22kvpuvd35y5fhbdawxa/captures","void":"https://api.sandbox.checkout.com/payments/pay_oqwbsd22kvpuvd35y5fhbdawxa/voids"}},"_links":{"self":{"href":"https://api.sandbox.checkout.com/workflows/events/evt_dli6ty4qo5vuxle5wklf5gwbwy"},"subject":{"href":"https://api.sandbox.checkout.com/workflows/events/subject/pay_oqwbsd22kvpuvd35y5fhbdawxa"},"payment":{"href":"https://api.sandbox.checkout.com/payments/pay_oqwbsd22kvpuvd35y5fhbdawxa"},"payment_actions":{"href":"https://api.sandbox.checkout.com/payments/pay_oqwbsd22kvpuvd35y5fhbdawxa/actions"},"capture":{"href":"https://api.sandbox.checkout.com/payments/pay_oqwbsd22kvpuvd35y5fhbdawxa/captures"},"void":{"href":"https://api.sandbox.checkout.com/payments/pay_oqwbsd22kvpuvd35y5fhbdawxa/voids"}}}   
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private function paymentApproved()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $payment_object = $this->webhook_array['data'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $payment = Payment::withTrashed()->where('transaction_reference', $payment_object['id'])->first();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if($payment && $payment->status_id == Payment::STATUS_COMPLETED)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if($payment){
 | 
				
			||||||
 | 
					            $payment->status_id = Payment::STATUS_COMPLETED;
 | 
				
			||||||
 | 
					            $payment->save();
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					         
 | 
				
			||||||
 | 
					        if(isset($this->webhook_array['metadata'])) {
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            $metadata = $this->webhook_array['metadata'];
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            $payment_hash = PaymentHash::where('hash', $metadata['udf2'])->first();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $driver = $this->company_gateway->driver($payment_hash->fee_invoice->client)->init()->setPaymentMethod();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $payment_hash->data = array_merge((array) $payment_hash->data, $this->webhook_array);
 | 
				
			||||||
 | 
					            $payment_hash->save();
 | 
				
			||||||
 | 
					            $driver->setPaymentHash($payment_hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $data = [
 | 
				
			||||||
 | 
					                'payment_method' => isset($this->webhook_array['source']['id']) ? $this->webhook_array['source']['id'] : '',
 | 
				
			||||||
 | 
					                'payment_type' => PaymentType::CREDIT_CARD_OTHER,
 | 
				
			||||||
 | 
					                'amount' => $payment_hash->data->raw_value,
 | 
				
			||||||
 | 
					                'transaction_reference' => $payment_object['id'],
 | 
				
			||||||
 | 
					                'gateway_type_id' => GatewayType::CREDIT_CARD,
 | 
				
			||||||
 | 
					            ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $payment = $driver->createPayment($data, \App\Models\Payment::STATUS_COMPLETED);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            SystemLogger::dispatch(
 | 
				
			||||||
 | 
					                ['response' => $this->webhook_array, 'data' => $data],
 | 
				
			||||||
 | 
					                SystemLog::CATEGORY_GATEWAY_RESPONSE,
 | 
				
			||||||
 | 
					                SystemLog::EVENT_GATEWAY_SUCCESS,
 | 
				
			||||||
 | 
					                SystemLog::TYPE_CHECKOUT,
 | 
				
			||||||
 | 
					                $payment_hash->fee_invoice->client,
 | 
				
			||||||
 | 
					                $this->company_gateway->company,
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -228,7 +228,7 @@ class CreditCard implements MethodInterface
 | 
				
			|||||||
        $paymentRequest->amount = $this->checkout->payment_hash->data->value;
 | 
					        $paymentRequest->amount = $this->checkout->payment_hash->data->value;
 | 
				
			||||||
        $paymentRequest->reference = substr($this->checkout->getDescription(), 0, 49);
 | 
					        $paymentRequest->reference = substr($this->checkout->getDescription(), 0, 49);
 | 
				
			||||||
        $paymentRequest->customer = $this->checkout->getCustomer();
 | 
					        $paymentRequest->customer = $this->checkout->getCustomer();
 | 
				
			||||||
        $paymentRequest->metadata = ['udf1' => 'Invoice Ninja'];
 | 
					        $paymentRequest->metadata = ['udf1' => 'Invoice Ninja', 'udf2' => $this->checkout->payment_hash->hash];
 | 
				
			||||||
        $paymentRequest->currency = $this->checkout->client->getCurrencyCode();
 | 
					        $paymentRequest->currency = $this->checkout->client->getCurrencyCode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->checkout->payment_hash->data = array_merge((array) $this->checkout->payment_hash->data, ['checkout_payment_ref' => $paymentRequest]);
 | 
					        $this->checkout->payment_hash->data = array_merge((array) $this->checkout->payment_hash->data, ['checkout_payment_ref' => $paymentRequest]);
 | 
				
			||||||
 | 
				
			|||||||
@ -12,12 +12,13 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\PaymentDrivers\CheckoutCom;
 | 
					namespace App\PaymentDrivers\CheckoutCom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Exceptions\PaymentFailed;
 | 
					 | 
				
			||||||
use App\Jobs\Util\SystemLogger;
 | 
					 | 
				
			||||||
use App\Models\GatewayType;
 | 
					 | 
				
			||||||
use App\Models\SystemLog;
 | 
					 | 
				
			||||||
use Exception;
 | 
					 | 
				
			||||||
use stdClass;
 | 
					use stdClass;
 | 
				
			||||||
 | 
					use Exception;
 | 
				
			||||||
 | 
					use App\Models\SystemLog;
 | 
				
			||||||
 | 
					use App\Models\GatewayType;
 | 
				
			||||||
 | 
					use App\Jobs\Util\SystemLogger;
 | 
				
			||||||
 | 
					use App\Exceptions\PaymentFailed;
 | 
				
			||||||
 | 
					use Checkout\Payments\PaymentType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
trait Utilities
 | 
					trait Utilities
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -60,7 +61,7 @@ trait Utilities
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $data = [
 | 
					        $data = [
 | 
				
			||||||
            'payment_method' => $_payment['source']['id'],
 | 
					            'payment_method' => $_payment['source']['id'],
 | 
				
			||||||
            'payment_type' => 12,
 | 
					            'payment_type' => \App\Models\PaymentType::CREDIT_CARD_OTHER,
 | 
				
			||||||
            'amount' => $this->getParent()->payment_hash->data->raw_value,
 | 
					            'amount' => $this->getParent()->payment_hash->data->raw_value,
 | 
				
			||||||
            'transaction_reference' => $_payment['id'],
 | 
					            'transaction_reference' => $_payment['id'],
 | 
				
			||||||
            'gateway_type_id' => GatewayType::CREDIT_CARD,
 | 
					            'gateway_type_id' => GatewayType::CREDIT_CARD,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										91
									
								
								app/PaymentDrivers/CheckoutCom/Webhook.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								app/PaymentDrivers/CheckoutCom/Webhook.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,91 @@
 | 
				
			|||||||
 | 
					<?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\PaymentDrivers\CheckoutCom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Exceptions\PaymentFailed;
 | 
				
			||||||
 | 
					use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
 | 
				
			||||||
 | 
					use App\Jobs\Util\SystemLogger;
 | 
				
			||||||
 | 
					use App\Models\ClientGatewayToken;
 | 
				
			||||||
 | 
					use App\Models\GatewayType;
 | 
				
			||||||
 | 
					use App\Models\SystemLog;
 | 
				
			||||||
 | 
					use App\PaymentDrivers\CheckoutComPaymentDriver;
 | 
				
			||||||
 | 
					use App\PaymentDrivers\Common\MethodInterface;
 | 
				
			||||||
 | 
					use App\Utils\Traits\MakesHash;
 | 
				
			||||||
 | 
					use Checkout\CheckoutApiException;
 | 
				
			||||||
 | 
					use Checkout\CheckoutArgumentException;
 | 
				
			||||||
 | 
					use Checkout\CheckoutAuthorizationException;
 | 
				
			||||||
 | 
					use Checkout\Payments\Four\Request\PaymentRequest;
 | 
				
			||||||
 | 
					use Checkout\Payments\Four\Request\Source\RequestTokenSource;
 | 
				
			||||||
 | 
					use Checkout\Payments\PaymentRequest as PaymentsPaymentRequest;
 | 
				
			||||||
 | 
					use Checkout\Payments\Source\RequestTokenSource as SourceRequestTokenSource;
 | 
				
			||||||
 | 
					use Illuminate\Contracts\View\Factory;
 | 
				
			||||||
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
 | 
					use Illuminate\View\View;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Webhook
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct(public CheckoutComPaymentDriver $checkout)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->checkout = $checkout;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Lists all possible events in checkout and a brief description
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getEventTypes()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $response = $this->checkout->gateway->getWorkflowsClient()->getEventTypes();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return $response;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } catch (CheckoutApiException $e) {
 | 
				
			||||||
 | 
					            // API error
 | 
				
			||||||
 | 
					            $error_details = $e->error_details;
 | 
				
			||||||
 | 
					            nlog($error_details);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $http_status_code = isset($e->http_metadata) ? $e->http_metadata->getStatusCode() : null;
 | 
				
			||||||
 | 
					        } catch (CheckoutAuthorizationException $e) {
 | 
				
			||||||
 | 
					            // Bad Invalid authorization
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Lists the workflows in Checkout
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getWorkFlows()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            $response = $this->checkout->gateway->getWorkflowsClient()->getWorkflows();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return $response;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } catch (CheckoutApiException $e) {
 | 
				
			||||||
 | 
					            // API error
 | 
				
			||||||
 | 
					            $error_details = $e->error_details;
 | 
				
			||||||
 | 
					            $http_status_code = isset($e->http_metadata) ? $e->http_metadata->getStatusCode() : null;
 | 
				
			||||||
 | 
					        } catch (CheckoutAuthorizationException $e) {
 | 
				
			||||||
 | 
					            // Bad Invalid authorization
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -27,6 +27,7 @@ use App\Models\PaymentType;
 | 
				
			|||||||
use App\Models\SystemLog;
 | 
					use App\Models\SystemLog;
 | 
				
			||||||
use App\PaymentDrivers\CheckoutCom\CreditCard;
 | 
					use App\PaymentDrivers\CheckoutCom\CreditCard;
 | 
				
			||||||
use App\PaymentDrivers\CheckoutCom\Utilities;
 | 
					use App\PaymentDrivers\CheckoutCom\Utilities;
 | 
				
			||||||
 | 
					use App\PaymentDrivers\CheckoutCom\CheckoutWebhook;
 | 
				
			||||||
use App\Utils\Traits\SystemLogTrait;
 | 
					use App\Utils\Traits\SystemLogTrait;
 | 
				
			||||||
use Checkout\CheckoutApi;
 | 
					use Checkout\CheckoutApi;
 | 
				
			||||||
use Checkout\CheckoutApiException;
 | 
					use Checkout\CheckoutApiException;
 | 
				
			||||||
@ -334,7 +335,7 @@ class CheckoutComPaymentDriver extends BaseDriver
 | 
				
			|||||||
        $paymentRequest->amount = $this->convertToCheckoutAmount($amount, $this->client->getCurrencyCode());
 | 
					        $paymentRequest->amount = $this->convertToCheckoutAmount($amount, $this->client->getCurrencyCode());
 | 
				
			||||||
        $paymentRequest->reference = '#'.$invoice->number.' - '.now();
 | 
					        $paymentRequest->reference = '#'.$invoice->number.' - '.now();
 | 
				
			||||||
        $paymentRequest->customer = $this->getCustomer();
 | 
					        $paymentRequest->customer = $this->getCustomer();
 | 
				
			||||||
        $paymentRequest->metadata = ['udf1' => 'Invoice Ninja'];
 | 
					        $paymentRequest->metadata = ['udf1' => 'Invoice Ninja', 'udf2' => $payment_hash->hash];
 | 
				
			||||||
        $paymentRequest->currency = $this->client->getCurrencyCode();
 | 
					        $paymentRequest->currency = $this->client->getCurrencyCode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $request = new PaymentResponseRequest();
 | 
					        $request = new PaymentResponseRequest();
 | 
				
			||||||
@ -421,7 +422,19 @@ class CheckoutComPaymentDriver extends BaseDriver
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function processWebhookRequest(PaymentWebhookRequest $request)
 | 
					    public function processWebhookRequest(PaymentWebhookRequest $request)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return true;
 | 
					
 | 
				
			||||||
 | 
					        header('Content-Type: text/plain');
 | 
				
			||||||
 | 
					        $webhook_payload = file_get_contents('php://input');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if($request->header('cko-signature') == hash_hmac('sha256', $webhook_payload, $this->company_gateway->company->company_key)) {
 | 
				
			||||||
 | 
					            CheckoutWebhook::dispatch($request->all(), $request->company_key, $this->company_gateway->id)->delay(10);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            nlog("Hash Mismatch = {$request->header('cko-signature')} ".hash_hmac('sha256', $webhook_payload, $this->company_gateway->company->company_key));
 | 
				
			||||||
 | 
					            nlog($request->all());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return response()->json(['success' => true]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function process3dsConfirmation(Checkout3dsRequest $request)
 | 
					    public function process3dsConfirmation(Checkout3dsRequest $request)
 | 
				
			||||||
@ -440,6 +453,9 @@ class CheckoutComPaymentDriver extends BaseDriver
 | 
				
			|||||||
                $request->query('cko-session-id')
 | 
					                $request->query('cko-session-id')
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            nlog("checkout3ds");
 | 
				
			||||||
 | 
					            nlog($payment);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (isset($payment['approved']) && $payment['approved']) {
 | 
					            if (isset($payment['approved']) && $payment['approved']) {
 | 
				
			||||||
                return $this->processSuccessfulPayment($payment);
 | 
					                return $this->processSuccessfulPayment($payment);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
 | 
				
			|||||||
@ -136,7 +136,7 @@ class ClientRepository extends BaseRepository
 | 
				
			|||||||
        $client->projects()->forceDelete();
 | 
					        $client->projects()->forceDelete();
 | 
				
			||||||
        $client->credits()->forceDelete();
 | 
					        $client->credits()->forceDelete();
 | 
				
			||||||
        $client->quotes()->forceDelete();
 | 
					        $client->quotes()->forceDelete();
 | 
				
			||||||
        $client->activities()->forceDelete();
 | 
					        $client->purgeable_activities()->forceDelete();
 | 
				
			||||||
        $client->recurring_invoices()->forceDelete();
 | 
					        $client->recurring_invoices()->forceDelete();
 | 
				
			||||||
        $client->expenses()->forceDelete();
 | 
					        $client->expenses()->forceDelete();
 | 
				
			||||||
        $client->recurring_expenses()->forceDelete();
 | 
					        $client->recurring_expenses()->forceDelete();
 | 
				
			||||||
 | 
				
			|||||||
@ -97,6 +97,10 @@ class InvoiceRepository extends BaseRepository
 | 
				
			|||||||
        // reversed delete invoice actions
 | 
					        // reversed delete invoice actions
 | 
				
			||||||
        $invoice = $invoice->service()->handleRestore()->save();
 | 
					        $invoice = $invoice->service()->handleRestore()->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* If the reverse did not succeed due to rules, then do not restore / unarchive */
 | 
				
			||||||
 | 
					        if($invoice->is_deleted)
 | 
				
			||||||
 | 
					            return $invoice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        parent::restore($invoice);
 | 
					        parent::restore($invoice);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $invoice;
 | 
					        return $invoice;
 | 
				
			||||||
 | 
				
			|||||||
@ -101,9 +101,6 @@ class TaskRepository extends BaseRepository
 | 
				
			|||||||
        $key_values = array_column($time_log, 0);
 | 
					        $key_values = array_column($time_log, 0);
 | 
				
			||||||
        array_multisort($key_values, SORT_ASC, $time_log);
 | 
					        array_multisort($key_values, SORT_ASC, $time_log);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // array_multisort($time_log);
 | 
					 | 
				
			||||||
        // ksort($time_log);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (isset($data['action'])) {
 | 
					        if (isset($data['action'])) {
 | 
				
			||||||
            if ($data['action'] == 'start') {
 | 
					            if ($data['action'] == 'start') {
 | 
				
			||||||
                $task->is_running = true;
 | 
					                $task->is_running = true;
 | 
				
			||||||
@ -121,8 +118,12 @@ class TaskRepository extends BaseRepository
 | 
				
			|||||||
            $task->is_running = $data['is_running'] ? 1 : 0;
 | 
					            $task->is_running = $data['is_running'] ? 1 : 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $task->calculated_start_date = $this->harvestStartDate($time_log);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        $task->time_log = json_encode($time_log);
 | 
					        $task->time_log = json_encode($time_log);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $task->saveQuietly();
 | 
					        $task->saveQuietly();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (array_key_exists('documents', $data)) {
 | 
					        if (array_key_exists('documents', $data)) {
 | 
				
			||||||
@ -132,6 +133,17 @@ class TaskRepository extends BaseRepository
 | 
				
			|||||||
        return $task;
 | 
					        return $task;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function harvestStartDate($time_log)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if(isset($time_log[0][0])){
 | 
				
			||||||
 | 
					            return \Carbon\Carbon::createFromTimestamp($time_log[0][0]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Store tasks in bulk.
 | 
					     * Store tasks in bulk.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@ -199,8 +211,12 @@ class TaskRepository extends BaseRepository
 | 
				
			|||||||
        if (strlen($task->time_log) < 5) {
 | 
					        if (strlen($task->time_log) < 5) {
 | 
				
			||||||
            $log = [];
 | 
					            $log = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $log = array_merge($log, [[time(), 0]]);
 | 
					            $start_time = time();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $log = array_merge($log, [[$start_time, 0]]);
 | 
				
			||||||
            $task->time_log = json_encode($log);
 | 
					            $task->time_log = json_encode($log);
 | 
				
			||||||
 | 
					            $task->calculated_start_date = \Carbon\Carbon::createFromTimestamp($start_time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $task->saveQuietly();
 | 
					            $task->saveQuietly();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -43,8 +43,14 @@ class VendorRepository extends BaseRepository
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function save(array $data, Vendor $vendor) : ?Vendor
 | 
					    public function save(array $data, Vendor $vendor) : ?Vendor
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $vendor->fill($data);
 | 
					        $saveable_vendor = $data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(array_key_exists('contacts', $data)) {
 | 
				
			||||||
 | 
					            unset($saveable_vendor['contacts']);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $vendor->fill($saveable_vendor);
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
        $vendor->saveQuietly();
 | 
					        $vendor->saveQuietly();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($vendor->number == '' || ! $vendor->number) {
 | 
					        if ($vendor->number == '' || ! $vendor->number) {
 | 
				
			||||||
 | 
				
			|||||||
@ -212,9 +212,9 @@ class FacturaEInvoice extends AbstractService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private function setPoNumber(): self
 | 
					    private function setPoNumber(): self
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if(strlen($this->invoice->po_number) > 1) {
 | 
					        $po = $this->invoice->po_number ?? '';
 | 
				
			||||||
            $this->fac->setReferences($this->invoice->po_number);
 | 
					
 | 
				
			||||||
        }
 | 
					        $this->fac->setReferences($po, $this->invoice->custom_value1, $this->invoice->custom_value2);        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this;
 | 
					        return $this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -233,10 +233,10 @@ class FacturaEInvoice extends AbstractService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        foreach($this->invoice->line_items as $item) {
 | 
					        foreach($this->invoice->line_items as $item) {
 | 
				
			||||||
            $this->fac->addItem(new FacturaeItem([
 | 
					            $this->fac->addItem(new FacturaeItem([
 | 
				
			||||||
                'name' => $item->product_key,
 | 
					                'name' => $item->notes,
 | 
				
			||||||
                'description' => $item->notes,
 | 
					                'description' => $item->product_key,
 | 
				
			||||||
                'quantity' => $item->quantity,
 | 
					                'quantity' => $item->quantity,
 | 
				
			||||||
                'unitPrice' => $item->cost,
 | 
					                'unitPriceWithoutTax' => $item->cost,
 | 
				
			||||||
                'discountsAndRebates' => $item->discount,
 | 
					                'discountsAndRebates' => $item->discount,
 | 
				
			||||||
                'charges' => [],
 | 
					                'charges' => [],
 | 
				
			||||||
                'discounts' => [],
 | 
					                'discounts' => [],
 | 
				
			||||||
 | 
				
			|||||||
@ -44,6 +44,7 @@ class HandleRestore extends AbstractService
 | 
				
			|||||||
        //cannot restore an invoice with a deleted payment
 | 
					        //cannot restore an invoice with a deleted payment
 | 
				
			||||||
        foreach ($this->invoice->payments as $payment) {
 | 
					        foreach ($this->invoice->payments as $payment) {
 | 
				
			||||||
            if (($this->invoice->paid_to_date == 0) && $payment->is_deleted) {
 | 
					            if (($this->invoice->paid_to_date == 0) && $payment->is_deleted) {
 | 
				
			||||||
 | 
					                $this->invoice->delete();
 | 
				
			||||||
                return $this->invoice;
 | 
					                return $this->invoice;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -148,7 +148,7 @@ class DeletePayment
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                $client
 | 
					                $client
 | 
				
			||||||
                ->service()
 | 
					                ->service()
 | 
				
			||||||
                ->updatePaidToDate(($paymentable_credit->pivot->amount) * -1)
 | 
					                // ->updatePaidToDate(($paymentable_credit->pivot->amount) * -1)
 | 
				
			||||||
                ->adjustCreditBalance($paymentable_credit->pivot->amount)
 | 
					                ->adjustCreditBalance($paymentable_credit->pivot->amount)
 | 
				
			||||||
                ->save();
 | 
					                ->save();
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
				
			|||||||
@ -11,11 +11,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Services\PurchaseOrder;
 | 
					namespace App\Services\PurchaseOrder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Jobs\Vendor\CreatePurchaseOrderPdf;
 | 
					 | 
				
			||||||
use App\Models\PurchaseOrder;
 | 
					use App\Models\PurchaseOrder;
 | 
				
			||||||
use App\Models\VendorContact;
 | 
					use App\Models\VendorContact;
 | 
				
			||||||
use App\Services\AbstractService;
 | 
					use App\Services\AbstractService;
 | 
				
			||||||
use Illuminate\Support\Facades\Storage;
 | 
					use Illuminate\Support\Facades\Storage;
 | 
				
			||||||
 | 
					use App\Jobs\Vendor\CreatePurchaseOrderPdf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GetPurchaseOrderPdf extends AbstractService
 | 
					class GetPurchaseOrderPdf extends AbstractService
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -31,6 +31,7 @@ class GetPurchaseOrderPdf extends AbstractService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $invitation = $this->purchase_order->invitations()->where('vendor_contact_id', $this->contact->id)->first();
 | 
					        $invitation = $this->purchase_order->invitations()->where('vendor_contact_id', $this->contact->id)->first();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (! $invitation) {
 | 
					        if (! $invitation) {
 | 
				
			||||||
            $invitation = $this->purchase_order->invitations()->first();
 | 
					            $invitation = $this->purchase_order->invitations()->first();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -150,7 +150,7 @@ class ClientTransformer extends EntityTransformer
 | 
				
			|||||||
            'has_valid_vat_number' => (bool) $client->has_valid_vat_number,
 | 
					            'has_valid_vat_number' => (bool) $client->has_valid_vat_number,
 | 
				
			||||||
            'is_tax_exempt' => (bool) $client->is_tax_exempt,
 | 
					            'is_tax_exempt' => (bool) $client->is_tax_exempt,
 | 
				
			||||||
            'routing_id' => (string) $client->routing_id,
 | 
					            'routing_id' => (string) $client->routing_id,
 | 
				
			||||||
            'tax_data' => $client->tax_data ?: '',
 | 
					            'tax_info' => $client->tax_data ?: new \stdClass,
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -133,7 +133,7 @@ class CompanyTransformer extends EntityTransformer
 | 
				
			|||||||
            'show_product_details' => (bool) $company->show_product_details,
 | 
					            'show_product_details' => (bool) $company->show_product_details,
 | 
				
			||||||
            'enable_product_quantity' => (bool) $company->enable_product_quantity,
 | 
					            'enable_product_quantity' => (bool) $company->enable_product_quantity,
 | 
				
			||||||
            'default_quantity' => (bool) $company->default_quantity,
 | 
					            'default_quantity' => (bool) $company->default_quantity,
 | 
				
			||||||
            'custom_fields' => $company->custom_fields ?? $std,
 | 
					            'custom_fields' =>  (object) $company->custom_fields ?? $std,
 | 
				
			||||||
            'size_id' => (string) $company->size_id ?: '',
 | 
					            'size_id' => (string) $company->size_id ?: '',
 | 
				
			||||||
            'industry_id' => (string) $company->industry_id ?: '',
 | 
					            'industry_id' => (string) $company->industry_id ?: '',
 | 
				
			||||||
            'first_month_of_year' => (string) $company->first_month_of_year ?: '',
 | 
					            'first_month_of_year' => (string) $company->first_month_of_year ?: '',
 | 
				
			||||||
 | 
				
			|||||||
@ -149,7 +149,7 @@ class InvoiceTransformer extends EntityTransformer
 | 
				
			|||||||
            'paid_to_date' => (float) $invoice->paid_to_date,
 | 
					            'paid_to_date' => (float) $invoice->paid_to_date,
 | 
				
			||||||
            'subscription_id' => $this->encodePrimaryKey($invoice->subscription_id),
 | 
					            'subscription_id' => $this->encodePrimaryKey($invoice->subscription_id),
 | 
				
			||||||
            'auto_bill_enabled' => (bool) $invoice->auto_bill_enabled,
 | 
					            'auto_bill_enabled' => (bool) $invoice->auto_bill_enabled,
 | 
				
			||||||
            'tax_data' => $invoice->tax_data ?: '',            
 | 
					            'tax_info' => $invoice->tax_data ?: new \stdClass,
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -37,6 +37,7 @@ class TaskTransformer extends EntityTransformer
 | 
				
			|||||||
        'status',
 | 
					        'status',
 | 
				
			||||||
        'project',
 | 
					        'project',
 | 
				
			||||||
        'user',
 | 
					        'user',
 | 
				
			||||||
 | 
					        'invoice',
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function includeDocuments(Task $task)
 | 
					    public function includeDocuments(Task $task)
 | 
				
			||||||
@ -46,6 +47,17 @@ class TaskTransformer extends EntityTransformer
 | 
				
			|||||||
        return $this->includeCollection($task->documents, $transformer, Document::class);
 | 
					        return $this->includeCollection($task->documents, $transformer, Document::class);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function includeInvoice(Task $task): ?Item
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $transformer = new InvoiceTransformer($this->serializer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!$task->user) {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->includeItem($task->invoice, $transformer, Invoice::class);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function includeUser(Task $task): ?Item
 | 
					    public function includeUser(Task $task): ?Item
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $transformer = new UserTransformer($this->serializer);
 | 
					        $transformer = new UserTransformer($this->serializer);
 | 
				
			||||||
@ -118,6 +130,7 @@ class TaskTransformer extends EntityTransformer
 | 
				
			|||||||
            'status_sort_order' => (int) $task->status_sort_order, //deprecated 5.0.34
 | 
					            'status_sort_order' => (int) $task->status_sort_order, //deprecated 5.0.34
 | 
				
			||||||
            'is_date_based' => (bool) $task->is_date_based,
 | 
					            'is_date_based' => (bool) $task->is_date_based,
 | 
				
			||||||
            'status_order' => is_null($task->status_order) ? null : (int) $task->status_order,
 | 
					            'status_order' => is_null($task->status_order) ? null : (int) $task->status_order,
 | 
				
			||||||
 | 
					            'date' => $task->calculated_start_date ?: '',
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -583,8 +583,11 @@ class HtmlEngine
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if ($this->settings->signature_on_pdf) {
 | 
					        if ($this->settings->signature_on_pdf) {
 | 
				
			||||||
            $data['$contact.signature'] = ['value' => $this->invitation->signature_base64, 'label' => ctrans('texts.signature')];
 | 
					            $data['$contact.signature'] = ['value' => $this->invitation->signature_base64, 'label' => ctrans('texts.signature')];
 | 
				
			||||||
 | 
					            $data['$contact.signature_date'] = ['value' => $this->translateDate($this->invitation->signature_date, $this->client->date_format(), $this->client->locale()), 'label' => ctrans('texts.date')];
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            $data['$contact.signature'] = ['value' => '', 'label' => ''];
 | 
					            $data['$contact.signature'] = ['value' => '', 'label' => ''];
 | 
				
			||||||
 | 
					            $data['$contact.signature_date'] = ['value' => '', 'label' => ctrans('texts.date')];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $data['$thanks'] = ['value' => '', 'label' => ctrans('texts.thanks')];
 | 
					        $data['$thanks'] = ['value' => '', 'label' => ctrans('texts.thanks')];
 | 
				
			||||||
 | 
				
			|||||||
@ -14,6 +14,7 @@ namespace App\Utils\Traits;
 | 
				
			|||||||
use DateTime;
 | 
					use DateTime;
 | 
				
			||||||
use DateTimeZone;
 | 
					use DateTimeZone;
 | 
				
			||||||
use Carbon\Carbon;
 | 
					use Carbon\Carbon;
 | 
				
			||||||
 | 
					use App\Models\Company;
 | 
				
			||||||
use App\DataMapper\Schedule\EmailStatement;
 | 
					use App\DataMapper\Schedule\EmailStatement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -119,8 +120,32 @@ trait MakesDates
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return array [$start_date, $end_date];
 | 
					     * @return array [$start_date, $end_date];
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function calculateStartAndEndDates(array $data): array
 | 
					    public function calculateStartAndEndDates(array $data, ?Company $company = null): array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        //override for financial years
 | 
				
			||||||
 | 
					        if($data['date_range'] == 'this_year') {
 | 
				
			||||||
 | 
					            $first_month_of_year = $company ? $company?->first_month_of_year : 1;
 | 
				
			||||||
 | 
					            $fin_year_start = now()->createFromDate(now()->year, $first_month_of_year, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(now()->lt($fin_year_start)) 
 | 
				
			||||||
 | 
					                $fin_year_start->subYearNoOverflow();
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //override for financial years
 | 
				
			||||||
 | 
					        if($data['date_range'] == 'last_year') {
 | 
				
			||||||
 | 
					            $first_month_of_year = $company ? $company?->first_month_of_year : 1;
 | 
				
			||||||
 | 
					            $fin_year_start = now()->createFromDate(now()->year, $first_month_of_year, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $fin_year_start->subYearNoOverflow();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(now()->subYear()->lt($fin_year_start)) {
 | 
				
			||||||
 | 
					                $fin_year_start->subYearNoOverflow();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return match ($data['date_range']) {
 | 
					        return match ($data['date_range']) {
 | 
				
			||||||
            EmailStatement::LAST7 => [now()->startOfDay()->subDays(7)->format('Y-m-d'), now()->startOfDay()->format('Y-m-d')],
 | 
					            EmailStatement::LAST7 => [now()->startOfDay()->subDays(7)->format('Y-m-d'), now()->startOfDay()->format('Y-m-d')],
 | 
				
			||||||
            EmailStatement::LAST30 => [now()->startOfDay()->subDays(30)->format('Y-m-d'), now()->startOfDay()->format('Y-m-d')],
 | 
					            EmailStatement::LAST30 => [now()->startOfDay()->subDays(30)->format('Y-m-d'), now()->startOfDay()->format('Y-m-d')],
 | 
				
			||||||
@ -129,8 +154,8 @@ trait MakesDates
 | 
				
			|||||||
            EmailStatement::LAST_MONTH => [now()->startOfDay()->subMonthNoOverflow()->firstOfMonth()->format('Y-m-d'), now()->startOfDay()->subMonthNoOverflow()->lastOfMonth()->format('Y-m-d')],
 | 
					            EmailStatement::LAST_MONTH => [now()->startOfDay()->subMonthNoOverflow()->firstOfMonth()->format('Y-m-d'), now()->startOfDay()->subMonthNoOverflow()->lastOfMonth()->format('Y-m-d')],
 | 
				
			||||||
            EmailStatement::THIS_QUARTER => [now()->startOfDay()->firstOfQuarter()->format('Y-m-d'), now()->startOfDay()->lastOfQuarter()->format('Y-m-d')],
 | 
					            EmailStatement::THIS_QUARTER => [now()->startOfDay()->firstOfQuarter()->format('Y-m-d'), now()->startOfDay()->lastOfQuarter()->format('Y-m-d')],
 | 
				
			||||||
            EmailStatement::LAST_QUARTER => [now()->startOfDay()->subQuarterNoOverflow()->firstOfQuarter()->format('Y-m-d'), now()->startOfDay()->subQuarterNoOverflow()->lastOfQuarter()->format('Y-m-d')],
 | 
					            EmailStatement::LAST_QUARTER => [now()->startOfDay()->subQuarterNoOverflow()->firstOfQuarter()->format('Y-m-d'), now()->startOfDay()->subQuarterNoOverflow()->lastOfQuarter()->format('Y-m-d')],
 | 
				
			||||||
            EmailStatement::THIS_YEAR => [now()->startOfDay()->firstOfYear()->format('Y-m-d'), now()->startOfDay()->lastOfYear()->format('Y-m-d')],
 | 
					            EmailStatement::THIS_YEAR => [$fin_year_start->format('Y-m-d'), $fin_year_start->copy()->addYear()->subDay()->format('Y-m-d')],
 | 
				
			||||||
            EmailStatement::LAST_YEAR => [now()->startOfDay()->subYearNoOverflow()->firstOfYear()->format('Y-m-d'), now()->startOfDay()->subYearNoOverflow()->lastOfYear()->format('Y-m-d')],
 | 
					            EmailStatement::LAST_YEAR => [$fin_year_start->format('Y-m-d'), $fin_year_start->copy()->addYear()->subDay()->format('Y-m-d')],
 | 
				
			||||||
            EmailStatement::CUSTOM_RANGE => [$data['start_date'], $data['end_date']],
 | 
					            EmailStatement::CUSTOM_RANGE => [$data['start_date'], $data['end_date']],
 | 
				
			||||||
            default => [now()->startOfDay()->firstOfMonth()->format('Y-m-d'), now()->startOfDay()->lastOfMonth()->format('Y-m-d')],
 | 
					            default => [now()->startOfDay()->firstOfMonth()->format('Y-m-d'), now()->startOfDay()->lastOfMonth()->format('Y-m-d')],
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										146
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										146
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							@ -424,16 +424,16 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "aws/aws-sdk-php",
 | 
					            "name": "aws/aws-sdk-php",
 | 
				
			||||||
            "version": "3.275.7",
 | 
					            "version": "3.276.2",
 | 
				
			||||||
            "source": {
 | 
					            "source": {
 | 
				
			||||||
                "type": "git",
 | 
					                "type": "git",
 | 
				
			||||||
                "url": "https://github.com/aws/aws-sdk-php.git",
 | 
					                "url": "https://github.com/aws/aws-sdk-php.git",
 | 
				
			||||||
                "reference": "54dcef3349c81b46c0f5f6e54b5f9bfb5db19903"
 | 
					                "reference": "78c9510280512121e8fdaa9538b744778ab48bf9"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "dist": {
 | 
					            "dist": {
 | 
				
			||||||
                "type": "zip",
 | 
					                "type": "zip",
 | 
				
			||||||
                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/54dcef3349c81b46c0f5f6e54b5f9bfb5db19903",
 | 
					                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/78c9510280512121e8fdaa9538b744778ab48bf9",
 | 
				
			||||||
                "reference": "54dcef3349c81b46c0f5f6e54b5f9bfb5db19903",
 | 
					                "reference": "78c9510280512121e8fdaa9538b744778ab48bf9",
 | 
				
			||||||
                "shasum": ""
 | 
					                "shasum": ""
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require": {
 | 
					            "require": {
 | 
				
			||||||
@ -513,9 +513,9 @@
 | 
				
			|||||||
            "support": {
 | 
					            "support": {
 | 
				
			||||||
                "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
 | 
					                "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
 | 
				
			||||||
                "issues": "https://github.com/aws/aws-sdk-php/issues",
 | 
					                "issues": "https://github.com/aws/aws-sdk-php/issues",
 | 
				
			||||||
                "source": "https://github.com/aws/aws-sdk-php/tree/3.275.7"
 | 
					                "source": "https://github.com/aws/aws-sdk-php/tree/3.276.2"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "time": "2023-07-13T18:21:04+00:00"
 | 
					            "time": "2023-07-20T18:16:37+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "bacon/bacon-qr-code",
 | 
					            "name": "bacon/bacon-qr-code",
 | 
				
			||||||
@ -2167,16 +2167,16 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "firebase/php-jwt",
 | 
					            "name": "firebase/php-jwt",
 | 
				
			||||||
            "version": "v6.8.0",
 | 
					            "version": "v6.8.1",
 | 
				
			||||||
            "source": {
 | 
					            "source": {
 | 
				
			||||||
                "type": "git",
 | 
					                "type": "git",
 | 
				
			||||||
                "url": "https://github.com/firebase/php-jwt.git",
 | 
					                "url": "https://github.com/firebase/php-jwt.git",
 | 
				
			||||||
                "reference": "48b0210c51718d682e53210c24d25c5a10a2299b"
 | 
					                "reference": "5dbc8959427416b8ee09a100d7a8588c00fb2e26"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "dist": {
 | 
					            "dist": {
 | 
				
			||||||
                "type": "zip",
 | 
					                "type": "zip",
 | 
				
			||||||
                "url": "https://api.github.com/repos/firebase/php-jwt/zipball/48b0210c51718d682e53210c24d25c5a10a2299b",
 | 
					                "url": "https://api.github.com/repos/firebase/php-jwt/zipball/5dbc8959427416b8ee09a100d7a8588c00fb2e26",
 | 
				
			||||||
                "reference": "48b0210c51718d682e53210c24d25c5a10a2299b",
 | 
					                "reference": "5dbc8959427416b8ee09a100d7a8588c00fb2e26",
 | 
				
			||||||
                "shasum": ""
 | 
					                "shasum": ""
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require": {
 | 
					            "require": {
 | 
				
			||||||
@ -2224,9 +2224,9 @@
 | 
				
			|||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "support": {
 | 
					            "support": {
 | 
				
			||||||
                "issues": "https://github.com/firebase/php-jwt/issues",
 | 
					                "issues": "https://github.com/firebase/php-jwt/issues",
 | 
				
			||||||
                "source": "https://github.com/firebase/php-jwt/tree/v6.8.0"
 | 
					                "source": "https://github.com/firebase/php-jwt/tree/v6.8.1"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "time": "2023-06-20T16:45:35+00:00"
 | 
					            "time": "2023-07-14T18:33:00+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "fruitcake/php-cors",
 | 
					            "name": "fruitcake/php-cors",
 | 
				
			||||||
@ -2485,16 +2485,16 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "google/apiclient-services",
 | 
					            "name": "google/apiclient-services",
 | 
				
			||||||
            "version": "v0.308.0",
 | 
					            "version": "v0.309.0",
 | 
				
			||||||
            "source": {
 | 
					            "source": {
 | 
				
			||||||
                "type": "git",
 | 
					                "type": "git",
 | 
				
			||||||
                "url": "https://github.com/googleapis/google-api-php-client-services.git",
 | 
					                "url": "https://github.com/googleapis/google-api-php-client-services.git",
 | 
				
			||||||
                "reference": "85cf00383e6bf6eca131bd3261b7859ea418a578"
 | 
					                "reference": "562f8e5ddbca68d52afc3bf47d03839e78722026"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "dist": {
 | 
					            "dist": {
 | 
				
			||||||
                "type": "zip",
 | 
					                "type": "zip",
 | 
				
			||||||
                "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/85cf00383e6bf6eca131bd3261b7859ea418a578",
 | 
					                "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/562f8e5ddbca68d52afc3bf47d03839e78722026",
 | 
				
			||||||
                "reference": "85cf00383e6bf6eca131bd3261b7859ea418a578",
 | 
					                "reference": "562f8e5ddbca68d52afc3bf47d03839e78722026",
 | 
				
			||||||
                "shasum": ""
 | 
					                "shasum": ""
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require": {
 | 
					            "require": {
 | 
				
			||||||
@ -2523,9 +2523,9 @@
 | 
				
			|||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "support": {
 | 
					            "support": {
 | 
				
			||||||
                "issues": "https://github.com/googleapis/google-api-php-client-services/issues",
 | 
					                "issues": "https://github.com/googleapis/google-api-php-client-services/issues",
 | 
				
			||||||
                "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.308.0"
 | 
					                "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.309.0"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "time": "2023-07-09T01:06:13+00:00"
 | 
					            "time": "2023-07-16T01:08:14+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "google/auth",
 | 
					            "name": "google/auth",
 | 
				
			||||||
@ -4554,16 +4554,16 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "laravel/socialite",
 | 
					            "name": "laravel/socialite",
 | 
				
			||||||
            "version": "v5.7.0",
 | 
					            "version": "v5.8.0",
 | 
				
			||||||
            "source": {
 | 
					            "source": {
 | 
				
			||||||
                "type": "git",
 | 
					                "type": "git",
 | 
				
			||||||
                "url": "https://github.com/laravel/socialite.git",
 | 
					                "url": "https://github.com/laravel/socialite.git",
 | 
				
			||||||
                "reference": "f5996f499e14db15407201a6bfbaba3ce6ce736c"
 | 
					                "reference": "50148edf24b6cd3e428aa9bc06a5d915b24376bb"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "dist": {
 | 
					            "dist": {
 | 
				
			||||||
                "type": "zip",
 | 
					                "type": "zip",
 | 
				
			||||||
                "url": "https://api.github.com/repos/laravel/socialite/zipball/f5996f499e14db15407201a6bfbaba3ce6ce736c",
 | 
					                "url": "https://api.github.com/repos/laravel/socialite/zipball/50148edf24b6cd3e428aa9bc06a5d915b24376bb",
 | 
				
			||||||
                "reference": "f5996f499e14db15407201a6bfbaba3ce6ce736c",
 | 
					                "reference": "50148edf24b6cd3e428aa9bc06a5d915b24376bb",
 | 
				
			||||||
                "shasum": ""
 | 
					                "shasum": ""
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require": {
 | 
					            "require": {
 | 
				
			||||||
@ -4620,7 +4620,7 @@
 | 
				
			|||||||
                "issues": "https://github.com/laravel/socialite/issues",
 | 
					                "issues": "https://github.com/laravel/socialite/issues",
 | 
				
			||||||
                "source": "https://github.com/laravel/socialite"
 | 
					                "source": "https://github.com/laravel/socialite"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "time": "2023-07-08T20:51:43+00:00"
 | 
					            "time": "2023-07-14T14:22:58+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "laravel/tinker",
 | 
					            "name": "laravel/tinker",
 | 
				
			||||||
@ -5716,16 +5716,16 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "microsoft/microsoft-graph",
 | 
					            "name": "microsoft/microsoft-graph",
 | 
				
			||||||
            "version": "1.102.0",
 | 
					            "version": "1.103.0",
 | 
				
			||||||
            "source": {
 | 
					            "source": {
 | 
				
			||||||
                "type": "git",
 | 
					                "type": "git",
 | 
				
			||||||
                "url": "https://github.com/microsoftgraph/msgraph-sdk-php.git",
 | 
					                "url": "https://github.com/microsoftgraph/msgraph-sdk-php.git",
 | 
				
			||||||
                "reference": "4b450b06ac9df3868bbdbddb31bfcc4595f643bc"
 | 
					                "reference": "6e325c22145dbed4e51970ffecca4d7648c3c27e"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "dist": {
 | 
					            "dist": {
 | 
				
			||||||
                "type": "zip",
 | 
					                "type": "zip",
 | 
				
			||||||
                "url": "https://api.github.com/repos/microsoftgraph/msgraph-sdk-php/zipball/4b450b06ac9df3868bbdbddb31bfcc4595f643bc",
 | 
					                "url": "https://api.github.com/repos/microsoftgraph/msgraph-sdk-php/zipball/6e325c22145dbed4e51970ffecca4d7648c3c27e",
 | 
				
			||||||
                "reference": "4b450b06ac9df3868bbdbddb31bfcc4595f643bc",
 | 
					                "reference": "6e325c22145dbed4e51970ffecca4d7648c3c27e",
 | 
				
			||||||
                "shasum": ""
 | 
					                "shasum": ""
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require": {
 | 
					            "require": {
 | 
				
			||||||
@ -5762,22 +5762,22 @@
 | 
				
			|||||||
            "homepage": "https://developer.microsoft.com/en-us/graph",
 | 
					            "homepage": "https://developer.microsoft.com/en-us/graph",
 | 
				
			||||||
            "support": {
 | 
					            "support": {
 | 
				
			||||||
                "issues": "https://github.com/microsoftgraph/msgraph-sdk-php/issues",
 | 
					                "issues": "https://github.com/microsoftgraph/msgraph-sdk-php/issues",
 | 
				
			||||||
                "source": "https://github.com/microsoftgraph/msgraph-sdk-php/tree/1.102.0"
 | 
					                "source": "https://github.com/microsoftgraph/msgraph-sdk-php/tree/1.103.0"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "time": "2023-07-05T13:07:19+00:00"
 | 
					            "time": "2023-07-19T03:27:15+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "mollie/mollie-api-php",
 | 
					            "name": "mollie/mollie-api-php",
 | 
				
			||||||
            "version": "v2.58.0",
 | 
					            "version": "v2.59.0",
 | 
				
			||||||
            "source": {
 | 
					            "source": {
 | 
				
			||||||
                "type": "git",
 | 
					                "type": "git",
 | 
				
			||||||
                "url": "https://github.com/mollie/mollie-api-php.git",
 | 
					                "url": "https://github.com/mollie/mollie-api-php.git",
 | 
				
			||||||
                "reference": "5120e5b3e4622a290b64acf87266ea47d10d7301"
 | 
					                "reference": "9834e5779c695d1cc278b2c78ee514de9434b084"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "dist": {
 | 
					            "dist": {
 | 
				
			||||||
                "type": "zip",
 | 
					                "type": "zip",
 | 
				
			||||||
                "url": "https://api.github.com/repos/mollie/mollie-api-php/zipball/5120e5b3e4622a290b64acf87266ea47d10d7301",
 | 
					                "url": "https://api.github.com/repos/mollie/mollie-api-php/zipball/9834e5779c695d1cc278b2c78ee514de9434b084",
 | 
				
			||||||
                "reference": "5120e5b3e4622a290b64acf87266ea47d10d7301",
 | 
					                "reference": "9834e5779c695d1cc278b2c78ee514de9434b084",
 | 
				
			||||||
                "shasum": ""
 | 
					                "shasum": ""
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require": {
 | 
					            "require": {
 | 
				
			||||||
@ -5854,9 +5854,9 @@
 | 
				
			|||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "support": {
 | 
					            "support": {
 | 
				
			||||||
                "issues": "https://github.com/mollie/mollie-api-php/issues",
 | 
					                "issues": "https://github.com/mollie/mollie-api-php/issues",
 | 
				
			||||||
                "source": "https://github.com/mollie/mollie-api-php/tree/v2.58.0"
 | 
					                "source": "https://github.com/mollie/mollie-api-php/tree/v2.59.0"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "time": "2023-07-11T12:01:27+00:00"
 | 
					            "time": "2023-07-18T13:41:40+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "moneyphp/money",
 | 
					            "name": "moneyphp/money",
 | 
				
			||||||
@ -8514,16 +8514,16 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "psy/psysh",
 | 
					            "name": "psy/psysh",
 | 
				
			||||||
            "version": "v0.11.18",
 | 
					            "version": "v0.11.19",
 | 
				
			||||||
            "source": {
 | 
					            "source": {
 | 
				
			||||||
                "type": "git",
 | 
					                "type": "git",
 | 
				
			||||||
                "url": "https://github.com/bobthecow/psysh.git",
 | 
					                "url": "https://github.com/bobthecow/psysh.git",
 | 
				
			||||||
                "reference": "4f00ee9e236fa6a48f4560d1300b9c961a70a7ec"
 | 
					                "reference": "1724ceff278daeeac5a006744633bacbb2dc4706"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "dist": {
 | 
					            "dist": {
 | 
				
			||||||
                "type": "zip",
 | 
					                "type": "zip",
 | 
				
			||||||
                "url": "https://api.github.com/repos/bobthecow/psysh/zipball/4f00ee9e236fa6a48f4560d1300b9c961a70a7ec",
 | 
					                "url": "https://api.github.com/repos/bobthecow/psysh/zipball/1724ceff278daeeac5a006744633bacbb2dc4706",
 | 
				
			||||||
                "reference": "4f00ee9e236fa6a48f4560d1300b9c961a70a7ec",
 | 
					                "reference": "1724ceff278daeeac5a006744633bacbb2dc4706",
 | 
				
			||||||
                "shasum": ""
 | 
					                "shasum": ""
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require": {
 | 
					            "require": {
 | 
				
			||||||
@ -8584,9 +8584,9 @@
 | 
				
			|||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "support": {
 | 
					            "support": {
 | 
				
			||||||
                "issues": "https://github.com/bobthecow/psysh/issues",
 | 
					                "issues": "https://github.com/bobthecow/psysh/issues",
 | 
				
			||||||
                "source": "https://github.com/bobthecow/psysh/tree/v0.11.18"
 | 
					                "source": "https://github.com/bobthecow/psysh/tree/v0.11.19"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "time": "2023-05-23T02:31:11+00:00"
 | 
					            "time": "2023-07-15T19:42:19+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "pusher/pusher-php-server",
 | 
					            "name": "pusher/pusher-php-server",
 | 
				
			||||||
@ -15188,16 +15188,16 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "friendsofphp/php-cs-fixer",
 | 
					            "name": "friendsofphp/php-cs-fixer",
 | 
				
			||||||
            "version": "v3.21.1",
 | 
					            "version": "v3.22.0",
 | 
				
			||||||
            "source": {
 | 
					            "source": {
 | 
				
			||||||
                "type": "git",
 | 
					                "type": "git",
 | 
				
			||||||
                "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
 | 
					                "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
 | 
				
			||||||
                "reference": "229b55b3eae4729a8e2a321441ba40fcb3720b86"
 | 
					                "reference": "92b019f6c8d79aa26349d0db7671d37440dc0ff3"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "dist": {
 | 
					            "dist": {
 | 
				
			||||||
                "type": "zip",
 | 
					                "type": "zip",
 | 
				
			||||||
                "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/229b55b3eae4729a8e2a321441ba40fcb3720b86",
 | 
					                "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/92b019f6c8d79aa26349d0db7671d37440dc0ff3",
 | 
				
			||||||
                "reference": "229b55b3eae4729a8e2a321441ba40fcb3720b86",
 | 
					                "reference": "92b019f6c8d79aa26349d0db7671d37440dc0ff3",
 | 
				
			||||||
                "shasum": ""
 | 
					                "shasum": ""
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require": {
 | 
					            "require": {
 | 
				
			||||||
@ -15207,7 +15207,7 @@
 | 
				
			|||||||
                "doctrine/lexer": "^2 || ^3",
 | 
					                "doctrine/lexer": "^2 || ^3",
 | 
				
			||||||
                "ext-json": "*",
 | 
					                "ext-json": "*",
 | 
				
			||||||
                "ext-tokenizer": "*",
 | 
					                "ext-tokenizer": "*",
 | 
				
			||||||
                "php": "^8.0.1",
 | 
					                "php": "^7.4 || ^8.0",
 | 
				
			||||||
                "sebastian/diff": "^4.0 || ^5.0",
 | 
					                "sebastian/diff": "^4.0 || ^5.0",
 | 
				
			||||||
                "symfony/console": "^5.4 || ^6.0",
 | 
					                "symfony/console": "^5.4 || ^6.0",
 | 
				
			||||||
                "symfony/event-dispatcher": "^5.4 || ^6.0",
 | 
					                "symfony/event-dispatcher": "^5.4 || ^6.0",
 | 
				
			||||||
@ -15221,6 +15221,7 @@
 | 
				
			|||||||
                "symfony/stopwatch": "^5.4 || ^6.0"
 | 
					                "symfony/stopwatch": "^5.4 || ^6.0"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require-dev": {
 | 
					            "require-dev": {
 | 
				
			||||||
 | 
					                "facile-it/paraunit": "^1.3 || ^2.0",
 | 
				
			||||||
                "justinrainbow/json-schema": "^5.2",
 | 
					                "justinrainbow/json-schema": "^5.2",
 | 
				
			||||||
                "keradus/cli-executor": "^2.0",
 | 
					                "keradus/cli-executor": "^2.0",
 | 
				
			||||||
                "mikey179/vfsstream": "^1.6.11",
 | 
					                "mikey179/vfsstream": "^1.6.11",
 | 
				
			||||||
@ -15272,7 +15273,7 @@
 | 
				
			|||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "support": {
 | 
					            "support": {
 | 
				
			||||||
                "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
 | 
					                "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
 | 
				
			||||||
                "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.21.1"
 | 
					                "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.22.0"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "funding": [
 | 
					            "funding": [
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@ -15280,7 +15281,7 @@
 | 
				
			|||||||
                    "type": "github"
 | 
					                    "type": "github"
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "time": "2023-07-05T21:50:25+00:00"
 | 
					            "time": "2023-07-16T23:08:06+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "hamcrest/hamcrest-php",
 | 
					            "name": "hamcrest/hamcrest-php",
 | 
				
			||||||
@ -15460,37 +15461,33 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "mockery/mockery",
 | 
					            "name": "mockery/mockery",
 | 
				
			||||||
            "version": "1.6.2",
 | 
					            "version": "1.6.4",
 | 
				
			||||||
            "source": {
 | 
					            "source": {
 | 
				
			||||||
                "type": "git",
 | 
					                "type": "git",
 | 
				
			||||||
                "url": "https://github.com/mockery/mockery.git",
 | 
					                "url": "https://github.com/mockery/mockery.git",
 | 
				
			||||||
                "reference": "13a7fa2642c76c58fa2806ef7f565344c817a191"
 | 
					                "reference": "d1413755e26fe56a63455f7753221c86cbb88f66"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "dist": {
 | 
					            "dist": {
 | 
				
			||||||
                "type": "zip",
 | 
					                "type": "zip",
 | 
				
			||||||
                "url": "https://api.github.com/repos/mockery/mockery/zipball/13a7fa2642c76c58fa2806ef7f565344c817a191",
 | 
					                "url": "https://api.github.com/repos/mockery/mockery/zipball/d1413755e26fe56a63455f7753221c86cbb88f66",
 | 
				
			||||||
                "reference": "13a7fa2642c76c58fa2806ef7f565344c817a191",
 | 
					                "reference": "d1413755e26fe56a63455f7753221c86cbb88f66",
 | 
				
			||||||
                "shasum": ""
 | 
					                "shasum": ""
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require": {
 | 
					            "require": {
 | 
				
			||||||
                "hamcrest/hamcrest-php": "^2.0.1",
 | 
					                "hamcrest/hamcrest-php": "^2.0.1",
 | 
				
			||||||
                "lib-pcre": ">=7.0",
 | 
					                "lib-pcre": ">=7.0",
 | 
				
			||||||
                "php": "^7.4 || ^8.0"
 | 
					                "php": ">=7.4,<8.3"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "conflict": {
 | 
					            "conflict": {
 | 
				
			||||||
                "phpunit/phpunit": "<8.0"
 | 
					                "phpunit/phpunit": "<8.0"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require-dev": {
 | 
					            "require-dev": {
 | 
				
			||||||
                "phpunit/phpunit": "^8.5 || ^9.3",
 | 
					                "phpunit/phpunit": "^8.5 || ^9.3",
 | 
				
			||||||
                "psalm/plugin-phpunit": "^0.18",
 | 
					                "psalm/plugin-phpunit": "^0.18.4",
 | 
				
			||||||
                "vimeo/psalm": "^5.9"
 | 
					                "symplify/easy-coding-standard": "^11.5.0",
 | 
				
			||||||
 | 
					                "vimeo/psalm": "^5.13.1"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "type": "library",
 | 
					            "type": "library",
 | 
				
			||||||
            "extra": {
 | 
					 | 
				
			||||||
                "branch-alias": {
 | 
					 | 
				
			||||||
                    "dev-main": "1.6.x-dev"
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            "autoload": {
 | 
					            "autoload": {
 | 
				
			||||||
                "files": [
 | 
					                "files": [
 | 
				
			||||||
                    "library/helpers.php",
 | 
					                    "library/helpers.php",
 | 
				
			||||||
@ -15508,12 +15505,20 @@
 | 
				
			|||||||
                {
 | 
					                {
 | 
				
			||||||
                    "name": "Pádraic Brady",
 | 
					                    "name": "Pádraic Brady",
 | 
				
			||||||
                    "email": "padraic.brady@gmail.com",
 | 
					                    "email": "padraic.brady@gmail.com",
 | 
				
			||||||
                    "homepage": "http://blog.astrumfutura.com"
 | 
					                    "homepage": "https://github.com/padraic",
 | 
				
			||||||
 | 
					                    "role": "Author"
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    "name": "Dave Marshall",
 | 
					                    "name": "Dave Marshall",
 | 
				
			||||||
                    "email": "dave.marshall@atstsolutions.co.uk",
 | 
					                    "email": "dave.marshall@atstsolutions.co.uk",
 | 
				
			||||||
                    "homepage": "http://davedevelopment.co.uk"
 | 
					                    "homepage": "https://davedevelopment.co.uk",
 | 
				
			||||||
 | 
					                    "role": "Developer"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Nathanael Esayeas",
 | 
				
			||||||
 | 
					                    "email": "nathanael.esayeas@protonmail.com",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/ghostwriter",
 | 
				
			||||||
 | 
					                    "role": "Lead Developer"
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "description": "Mockery is a simple yet flexible PHP mock object framework",
 | 
					            "description": "Mockery is a simple yet flexible PHP mock object framework",
 | 
				
			||||||
@ -15531,10 +15536,13 @@
 | 
				
			|||||||
                "testing"
 | 
					                "testing"
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "support": {
 | 
					            "support": {
 | 
				
			||||||
 | 
					                "docs": "https://docs.mockery.io/",
 | 
				
			||||||
                "issues": "https://github.com/mockery/mockery/issues",
 | 
					                "issues": "https://github.com/mockery/mockery/issues",
 | 
				
			||||||
                "source": "https://github.com/mockery/mockery/tree/1.6.2"
 | 
					                "rss": "https://github.com/mockery/mockery/releases.atom",
 | 
				
			||||||
 | 
					                "security": "https://github.com/mockery/mockery/security/advisories",
 | 
				
			||||||
 | 
					                "source": "https://github.com/mockery/mockery"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "time": "2023-06-07T09:07:52+00:00"
 | 
					            "time": "2023-07-19T15:51:02+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "myclabs/deep-copy",
 | 
					            "name": "myclabs/deep-copy",
 | 
				
			||||||
@ -16140,16 +16148,16 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "phpstan/phpstan",
 | 
					            "name": "phpstan/phpstan",
 | 
				
			||||||
            "version": "1.10.25",
 | 
					            "version": "1.10.26",
 | 
				
			||||||
            "source": {
 | 
					            "source": {
 | 
				
			||||||
                "type": "git",
 | 
					                "type": "git",
 | 
				
			||||||
                "url": "https://github.com/phpstan/phpstan.git",
 | 
					                "url": "https://github.com/phpstan/phpstan.git",
 | 
				
			||||||
                "reference": "578f4e70d117f9a90699324c555922800ac38d8c"
 | 
					                "reference": "5d660cbb7e1b89253a47147ae44044f49832351f"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "dist": {
 | 
					            "dist": {
 | 
				
			||||||
                "type": "zip",
 | 
					                "type": "zip",
 | 
				
			||||||
                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/578f4e70d117f9a90699324c555922800ac38d8c",
 | 
					                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/5d660cbb7e1b89253a47147ae44044f49832351f",
 | 
				
			||||||
                "reference": "578f4e70d117f9a90699324c555922800ac38d8c",
 | 
					                "reference": "5d660cbb7e1b89253a47147ae44044f49832351f",
 | 
				
			||||||
                "shasum": ""
 | 
					                "shasum": ""
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "require": {
 | 
					            "require": {
 | 
				
			||||||
@ -16198,7 +16206,7 @@
 | 
				
			|||||||
                    "type": "tidelift"
 | 
					                    "type": "tidelift"
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "time": "2023-07-06T12:11:37+00:00"
 | 
					            "time": "2023-07-19T12:44:37+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "phpunit/php-code-coverage",
 | 
					            "name": "phpunit/php-code-coverage",
 | 
				
			||||||
 | 
				
			|||||||
@ -15,8 +15,8 @@ return [
 | 
				
			|||||||
    'require_https' => env('REQUIRE_HTTPS', true),
 | 
					    'require_https' => env('REQUIRE_HTTPS', true),
 | 
				
			||||||
    'app_url' => rtrim(env('APP_URL', ''), '/'),
 | 
					    'app_url' => rtrim(env('APP_URL', ''), '/'),
 | 
				
			||||||
    'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
 | 
					    'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
 | 
				
			||||||
    'app_version' => env('APP_VERSION','5.6.19'),
 | 
					    'app_version' => env('APP_VERSION','5.6.21'),
 | 
				
			||||||
    'app_tag' => env('APP_TAG','5.6.19'),
 | 
					    'app_tag' => env('APP_TAG','5.6.21'),
 | 
				
			||||||
    'minimum_client_version' => '5.0.16',
 | 
					    'minimum_client_version' => '5.0.16',
 | 
				
			||||||
    'terms_version' => '1.0.1',
 | 
					    'terms_version' => '1.0.1',
 | 
				
			||||||
    'api_secret' => env('API_SECRET', ''),
 | 
					    'api_secret' => env('API_SECRET', ''),
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Database\Migrations\Migration;
 | 
				
			||||||
 | 
					use Illuminate\Database\Schema\Blueprint;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Schema;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					return new class extends Migration
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Run the migrations.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function up()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Schema::table('tasks', function (Blueprint $table) {
 | 
				
			||||||
 | 
					            $table->date('calculated_start_date')->nullable();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Schema::table('webhooks', function (Blueprint $table){
 | 
				
			||||||
 | 
					            $table->text('target_url')->change();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Reverse the migrations.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function down()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Database\Migrations\Migration;
 | 
				
			||||||
 | 
					use Illuminate\Database\Schema\Blueprint;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Schema;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					return new class extends Migration
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Run the migrations.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function up()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $ir = \App\Models\Currency::where('code', 'IDR')->first();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if($ir){
 | 
				
			||||||
 | 
					            $ir->thousand_separator = '.';
 | 
				
			||||||
 | 
					            $ir->decimal_separator = ',';
 | 
				
			||||||
 | 
					            $ir->save();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $ld = \App\Models\Currency::find(115);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!$ld) {
 | 
				
			||||||
 | 
					            $ld = new \App\Models\Currency();
 | 
				
			||||||
 | 
					            $ld->id = 115;
 | 
				
			||||||
 | 
					            $ld->code = 'LYD';
 | 
				
			||||||
 | 
					            $ld->name = 'Libyan Dinar';
 | 
				
			||||||
 | 
					            $ld->symbol = 'LD';
 | 
				
			||||||
 | 
					            $ld->thousand_separator = ',';
 | 
				
			||||||
 | 
					            $ld->decimal_separator = '.';
 | 
				
			||||||
 | 
					            $ld->precision = 3;
 | 
				
			||||||
 | 
					            $ld->save();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Reverse the migrations.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function down()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -49,7 +49,7 @@ class CurrenciesSeeder extends Seeder
 | 
				
			|||||||
            ['id' => 24, 'name' => 'Bangladeshi Taka', 'code' => 'BDT', 'symbol' => 'Tk', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
					            ['id' => 24, 'name' => 'Bangladeshi Taka', 'code' => 'BDT', 'symbol' => 'Tk', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
				
			||||||
            ['id' => 25, 'name' => 'United Arab Emirates Dirham', 'code' => 'AED', 'symbol' => 'DH ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
					            ['id' => 25, 'name' => 'United Arab Emirates Dirham', 'code' => 'AED', 'symbol' => 'DH ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
				
			||||||
            ['id' => 26, 'name' => 'Hong Kong Dollar', 'code' => 'HKD', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
					            ['id' => 26, 'name' => 'Hong Kong Dollar', 'code' => 'HKD', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
				
			||||||
            ['id' => 27, 'name' => 'Indonesian Rupiah', 'code' => 'IDR', 'symbol' => 'Rp', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
					            ['id' => 27, 'name' => 'Indonesian Rupiah', 'code' => 'IDR', 'symbol' => 'Rp', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
 | 
				
			||||||
            ['id' => 28, 'name' => 'Mexican Peso', 'code' => 'MXN', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
					            ['id' => 28, 'name' => 'Mexican Peso', 'code' => 'MXN', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
				
			||||||
            ['id' => 29, 'name' => 'Egyptian Pound', 'code' => 'EGP', 'symbol' => 'E£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
					            ['id' => 29, 'name' => 'Egyptian Pound', 'code' => 'EGP', 'symbol' => 'E£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
				
			||||||
            ['id' => 30, 'name' => 'Colombian Peso', 'code' => 'COP', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
 | 
					            ['id' => 30, 'name' => 'Colombian Peso', 'code' => 'COP', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
 | 
				
			||||||
@ -136,6 +136,8 @@ class CurrenciesSeeder extends Seeder
 | 
				
			|||||||
            ['id' => 111, 'name' => 'Cuban Peso', 'code' => 'CUP', 'symbol' => '₱', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
					            ['id' => 111, 'name' => 'Cuban Peso', 'code' => 'CUP', 'symbol' => '₱', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
				
			||||||
            ['id' => 112, 'name' => 'Cayman Island Dollar', 'code' => 'KYD', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
					            ['id' => 112, 'name' => 'Cayman Island Dollar', 'code' => 'KYD', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
				
			||||||
            ['id' => 113, 'name' => 'Swazi lilangeni', 'code' => 'SZL', 'symbol' => 'E', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
					            ['id' => 113, 'name' => 'Swazi lilangeni', 'code' => 'SZL', 'symbol' => 'E', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
				
			||||||
 | 
					            ['id' => 114, 'name' => 'BZ Dollar', 'code' => 'BZD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
				
			||||||
 | 
					            ['id' => 115, 'name' => 'Libyan Dinar', 'code' => 'LYD', 'symbol' => 'LD', 'precision' => '3', 'thousand_separator' => ',', 'decimal_separator' => '.'],
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($currencies as $currency) {
 | 
					        foreach ($currencies as $currency) {
 | 
				
			||||||
 | 
				
			|||||||
@ -4,9 +4,9 @@ includes:
 | 
				
			|||||||
parameters:
 | 
					parameters:
 | 
				
			||||||
    treatPhpDocTypesAsCertain: false
 | 
					    treatPhpDocTypesAsCertain: false
 | 
				
			||||||
    parallel:
 | 
					    parallel:
 | 
				
			||||||
        jobSize: 5
 | 
					        jobSize: 10
 | 
				
			||||||
        maximumNumberOfProcesses: 16
 | 
					        maximumNumberOfProcesses: 1
 | 
				
			||||||
        processTimeout: 600.0
 | 
					        processTimeout: 60.0
 | 
				
			||||||
    ignoreErrors:
 | 
					    ignoreErrors:
 | 
				
			||||||
        - '#Call to an undefined method .*badMethod\(\)#'
 | 
					        - '#Call to an undefined method .*badMethod\(\)#'
 | 
				
			||||||
        - '#Call to an undefined method Illuminate\Database\Eloquent\Builder::exclude#'
 | 
					        - '#Call to an undefined method Illuminate\Database\Eloquent\Builder::exclude#'
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								public/flutter_service_worker.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								public/flutter_service_worker.js
									
									
									
									
										vendored
									
									
								
							@ -3,10 +3,10 @@ const MANIFEST = 'flutter-app-manifest';
 | 
				
			|||||||
const TEMP = 'flutter-temp-cache';
 | 
					const TEMP = 'flutter-temp-cache';
 | 
				
			||||||
const CACHE_NAME = 'flutter-app-cache';
 | 
					const CACHE_NAME = 'flutter-app-cache';
 | 
				
			||||||
const RESOURCES = {
 | 
					const RESOURCES = {
 | 
				
			||||||
"/": "0aa10ee6dcb142946702cadae9812704",
 | 
					"/": "dad42af82faab711765c59e9a7596b11",
 | 
				
			||||||
"flutter.js": "a85fcf6324d3c4d3ae3be1ae4931e9c5",
 | 
					"flutter.js": "a85fcf6324d3c4d3ae3be1ae4931e9c5",
 | 
				
			||||||
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
 | 
					"favicon.png": "dca91c54388f52eded692718d5a98b8b",
 | 
				
			||||||
"main.dart.js": "23a2e1cbb7cb043fd5ef1e51de367bb6",
 | 
					"main.dart.js": "b11ed73562dd3c3db2c346bc14702036",
 | 
				
			||||||
"version.json": "bf49df736fed3f74ade0dbaebf08de11",
 | 
					"version.json": "bf49df736fed3f74ade0dbaebf08de11",
 | 
				
			||||||
"canvaskit/profiling/canvaskit.js": "c21852696bc1cc82e8894d851c01921a",
 | 
					"canvaskit/profiling/canvaskit.js": "c21852696bc1cc82e8894d851c01921a",
 | 
				
			||||||
"canvaskit/profiling/canvaskit.wasm": "371bc4e204443b0d5e774d64a046eb99",
 | 
					"canvaskit/profiling/canvaskit.wasm": "371bc4e204443b0d5e774d64a046eb99",
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										353472
									
								
								public/main.dart.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										353472
									
								
								public/main.dart.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							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