mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-02 22:57:33 -05:00 
			
		
		
		
	
						commit
						ee00defdc6
					
				@ -1 +1 @@
 | 
				
			|||||||
5.1.6
 | 
					5.1.7
 | 
				
			||||||
@ -39,10 +39,10 @@ class PaymentWasEmailedAndFailed
 | 
				
			|||||||
     * PaymentWasEmailedAndFailed constructor.
 | 
					     * PaymentWasEmailedAndFailed constructor.
 | 
				
			||||||
     * @param Payment $payment
 | 
					     * @param Payment $payment
 | 
				
			||||||
     * @param $company
 | 
					     * @param $company
 | 
				
			||||||
     * @param array $errors
 | 
					     * @param string $errors
 | 
				
			||||||
     * @param array $event_vars
 | 
					     * @param array $event_vars
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function __construct(Payment $payment, Company $company, array $errors, array $event_vars)
 | 
					    public function __construct(Payment $payment, Company $company, string $errors, array $event_vars)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->payment = $payment;
 | 
					        $this->payment = $payment;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -18,11 +18,13 @@ class ContactRegisterController extends Controller
 | 
				
			|||||||
        $this->middleware(['guest', 'contact.register']);
 | 
					        $this->middleware(['guest', 'contact.register']);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function showRegisterForm(string $company_key)
 | 
					    public function showRegisterForm(string $company_key = '')
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $company = Company::where('company_key', $company_key)->firstOrFail();
 | 
					        $key = request()->has('key') ? request('key') : $company_key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return render('auth.register', compact(['company']));
 | 
					        $company = Company::where('company_key', $key)->firstOrFail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return render('auth.register', ['company' => $company]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function register(RegisterRequest $request)
 | 
					    public function register(RegisterRequest $request)
 | 
				
			||||||
 | 
				
			|||||||
@ -76,10 +76,10 @@ class DocumentController extends Controller
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $options->setSendHttpHeaders(true);
 | 
					        $options->setSendHttpHeaders(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $zip = new ZipStream('files.zip', $options);
 | 
					        $zip = new ZipStream(now() . '-documents.zip', $options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($documents as $document) {
 | 
					        foreach ($documents as $document) {
 | 
				
			||||||
            $zip->addFileFromPath(basename($document->filePath()), TempFile::path($document->filePath()));
 | 
					            $zip->addFileFromPath(basename($document->diskPath()), TempFile::path($document->diskPath()));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $zip->finish();
 | 
					        $zip->finish();
 | 
				
			||||||
 | 
				
			|||||||
@ -14,19 +14,20 @@ namespace App\Http\Controllers;
 | 
				
			|||||||
use App\Http\Requests\Import\ImportRequest;
 | 
					use App\Http\Requests\Import\ImportRequest;
 | 
				
			||||||
use App\Http\Requests\Import\PreImportRequest;
 | 
					use App\Http\Requests\Import\PreImportRequest;
 | 
				
			||||||
use App\Jobs\Import\CSVImport;
 | 
					use App\Jobs\Import\CSVImport;
 | 
				
			||||||
 | 
					use Illuminate\Http\UploadedFile;
 | 
				
			||||||
use Illuminate\Support\Facades\Cache;
 | 
					use Illuminate\Support\Facades\Cache;
 | 
				
			||||||
use Illuminate\Support\Str;
 | 
					use Illuminate\Support\Str;
 | 
				
			||||||
use League\Csv\Reader;
 | 
					use League\Csv\Reader;
 | 
				
			||||||
use League\Csv\Statement;
 | 
					use League\Csv\Statement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ImportController extends Controller
 | 
					class ImportController extends Controller {
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Store a newly created resource in storage.
 | 
						 * Store a newly created resource in storage.
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
     * @param StoreImportRequest $request
 | 
						 * @param PreImportRequest $request
 | 
				
			||||||
     * @return Response
 | 
						 *
 | 
				
			||||||
 | 
						 * @return \Illuminate\Http\JsonResponse
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * @OA\Post(
 | 
						 * @OA\Post(
 | 
				
			||||||
	 *      path="/api/v1/preimport",
 | 
						 *      path="/api/v1/preimport",
 | 
				
			||||||
@ -69,42 +70,61 @@ class ImportController extends Controller
 | 
				
			|||||||
	 *       ),
 | 
						 *       ),
 | 
				
			||||||
	 *     )
 | 
						 *     )
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
    public function preimport(PreImportRequest $request)
 | 
						public function preimport( PreImportRequest $request ) {
 | 
				
			||||||
    {
 | 
							// Create a reference
 | 
				
			||||||
        //create a reference
 | 
					 | 
				
			||||||
		$hash = Str::random( 32 );
 | 
							$hash = Str::random( 32 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //store the csv in cache with an expiry of 10 minutes
 | 
					 | 
				
			||||||
        Cache::put($hash, base64_encode(file_get_contents($request->file('file')->getPathname())), 3600);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //parse CSV
 | 
					 | 
				
			||||||
        $csv_array = $this->getCsvData(file_get_contents($request->file('file')->getPathname()));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $class_map = $this->getEntityMap($request->input('entity_type'));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		$data = [
 | 
							$data = [
 | 
				
			||||||
			'hash'     => $hash,
 | 
								'hash'     => $hash,
 | 
				
			||||||
            'available' => $class_map::importable(),
 | 
								'mappings' => [],
 | 
				
			||||||
            'headers' => array_slice($csv_array, 0, 2)
 | 
					 | 
				
			||||||
		];
 | 
							];
 | 
				
			||||||
 | 
							/** @var UploadedFile $file */
 | 
				
			||||||
 | 
							foreach ( $request->files->get( 'files' ) as $entityType => $file ) {
 | 
				
			||||||
 | 
								$contents = file_get_contents( $file->getPathname() );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Store the csv in cache with an expiry of 10 minutes
 | 
				
			||||||
 | 
								Cache::put( $hash . '-' . $entityType, base64_encode( $contents ), 3600 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Parse CSV
 | 
				
			||||||
 | 
								$csv_array = $this->getCsvData( $contents );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								$class_map = $this->getEntityMap( $entityType );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								$data['mappings'][ $entityType ] = [
 | 
				
			||||||
 | 
									'available' => $class_map::importable(),
 | 
				
			||||||
 | 
									'headers'   => array_slice( $csv_array, 0, 2 ),
 | 
				
			||||||
 | 
								];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return response()->json( $data );
 | 
							return response()->json( $data );
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function import(ImportRequest $request)
 | 
						public function import( ImportRequest $request ) {
 | 
				
			||||||
    {
 | 
							$data = $request->all();
 | 
				
			||||||
        CSVImport::dispatch($request->all(), auth()->user()->company());
 | 
					
 | 
				
			||||||
 | 
							if ( empty( $data['hash'] ) ) {
 | 
				
			||||||
 | 
								// Create a reference
 | 
				
			||||||
 | 
								$data['hash'] = $hash = Str::random( 32 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/** @var UploadedFile $file */
 | 
				
			||||||
 | 
								foreach ( $request->files->get( 'files' ) as $entityType => $file ) {
 | 
				
			||||||
 | 
									$contents = file_get_contents( $file->getPathname() );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Store the csv in cache with an expiry of 10 minutes
 | 
				
			||||||
 | 
									Cache::put( $hash . '-' . $entityType, base64_encode( $contents ), 3600 );
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							CSVImport::dispatch( $data, auth()->user()->company() );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return response()->json( [ 'message' => ctrans( 'texts.import_started' ) ], 200 );
 | 
							return response()->json( [ 'message' => ctrans( 'texts.import_started' ) ], 200 );
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function getEntityMap($entity_type)
 | 
						private function getEntityMap( $entity_type ) {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
		return sprintf( 'App\\Import\\Definitions\%sMap', ucfirst( $entity_type ) );
 | 
							return sprintf( 'App\\Import\\Definitions\%sMap', ucfirst( $entity_type ) );
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function getCsvData($csvfile)
 | 
						private function getCsvData( $csvfile ) {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
		if ( ! ini_get( 'auto_detect_line_endings' ) ) {
 | 
							if ( ! ini_get( 'auto_detect_line_endings' ) ) {
 | 
				
			||||||
			ini_set( 'auto_detect_line_endings', '1' );
 | 
								ini_set( 'auto_detect_line_endings', '1' );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -123,7 +143,7 @@ class ImportController extends Controller
 | 
				
			|||||||
                if (strstr($firstCell, (string)config('ninja.app_name'))) {
 | 
					                if (strstr($firstCell, (string)config('ninja.app_name'))) {
 | 
				
			||||||
					array_shift( $data ); // Invoice Ninja...
 | 
										array_shift( $data ); // Invoice Ninja...
 | 
				
			||||||
					array_shift( $data ); // <blank line>
 | 
										array_shift( $data ); // <blank line>
 | 
				
			||||||
                    array_shift($data); // Enitty Type Header
 | 
										array_shift( $data ); // Entity Type Header
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -532,7 +532,7 @@ class InvoiceController extends BaseController
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ZipInvoices::dispatch($invoices, $invoices->first()->company, auth()->user()->email);
 | 
					            ZipInvoices::dispatch($invoices, $invoices->first()->company, auth()->user());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return response()->json(['message' => ctrans('texts.sent_message')], 200);
 | 
					            return response()->json(['message' => ctrans('texts.sent_message')], 200);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,8 @@ namespace App\Http\Controllers;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use App\Console\Commands\ImportMigrations;
 | 
					use App\Console\Commands\ImportMigrations;
 | 
				
			||||||
use App\DataMapper\CompanySettings;
 | 
					use App\DataMapper\CompanySettings;
 | 
				
			||||||
use App\Jobs\Mail\MailRouter;
 | 
					use App\Jobs\Mail\NinjaMailerJob;
 | 
				
			||||||
 | 
					use App\Jobs\Mail\NinjaMailerObject;
 | 
				
			||||||
use App\Jobs\Util\StartMigration;
 | 
					use App\Jobs\Util\StartMigration;
 | 
				
			||||||
use App\Mail\ExistingMigration;
 | 
					use App\Mail\ExistingMigration;
 | 
				
			||||||
use App\Models\Company;
 | 
					use App\Models\Company;
 | 
				
			||||||
@ -248,7 +249,13 @@ class MigrationController extends BaseController
 | 
				
			|||||||
            if ($checks['existing_company'] == true && $checks['force'] == false) {
 | 
					            if ($checks['existing_company'] == true && $checks['force'] == false) {
 | 
				
			||||||
                nlog('Migrating: Existing company without force. (CASE_01)');
 | 
					                nlog('Migrating: Existing company without force. (CASE_01)');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                MailRouter::dispatch(new ExistingMigration(), $existing_company, $user);
 | 
					                $nmo = new NinjaMailerObject;
 | 
				
			||||||
 | 
					                $nmo->mailable = new ExistingMigration();
 | 
				
			||||||
 | 
					                $nmo->company = $existing_company;
 | 
				
			||||||
 | 
					                $nmo->settings = $existing_company->settings;
 | 
				
			||||||
 | 
					                $nmo->to_user = $user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                NinjaMailerJob::dispatch($nmo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return response()->json([
 | 
					                return response()->json([
 | 
				
			||||||
                    '_id' => Str::uuid(),
 | 
					                    '_id' => Str::uuid(),
 | 
				
			||||||
 | 
				
			|||||||
@ -524,7 +524,7 @@ class QuoteController extends BaseController
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ZipInvoices::dispatch($quotes, $quotes->first()->company, auth()->user()->email);
 | 
					            ZipInvoices::dispatch($quotes, $quotes->first()->company, auth()->user());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return response()->json(['message' => ctrans('texts.sent_message')], 200);
 | 
					            return response()->json(['message' => ctrans('texts.sent_message')], 200);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -369,18 +369,21 @@ class UserController extends BaseController
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function update(UpdateUserRequest $request, User $user)
 | 
					    public function update(UpdateUserRequest $request, User $user)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $old_email = $user->email;
 | 
					
 | 
				
			||||||
        $old_company_user = $user->company_user;
 | 
					        $old_company_user = $user->company_user;
 | 
				
			||||||
        $old_user = $user;
 | 
					        $old_user = json_encode($user);
 | 
				
			||||||
 | 
					        $old_user_email = $user->getOriginal('email');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $new_email = $request->input('email');
 | 
					        $new_email = $request->input('email');
 | 
				
			||||||
 | 
					        $new_user = $this->user_repo->save($request->all(), $user);
 | 
				
			||||||
 | 
					        $new_user = $user->fresh();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $user = $this->user_repo->save($request->all(), $user);
 | 
					 | 
				
			||||||
        $user = $user->fresh();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($old_email != $new_email) {
 | 
					        nlog($old_user);
 | 
				
			||||||
            UserEmailChanged::dispatch($new_email, $old_email, auth()->user()->company());
 | 
					
 | 
				
			||||||
        }
 | 
					        if ($old_user_email != $new_email) 
 | 
				
			||||||
 | 
					            UserEmailChanged::dispatch($new_user, json_decode($old_user), auth()->user()->company());
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if(
 | 
					        if(
 | 
				
			||||||
            strcasecmp($old_company_user->permissions, $user->company_user->permissions) != 0 ||
 | 
					            strcasecmp($old_company_user->permissions, $user->company_user->permissions) != 0 ||
 | 
				
			||||||
 | 
				
			|||||||
@ -25,38 +25,15 @@ class DocumentsTable extends Component
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public $per_page = 10;
 | 
					    public $per_page = 10;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public $status = [
 | 
					 | 
				
			||||||
        'resources',
 | 
					 | 
				
			||||||
    ];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function mount($client)
 | 
					    public function mount($client)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->client = $client;
 | 
					        $this->client = $client;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function statusChange($status)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (in_array($status, $this->status)) {
 | 
					 | 
				
			||||||
            return $this->status = array_diff($this->status, [$status]);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        array_push($this->status, $status);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function render()
 | 
					    public function render()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $query = $this->client->documents();
 | 
					        $query = $this->client
 | 
				
			||||||
 | 
					            ->documents()
 | 
				
			||||||
        if (in_array('resources', $this->status) && ! in_array('client', $this->status)) {
 | 
					 | 
				
			||||||
            $query = $query->where('documentable_type', '!=', Client::class);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (in_array('client', $this->status) && ! in_array('resources', $this->status)) {
 | 
					 | 
				
			||||||
            $query = $query->where('documentable_type', Client::class);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $query = $query
 | 
					 | 
				
			||||||
            ->where('is_public', true)
 | 
					 | 
				
			||||||
            ->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc')
 | 
					            ->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc')
 | 
				
			||||||
            ->paginate($this->per_page);
 | 
					            ->paginate($this->per_page);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Http\Middleware;
 | 
					namespace App\Http\Middleware;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Models\Account;
 | 
				
			||||||
use App\Models\Company;
 | 
					use App\Models\Company;
 | 
				
			||||||
 | 
					use App\Utils\Ninja;
 | 
				
			||||||
use Closure;
 | 
					use Closure;
 | 
				
			||||||
use Illuminate\Http\Request;
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -17,29 +19,39 @@ class ContactRegister
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function handle($request, Closure $next)
 | 
					    public function handle($request, Closure $next)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        /*
 | 
					        // Resolving based on subdomain. Used in version 5 hosted platform.
 | 
				
			||||||
         * Notes:
 | 
					 | 
				
			||||||
         *
 | 
					 | 
				
			||||||
         * 1. If request supports subdomain (for hosted) check domain and continue request.
 | 
					 | 
				
			||||||
         * 2. If request doesn't support subdomain and doesn' have company_key, abort
 | 
					 | 
				
			||||||
         * 3. firstOrFail() will abort with 404 if company with company_key wasn't found.
 | 
					 | 
				
			||||||
         * 4. Abort if setting isn't enabled.
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($request->subdomain) {
 | 
					        if ($request->subdomain) {
 | 
				
			||||||
            $company = Company::where('subdomain', $request->subdomain)->firstOrFail();
 | 
					            $company = Company::where('subdomain', $request->subdomain)->firstOrFail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            abort_unless($company->getSetting('enable_client_registration'), 404);
 | 
					            abort_unless($company->getSetting('enable_client_registration'), 404);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $request->merge(['key' => $company->company_key]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return $next($request);
 | 
					            return $next($request);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        abort_unless($request->company_key, 404);
 | 
					        // For self-hosted platforms with multiple companies, resolving is done using company key
 | 
				
			||||||
 | 
					        // if it doesn't resolve using a domain.
 | 
				
			||||||
 | 
					        if ($request->route()->parameter('company_key') && Ninja::isSelfHost()) {
 | 
				
			||||||
            $company = Company::where('company_key', $request->company_key)->firstOrFail();
 | 
					            $company = Company::where('company_key', $request->company_key)->firstOrFail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            abort_unless($company->client_can_register, 404);
 | 
					            abort_unless($company->client_can_register, 404);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return $next($request);
 | 
					            return $next($request);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // As a fallback for self-hosted, it will use default company in the system
 | 
				
			||||||
 | 
					        // if key isn't provided in the url.
 | 
				
			||||||
 | 
					        if (!$request->route()->parameter('company_key') && Ninja::isSelfHost()) {
 | 
				
			||||||
 | 
					            $company = Account::first()->default_company;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            abort_unless($company->client_can_register, 404);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $request->merge(['key' => $company->company_key]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return $next($request);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return abort(404);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -27,7 +27,8 @@ class ShowDocumentRequest extends FormRequest
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function authorize()
 | 
					    public function authorize()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return auth()->user('contact')->client->id == $this->document->documentable_id;
 | 
					        return auth()->user('contact')->client->id == $this->document->documentable_id
 | 
				
			||||||
 | 
					            || $this->document->documentable->client_id == auth()->user('contact')->client->id;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -28,10 +28,12 @@ class ImportRequest extends Request
 | 
				
			|||||||
    public function rules()
 | 
					    public function rules()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            'hash' => 'required|string',
 | 
								'import_type' => 'required',
 | 
				
			||||||
            'entity_type' => 'required|string',
 | 
					            'files' => 'required_without:hash|array|min:1|max:6',
 | 
				
			||||||
            'column_map' => 'required|array',
 | 
					            'hash' => 'nullable|string',
 | 
				
			||||||
            'skip_header' => 'required|boolean'
 | 
					            'column_map' => 'required_with:hash|array',
 | 
				
			||||||
 | 
					            'skip_header' => 'required_with:hash|boolean',
 | 
				
			||||||
 | 
								'files.*' => 'file|mimes:csv,txt',
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -28,8 +28,9 @@ class PreImportRequest extends Request
 | 
				
			|||||||
    public function rules()
 | 
					    public function rules()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            'file' => 'required|file|mimes:csv,txt',
 | 
								'files.*' => 'file|mimes:csv,txt',
 | 
				
			||||||
            'entity_type' => 'required',
 | 
					            'files' => 'required|array|min:1|max:6',
 | 
				
			||||||
 | 
					            'import_type' => 'required',
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -57,6 +57,7 @@ class PortalComposer
 | 
				
			|||||||
        $data['client'] = auth()->user()->client;
 | 
					        $data['client'] = auth()->user()->client;
 | 
				
			||||||
        $data['settings'] = $this->settings;
 | 
					        $data['settings'] = $this->settings;
 | 
				
			||||||
        $data['currencies'] = TranslationHelper::getCurrencies();
 | 
					        $data['currencies'] = TranslationHelper::getCurrencies();
 | 
				
			||||||
 | 
					        $data['contact'] = auth('contact')->user();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $data['multiple_contacts'] = session()->get('multiple_contacts');
 | 
					        $data['multiple_contacts'] = session()->get('multiple_contacts');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -69,8 +70,8 @@ class PortalComposer
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        //@todo wire this back in when we are happy with dashboard.
 | 
					        //@todo wire this back in when we are happy with dashboard.
 | 
				
			||||||
        // if($this->settings->enable_client_portal_dashboard == TRUE)
 | 
					        // if($this->settings->enable_client_portal_dashboard == TRUE)
 | 
				
			||||||
        //     $data[] = [ 'title' => ctrans('texts.dashboard'), 'url' => 'client.dashboard', 'icon' => 'activity'];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//        $data[] = [ 'title' => ctrans('texts.dashboard'), 'url' => 'client.dashboard', 'icon' => 'activity'];
 | 
				
			||||||
        $data[] = ['title' => ctrans('texts.invoices'), 'url' => 'client.invoices.index', 'icon' => 'file-text'];
 | 
					        $data[] = ['title' => ctrans('texts.invoices'), 'url' => 'client.invoices.index', 'icon' => 'file-text'];
 | 
				
			||||||
        $data[] = ['title' => ctrans('texts.recurring_invoices'), 'url' => 'client.recurring_invoices.index', 'icon' => 'file'];
 | 
					        $data[] = ['title' => ctrans('texts.recurring_invoices'), 'url' => 'client.recurring_invoices.index', 'icon' => 'file'];
 | 
				
			||||||
        $data[] = ['title' => ctrans('texts.payments'), 'url' => 'client.payments.index', 'icon' => 'credit-card'];
 | 
					        $data[] = ['title' => ctrans('texts.payments'), 'url' => 'client.payments.index', 'icon' => 'credit-card'];
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * client Ninja (https://clientninja.com).
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @link https://github.com/clientninja/clientninja source repository
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
					 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @license https://opensource.org/licenses/AAL
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										51
									
								
								app/Import/Definitions/ExpenseMap.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								app/Import/Definitions/ExpenseMap.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * client Ninja (https://clientninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/clientninja/clientninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Import\Definitions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ExpenseMap
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static function importable()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            0 => 'expense.vendor',
 | 
				
			||||||
 | 
					            1 => 'expense.client',
 | 
				
			||||||
 | 
					            2 => 'expense.project',
 | 
				
			||||||
 | 
					            3 => 'expense.category',
 | 
				
			||||||
 | 
					            4 => 'expense.amount',
 | 
				
			||||||
 | 
					            5 => 'expense.currency',
 | 
				
			||||||
 | 
					            6 => 'expense.date',
 | 
				
			||||||
 | 
					            7 => 'expense.payment_type',
 | 
				
			||||||
 | 
					            8 => 'expense.payment_date',
 | 
				
			||||||
 | 
					            9 => 'expense.transaction_reference',
 | 
				
			||||||
 | 
					            10 => 'expense.public_notes',
 | 
				
			||||||
 | 
					            11 => 'expense.private_notes',
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static function import_keys()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            0 => 'texts.vendor',
 | 
				
			||||||
 | 
										 1 => 'texts.client',
 | 
				
			||||||
 | 
										 2 => 'texts.project',
 | 
				
			||||||
 | 
										 3 => 'texts.category',
 | 
				
			||||||
 | 
										 4 => 'texts.amount',
 | 
				
			||||||
 | 
										 5 => 'texts.currency',
 | 
				
			||||||
 | 
										 6 => 'texts.date',
 | 
				
			||||||
 | 
					           7 => 'texts.payment_type',
 | 
				
			||||||
 | 
					           8 => 'texts.payment_date',
 | 
				
			||||||
 | 
					           9 => 'texts.transaction_reference',
 | 
				
			||||||
 | 
										 10 => 'texts.public_notes',
 | 
				
			||||||
 | 
										 11 => 'texts.private_notes',
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -26,50 +26,51 @@ class InvoiceMap
 | 
				
			|||||||
            7 => 'invoice.date',
 | 
					            7 => 'invoice.date',
 | 
				
			||||||
            8 => 'invoice.due_date',
 | 
					            8 => 'invoice.due_date',
 | 
				
			||||||
            9 => 'invoice.terms',
 | 
					            9 => 'invoice.terms',
 | 
				
			||||||
            10 => 'invoice.public_notes',
 | 
								10 => 'invoice.status',
 | 
				
			||||||
            11 => 'invoice.is_sent',
 | 
					            11 => 'invoice.public_notes',
 | 
				
			||||||
            12 => 'invoice.private_notes',
 | 
					            12 => 'invoice.is_sent',
 | 
				
			||||||
            13 => 'invoice.uses_inclusive_taxes',
 | 
					            13 => 'invoice.private_notes',
 | 
				
			||||||
            14 => 'invoice.tax_name1',
 | 
					            14 => 'invoice.uses_inclusive_taxes',
 | 
				
			||||||
            15 => 'invoice.tax_rate1',
 | 
					            15 => 'invoice.tax_name1',
 | 
				
			||||||
            16 => 'invoice.tax_name2',
 | 
					            16 => 'invoice.tax_rate1',
 | 
				
			||||||
            17 => 'invoice.tax_rate2',
 | 
					            17 => 'invoice.tax_name2',
 | 
				
			||||||
            18 => 'invoice.tax_name3',
 | 
					            18 => 'invoice.tax_rate2',
 | 
				
			||||||
            19 => 'invoice.tax_rate3',
 | 
					            19 => 'invoice.tax_name3',
 | 
				
			||||||
            20 => 'invoice.is_amount_discount',
 | 
					            20 => 'invoice.tax_rate3',
 | 
				
			||||||
            21 => 'invoice.footer',
 | 
					            21 => 'invoice.is_amount_discount',
 | 
				
			||||||
            22 => 'invoice.partial',
 | 
					            22 => 'invoice.footer',
 | 
				
			||||||
            23 => 'invoice.partial_due_date',
 | 
					            23 => 'invoice.partial',
 | 
				
			||||||
            24 => 'invoice.custom_value1',
 | 
					            24 => 'invoice.partial_due_date',
 | 
				
			||||||
            25 => 'invoice.custom_value2',
 | 
					            25 => 'invoice.custom_value1',
 | 
				
			||||||
            26 => 'invoice.custom_value3',
 | 
					            26 => 'invoice.custom_value2',
 | 
				
			||||||
            27 => 'invoice.custom_value4',
 | 
					            27 => 'invoice.custom_value3',
 | 
				
			||||||
            28 => 'invoice.custom_surcharge1',
 | 
					            28 => 'invoice.custom_value4',
 | 
				
			||||||
            29 => 'invoice.custom_surcharge2',
 | 
					            29 => 'invoice.custom_surcharge1',
 | 
				
			||||||
            30 => 'invoice.custom_surcharge3',
 | 
					            30 => 'invoice.custom_surcharge2',
 | 
				
			||||||
            31 => 'invoice.custom_surcharge4',
 | 
					            31 => 'invoice.custom_surcharge3',
 | 
				
			||||||
            32 => 'invoice.exchange_rate',
 | 
					            32 => 'invoice.custom_surcharge4',
 | 
				
			||||||
            33 => 'payment.date',
 | 
					            33 => 'invoice.exchange_rate',
 | 
				
			||||||
            34 => 'payment.amount',
 | 
					            34 => 'payment.date',
 | 
				
			||||||
            35 => 'payment.transaction_reference',
 | 
					            35 => 'payment.amount',
 | 
				
			||||||
            36 => 'item.quantity',
 | 
					            36 => 'payment.transaction_reference',
 | 
				
			||||||
            37 => 'item.cost',
 | 
					            37 => 'item.quantity',
 | 
				
			||||||
            38 => 'item.product_key',
 | 
					            38 => 'item.cost',
 | 
				
			||||||
            39 => 'item.notes',
 | 
					            39 => 'item.product_key',
 | 
				
			||||||
            40 => 'item.discount',
 | 
					            40 => 'item.notes',
 | 
				
			||||||
            41 => 'item.is_amount_discount',
 | 
					            41 => 'item.discount',
 | 
				
			||||||
            42 => 'item.tax_name1',
 | 
					            42 => 'item.is_amount_discount',
 | 
				
			||||||
            43 => 'item.tax_rate1',
 | 
					            43 => 'item.tax_name1',
 | 
				
			||||||
            44 => 'item.tax_name2',
 | 
					            44 => 'item.tax_rate1',
 | 
				
			||||||
            45 => 'item.tax_rate2',
 | 
					            45 => 'item.tax_name2',
 | 
				
			||||||
            46 => 'item.tax_name3',
 | 
					            46 => 'item.tax_rate2',
 | 
				
			||||||
            47 => 'item.tax_rate3',
 | 
					            47 => 'item.tax_name3',
 | 
				
			||||||
            48 => 'item.custom_value1',
 | 
					            48 => 'item.tax_rate3',
 | 
				
			||||||
            49 => 'item.custom_value2',
 | 
					            49 => 'item.custom_value1',
 | 
				
			||||||
            50 => 'item.custom_value3',
 | 
					            50 => 'item.custom_value2',
 | 
				
			||||||
            51 => 'item.custom_value4',
 | 
					            51 => 'item.custom_value3',
 | 
				
			||||||
            52 => 'item.type_id',
 | 
					            52 => 'item.custom_value4',
 | 
				
			||||||
            53 => 'client.email',
 | 
					            53 => 'item.type_id',
 | 
				
			||||||
 | 
					            54 => 'client.email',
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -86,50 +87,51 @@ class InvoiceMap
 | 
				
			|||||||
            7 => 'texts.date',
 | 
					            7 => 'texts.date',
 | 
				
			||||||
            8 => 'texts.due_date',
 | 
					            8 => 'texts.due_date',
 | 
				
			||||||
            9 => 'texts.terms',
 | 
					            9 => 'texts.terms',
 | 
				
			||||||
            10 => 'texts.public_notes',
 | 
								10 => 'texts.status',
 | 
				
			||||||
            11 => 'texts.sent',
 | 
					            11 => 'texts.public_notes',
 | 
				
			||||||
            12 => 'texts.private_notes',
 | 
					            12 => 'texts.sent',
 | 
				
			||||||
            13 => 'texts.uses_inclusive_taxes',
 | 
					            13 => 'texts.private_notes',
 | 
				
			||||||
            14 => 'texts.tax_name',
 | 
					            14 => 'texts.uses_inclusive_taxes',
 | 
				
			||||||
            15 => 'texts.tax_rate',
 | 
					            15 => 'texts.tax_name',
 | 
				
			||||||
            16 => 'texts.tax_name',
 | 
					            16 => 'texts.tax_rate',
 | 
				
			||||||
            17 => 'texts.tax_rate',
 | 
					            17 => 'texts.tax_name',
 | 
				
			||||||
            18 => 'texts.tax_name',
 | 
					            18 => 'texts.tax_rate',
 | 
				
			||||||
            19 => 'texts.tax_rate',
 | 
					            19 => 'texts.tax_name',
 | 
				
			||||||
            20 => 'texts.is_amount_discount',
 | 
					            20 => 'texts.tax_rate',
 | 
				
			||||||
            21 => 'texts.footer',
 | 
					            21 => 'texts.is_amount_discount',
 | 
				
			||||||
            22 => 'texts.partial',
 | 
					            22 => 'texts.footer',
 | 
				
			||||||
            23 => 'texts.partial_due_date',
 | 
					            23 => 'texts.partial',
 | 
				
			||||||
            24 => 'texts.custom_value1',
 | 
					            24 => 'texts.partial_due_date',
 | 
				
			||||||
            25 => 'texts.custom_value2',
 | 
					            25 => 'texts.custom_value1',
 | 
				
			||||||
            26 => 'texts.custom_value3',
 | 
					            26 => 'texts.custom_value2',
 | 
				
			||||||
            27 => 'texts.custom_value4',
 | 
					            27 => 'texts.custom_value3',
 | 
				
			||||||
            28 => 'texts.surcharge',
 | 
					            28 => 'texts.custom_value4',
 | 
				
			||||||
            29 => 'texts.surcharge',
 | 
					            29 => 'texts.surcharge',
 | 
				
			||||||
            30 => 'texts.surcharge',
 | 
					            30 => 'texts.surcharge',
 | 
				
			||||||
            31 => 'texts.surcharge',
 | 
					            31 => 'texts.surcharge',
 | 
				
			||||||
            32 => 'texts.exchange_rate',
 | 
					            32 => 'texts.surcharge',
 | 
				
			||||||
            33 => 'texts.payment_date',
 | 
					            33 => 'texts.exchange_rate',
 | 
				
			||||||
            34 => 'texts.payment_amount',
 | 
					            34 => 'texts.payment_date',
 | 
				
			||||||
            35 => 'texts.transaction_reference',
 | 
					            35 => 'texts.payment_amount',
 | 
				
			||||||
            36 => 'texts.quantity',
 | 
					            36 => 'texts.transaction_reference',
 | 
				
			||||||
            37 => 'texts.cost',
 | 
					            37 => 'texts.quantity',
 | 
				
			||||||
            38 => 'texts.product_key',
 | 
					            38 => 'texts.cost',
 | 
				
			||||||
            39 => 'texts.notes',
 | 
					            39 => 'texts.product_key',
 | 
				
			||||||
            40 => 'texts.discount',
 | 
					            40 => 'texts.notes',
 | 
				
			||||||
            41 => 'texts.is_amount_discount',
 | 
					            41 => 'texts.discount',
 | 
				
			||||||
            42 => 'texts.tax_name',
 | 
					            42 => 'texts.is_amount_discount',
 | 
				
			||||||
            43 => 'texts.tax_rate',
 | 
					            43 => 'texts.tax_name',
 | 
				
			||||||
            44 => 'texts.tax_name',
 | 
					            44 => 'texts.tax_rate',
 | 
				
			||||||
            45 => 'texts.tax_rate',
 | 
					            45 => 'texts.tax_name',
 | 
				
			||||||
            46 => 'texts.tax_name',
 | 
					            46 => 'texts.tax_rate',
 | 
				
			||||||
            47 => 'texts.tax_rate',
 | 
					            47 => 'texts.tax_name',
 | 
				
			||||||
            48 => 'texts.custom_value',
 | 
					            48 => 'texts.tax_rate',
 | 
				
			||||||
            49 => 'texts.custom_value',
 | 
					            49 => 'texts.custom_value',
 | 
				
			||||||
            50 => 'texts.custom_value',
 | 
					            50 => 'texts.custom_value',
 | 
				
			||||||
            51 => 'texts.custom_value',
 | 
					            51 => 'texts.custom_value',
 | 
				
			||||||
            52 => 'texts.type',
 | 
					            52 => 'texts.custom_value',
 | 
				
			||||||
            53 => 'texts.email',
 | 
					            53 => 'texts.type',
 | 
				
			||||||
 | 
					            54 => 'texts.email',
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * client Ninja (https://clientninja.com).
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @link https://github.com/clientninja/clientninja source repository
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
					 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @license https://opensource.org/licenses/AAL
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * client Ninja (https://clientninja.com).
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @link https://github.com/clientninja/clientninja source repository
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
					 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @license https://opensource.org/licenses/AAL
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										61
									
								
								app/Import/Definitions/VendorMap.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								app/Import/Definitions/VendorMap.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * client Ninja (https://clientninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/clientninja/clientninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Import\Definitions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class VendorMap
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public static function importable()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return [
 | 
				
			||||||
 | 
								0 => 'vendor.name',
 | 
				
			||||||
 | 
								1 => 'vendor.phone',
 | 
				
			||||||
 | 
								2 => 'vendor.id_number',
 | 
				
			||||||
 | 
								3 => 'vendor.vat_number',
 | 
				
			||||||
 | 
								4 => 'vendor.website',
 | 
				
			||||||
 | 
								5 => 'vendor.first_name',
 | 
				
			||||||
 | 
								6 => 'vendor.last_name',
 | 
				
			||||||
 | 
								7 => 'vendor.email',
 | 
				
			||||||
 | 
								8 => 'vendor.currency_id',
 | 
				
			||||||
 | 
								9 => 'vendor.public_notes',
 | 
				
			||||||
 | 
								10 => 'vendor.private_notes',
 | 
				
			||||||
 | 
								11 => 'vendor.address1',
 | 
				
			||||||
 | 
								12 => 'vendor.address2',
 | 
				
			||||||
 | 
								13 => 'vendor.city',
 | 
				
			||||||
 | 
								14 => 'vendor.state',
 | 
				
			||||||
 | 
								15 => 'vendor.postal_code',
 | 
				
			||||||
 | 
								16 => 'vendor.country_id',
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static function import_keys()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return [
 | 
				
			||||||
 | 
								0 => 'texts.name',
 | 
				
			||||||
 | 
								1 => 'texts.phone',
 | 
				
			||||||
 | 
								2 => 'texts.id_number',
 | 
				
			||||||
 | 
								3 => 'texts.vat_number',
 | 
				
			||||||
 | 
								4 => 'texts.website',
 | 
				
			||||||
 | 
								5 => 'texts.first_name',
 | 
				
			||||||
 | 
								6 => 'texts.last_name',
 | 
				
			||||||
 | 
								7 => 'texts.email',
 | 
				
			||||||
 | 
								8 => 'texts.currency',
 | 
				
			||||||
 | 
								9 => 'texts.public_notes',
 | 
				
			||||||
 | 
								10 => 'texts.private_notes',
 | 
				
			||||||
 | 
								11 => 'texts.address1',
 | 
				
			||||||
 | 
								12 => 'texts.address2',
 | 
				
			||||||
 | 
								13 => 'texts.city',
 | 
				
			||||||
 | 
								14 => 'texts.state',
 | 
				
			||||||
 | 
								15 => 'texts.postal_code',
 | 
				
			||||||
 | 
								16 => 'texts.country',
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										6
									
								
								app/Import/ImportException.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								app/Import/ImportException.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					namespace App\Import;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ImportException extends \Exception{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * client Ninja (https://clientninja.com).
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @link https://github.com/clientninja/clientninja source repository
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
					 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @license https://opensource.org/licenses/AAL
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -53,23 +53,13 @@ class BaseTransformer
 | 
				
			|||||||
        return (isset($data[$field]) && $data[$field]) ? $data[$field] : '1';
 | 
					        return (isset($data[$field]) && $data[$field]) ? $data[$field] : '1';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function getCurrencyByCode($data)
 | 
					    public function getCurrencyByCode( $data, $key = 'client.currency_id' ) {
 | 
				
			||||||
    {
 | 
							$code = array_key_exists( $key, $data ) ? $data[ $key ] : false;
 | 
				
			||||||
        $code = array_key_exists('client.currency_id', $data) ? $data['client.currency_id'] : false;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($code) {
 | 
							return $this->maps['currencies'][ $code ] ?? $this->maps['company']->settings->currency_id;
 | 
				
			||||||
            $currency = $this->maps['currencies']->where('code', $code)->first();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if ($currency) {
 | 
					 | 
				
			||||||
                return $currency->id;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this->maps['company']->settings->currency_id;
 | 
					    public function getClient($client_name, $client_email) {
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function getClient($client_name, $client_email)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
		$clients = $this->maps['company']->clients;
 | 
							$clients = $this->maps['company']->clients;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$clients = $clients->where( 'name', $client_name );
 | 
							$clients = $clients->where( 'name', $client_name );
 | 
				
			||||||
@ -78,13 +68,14 @@ class BaseTransformer
 | 
				
			|||||||
			return $clients->first()->id;
 | 
								return $clients->first()->id;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( ! empty( $client_email ) ) {
 | 
				
			||||||
			$contacts = ClientContact::where( 'company_id', $this->maps['company']->id )
 | 
								$contacts = ClientContact::where( 'company_id', $this->maps['company']->id )
 | 
				
			||||||
									 ->where( 'email', $client_email );
 | 
														 ->where( 'email', $client_email );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if ( $contacts->count() >= 1 ) {
 | 
								if ( $contacts->count() >= 1 ) {
 | 
				
			||||||
				return $contacts->first()->client_id;
 | 
									return $contacts->first()->client_id;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return null;
 | 
							return null;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -101,7 +92,7 @@ class BaseTransformer
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $name = trim(strtolower($name));
 | 
					        $name = trim(strtolower($name));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return isset($this->maps[ENTITY_CLIENT][$name]);
 | 
							return isset( $this->maps['client'][ $name ] );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -113,7 +104,7 @@ class BaseTransformer
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $name = trim(strtolower($name));
 | 
					        $name = trim(strtolower($name));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return isset($this->maps[ENTITY_VENDOR][$name]);
 | 
							return isset( $this->maps['vendor'][ $name ] );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -126,7 +117,7 @@ class BaseTransformer
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $key = trim(strtolower($key));
 | 
					        $key = trim(strtolower($key));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return isset($this->maps[ENTITY_PRODUCT][$key]);
 | 
							return isset( $this->maps['product'][ $key ] );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -167,7 +158,7 @@ class BaseTransformer
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $name = strtolower(trim($name));
 | 
					        $name = strtolower(trim($name));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return isset($this->maps[ENTITY_CLIENT][$name]) ? $this->maps[ENTITY_CLIENT][$name] : null;
 | 
							return isset( $this->maps['client'][ $name ] ) ? $this->maps['client'][ $name ] : null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -322,7 +313,7 @@ class BaseTransformer
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function getInvoiceNumber($number)
 | 
					    public function getInvoiceNumber($number)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $number ? str_pad(trim($number), 4, '0', STR_PAD_LEFT) : null;
 | 
							return $number ? ltrim( trim( $number ), '0' ) : null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -334,7 +325,8 @@ class BaseTransformer
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $invoiceNumber = $this->getInvoiceNumber($invoiceNumber);
 | 
					        $invoiceNumber = $this->getInvoiceNumber($invoiceNumber);
 | 
				
			||||||
        $invoiceNumber = strtolower($invoiceNumber);
 | 
					        $invoiceNumber = strtolower($invoiceNumber);
 | 
				
			||||||
        return isset($this->maps[ENTITY_INVOICE][$invoiceNumber]) ? $this->maps[ENTITY_INVOICE][$invoiceNumber] : null;
 | 
					
 | 
				
			||||||
 | 
							return isset( $this->maps['invoice'][ $invoiceNumber ] ) ? $this->maps['invoice'][ $invoiceNumber ] : null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -346,7 +338,8 @@ class BaseTransformer
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $invoiceNumber = $this->getInvoiceNumber($invoiceNumber);
 | 
					        $invoiceNumber = $this->getInvoiceNumber($invoiceNumber);
 | 
				
			||||||
        $invoiceNumber = strtolower($invoiceNumber);
 | 
					        $invoiceNumber = strtolower($invoiceNumber);
 | 
				
			||||||
        return isset($this->maps['invoices'][$invoiceNumber]) ? $this->maps['invoices'][$invoiceNumber]->public_id : null;
 | 
					
 | 
				
			||||||
 | 
							return isset( $this->maps['invoice'][ $invoiceNumber ] ) ? $this->maps['invoices'][ $invoiceNumber ]->public_id : null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -359,7 +352,7 @@ class BaseTransformer
 | 
				
			|||||||
        $invoiceNumber = $this->getInvoiceNumber($invoiceNumber);
 | 
					        $invoiceNumber = $this->getInvoiceNumber($invoiceNumber);
 | 
				
			||||||
        $invoiceNumber = strtolower($invoiceNumber);
 | 
					        $invoiceNumber = strtolower($invoiceNumber);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return isset($this->maps[ENTITY_INVOICE][$invoiceNumber]);
 | 
							return $this->maps['invoice'][ $invoiceNumber ] ?? null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -372,7 +365,7 @@ class BaseTransformer
 | 
				
			|||||||
        $invoiceNumber = $this->getInvoiceNumber($invoiceNumber);
 | 
					        $invoiceNumber = $this->getInvoiceNumber($invoiceNumber);
 | 
				
			||||||
        $invoiceNumber = strtolower($invoiceNumber);
 | 
					        $invoiceNumber = strtolower($invoiceNumber);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return isset($this->maps[ENTITY_INVOICE.'_'.ENTITY_CLIENT][$invoiceNumber]) ? $this->maps[ENTITY_INVOICE.'_'.ENTITY_CLIENT][$invoiceNumber] : null;
 | 
							return $this->maps['invoice_client'][ $invoiceNumber ] ?? null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -384,7 +377,7 @@ class BaseTransformer
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $name = strtolower(trim($name));
 | 
					        $name = strtolower(trim($name));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return isset($this->maps[ENTITY_VENDOR][$name]) ? $this->maps[ENTITY_VENDOR][$name] : null;
 | 
							return $this->maps['vendor'][ $name ] ?? null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
@ -392,10 +385,31 @@ class BaseTransformer
 | 
				
			|||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * @return null
 | 
						 * @return null
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
    public function getExpenseCategoryId($name)
 | 
						public function getExpenseCategoryId( $name ) {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
		$name = strtolower( trim( $name ) );
 | 
							$name = strtolower( trim( $name ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return isset($this->maps[ENTITY_EXPENSE_CATEGORY][$name]) ? $this->maps[ENTITY_EXPENSE_CATEGORY][$name] : null;
 | 
							return $this->maps['expense_category'][ $name ] ?? null;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param $name
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return null
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function getProjectId( $name ) {
 | 
				
			||||||
 | 
							$name = strtolower( trim( $name ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return $this->maps['project'][ $name ] ?? null;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param $name
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return null
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function getPaymentTypeId( $name ) {
 | 
				
			||||||
 | 
							$name = strtolower( trim( $name ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return $this->maps['payment_type'][ $name ] ?? null;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * client Ninja (https://clientninja.com).
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @link https://github.com/clientninja/clientninja source repository
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
					 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @license https://opensource.org/licenses/AAL
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										79
									
								
								app/Import/Transformers/Csv/ClientTransformer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								app/Import/Transformers/Csv/ClientTransformer.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,79 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * client Ninja (https://clientninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/clientninja/clientninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Import\Transformers\Csv;
 | 
				
			||||||
 | 
					use App\Import\ImportException;
 | 
				
			||||||
 | 
					use App\Import\Transformers\BaseTransformer;
 | 
				
			||||||
 | 
					use Illuminate\Support\Str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class ClientTransformer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class ClientTransformer extends BaseTransformer
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
						 * @param $data
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return array|bool
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					    public function transform($data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (isset($data->name) && $this->hasClient($data->name)) {
 | 
				
			||||||
 | 
					            throw new ImportException('Client already exists');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $settings = new \stdClass;
 | 
				
			||||||
 | 
							$settings->currency_id = (string)$this->getCurrencyByCode($data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return [
 | 
				
			||||||
 | 
								'company_id'           => $this->maps['company']->id,
 | 
				
			||||||
 | 
								'name'                 => $this->getString( $data, 'client.name' ),
 | 
				
			||||||
 | 
								'work_phone'           => $this->getString( $data, 'client.phone' ),
 | 
				
			||||||
 | 
								'address1'             => $this->getString( $data, 'client.address1' ),
 | 
				
			||||||
 | 
								'address2'             => $this->getString( $data, 'client.address2' ),
 | 
				
			||||||
 | 
								'city'                 => $this->getString( $data, 'client.city' ),
 | 
				
			||||||
 | 
								'state'                => $this->getString( $data, 'client.state' ),
 | 
				
			||||||
 | 
								'shipping_address1'    => $this->getString( $data, 'client.shipping_address1' ),
 | 
				
			||||||
 | 
								'shipping_address2'    => $this->getString( $data, 'client.shipping_address2' ),
 | 
				
			||||||
 | 
								'shipping_city'        => $this->getString( $data, 'client.shipping_city' ),
 | 
				
			||||||
 | 
								'shipping_state'       => $this->getString( $data, 'client.shipping_state' ),
 | 
				
			||||||
 | 
								'shipping_postal_code' => $this->getString( $data, 'client.shipping_postal_code' ),
 | 
				
			||||||
 | 
								'public_notes'         => $this->getString( $data, 'client.public_notes' ),
 | 
				
			||||||
 | 
								'private_notes'        => $this->getString( $data, 'client.private_notes' ),
 | 
				
			||||||
 | 
								'website'              => $this->getString( $data, 'client.website' ),
 | 
				
			||||||
 | 
								'vat_number'           => $this->getString( $data, 'client.vat_number' ),
 | 
				
			||||||
 | 
								'id_number'            => $this->getString( $data, 'client.id_number' ),
 | 
				
			||||||
 | 
								'custom_value1'        => $this->getString( $data, 'client.custom1' ),
 | 
				
			||||||
 | 
								'custom_value2'        => $this->getString( $data, 'client.custom2' ),
 | 
				
			||||||
 | 
								'custom_value3'        => $this->getString( $data, 'client.custom3' ),
 | 
				
			||||||
 | 
								'custom_value4'        => $this->getString( $data, 'client.custom4' ),
 | 
				
			||||||
 | 
								'balance'              => preg_replace( '/[^0-9,.]+/', '', $this->getFloat( $data, 'client.balance' ) ),
 | 
				
			||||||
 | 
								'paid_to_date'         => preg_replace( '/[^0-9,.]+/', '', $this->getFloat( $data, 'client.paid_to_date' ) ),
 | 
				
			||||||
 | 
								'credit_balance'       => 0,
 | 
				
			||||||
 | 
								'settings'             => $settings,
 | 
				
			||||||
 | 
								'client_hash'          => Str::random( 40 ),
 | 
				
			||||||
 | 
								'contacts'             => [
 | 
				
			||||||
 | 
									[
 | 
				
			||||||
 | 
										'first_name'    => $this->getString( $data, 'contact.first_name' ),
 | 
				
			||||||
 | 
										'last_name'     => $this->getString( $data, 'contact.last_name' ),
 | 
				
			||||||
 | 
										'email'         => $this->getString( $data, 'contact.email' ),
 | 
				
			||||||
 | 
										'phone'         => $this->getString( $data, 'contact.phone' ),
 | 
				
			||||||
 | 
										'custom_value1' => $this->getString( $data, 'contact.custom1' ),
 | 
				
			||||||
 | 
										'custom_value2' => $this->getString( $data, 'contact.custom2' ),
 | 
				
			||||||
 | 
										'custom_value3' => $this->getString( $data, 'contact.custom3' ),
 | 
				
			||||||
 | 
										'custom_value4' => $this->getString( $data, 'contact.custom4' ),
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								],
 | 
				
			||||||
 | 
								'country_id'           => isset( $data['client.country'] ) ? $this->getCountryId( $data['client.country']) : null,
 | 
				
			||||||
 | 
								'shipping_country_id'  => isset($data['client.shipping_country'] ) ? $this->getCountryId( $data['client.shipping_country']  ) : null,
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										36
									
								
								app/Import/Transformers/Csv/ExpenseTransformer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/Import/Transformers/Csv/ExpenseTransformer.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Import\Transformers\Csv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Import\Transformers\BaseTransformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class InvoiceTransformer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class ExpenseTransformer extends BaseTransformer {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param $data
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return bool|array
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function transform( $data ) {
 | 
				
			||||||
 | 
							$clientId = isset( $data['expense.client'] ) ? $this->getClientId( $data['expense.client'] ) : null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return [
 | 
				
			||||||
 | 
								'company_id'            => $this->maps['company']->id,
 | 
				
			||||||
 | 
								'amount'                => $this->getFloat( $data, 'expense.amount' ),
 | 
				
			||||||
 | 
								'currency_id'           => $this->getCurrencyByCode( $data, 'expense.currency_id' ),
 | 
				
			||||||
 | 
								'vendor_id'             => isset( $data['expense.vendor'] ) ? $this->getVendorId( $data['expense.vendor'] ) : null,
 | 
				
			||||||
 | 
								'client_id'             => isset( $data['expense.client'] ) ? $this->getClientId( $data['expense.client'] ) : null,
 | 
				
			||||||
 | 
								'expense_date'          => isset( $data['expense.date'] ) ? date( 'Y-m-d', strtotime( $data['expense.date'] ) ) : null,
 | 
				
			||||||
 | 
								'public_notes'          => $this->getString( $data, 'expense.public_notes' ),
 | 
				
			||||||
 | 
								'private_notes'         => $this->getString( $data, 'expense.private_notes' ),
 | 
				
			||||||
 | 
								'expense_category_id'   => isset( $data['expense.category'] ) ? $this->getExpenseCategoryId( $data['expense.category'] ) : null,
 | 
				
			||||||
 | 
								'project_id'            => isset( $data['expense.project'] ) ? $this->getProjectId( $data['expense.project'] ) : null,
 | 
				
			||||||
 | 
								'payment_type_id'       => isset( $data['expense.payment_type'] ) ? $this->getPaymentTypeId( $data['expense.payment_type'] ) : null,
 | 
				
			||||||
 | 
								'payment_date'          => isset( $data['expense.payment_date'] ) ? date( 'Y-m-d', strtotime( $data['expense.payment_date'] ) ) : null,
 | 
				
			||||||
 | 
								'transaction_reference' => $this->getString( $data, 'expense.transaction_reference' ),
 | 
				
			||||||
 | 
								'should_be_invoiced'    => $clientId ? true : false,
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										131
									
								
								app/Import/Transformers/Csv/InvoiceTransformer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								app/Import/Transformers/Csv/InvoiceTransformer.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,131 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * client Ninja (https://clientninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/clientninja/clientninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Import\Transformers\Csv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Import\ImportException;
 | 
				
			||||||
 | 
					use App\Import\Transformers\BaseTransformer;
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class InvoiceTransformer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class InvoiceTransformer extends BaseTransformer {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param $data
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return bool|array
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function transform( $line_items_data ) {
 | 
				
			||||||
 | 
							$invoice_data = reset( $line_items_data );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( $this->hasInvoice( $invoice_data['invoice.number'] ) ) {
 | 
				
			||||||
 | 
								throw new ImportException( 'Invoice number already exists' );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$invoiceStatusMap = [
 | 
				
			||||||
 | 
								'sent'  => Invoice::STATUS_SENT,
 | 
				
			||||||
 | 
								'draft' => Invoice::STATUS_DRAFT,
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$transformed = [
 | 
				
			||||||
 | 
								'company_id'        => $this->maps['company']->id,
 | 
				
			||||||
 | 
								'number'            => $this->getString( $invoice_data, 'invoice.number' ),
 | 
				
			||||||
 | 
								'user_id'           => $this->getString( $invoice_data, 'invoice.user_id' ),
 | 
				
			||||||
 | 
								'amount'            => $amount = $this->getFloat( $invoice_data, 'invoice.amount' ),
 | 
				
			||||||
 | 
								'balance'           => isset( $invoice_data['invoice.balance'] ) ? $this->getFloat( $invoice_data, 'invoice.balance' ) : $amount,
 | 
				
			||||||
 | 
								'client_id'         => $this->getClient( $this->getString( $invoice_data, 'client.name' ), $this->getString( $invoice_data, 'client.email' ) ),
 | 
				
			||||||
 | 
								'discount'          => $this->getFloat( $invoice_data, 'invoice.discount' ),
 | 
				
			||||||
 | 
								'po_number'         => $this->getString( $invoice_data, 'invoice.po_number' ),
 | 
				
			||||||
 | 
								'date'              => isset( $invoice_data['invoice.date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['invoice.date'] ) ) : null,
 | 
				
			||||||
 | 
								'due_date'          => isset( $invoice_data['invoice.due_date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['invoice.due_date'] ) ) : null,
 | 
				
			||||||
 | 
								'terms'             => $this->getString( $invoice_data, 'invoice.terms' ),
 | 
				
			||||||
 | 
								'public_notes'      => $this->getString( $invoice_data, 'invoice.public_notes' ),
 | 
				
			||||||
 | 
								'is_sent'           => $this->getString( $invoice_data, 'invoice.is_sent' ),
 | 
				
			||||||
 | 
								'private_notes'     => $this->getString( $invoice_data, 'invoice.private_notes' ),
 | 
				
			||||||
 | 
								'tax_name1'         => $this->getString( $invoice_data, 'invoice.tax_name1' ),
 | 
				
			||||||
 | 
								'tax_rate1'         => $this->getFloat( $invoice_data, 'invoice.tax_rate1' ),
 | 
				
			||||||
 | 
								'tax_name2'         => $this->getString( $invoice_data, 'invoice.tax_name2' ),
 | 
				
			||||||
 | 
								'tax_rate2'         => $this->getFloat( $invoice_data, 'invoice.tax_rate2' ),
 | 
				
			||||||
 | 
								'tax_name3'         => $this->getString( $invoice_data, 'invoice.tax_name3' ),
 | 
				
			||||||
 | 
								'tax_rate3'         => $this->getFloat( $invoice_data, 'invoice.tax_rate3' ),
 | 
				
			||||||
 | 
								'custom_value1'     => $this->getString( $invoice_data, 'invoice.custom_value1' ),
 | 
				
			||||||
 | 
								'custom_value2'     => $this->getString( $invoice_data, 'invoice.custom_value2' ),
 | 
				
			||||||
 | 
								'custom_value3'     => $this->getString( $invoice_data, 'invoice.custom_value3' ),
 | 
				
			||||||
 | 
								'custom_value4'     => $this->getString( $invoice_data, 'invoice.custom_value4' ),
 | 
				
			||||||
 | 
								'footer'            => $this->getString( $invoice_data, 'invoice.footer' ),
 | 
				
			||||||
 | 
								'partial'           => $this->getFloat( $invoice_data, 'invoice.partial' ),
 | 
				
			||||||
 | 
								'partial_due_date'  => $this->getString( $invoice_data, 'invoice.partial_due_date' ),
 | 
				
			||||||
 | 
								'custom_surcharge1' => $this->getString( $invoice_data, 'invoice.custom_surcharge1' ),
 | 
				
			||||||
 | 
								'custom_surcharge2' => $this->getString( $invoice_data, 'invoice.custom_surcharge2' ),
 | 
				
			||||||
 | 
								'custom_surcharge3' => $this->getString( $invoice_data, 'invoice.custom_surcharge3' ),
 | 
				
			||||||
 | 
								'custom_surcharge4' => $this->getString( $invoice_data, 'invoice.custom_surcharge4' ),
 | 
				
			||||||
 | 
								'exchange_rate'     => $this->getString( $invoice_data, 'invoice.exchange_rate' ),
 | 
				
			||||||
 | 
								'status_id'         => $invoiceStatusMap[ $status =
 | 
				
			||||||
 | 
										strtolower( $this->getString( $invoice_data, 'invoice.status' ) ) ] ??
 | 
				
			||||||
 | 
									Invoice::STATUS_SENT,
 | 
				
			||||||
 | 
								'viewed'            => $status === 'viewed',
 | 
				
			||||||
 | 
								'archived'          => $status === 'archived',
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( isset( $invoice_data['payment.amount'] ) ) {
 | 
				
			||||||
 | 
								$transformed['payments'] = [
 | 
				
			||||||
 | 
									[
 | 
				
			||||||
 | 
										'date'                  => isset( $invoice_data['payment.date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['payment.date'] ) ) : date( 'y-m-d' ),
 | 
				
			||||||
 | 
										'transaction_reference' => $this->getString( $invoice_data, 'payment.transaction_reference' ),
 | 
				
			||||||
 | 
										'amount'                => $this->getFloat( $invoice_data, 'payment.amount' ),
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								];
 | 
				
			||||||
 | 
							} elseif ( $status === 'paid' ) {
 | 
				
			||||||
 | 
								$transformed['payments'] = [
 | 
				
			||||||
 | 
									[
 | 
				
			||||||
 | 
										'date'                  => isset( $invoice_data['payment.date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['payment.date'] ) ) : date( 'y-m-d' ),
 | 
				
			||||||
 | 
										'transaction_reference' => $this->getString( $invoice_data, 'payment.transaction_reference' ),
 | 
				
			||||||
 | 
										'amount'                => $this->getFloat( $invoice_data, 'invoice.amount' ),
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								];
 | 
				
			||||||
 | 
							} elseif ( isset( $transformed['amount'] ) && isset( $transformed['balance'] ) ) {
 | 
				
			||||||
 | 
								$transformed['payments'] = [
 | 
				
			||||||
 | 
									[
 | 
				
			||||||
 | 
										'date'                  => isset( $invoice_data['payment.date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['payment.date'] ) ) : date( 'y-m-d' ),
 | 
				
			||||||
 | 
										'transaction_reference' => $this->getString( $invoice_data, 'payment.transaction_reference' ),
 | 
				
			||||||
 | 
										'amount'                => $transformed['amount'] - $transformed['balance'],
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$line_items = [];
 | 
				
			||||||
 | 
							foreach ( $line_items_data as $record ) {
 | 
				
			||||||
 | 
								$line_items[] = [
 | 
				
			||||||
 | 
									'quantity'           => $this->getFloat( $record, 'item.quantity' ),
 | 
				
			||||||
 | 
									'cost'               => $this->getFloat( $record, 'item.cost' ),
 | 
				
			||||||
 | 
									'product_key'        => $this->getString( $record, 'item.product_key' ),
 | 
				
			||||||
 | 
									'notes'              => $this->getString( $record, 'item.notes' ),
 | 
				
			||||||
 | 
									'discount'           => $this->getFloat( $record, 'item.discount' ),
 | 
				
			||||||
 | 
									'is_amount_discount' => filter_var( $this->getString( $record, 'item.is_amount_discount' ), FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ),
 | 
				
			||||||
 | 
									'tax_name1'          => $this->getString( $record, 'item.tax_name1' ),
 | 
				
			||||||
 | 
									'tax_rate1'          => $this->getFloat( $record, 'item.tax_rate1' ),
 | 
				
			||||||
 | 
									'tax_name2'          => $this->getString( $record, 'item.tax_name2' ),
 | 
				
			||||||
 | 
									'tax_rate2'          => $this->getFloat( $record, 'item.tax_rate2' ),
 | 
				
			||||||
 | 
									'tax_name3'          => $this->getString( $record, 'item.tax_name3' ),
 | 
				
			||||||
 | 
									'tax_rate3'          => $this->getFloat( $record, 'item.tax_rate3' ),
 | 
				
			||||||
 | 
									'custom_value1'      => $this->getString( $record, 'item.custom_value1' ),
 | 
				
			||||||
 | 
									'custom_value2'      => $this->getString( $record, 'item.custom_value2' ),
 | 
				
			||||||
 | 
									'custom_value3'      => $this->getString( $record, 'item.custom_value3' ),
 | 
				
			||||||
 | 
									'custom_value4'      => $this->getString( $record, 'item.custom_value4' ),
 | 
				
			||||||
 | 
									'type_id'            => $this->getInvoiceTypeId( $record, 'item.type_id' ),
 | 
				
			||||||
 | 
								];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							$transformed['line_items'] = $line_items;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return $transformed;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										64
									
								
								app/Import/Transformers/Csv/PaymentTransformer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								app/Import/Transformers/Csv/PaymentTransformer.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * client Ninja (https://clientninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/clientninja/clientninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Import\Transformers\Csv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Import\ImportException;
 | 
				
			||||||
 | 
					use App\Import\Transformers\BaseTransformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class PaymentTransformer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class PaymentTransformer extends BaseTransformer {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param $data
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return array
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function transform( $data ) {
 | 
				
			||||||
 | 
							$client_id =
 | 
				
			||||||
 | 
								$this->getClient( $this->getString( $data, 'payment.client_id' ), $this->getString( $data, 'payment.client_id' ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( empty( $client_id ) ) {
 | 
				
			||||||
 | 
								throw new ImportException( 'Could not find client.' );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$transformed = [
 | 
				
			||||||
 | 
								'company_id'            => $this->maps['company']->id,
 | 
				
			||||||
 | 
								'number'                => $this->getString( $data, 'payment.number' ),
 | 
				
			||||||
 | 
								'user_id'               => $this->getString( $data, 'payment.user_id' ),
 | 
				
			||||||
 | 
								'amount'                => $this->getFloat( $data, 'payment.amount' ),
 | 
				
			||||||
 | 
								'refunded'              => $this->getFloat( $data, 'payment.refunded' ),
 | 
				
			||||||
 | 
								'applied'               => $this->getFloat( $data, 'payment.applied' ),
 | 
				
			||||||
 | 
								'transaction_reference' => $this->getString( $data, 'payment.transaction_reference ' ),
 | 
				
			||||||
 | 
								'date'                  => $this->getString( $data, 'payment.date' ),
 | 
				
			||||||
 | 
								'private_notes'         => $this->getString( $data, 'payment.private_notes' ),
 | 
				
			||||||
 | 
								'custom_value1'         => $this->getString( $data, 'payment.custom_value1' ),
 | 
				
			||||||
 | 
								'custom_value2'         => $this->getString( $data, 'payment.custom_value2' ),
 | 
				
			||||||
 | 
								'custom_value3'         => $this->getString( $data, 'payment.custom_value3' ),
 | 
				
			||||||
 | 
								'custom_value4'         => $this->getString( $data, 'payment.custom_value4' ),
 | 
				
			||||||
 | 
								'client_id'             => $client_id,
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( isset( $data['payment.invoice_number'] ) &&
 | 
				
			||||||
 | 
								$invoice_id = $this->getInvoiceId( $data['payment.invoice_number'] ) ) {
 | 
				
			||||||
 | 
								$transformed['invoices'] = [
 | 
				
			||||||
 | 
									[
 | 
				
			||||||
 | 
										'invoice_id' => $invoice_id,
 | 
				
			||||||
 | 
										'amount'     => $transformed['amount'] ?? null,
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return $transformed;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,16 +1,16 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * client Ninja (https://clientninja.com).
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @link https://github.com/clientninja/clientninja source repository
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
					 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @license https://opensource.org/licenses/AAL
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace App\Import\Transformers;
 | 
					namespace App\Import\Transformers\Csv;
 | 
				
			||||||
 | 
					use App\Import\Transformers\BaseTransformer;
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Class ProductTransformer.
 | 
					 * Class ProductTransformer.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -19,7 +19,7 @@ class ProductTransformer extends BaseTransformer
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @param $data
 | 
					     * @param $data
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return bool|Item
 | 
					     * @return array
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function transform($data)
 | 
					    public function transform($data)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
							
								
								
									
										47
									
								
								app/Import/Transformers/Csv/VendorTransformer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								app/Import/Transformers/Csv/VendorTransformer.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Import\Transformers\Csv;
 | 
				
			||||||
 | 
					use App\Import\ImportException;
 | 
				
			||||||
 | 
					use App\Import\Transformers\BaseTransformer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class VendorTransformer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class VendorTransformer extends BaseTransformer {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param $data
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return array|bool
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function transform( $data ) {
 | 
				
			||||||
 | 
							if ( isset( $data->name ) && $this->hasVendor( $data->name ) ) {
 | 
				
			||||||
 | 
								throw new ImportException('Vendor already exists');
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return [
 | 
				
			||||||
 | 
								'company_id' => $this->maps['company']->id,
 | 
				
			||||||
 | 
								'name'            => $this->getString( $data, 'vendor.name' ),
 | 
				
			||||||
 | 
								'phone'           => $this->getString( $data, 'vendor.phone' ),
 | 
				
			||||||
 | 
								'id_number'       => $this->getString( $data, 'vendor.id_number' ),
 | 
				
			||||||
 | 
								'vat_number'      => $this->getString( $data, 'vendor.vat_number' ),
 | 
				
			||||||
 | 
								'website'         => $this->getString( $data, 'vendor.website' ),
 | 
				
			||||||
 | 
								'currency_id'     => $this->getCurrencyByCode( $data, 'vendor.currency_id' ),
 | 
				
			||||||
 | 
								'public_notes'    => $this->getString( $data, 'vendor.public_notes' ),
 | 
				
			||||||
 | 
								'private_notes'   => $this->getString( $data, 'vendor.private_notes' ),
 | 
				
			||||||
 | 
								'address1'        => $this->getString( $data, 'vendor.address1' ),
 | 
				
			||||||
 | 
								'address2'        => $this->getString( $data, 'vendor.address2' ),
 | 
				
			||||||
 | 
								'city'            => $this->getString( $data, 'vendor.city' ),
 | 
				
			||||||
 | 
								'state'           => $this->getString( $data, 'vendor.state' ),
 | 
				
			||||||
 | 
								'postal_code'     => $this->getString( $data, 'vendor.postal_code' ),
 | 
				
			||||||
 | 
								'vendor_contacts' => [
 | 
				
			||||||
 | 
									[
 | 
				
			||||||
 | 
										'first_name' => $this->getString( $data, 'vendor.first_name' ),
 | 
				
			||||||
 | 
										'last_name'  => $this->getString( $data, 'vendor.last_name' ),
 | 
				
			||||||
 | 
										'email'      => $this->getString( $data, 'vendor.email' ),
 | 
				
			||||||
 | 
										'phone'      => $this->getString( $data, 'vendor.phone' ),
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								],
 | 
				
			||||||
 | 
								'country_id'      => isset( $data['vendor.country_id'] ) ? $this->getCountryId( $data['vendor.country_id'] ) : null,
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										55
									
								
								app/Import/Transformers/Freshbooks/ClientTransformer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								app/Import/Transformers/Freshbooks/ClientTransformer.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Invoice Ninja (https://clientninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/clientninja/clientninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Import\Transformers\Freshbooks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Import\ImportException;
 | 
				
			||||||
 | 
					use App\Import\Transformers\BaseTransformer;
 | 
				
			||||||
 | 
					use Illuminate\Support\Str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class ClientTransformer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class ClientTransformer extends BaseTransformer {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param $data
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return array|bool
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function transform( $data ) {
 | 
				
			||||||
 | 
							if ( isset( $data['Organization'] ) && $this->hasClient( $data['Organization'] ) ) {
 | 
				
			||||||
 | 
								throw new ImportException('Client already exists');
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return [
 | 
				
			||||||
 | 
								'company_id'     => $this->maps['company']->id,
 | 
				
			||||||
 | 
								'name'           => $this->getString( $data, 'Organization' ),
 | 
				
			||||||
 | 
								'work_phone'     => $this->getString( $data, 'Phone' ),
 | 
				
			||||||
 | 
								'address1'       => $this->getString( $data, 'Street' ),
 | 
				
			||||||
 | 
								'city'           => $this->getString( $data, 'City' ),
 | 
				
			||||||
 | 
								'state'          => $this->getString( $data, 'Province/State' ),
 | 
				
			||||||
 | 
								'postal_code'    => $this->getString( $data, 'Postal Code' ),
 | 
				
			||||||
 | 
								'country_id'     => isset( $data['Country'] ) ? $this->getCountryId( $data['Country'] ) : null,
 | 
				
			||||||
 | 
								'private_notes'   => $this->getString( $data, 'Notes' ),
 | 
				
			||||||
 | 
								'credit_balance' => 0,
 | 
				
			||||||
 | 
								'settings'       => new \stdClass,
 | 
				
			||||||
 | 
								'client_hash'    => Str::random( 40 ),
 | 
				
			||||||
 | 
								'contacts'       => [
 | 
				
			||||||
 | 
									[
 | 
				
			||||||
 | 
										'first_name'    => $this->getString( $data, 'First Name' ),
 | 
				
			||||||
 | 
										'last_name'     => $this->getString( $data, 'Last Name' ),
 | 
				
			||||||
 | 
										'email'         => $this->getString( $data, 'Email' ),
 | 
				
			||||||
 | 
										'phone'         => $this->getString( $data, 'Phone' ),
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								],
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										78
									
								
								app/Import/Transformers/Freshbooks/InvoiceTransformer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								app/Import/Transformers/Freshbooks/InvoiceTransformer.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * client Ninja (https://clientninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/clientninja/clientninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Import\Transformers\Freshbooks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Import\ImportException;
 | 
				
			||||||
 | 
					use App\Import\Transformers\BaseTransformer;
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class InvoiceTransformer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class InvoiceTransformer extends BaseTransformer {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param $line_items_data
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return bool|array
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function transform( $line_items_data ) {
 | 
				
			||||||
 | 
							$invoice_data = reset( $line_items_data );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( $this->hasInvoice( $invoice_data['Invoice #'] ) ) {
 | 
				
			||||||
 | 
								throw new ImportException( 'Invoice number already exists' );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$invoiceStatusMap = [
 | 
				
			||||||
 | 
								'sent'  => Invoice::STATUS_SENT,
 | 
				
			||||||
 | 
								'draft' => Invoice::STATUS_DRAFT,
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$transformed = [
 | 
				
			||||||
 | 
								'company_id'  => $this->maps['company']->id,
 | 
				
			||||||
 | 
								'client_id'   => $this->getClient( $this->getString( $invoice_data, 'Client Name' ), null ),
 | 
				
			||||||
 | 
								'number'      => $this->getString( $invoice_data, 'Invoice #' ),
 | 
				
			||||||
 | 
								'date'        => isset( $invoice_data['Date Issued'] ) ? date( 'Y-m-d', strtotime( $invoice_data['Date Issued'] ) ) : null,
 | 
				
			||||||
 | 
								'currency_id' => $this->getCurrencyByCode( $invoice_data, 'Currency' ),
 | 
				
			||||||
 | 
								'amount'      => 0,
 | 
				
			||||||
 | 
								'status_id'   => $invoiceStatusMap[ $status =
 | 
				
			||||||
 | 
										strtolower( $this->getString( $invoice_data, 'Invoice Status' ) ) ] ?? Invoice::STATUS_SENT,
 | 
				
			||||||
 | 
								'viewed'      => $status === 'viewed',
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$line_items = [];
 | 
				
			||||||
 | 
							foreach ( $line_items_data as $record ) {
 | 
				
			||||||
 | 
								$line_items[]          = [
 | 
				
			||||||
 | 
									'product_key'        => $this->getString( $record, 'Item Name' ),
 | 
				
			||||||
 | 
									'notes'              => $this->getString( $record, 'Item Description' ),
 | 
				
			||||||
 | 
									'cost'               => $this->getFloat( $record, 'Rate' ),
 | 
				
			||||||
 | 
									'quantity'           => $this->getFloat( $record, 'Quantity' ),
 | 
				
			||||||
 | 
									'discount'           => $this->getFloat( $record, 'Discount Percentage' ),
 | 
				
			||||||
 | 
									'is_amount_discount' => false,
 | 
				
			||||||
 | 
									'tax_name1'          => $this->getString( $record, 'Tax 1 Type' ),
 | 
				
			||||||
 | 
									'tax_rate1'          => $this->getFloat( $record, 'Tax 1 Amount' ),
 | 
				
			||||||
 | 
									'tax_name2'          => $this->getString( $record, 'Tax 2 Type' ),
 | 
				
			||||||
 | 
									'tax_rate2'          => $this->getFloat( $record, 'Tax 2 Amount' ),
 | 
				
			||||||
 | 
								];
 | 
				
			||||||
 | 
								$transformed['amount'] += $this->getFloat( $record, 'Line Total' );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							$transformed['line_items'] = $line_items;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( ! empty( $invoice_data['Date Paid'] ) ) {
 | 
				
			||||||
 | 
								$transformed['payments'] = [[
 | 
				
			||||||
 | 
									'date'   => date( 'Y-m-d', strtotime( $invoice_data['Date Paid'] ) ),
 | 
				
			||||||
 | 
									'amount' => $transformed['amount'],
 | 
				
			||||||
 | 
								]];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return $transformed;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										89
									
								
								app/Import/Transformers/Invoice2Go/InvoiceTransformer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								app/Import/Transformers/Invoice2Go/InvoiceTransformer.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,89 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * client Ninja (https://clientninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/clientninja/clientninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Import\Transformers\Invoice2Go;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Import\ImportException;
 | 
				
			||||||
 | 
					use App\Import\Transformers\BaseTransformer;
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					use Illuminate\Support\Str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class InvoiceTransformer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class InvoiceTransformer extends BaseTransformer {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param $line_items_data
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return bool|array
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function transform( $invoice_data ) {
 | 
				
			||||||
 | 
							if ( $this->hasInvoice( $invoice_data['DocumentNumber'] ) ) {
 | 
				
			||||||
 | 
								throw new ImportException( 'Invoice number already exists' );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$invoiceStatusMap = [
 | 
				
			||||||
 | 
								'unsent' => Invoice::STATUS_DRAFT,
 | 
				
			||||||
 | 
								'sent'   => Invoice::STATUS_SENT,
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$transformed = [
 | 
				
			||||||
 | 
								'company_id'  => $this->maps['company']->id,
 | 
				
			||||||
 | 
								'number'      => $this->getString( $invoice_data, 'DocumentNumber' ),
 | 
				
			||||||
 | 
								'notes'       => $this->getString( $invoice_data, 'Comment' ),
 | 
				
			||||||
 | 
								'date'        => isset( $invoice_data['DocumentDate'] ) ? date( 'Y-m-d', strtotime( $invoice_data['DocumentDate'] ) ) : null,
 | 
				
			||||||
 | 
								'currency_id' => $this->getCurrencyByCode( $invoice_data, 'Currency' ),
 | 
				
			||||||
 | 
								'amount'      => 0,
 | 
				
			||||||
 | 
								'status_id'   => $invoiceStatusMap[ $status =
 | 
				
			||||||
 | 
										strtolower( $this->getString( $invoice_data, 'DocumentStatus' ) ) ] ?? Invoice::STATUS_SENT,
 | 
				
			||||||
 | 
								'viewed'      => $status === 'viewed',
 | 
				
			||||||
 | 
								'line_items'  => [
 | 
				
			||||||
 | 
									[
 | 
				
			||||||
 | 
										'amount'             => $amount = $this->getFloat( $invoice_data, 'TotalAmount' ),
 | 
				
			||||||
 | 
										'quantity'           => 1,
 | 
				
			||||||
 | 
										'discount'           => $this->getFloat( $invoice_data, 'DiscountValue' ),
 | 
				
			||||||
 | 
										'is_amount_discount' => false,
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								],
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$client_id =
 | 
				
			||||||
 | 
								$this->getClient( $this->getString( $invoice_data, 'Name' ), $this->getString( $invoice_data, 'EmailRecipient' ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( $client_id ) {
 | 
				
			||||||
 | 
								$transformed['client_id'] = $client_id;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								$transformed['client'] = [
 | 
				
			||||||
 | 
									'name'              => $this->getString( $invoice_data, 'Name' ),
 | 
				
			||||||
 | 
									'address1'          => $this->getString( $invoice_data, 'DocumentRecipientAddress' ),
 | 
				
			||||||
 | 
									'shipping_address1' => $this->getString( $invoice_data, 'ShipAddress' ),
 | 
				
			||||||
 | 
									'credit_balance'    => 0,
 | 
				
			||||||
 | 
									'settings'          => new \stdClass,
 | 
				
			||||||
 | 
									'client_hash'       => Str::random( 40 ),
 | 
				
			||||||
 | 
									'contacts'          => [
 | 
				
			||||||
 | 
										[
 | 
				
			||||||
 | 
											'email' => $this->getString( $invoice_data, 'Email' ),
 | 
				
			||||||
 | 
										],
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if ( ! empty( $invoice_data['Date Paid'] ) ) {
 | 
				
			||||||
 | 
								$transformed['payments'] = [
 | 
				
			||||||
 | 
									[
 | 
				
			||||||
 | 
										'date'   => date( 'Y-m-d', strtotime( $invoice_data['DatePaid'] ) ),
 | 
				
			||||||
 | 
										'amount' => $this->getFloat( $invoice_data, 'Payments' ),
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return $transformed;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * client Ninja (https://clientninja.com).
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @link https://github.com/clientninja/clientninja source repository
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
					 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @license https://opensource.org/licenses/AAL
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * client Ninja (https://clientninja.com).
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @link https://github.com/clientninja/clientninja source repository
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
					 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @license https://opensource.org/licenses/AAL
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										48
									
								
								app/Import/Transformers/Invoicely/ClientTransformer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								app/Import/Transformers/Invoicely/ClientTransformer.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Invoice Ninja (https://clientninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/clientninja/clientninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Import\Transformers\Invoicely;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Import\ImportException;
 | 
				
			||||||
 | 
					use App\Import\Transformers\BaseTransformer;
 | 
				
			||||||
 | 
					use Illuminate\Support\Str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class ClientTransformer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class ClientTransformer extends BaseTransformer {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param $data
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return array|bool
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function transform( $data ) {
 | 
				
			||||||
 | 
							if ( isset( $data['Client Name'] ) && $this->hasClient( $data['Client Name'] ) ) {
 | 
				
			||||||
 | 
								throw new ImportException('Client already exists');
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return [
 | 
				
			||||||
 | 
								'company_id'     => $this->maps['company']->id,
 | 
				
			||||||
 | 
								'name'           => $this->getString( $data, 'Client Name' ),
 | 
				
			||||||
 | 
								'work_phone'     => $this->getString( $data, 'Phone' ),
 | 
				
			||||||
 | 
								'country_id'     => isset( $data['Country'] ) ? $this->getCountryIdBy2( $data['Country'] ) : null,
 | 
				
			||||||
 | 
								'credit_balance' => 0,
 | 
				
			||||||
 | 
								'settings'       => new \stdClass,
 | 
				
			||||||
 | 
								'client_hash'    => Str::random( 40 ),
 | 
				
			||||||
 | 
								'contacts'       => [
 | 
				
			||||||
 | 
									[
 | 
				
			||||||
 | 
										'email'         => $this->getString( $data, 'Email' ),
 | 
				
			||||||
 | 
										'phone'         => $this->getString( $data, 'Phone' ),
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								],
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										58
									
								
								app/Import/Transformers/Invoicely/InvoiceTransformer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								app/Import/Transformers/Invoicely/InvoiceTransformer.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * client Ninja (https://clientninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/clientninja/clientninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Import\Transformers\Invoicely;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Import\ImportException;
 | 
				
			||||||
 | 
					use App\Import\Transformers\BaseTransformer;
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class InvoiceTransformer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class InvoiceTransformer extends BaseTransformer {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param $data
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return bool|array
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function transform( $data ) {
 | 
				
			||||||
 | 
							if ( $this->hasInvoice( $data['Details'] ) ) {
 | 
				
			||||||
 | 
								throw new ImportException( 'Invoice number already exists' );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$transformed = [
 | 
				
			||||||
 | 
								'company_id' => $this->maps['company']->id,
 | 
				
			||||||
 | 
								'client_id'  => $this->getClient( $this->getString( $data, 'Client' ), null ),
 | 
				
			||||||
 | 
								'number'     => $this->getString( $data, 'Details' ),
 | 
				
			||||||
 | 
								'date'       => isset( $data['Date'] ) ? date( 'Y-m-d', strtotime( $data['Date'] ) ) : null,
 | 
				
			||||||
 | 
								'due_date'   => isset( $data['Due'] ) ? date( 'Y-m-d', strtotime( $data['Due'] ) ) : null,
 | 
				
			||||||
 | 
								'status_id'  => Invoice::STATUS_SENT,
 | 
				
			||||||
 | 
								'line_items' => [
 | 
				
			||||||
 | 
									[
 | 
				
			||||||
 | 
										'cost'     => $amount = $this->getFloat( $data, 'Total' ),
 | 
				
			||||||
 | 
										'quantity' => 1,
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								],
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( strtolower( $data['Status'] ) === 'paid' ) {
 | 
				
			||||||
 | 
								$transformed['payments'] = [
 | 
				
			||||||
 | 
									[
 | 
				
			||||||
 | 
										'date'   => date( 'Y-m-d' ),
 | 
				
			||||||
 | 
										'amount' => $amount,
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return $transformed;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * client Ninja (https://clientninja.com).
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @link https://github.com/clientninja/clientninja source repository
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
					 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @license https://opensource.org/licenses/AAL
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										74
									
								
								app/Import/Transformers/Waveaccounting/ClientTransformer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								app/Import/Transformers/Waveaccounting/ClientTransformer.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Invoice Ninja (https://clientninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/clientninja/clientninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Import\Transformers\Waveaccounting;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Import\ImportException;
 | 
				
			||||||
 | 
					use App\Import\Transformers\BaseTransformer;
 | 
				
			||||||
 | 
					use Illuminate\Support\Str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class ClientTransformer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class ClientTransformer extends BaseTransformer {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param $data
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return array|bool
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function transform( $data ) {
 | 
				
			||||||
 | 
							if ( isset( $data['customer_name'] ) && $this->hasClient( $data['customer_name'] ) ) {
 | 
				
			||||||
 | 
								throw new ImportException('Client already exists');
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$settings              = new \stdClass;
 | 
				
			||||||
 | 
							$settings->currency_id = (string) $this->getCurrencyByCode( $data, 'customer_currency' );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( strval( $data['Payment Terms'] ?? '' ) > 0 ) {
 | 
				
			||||||
 | 
								$settings->payment_terms = $data['Payment Terms'];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return [
 | 
				
			||||||
 | 
								'company_id'     => $this->maps['company']->id,
 | 
				
			||||||
 | 
								'name'           => $this->getString( $data, 'customer_name' ),
 | 
				
			||||||
 | 
								'number'           => $this->getString( $data, 'account_number' ),
 | 
				
			||||||
 | 
								'work_phone'     => $this->getString( $data, 'phone' ),
 | 
				
			||||||
 | 
								'website'     => $this->getString( $data, 'website' ),
 | 
				
			||||||
 | 
								'country_id'     => !empty( $data['country'] ) ? $this->getCountryId( $data['country'] ) : null,
 | 
				
			||||||
 | 
								'state'          => $this->getString( $data, 'province/state' ),
 | 
				
			||||||
 | 
								'address1'       => $this->getString( $data, 'address_line_1' ),
 | 
				
			||||||
 | 
								'address2'       => $this->getString( $data, 'address_line_2' ),
 | 
				
			||||||
 | 
								'city'           => $this->getString( $data, 'city' ),
 | 
				
			||||||
 | 
								'postal_code'    => $this->getString( $data, 'postal_code/zip_code' ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								'shipping_country_id'     => !empty( $data['ship-to_country'] ) ? $this->getCountryId( $data['country'] ) : null,
 | 
				
			||||||
 | 
								'shipping_state'          => $this->getString( $data, 'ship-to_province/state' ),
 | 
				
			||||||
 | 
								'shipping_address1'       => $this->getString( $data, 'ship-to_address_line_1' ),
 | 
				
			||||||
 | 
								'shipping_address2'       => $this->getString( $data, 'ship-to_address_line_2' ),
 | 
				
			||||||
 | 
								'shipping_city'           => $this->getString( $data, 'ship-to_city' ),
 | 
				
			||||||
 | 
								'shipping_postal_code'    => $this->getString( $data, 'ship-to_postal_code/zip_code' ),
 | 
				
			||||||
 | 
								'public_notes'    => $this->getString( $data, 'delivery_instructions' ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								'credit_balance' => 0,
 | 
				
			||||||
 | 
								'settings'       =>$settings,
 | 
				
			||||||
 | 
								'client_hash'    => Str::random( 40 ),
 | 
				
			||||||
 | 
								'contacts'       => [
 | 
				
			||||||
 | 
									[
 | 
				
			||||||
 | 
										'first_name'    => $this->getString( $data, 'contact_first_name' ),
 | 
				
			||||||
 | 
										'last_name'     => $this->getString( $data, 'contact_last_name' ),
 | 
				
			||||||
 | 
										'email'         => $this->getString( $data, 'email' ),
 | 
				
			||||||
 | 
										'phone'         => $this->getString( $data, 'phone' ),
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								],
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,80 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * client Ninja (https://clientninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/clientninja/clientninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Import\Transformers\Waveaccounting;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Import\ImportException;
 | 
				
			||||||
 | 
					use App\Import\Transformers\BaseTransformer;
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class InvoiceTransformer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class InvoiceTransformer extends BaseTransformer {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param $line_items_data
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return bool|array
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function transform( $line_items_data ) {
 | 
				
			||||||
 | 
							$invoice_data = reset( $line_items_data );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( $this->hasInvoice( $invoice_data['Invoice Number'] ) ) {
 | 
				
			||||||
 | 
								throw new ImportException( 'Invoice number already exists' );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$transformed = [
 | 
				
			||||||
 | 
								'company_id'  => $this->maps['company']->id,
 | 
				
			||||||
 | 
								'client_id'   => $this->getClient( $customer_name = $this->getString( $invoice_data, 'Customer' ), null ),
 | 
				
			||||||
 | 
								'number'      => $invoice_number = $this->getString( $invoice_data, 'Invoice Number' ),
 | 
				
			||||||
 | 
								'date'        => isset( $invoice_data['Invoice Date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['Transaction Date'] ) ) : null,
 | 
				
			||||||
 | 
								'currency_id' => $this->getCurrencyByCode( $invoice_data, 'Currency' ),
 | 
				
			||||||
 | 
								'status_id'   => Invoice::STATUS_SENT,
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$line_items = [];
 | 
				
			||||||
 | 
							$payments   = [];
 | 
				
			||||||
 | 
							foreach ( $line_items_data as $record ) {
 | 
				
			||||||
 | 
								if ( $record['Account Type'] === 'Income' ) {
 | 
				
			||||||
 | 
									$description = $this->getString( $record, 'Transaction Line Description' );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Remove duplicate data from description
 | 
				
			||||||
 | 
									if ( substr( $description, 0, strlen( $customer_name ) + 3 ) === $customer_name . ' - ' ) {
 | 
				
			||||||
 | 
										$description = substr( $description, strlen( $customer_name ) + 3 );
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if ( substr( $description, 0, strlen( $invoice_number ) + 3 ) === $invoice_number . ' - ' ) {
 | 
				
			||||||
 | 
										$description = substr( $description, strlen( $invoice_number ) + 3 );
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									$line_items[] = [
 | 
				
			||||||
 | 
										'notes'     => $description,
 | 
				
			||||||
 | 
										'cost'      => $this->getFloat( $record, 'Amount Before Sales Tax' ),
 | 
				
			||||||
 | 
										'tax_name1' => $this->getString( $record, 'Sales Tax Name' ),
 | 
				
			||||||
 | 
										'tax_rate1' => $this->getFloat( $record, 'Sales Tax Amount' ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										'quantity' => 1,
 | 
				
			||||||
 | 
									];
 | 
				
			||||||
 | 
								} elseif ( $record['Account Type'] === 'System Receivable Invoice' ) {
 | 
				
			||||||
 | 
									// This is a payment
 | 
				
			||||||
 | 
									$payments[] = [
 | 
				
			||||||
 | 
										'date'   => date( 'Y-m-d', strtotime( $invoice_data['Transaction Date'] ) ),
 | 
				
			||||||
 | 
										'amount' => $this->getFloat( $record, 'Amount (One column)' ),
 | 
				
			||||||
 | 
									];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$transformed['line_items'] = $line_items;
 | 
				
			||||||
 | 
							$transformed['payments']   = $payments;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return $transformed;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										72
									
								
								app/Import/Transformers/Zoho/ClientTransformer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								app/Import/Transformers/Zoho/ClientTransformer.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Invoice Ninja (https://clientninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/clientninja/clientninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Import\Transformers\Zoho;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Import\ImportException;
 | 
				
			||||||
 | 
					use App\Import\Transformers\BaseTransformer;
 | 
				
			||||||
 | 
					use Illuminate\Support\Str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class ClientTransformer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class ClientTransformer extends BaseTransformer {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param $data
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return array|bool
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function transform( $data ) {
 | 
				
			||||||
 | 
							if ( isset( $data['Company Name'] ) && $this->hasClient( $data['Company Name'] ) ) {
 | 
				
			||||||
 | 
								throw new ImportException( 'Client already exists' );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$settings              = new \stdClass;
 | 
				
			||||||
 | 
							$settings->currency_id = (string) $this->getCurrencyByCode( $data, 'Currency' );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( strval( $data['Payment Terms'] ?? '' ) > 0 ) {
 | 
				
			||||||
 | 
								$settings->payment_terms = $data['Payment Terms'];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return [
 | 
				
			||||||
 | 
								'company_id'    => $this->maps['company']->id,
 | 
				
			||||||
 | 
								'name'          => $this->getString( $data, 'Company Name' ),
 | 
				
			||||||
 | 
								'work_phone'    => $this->getString( $data, 'Phone' ),
 | 
				
			||||||
 | 
								'private_notes' => $this->getString( $data, 'Notes' ),
 | 
				
			||||||
 | 
								'website'       => $this->getString( $data, 'Website' ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								'address1'    => $this->getString( $data, 'Billing Address' ),
 | 
				
			||||||
 | 
								'address2'    => $this->getString( $data, 'Billing Street2' ),
 | 
				
			||||||
 | 
								'city'        => $this->getString( $data, 'Billing City' ),
 | 
				
			||||||
 | 
								'state'       => $this->getString( $data, 'Billing State' ),
 | 
				
			||||||
 | 
								'postal_code' => $this->getString( $data, 'Billing Code' ),
 | 
				
			||||||
 | 
								'country_id'  => isset( $data['Billing Country'] ) ? $this->getCountryId( $data['Billing Country'] ) : null,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								'shipping_address1'    => $this->getString( $data, 'Shipping Address' ),
 | 
				
			||||||
 | 
								'shipping_address2'    => $this->getString( $data, 'Shipping Street2' ),
 | 
				
			||||||
 | 
								'shipping_city'        => $this->getString( $data, 'Shipping City' ),
 | 
				
			||||||
 | 
								'shipping_state'       => $this->getString( $data, 'Shipping State' ),
 | 
				
			||||||
 | 
								'shipping_postal_code' => $this->getString( $data, 'Shipping Code' ),
 | 
				
			||||||
 | 
								'shipping_country_id'  => isset( $data['Shipping Country'] ) ? $this->getCountryId( $data['Shipping Country'] ) : null,
 | 
				
			||||||
 | 
								'credit_balance' => 0,
 | 
				
			||||||
 | 
								'settings'       => $settings,
 | 
				
			||||||
 | 
								'client_hash'    => Str::random( 40 ),
 | 
				
			||||||
 | 
								'contacts'       => [
 | 
				
			||||||
 | 
									[
 | 
				
			||||||
 | 
										'first_name' => $this->getString( $data, 'First Name' ),
 | 
				
			||||||
 | 
										'last_name'  => $this->getString( $data, 'Last Name' ),
 | 
				
			||||||
 | 
										'email'      => $this->getString( $data, 'Email' ),
 | 
				
			||||||
 | 
										'phone'      => $this->getString( $data, 'Phone' ),
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								],
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										77
									
								
								app/Import/Transformers/Zoho/InvoiceTransformer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								app/Import/Transformers/Zoho/InvoiceTransformer.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * client Ninja (https://clientninja.com).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @link https://github.com/clientninja/clientninja source repository
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Import\Transformers\Zoho;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Import\ImportException;
 | 
				
			||||||
 | 
					use App\Import\Transformers\BaseTransformer;
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class InvoiceTransformer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class InvoiceTransformer extends BaseTransformer {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param $line_items_data
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return bool|array
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function transform( $line_items_data ) {
 | 
				
			||||||
 | 
							$invoice_data = reset( $line_items_data );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( $this->hasInvoice( $invoice_data['Invoice Number'] ) ) {
 | 
				
			||||||
 | 
								throw new ImportException( 'Invoice number already exists' );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$invoiceStatusMap = [
 | 
				
			||||||
 | 
								'sent'  => Invoice::STATUS_SENT,
 | 
				
			||||||
 | 
								'draft' => Invoice::STATUS_DRAFT,
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$transformed = [
 | 
				
			||||||
 | 
								'company_id'   => $this->maps['company']->id,
 | 
				
			||||||
 | 
								'client_id'    => $this->getClient( $this->getString( $invoice_data, 'Company Name' ), null ),
 | 
				
			||||||
 | 
								'number'       => $this->getString( $invoice_data, 'Invoice Number' ),
 | 
				
			||||||
 | 
								'date'         => isset( $invoice_data['Invoice Date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['Invoice Date'] ) ) : null,
 | 
				
			||||||
 | 
								'due_date'     => isset( $invoice_data['Due Date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['Due Date'] ) ) : null,
 | 
				
			||||||
 | 
								'po_number'    => $this->getString( $invoice_data, 'PurchaseOrder' ),
 | 
				
			||||||
 | 
								'public_notes' => $this->getString( $invoice_data, 'Notes' ),
 | 
				
			||||||
 | 
								'currency_id'  => $this->getCurrencyByCode( $invoice_data, 'Currency' ),
 | 
				
			||||||
 | 
								'amount'       => $this->getFloat( $invoice_data, 'Total' ),
 | 
				
			||||||
 | 
								'balance'      => $this->getFloat( $invoice_data, 'Balance' ),
 | 
				
			||||||
 | 
								'status_id'    => $invoiceStatusMap[ $status =
 | 
				
			||||||
 | 
										strtolower( $this->getString( $invoice_data, 'Invoice Status' ) ) ] ?? Invoice::STATUS_SENT,
 | 
				
			||||||
 | 
								'viewed'       => $status === 'viewed',
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$line_items = [];
 | 
				
			||||||
 | 
							foreach ( $line_items_data as $record ) {
 | 
				
			||||||
 | 
								$line_items[] = [
 | 
				
			||||||
 | 
									'product_key'        => $this->getString( $record, 'Item Name' ),
 | 
				
			||||||
 | 
									'notes'              => $this->getString( $record, 'Item Description' ),
 | 
				
			||||||
 | 
									'cost'               => $this->getFloat( $record, 'Item Price' ),
 | 
				
			||||||
 | 
									'quantity'           => $this->getFloat( $record, 'Quantity' ),
 | 
				
			||||||
 | 
									'discount'           => $this->getFloat( $record, 'Discount Amount' ),
 | 
				
			||||||
 | 
									'is_amount_discount' => true,
 | 
				
			||||||
 | 
								];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							$transformed['line_items'] = $line_items;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( $transformed['balance'] < $transformed['amount'] ) {
 | 
				
			||||||
 | 
								$transformed['payments'] = [[
 | 
				
			||||||
 | 
									'date'   => date( 'Y-m-d' ),
 | 
				
			||||||
 | 
									'amount' => $transformed['amount'] - $transformed['balance'],
 | 
				
			||||||
 | 
								]];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return $transformed;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -128,14 +128,17 @@ class CreateEntityPdf implements ShouldQueue
 | 
				
			|||||||
            $template = new PdfMakerDesign(strtolower($design->name));
 | 
					            $template = new PdfMakerDesign(strtolower($design->name));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $variables = $html->generateLabelsAndValues();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $state = [
 | 
					        $state = [
 | 
				
			||||||
            'template' => $template->elements([
 | 
					            'template' => $template->elements([
 | 
				
			||||||
                'client' => $this->entity->client,
 | 
					                'client' => $this->entity->client,
 | 
				
			||||||
                'entity' => $this->entity,
 | 
					                'entity' => $this->entity,
 | 
				
			||||||
                'pdf_variables' => (array) $this->entity->company->settings->pdf_variables,
 | 
					                'pdf_variables' => (array) $this->entity->company->settings->pdf_variables,
 | 
				
			||||||
                '$product' => $design->design->product,
 | 
					                '$product' => $design->design->product,
 | 
				
			||||||
 | 
					                'variables' => $variables,
 | 
				
			||||||
            ]),
 | 
					            ]),
 | 
				
			||||||
            'variables' => $html->generateLabelsAndValues(),
 | 
					            'variables' => $variables,
 | 
				
			||||||
            'options' => [
 | 
					            'options' => [
 | 
				
			||||||
                'all_pages_header' => $this->entity->client->getSetting('all_pages_header'),
 | 
					                'all_pages_header' => $this->entity->client->getSetting('all_pages_header'),
 | 
				
			||||||
                'all_pages_footer' => $this->entity->client->getSetting('all_pages_footer'),
 | 
					                'all_pages_footer' => $this->entity->client->getSetting('all_pages_footer'),
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,6 @@ namespace App\Jobs\Entity;
 | 
				
			|||||||
use App\Events\Invoice\InvoiceReminderWasEmailed;
 | 
					use App\Events\Invoice\InvoiceReminderWasEmailed;
 | 
				
			||||||
use App\Events\Invoice\InvoiceWasEmailed;
 | 
					use App\Events\Invoice\InvoiceWasEmailed;
 | 
				
			||||||
use App\Events\Invoice\InvoiceWasEmailedAndFailed;
 | 
					use App\Events\Invoice\InvoiceWasEmailedAndFailed;
 | 
				
			||||||
use App\Jobs\Mail\BaseMailerJob;
 | 
					 | 
				
			||||||
use App\Jobs\Mail\EntityFailedSendMailer;
 | 
					use App\Jobs\Mail\EntityFailedSendMailer;
 | 
				
			||||||
use App\Jobs\Mail\NinjaMailerJob;
 | 
					use App\Jobs\Mail\NinjaMailerJob;
 | 
				
			||||||
use App\Jobs\Mail\NinjaMailerObject;
 | 
					use App\Jobs\Mail\NinjaMailerObject;
 | 
				
			||||||
@ -113,6 +112,7 @@ class EmailEntity implements ShouldQueue
 | 
				
			|||||||
        $nmo->entity_string = $this->entity_string;
 | 
					        $nmo->entity_string = $this->entity_string;
 | 
				
			||||||
        $nmo->invitation = $this->invitation;
 | 
					        $nmo->invitation = $this->invitation;
 | 
				
			||||||
        $nmo->reminder_template = $this->reminder_template;
 | 
					        $nmo->reminder_template = $this->reminder_template;
 | 
				
			||||||
 | 
					        $nmo->entity = $this->entity;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        NinjaMailerJob::dispatch($nmo);
 | 
					        NinjaMailerJob::dispatch($nmo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -13,26 +13,31 @@ namespace App\Jobs\Import;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use App\Factory\ClientFactory;
 | 
					use App\Factory\ClientFactory;
 | 
				
			||||||
use App\Factory\InvoiceFactory;
 | 
					use App\Factory\InvoiceFactory;
 | 
				
			||||||
use App\Factory\ProductFactory;
 | 
					use App\Factory\PaymentFactory;
 | 
				
			||||||
use App\Http\Requests\Client\StoreClientRequest;
 | 
					 | 
				
			||||||
use App\Http\Requests\Invoice\StoreInvoiceRequest;
 | 
					use App\Http\Requests\Invoice\StoreInvoiceRequest;
 | 
				
			||||||
use App\Http\Requests\Product\StoreProductRequest;
 | 
					use App\Import\ImportException;
 | 
				
			||||||
use App\Import\Transformers\ClientTransformer;
 | 
					use App\Import\Transformers\BaseTransformer;
 | 
				
			||||||
use App\Import\Transformers\InvoiceItemTransformer;
 | 
					use App\Jobs\Mail\NinjaMailerJob;
 | 
				
			||||||
use App\Import\Transformers\InvoiceTransformer;
 | 
					use App\Jobs\Mail\NinjaMailerObject;
 | 
				
			||||||
use App\Import\Transformers\ProductTransformer;
 | 
					 | 
				
			||||||
use App\Jobs\Mail\MailRouter;
 | 
					 | 
				
			||||||
use App\Libraries\MultiDB;
 | 
					use App\Libraries\MultiDB;
 | 
				
			||||||
use App\Mail\Import\ImportCompleted;
 | 
					use App\Mail\Import\ImportCompleted;
 | 
				
			||||||
use App\Models\Client;
 | 
					use App\Models\Client;
 | 
				
			||||||
 | 
					use App\Models\ClientContact;
 | 
				
			||||||
use App\Models\Company;
 | 
					use App\Models\Company;
 | 
				
			||||||
 | 
					use App\Models\Country;
 | 
				
			||||||
use App\Models\Currency;
 | 
					use App\Models\Currency;
 | 
				
			||||||
 | 
					use App\Models\ExpenseCategory;
 | 
				
			||||||
use App\Models\Invoice;
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					use App\Models\PaymentType;
 | 
				
			||||||
 | 
					use App\Models\Product;
 | 
				
			||||||
 | 
					use App\Models\Project;
 | 
				
			||||||
 | 
					use App\Models\TaxRate;
 | 
				
			||||||
use App\Models\User;
 | 
					use App\Models\User;
 | 
				
			||||||
use App\Repositories\ClientContactRepository;
 | 
					use App\Models\Vendor;
 | 
				
			||||||
 | 
					use App\Repositories\BaseRepository;
 | 
				
			||||||
use App\Repositories\ClientRepository;
 | 
					use App\Repositories\ClientRepository;
 | 
				
			||||||
use App\Repositories\InvoiceRepository;
 | 
					use App\Repositories\InvoiceRepository;
 | 
				
			||||||
use App\Repositories\ProductRepository;
 | 
					use App\Repositories\PaymentRepository;
 | 
				
			||||||
use App\Utils\Traits\CleanLineItems;
 | 
					use App\Utils\Traits\CleanLineItems;
 | 
				
			||||||
use Illuminate\Bus\Queueable;
 | 
					use Illuminate\Bus\Queueable;
 | 
				
			||||||
use Illuminate\Contracts\Queue\ShouldQueue;
 | 
					use Illuminate\Contracts\Queue\ShouldQueue;
 | 
				
			||||||
@ -42,11 +47,13 @@ use Illuminate\Queue\SerializesModels;
 | 
				
			|||||||
use Illuminate\Support\Facades\Auth;
 | 
					use Illuminate\Support\Facades\Auth;
 | 
				
			||||||
use Illuminate\Support\Facades\Cache;
 | 
					use Illuminate\Support\Facades\Cache;
 | 
				
			||||||
use Illuminate\Support\Facades\Validator;
 | 
					use Illuminate\Support\Facades\Validator;
 | 
				
			||||||
 | 
					use Illuminate\Support\Str;
 | 
				
			||||||
use League\Csv\Reader;
 | 
					use League\Csv\Reader;
 | 
				
			||||||
use League\Csv\Statement;
 | 
					use League\Csv\Statement;
 | 
				
			||||||
 | 
					use Symfony\Component\HttpFoundation\ParameterBag;
 | 
				
			||||||
 | 
					use Symfony\Component\HttpFoundation\Request;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CSVImport implements ShouldQueue
 | 
					class CSVImport implements ShouldQueue {
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, CleanLineItems;
 | 
						use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, CleanLineItems;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public $invoice;
 | 
						public $invoice;
 | 
				
			||||||
@ -55,7 +62,7 @@ class CSVImport implements ShouldQueue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	public $hash;
 | 
						public $hash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public $entity_type;
 | 
						public $import_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public $skip_header;
 | 
						public $skip_header;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -63,21 +70,16 @@ class CSVImport implements ShouldQueue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	public $import_array;
 | 
						public $import_array;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public $error_array;
 | 
						public $error_array = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public $maps;
 | 
						public $maps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function __construct(array $request, Company $company)
 | 
						public function __construct( array $request, Company $company ) {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
		$this->company     = $company;
 | 
							$this->company     = $company;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		$this->hash        = $request['hash'];
 | 
							$this->hash        = $request['hash'];
 | 
				
			||||||
 | 
							$this->import_type = $request['import_type'];
 | 
				
			||||||
        $this->entity_type = $request['entity_type'];
 | 
							$this->skip_header = $request['skip_header'] ?? null;
 | 
				
			||||||
 | 
							$this->column_map  = $request['column_map'] ?? null;
 | 
				
			||||||
        $this->skip_header = $request['skip_header'];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->column_map = $request['column_map'];
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
@ -86,251 +88,484 @@ class CSVImport implements ShouldQueue
 | 
				
			|||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * @return void
 | 
						 * @return void
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
    public function handle()
 | 
						public function handle() {
 | 
				
			||||||
    {
 | 
					
 | 
				
			||||||
		MultiDB::setDb( $this->company->db );
 | 
							MultiDB::setDb( $this->company->db );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->company->owner()->setCompany($this->company);
 | 
					 | 
				
			||||||
		Auth::login( $this->company->owner(), true );
 | 
							Auth::login( $this->company->owner(), true );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$this->company->owner()->setCompany( $this->company );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$this->buildMaps();
 | 
							$this->buildMaps();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //sort the array by key
 | 
							nlog( "import " . $this->import_type );
 | 
				
			||||||
        ksort($this->column_map);
 | 
							foreach ( [ 'client', 'product', 'invoice', 'payment', 'vendor', 'expense' ] as $entityType ) {
 | 
				
			||||||
 | 
								$csvData = $this->getCsvData( $entityType );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        nlog("import".ucfirst($this->entity_type));
 | 
								if ( ! empty( $csvData ) ) {
 | 
				
			||||||
        $this->{"import".ucfirst($this->entity_type)}();
 | 
									$importFunction       = "import" . Str::plural( Str::title( $entityType ) );
 | 
				
			||||||
 | 
									$preTransformFunction = "preTransform" . Str::title( $this->import_type );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $data = [
 | 
									if ( method_exists( $this, $preTransformFunction ) ) {
 | 
				
			||||||
            'entity' => ucfirst($this->entity_type),
 | 
										$csvData = $this->$preTransformFunction( $csvData, $entityType );
 | 
				
			||||||
            'errors' => $this->error_array,
 | 
					 | 
				
			||||||
            'clients' => $this->maps['clients'],
 | 
					 | 
				
			||||||
            'products' => $this->maps['products'],
 | 
					 | 
				
			||||||
            'invoices' => $this->maps['invoices'],
 | 
					 | 
				
			||||||
            'settings' => $this->company->settings
 | 
					 | 
				
			||||||
        ];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //nlog(print_r($data, 1));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        MailRouter::dispatch(new ImportCompleted($data), $this->company, auth()->user());
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function failed($exception)
 | 
									if ( empty( $csvData ) ) {
 | 
				
			||||||
    {
 | 
										continue;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if ( method_exists( $this, $importFunction ) ) {
 | 
				
			||||||
 | 
										// If there's an entity-specific import function, use that.
 | 
				
			||||||
 | 
										$this->$importFunction( $csvData );
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										// Otherwise, use the generic import function.
 | 
				
			||||||
 | 
										$this->importEntities( $csvData, $entityType );
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$data = [
 | 
				
			||||||
 | 
								'errors'  => $this->error_array,
 | 
				
			||||||
 | 
								'company' => $this->company,
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$nmo = new NinjaMailerObject;
 | 
				
			||||||
 | 
							$nmo->mailable = new ImportCompleted( $data );
 | 
				
			||||||
 | 
							$nmo->company = $this->company;
 | 
				
			||||||
 | 
							$nmo->settings = $this->company->settings;
 | 
				
			||||||
 | 
							$nmo->to_user = $this->company->owner();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							NinjaMailerJob::dispatch($nmo);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
						//////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
    
 | 
						private function preTransformCsv( $csvData, $entityType ) {
 | 
				
			||||||
 | 
							if ( empty( $this->column_map[ $entityType ] ) ) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
    private function importInvoice()
 | 
							}
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $invoice_transformer = new InvoiceTransformer($this->maps);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $records = $this->getCsvData();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $invoice_number_key = array_search('Invoice Number', reset($records));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ( $this->skip_header ) {
 | 
							if ( $this->skip_header ) {
 | 
				
			||||||
            array_shift($records);
 | 
								array_shift( $csvData );
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!$invoice_number_key) {
 | 
							//sort the array by key
 | 
				
			||||||
            nlog("no invoice number to use as key - returning");
 | 
							$keys = $this->column_map[ $entityType ];
 | 
				
			||||||
            return;
 | 
							ksort( $keys );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$csvData = array_map( function ( $row ) use ( $keys ) {
 | 
				
			||||||
 | 
								return array_combine( $keys, array_intersect_key( $row, $keys ) );
 | 
				
			||||||
 | 
							}, $csvData );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( $entityType === 'invoice' ) {
 | 
				
			||||||
 | 
								$csvData = $this->groupInvoices( $csvData, 'invoice.number' );
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $unique_invoices = [];
 | 
							return $csvData;
 | 
				
			||||||
 | 
					 | 
				
			||||||
        //get an array of unique invoice numbers
 | 
					 | 
				
			||||||
        foreach ($records as $key => $value) {
 | 
					 | 
				
			||||||
            $unique_invoices[] = $value[$invoice_number_key];
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($unique_invoices as $unique) {
 | 
						private function preTransformFreshbooks( $csvData, $entityType ) {
 | 
				
			||||||
            $invoices = array_filter($records, function ($value) use ($invoice_number_key, $unique) {
 | 
							$csvData = $this->mapCSVHeaderToKeys( $csvData );
 | 
				
			||||||
                return $value[$invoice_number_key] == $unique;
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $keys = $this->column_map;
 | 
							if ( $entityType === 'invoice' ) {
 | 
				
			||||||
            $values = array_intersect_key(reset($invoices), $this->column_map);
 | 
								$csvData = $this->groupInvoices( $csvData, 'Invoice #' );
 | 
				
			||||||
            $invoice_data = array_combine($keys, $values);
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $invoice = $invoice_transformer->transform($invoice_data);
 | 
							return $csvData;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $this->processInvoice($invoices, $invoice);
 | 
						private function preTransformInvoicely( $csvData, $entityType ) {
 | 
				
			||||||
 | 
							$csvData = $this->mapCSVHeaderToKeys( $csvData );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return $csvData;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private function preTransformInvoice2go( $csvData, $entityType ) {
 | 
				
			||||||
 | 
							$csvData = $this->mapCSVHeaderToKeys( $csvData );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return $csvData;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private function preTransformZoho( $csvData, $entityType ) {
 | 
				
			||||||
 | 
							$csvData = $this->mapCSVHeaderToKeys( $csvData );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( $entityType === 'invoice' ) {
 | 
				
			||||||
 | 
								$csvData = $this->groupInvoices( $csvData, 'Invoice Number' );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return $csvData;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private function preTransformWaveaccounting( $csvData, $entityType ) {
 | 
				
			||||||
 | 
							$csvData = $this->mapCSVHeaderToKeys( $csvData );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( $entityType === 'invoice' ) {
 | 
				
			||||||
 | 
								$csvData = $this->groupInvoices( $csvData, 'Invoice Number' );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return $csvData;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private function groupInvoices( $csvData, $key ) {
 | 
				
			||||||
 | 
							// Group by invoice.
 | 
				
			||||||
 | 
							$grouped = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							foreach ( $csvData as $line_item ) {
 | 
				
			||||||
 | 
								if ( empty( $line_item[ $key ] ) ) {
 | 
				
			||||||
 | 
									$this->error_array['invoice'][] = [ 'invoice' => $line_item, 'error' => 'No invoice number' ];
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									$grouped[ $line_item[ $key ] ][] = $line_item;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function processInvoice($invoices, $invoice)
 | 
							return $grouped;
 | 
				
			||||||
    {
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private function mapCSVHeaderToKeys( $csvData ) {
 | 
				
			||||||
 | 
							$keys = array_shift( $csvData );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return array_map( function ( $values ) use ( $keys ) {
 | 
				
			||||||
 | 
								return array_combine( $keys, $values );
 | 
				
			||||||
 | 
							}, $csvData );
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
						private function importInvoices( $invoices ) {
 | 
				
			||||||
 | 
							$invoice_transformer = $this->getTransformer( 'invoice' );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/** @var PaymentRepository $payment_repository */
 | 
				
			||||||
 | 
							$payment_repository              = app()->make( PaymentRepository::class );
 | 
				
			||||||
 | 
							$payment_repository->import_mode = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/** @var ClientRepository $client_repository */
 | 
				
			||||||
 | 
							$client_repository              = app()->make( ClientRepository::class );
 | 
				
			||||||
 | 
							$client_repository->import_mode = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$invoice_repository              = new InvoiceRepository();
 | 
							$invoice_repository              = new InvoiceRepository();
 | 
				
			||||||
        $item_transformer = new InvoiceItemTransformer($this->maps);
 | 
							$invoice_repository->import_mode = true;
 | 
				
			||||||
        $items = [];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($invoices as $record) {
 | 
							foreach ( $invoices as $raw_invoice ) {
 | 
				
			||||||
            $keys = $this->column_map;
 | 
								try {
 | 
				
			||||||
            $values = array_intersect_key($record, $this->column_map);
 | 
									$invoice_data = $invoice_transformer->transform( $raw_invoice );
 | 
				
			||||||
            $invoice_data = array_combine($keys, $values);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $items[] = $item_transformer->transform($invoice_data);
 | 
									$invoice_data['line_items'] = $this->cleanItems( $invoice_data['line_items'] ?? [] );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// If we don't have a client ID, but we do have client data, go ahead and create the client.
 | 
				
			||||||
 | 
									if ( empty( $invoice_data['client_id'] ) && ! empty( $invoice_data['client'] ) ) {
 | 
				
			||||||
 | 
										$client_data            = $invoice_data['client'];
 | 
				
			||||||
 | 
										$client_data['user_id'] = $this->getUserIDForRecord( $invoice_data );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										$client_repository->save(
 | 
				
			||||||
 | 
											$client_data,
 | 
				
			||||||
 | 
											$client = ClientFactory::create( $this->company->id, $client_data['user_id'] )
 | 
				
			||||||
 | 
										);
 | 
				
			||||||
 | 
										$invoice_data['client_id'] = $client->id;
 | 
				
			||||||
 | 
										unset( $invoice_data['client'] );
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $invoice['line_items'] = $this->cleanItems($items);
 | 
									$validator = Validator::make( $invoice_data, ( new StoreInvoiceRequest() )->rules() );
 | 
				
			||||||
 | 
					 | 
				
			||||||
        $validator = Validator::make($invoice, (new StoreInvoiceRequest())->rules());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if ( $validator->fails() ) {
 | 
									if ( $validator->fails() ) {
 | 
				
			||||||
            $this->error_array['invoices'] = ['invoice' => $invoice, 'error' => json_encode($validator->errors())];
 | 
										$this->error_array['invoice'][] =
 | 
				
			||||||
 | 
											[ 'invoice' => $invoice_data, 'error' => $validator->errors()->all() ];
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
            if ($validator->fails()) {
 | 
										$invoice = InvoiceFactory::create( $this->company->id, $this->getUserIDForRecord( $invoice_data ) );
 | 
				
			||||||
                $this->error_array[] = ['invoice' => $invoice, 'error' => json_encode($validator->errors())];
 | 
										if ( ! empty( $invoice_data['status_id'] ) ) {
 | 
				
			||||||
 | 
											$invoice->status_id = $invoice_data['status_id'];
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										$invoice_repository->save( $invoice_data, $invoice );
 | 
				
			||||||
 | 
										$this->addInvoiceToMaps( $invoice );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// 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 platform-specific import, trust the platform to only return payment info if there's not a separate payment CSV.
 | 
				
			||||||
 | 
										if ( $this->import_type !== 'csv' || empty( $this->column_map['payment'] ) ) {
 | 
				
			||||||
 | 
											// Check for payment columns
 | 
				
			||||||
 | 
											if ( ! empty( $invoice_data['payments'] ) ) {
 | 
				
			||||||
 | 
												foreach ( $invoice_data['payments'] as $payment_data ) {
 | 
				
			||||||
 | 
													$payment_data['user_id']   = $invoice->user_id;
 | 
				
			||||||
 | 
													$payment_data['client_id'] = $invoice->client_id;
 | 
				
			||||||
 | 
													$payment_data['invoices']  = [
 | 
				
			||||||
 | 
														[
 | 
				
			||||||
 | 
															'invoice_id' => $invoice->id,
 | 
				
			||||||
 | 
															'amount'     => $payment_data['amount'] ?? null,
 | 
				
			||||||
 | 
														],
 | 
				
			||||||
 | 
													];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
													$payment_repository->save(
 | 
				
			||||||
 | 
														$payment_data,
 | 
				
			||||||
 | 
														PaymentFactory::create( $this->company->id, $invoice->user_id, $invoice->client_id )
 | 
				
			||||||
 | 
													);
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										$this->actionInvoiceStatus( $invoice, $invoice_data, $invoice_repository );
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} catch ( \Exception $ex ) {
 | 
				
			||||||
 | 
									if ( $ex instanceof ImportException ) {
 | 
				
			||||||
 | 
										$message = $ex->getMessage();
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
                $invoice = $invoice_repository->save($invoice, InvoiceFactory::create($this->company->id, $this->setUser($record)));
 | 
										report( $ex );
 | 
				
			||||||
 | 
										$message = 'Unknown error';
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $this->maps['invoices'][] = $invoice->id;
 | 
									$this->error_array['invoice'][] = [ 'invoice' => $raw_invoice, 'error' => $message ];
 | 
				
			||||||
 | 
					 | 
				
			||||||
                $this->performInvoiceActions($invoice, $record, $invoice_repository);
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function performInvoiceActions($invoice, $record, $invoice_repository)
 | 
						private function actionInvoiceStatus( $invoice, $invoice_data, $invoice_repository ) {
 | 
				
			||||||
    {
 | 
							if ( ! empty( $invoice_data['archived'] ) ) {
 | 
				
			||||||
        $invoice = $this->actionInvoiceStatus($invoice, $record, $invoice_repository);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private function actionInvoiceStatus($invoice, $status, $invoice_repository)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        switch ($status) {
 | 
					 | 
				
			||||||
            case 'Archived':
 | 
					 | 
				
			||||||
			$invoice_repository->archive( $invoice );
 | 
								$invoice_repository->archive( $invoice );
 | 
				
			||||||
			$invoice->fresh();
 | 
								$invoice->fresh();
 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            case 'Sent':
 | 
					 | 
				
			||||||
                $invoice = $invoice->service()->markSent()->save();
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            case 'Viewed':
 | 
					 | 
				
			||||||
                $invoice = $invoice->service()->markSent()->save();
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            default:
 | 
					 | 
				
			||||||
                # code...
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($invoice->balance < $invoice->amount && $invoice->status_id <= Invoice::STATUS_SENT) {
 | 
							if ( ! empty( $invoice_data['viewed'] ) ) {
 | 
				
			||||||
 | 
								$invoice = $invoice->service()->markViewed()->save();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( $invoice->status_id === Invoice::STATUS_SENT ) {
 | 
				
			||||||
 | 
								$invoice = $invoice->service()->markSent()->save();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ( $invoice->status_id <= Invoice::STATUS_SENT && $invoice->amount > 0 ) {
 | 
				
			||||||
 | 
								if ( $invoice->balance < $invoice->amount ) {
 | 
				
			||||||
				$invoice->status_id = Invoice::STATUS_PARTIAL;
 | 
									$invoice->status_id = Invoice::STATUS_PARTIAL;
 | 
				
			||||||
				$invoice->save();
 | 
									$invoice->save();
 | 
				
			||||||
 | 
								} elseif ( $invoice->balance <= 0 ) {
 | 
				
			||||||
 | 
									$invoice->status_id = Invoice::STATUS_PAID;
 | 
				
			||||||
 | 
									$invoice->save();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return $invoice;
 | 
							return $invoice;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //todo limit client imports for hosted version
 | 
						private function importEntities( $records, $entity_type ) {
 | 
				
			||||||
    private function importClient()
 | 
							$entity_type           = Str::slug( $entity_type, '_' );
 | 
				
			||||||
    {
 | 
							$formatted_entity_type = Str::title( $entity_type );
 | 
				
			||||||
        //clients
 | 
					 | 
				
			||||||
        $records = $this->getCsvData();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $contact_repository = new ClientContactRepository();
 | 
							$request_name    = "\\App\\Http\\Requests\\${formatted_entity_type}\\Store${formatted_entity_type}Request";
 | 
				
			||||||
        $client_repository = new ClientRepository($contact_repository);
 | 
							$repository_name = '\\App\\Repositories\\' . $formatted_entity_type . 'Repository';
 | 
				
			||||||
        $client_transformer = new ClientTransformer($this->maps);
 | 
							$factoryName     = '\\App\\Factory\\' . $formatted_entity_type . 'Factory';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($this->skip_header) {
 | 
							/** @var BaseRepository $repository */
 | 
				
			||||||
            array_shift($records);
 | 
							$repository              = app()->make( $repository_name );
 | 
				
			||||||
        }
 | 
							$repository->import_mode = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$transformer = $this->getTransformer( $entity_type );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		foreach ( $records as $record ) {
 | 
							foreach ( $records as $record ) {
 | 
				
			||||||
            $keys = $this->column_map;
 | 
								try {
 | 
				
			||||||
            $values = array_intersect_key($record, $this->column_map);
 | 
									$entity = $transformer->transform( $record );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $client_data = array_combine($keys, $values);
 | 
									/** @var \App\Http\Requests\Request $request */
 | 
				
			||||||
 | 
									$request = new $request_name();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $client = $client_transformer->transform($client_data);
 | 
									// Pass entity data to request so it can be validated
 | 
				
			||||||
 | 
									$request->query = $request->request = new ParameterBag( $entity );
 | 
				
			||||||
            $validator = Validator::make($client, (new StoreClientRequest())->rules());
 | 
									$validator = Validator::make( $entity, $request->rules() );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if ( $validator->fails() ) {
 | 
									if ( $validator->fails() ) {
 | 
				
			||||||
                $this->error_array['clients'] = ['client' => $client, 'error' => json_encode($validator->errors())];
 | 
										$this->error_array[ $entity_type ][] =
 | 
				
			||||||
 | 
											[ $entity_type => $record, 'error' => $validator->errors()->all() ];
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
                $client = $client_repository->save($client, ClientFactory::create($this->company->id, $this->setUser($record)));
 | 
										$entity =
 | 
				
			||||||
 | 
											$repository->save(
 | 
				
			||||||
 | 
												array_diff_key( $entity, [ 'user_id' => false ] ),
 | 
				
			||||||
 | 
												$factoryName::create( $this->company->id, $this->getUserIDForRecord( $entity ) ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (array_key_exists('client.balance', $client_data)) {
 | 
										$entity->save();
 | 
				
			||||||
                    $client->balance = preg_replace('/[^0-9,.]+/', '', $client_data['client.balance']);
 | 
										if ( method_exists( $this, 'add' . $formatted_entity_type . 'ToMaps' ) ) {
 | 
				
			||||||
                }
 | 
											$this->{'add' . $formatted_entity_type . 'ToMaps'}( $entity );
 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (array_key_exists('client.paid_to_date', $client_data)) {
 | 
					 | 
				
			||||||
                    $client->paid_to_date = preg_replace('/[^0-9,.]+/', '', $client_data['client.paid_to_date']);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                $client->save();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                $this->maps['clients'][] = $client->id;
 | 
					 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
    }
 | 
								} catch ( \Exception $ex ) {
 | 
				
			||||||
 | 
									if ( $ex instanceof ImportException ) {
 | 
				
			||||||
 | 
										$message = $ex->getMessage();
 | 
				
			||||||
    private function importProduct()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $product_repository = new ProductRepository();
 | 
					 | 
				
			||||||
        $product_transformer = new ProductTransformer($this->maps);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $records = $this->getCsvData();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($this->skip_header) {
 | 
					 | 
				
			||||||
            array_shift($records);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        foreach ($records as $record) {
 | 
					 | 
				
			||||||
            $keys = $this->column_map;
 | 
					 | 
				
			||||||
            $values = array_intersect_key($record, $this->column_map);
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            $product_data = array_combine($keys, $values);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $product = $product_transformer->transform($product_data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $validator = Validator::make($product, (new StoreProductRequest())->rules());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if ($validator->fails()) {
 | 
					 | 
				
			||||||
                $this->error_array['products'] = ['product' => $product, 'error' => json_encode($validator->errors())];
 | 
					 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
                $product = $product_repository->save($product, ProductFactory::create($this->company->id, $this->setUser($record)));
 | 
										report( $ex );
 | 
				
			||||||
 | 
										$message = 'Unknown error';
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $product->save();
 | 
									$this->error_array[ $entity_type ][] = [ $entity_type => $record, 'error' => $message ];
 | 
				
			||||||
 | 
					 | 
				
			||||||
                $this->maps['products'][] = $product->id;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param $entity_type
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @return BaseTransformer
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						private function getTransformer( $entity_type ) {
 | 
				
			||||||
 | 
							$formatted_entity_type = Str::title( $entity_type );
 | 
				
			||||||
 | 
							$formatted_import_type = Str::title( $this->import_type );
 | 
				
			||||||
 | 
							$transformer_name      =
 | 
				
			||||||
 | 
								'\\App\\Import\\Transformers\\' . $formatted_import_type . '\\' . $formatted_entity_type . 'Transformer';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return new $transformer_name( $this->maps );
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
						//////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
    private function buildMaps()
 | 
						private function buildMaps() {
 | 
				
			||||||
    {
 | 
							$this->maps = [
 | 
				
			||||||
        $this->maps['currencies'] = Currency::all();
 | 
								'company'            => $this->company,
 | 
				
			||||||
        $this->maps['users'] = $this->company->users;
 | 
								'client'             => [],
 | 
				
			||||||
        $this->maps['company'] = $this->company;
 | 
								'contact'            => [],
 | 
				
			||||||
        $this->maps['clients'] = [];
 | 
								'invoice'            => [],
 | 
				
			||||||
        $this->maps['products'] = [];
 | 
								'invoice_client'     => [],
 | 
				
			||||||
        $this->maps['invoices'] = [];
 | 
								'product'            => [],
 | 
				
			||||||
 | 
								'countries'          => [],
 | 
				
			||||||
 | 
								'countries2'         => [],
 | 
				
			||||||
 | 
								'currencies'         => [],
 | 
				
			||||||
 | 
								'client_ids'         => [],
 | 
				
			||||||
 | 
								'invoice_ids'        => [],
 | 
				
			||||||
 | 
								'vendors'            => [],
 | 
				
			||||||
 | 
								'expense_categories' => [],
 | 
				
			||||||
 | 
								'payment_types'      => [],
 | 
				
			||||||
 | 
								'tax_rates'          => [],
 | 
				
			||||||
 | 
								'tax_names'          => [],
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $this;
 | 
							$clients = Client::scope()->get();
 | 
				
			||||||
 | 
							foreach ( $clients as $client ) {
 | 
				
			||||||
 | 
								$this->addClientToMaps( $client );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$contacts = ClientContact::scope()->get();
 | 
				
			||||||
 | 
							foreach ( $contacts as $contact ) {
 | 
				
			||||||
 | 
								$this->addContactToMaps( $contact );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$invoices = Invoice::scope()->get();
 | 
				
			||||||
 | 
							foreach ( $invoices as $invoice ) {
 | 
				
			||||||
 | 
								$this->addInvoiceToMaps( $invoice );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$products = Product::scope()->get();
 | 
				
			||||||
 | 
							foreach ( $products as $product ) {
 | 
				
			||||||
 | 
								$this->addProductToMaps( $product );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$projects = Project::scope()->get();
 | 
				
			||||||
 | 
							foreach ( $projects as $project ) {
 | 
				
			||||||
 | 
								$this->addProjectToMaps( $project );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$countries = Country::all();
 | 
				
			||||||
 | 
							foreach ( $countries as $country ) {
 | 
				
			||||||
 | 
								$this->maps['countries'][ strtolower( $country->name ) ]        = $country->id;
 | 
				
			||||||
 | 
								$this->maps['countries2'][ strtolower( $country->iso_3166_2 ) ] = $country->id;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$currencies = Currency::all();
 | 
				
			||||||
 | 
							foreach ( $currencies as $currency ) {
 | 
				
			||||||
 | 
								$this->maps['currencies'][ strtolower( $currency->code ) ] = $currency->id;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$payment_types = PaymentType::all();
 | 
				
			||||||
 | 
							foreach ( $payment_types as $payment_type ) {
 | 
				
			||||||
 | 
								$this->maps['payment_types'][ strtolower( $payment_type->name ) ] = $payment_type->id;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$vendors = Vendor::scope()->get();
 | 
				
			||||||
 | 
							foreach ( $vendors as $vendor ) {
 | 
				
			||||||
 | 
								$this->addVendorToMaps( $vendor );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$expenseCaegories = ExpenseCategory::scope()->get();
 | 
				
			||||||
 | 
							foreach ( $expenseCaegories as $category ) {
 | 
				
			||||||
 | 
								$this->addExpenseCategoryToMaps( $category );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$taxRates = TaxRate::scope()->get();
 | 
				
			||||||
 | 
							foreach ( $taxRates as $taxRate ) {
 | 
				
			||||||
 | 
								$name                             = trim( strtolower( $taxRate->name ) );
 | 
				
			||||||
 | 
								$this->maps['tax_rates'][ $name ] = $taxRate->rate;
 | 
				
			||||||
 | 
								$this->maps['tax_names'][ $name ] = $taxRate->name;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param Invoice $invoice
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						private function addInvoiceToMaps( Invoice $invoice ) {
 | 
				
			||||||
 | 
							if ( $number = strtolower( trim( $invoice->number ) ) ) {
 | 
				
			||||||
 | 
								$this->maps['invoices'][ $number ]                = $invoice;
 | 
				
			||||||
 | 
								$this->maps['invoice'][ $number ]                 = $invoice->id;
 | 
				
			||||||
 | 
								$this->maps['invoice_client'][ $number ]          = $invoice->client_id;
 | 
				
			||||||
 | 
								$this->maps['invoice_ids'][ $invoice->public_id ] = $invoice->id;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param Client $client
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						private function addClientToMaps( Client $client ) {
 | 
				
			||||||
 | 
							if ( $name = strtolower( trim( $client->name ) ) ) {
 | 
				
			||||||
 | 
								$this->maps['client'][ $name ]                  = $client->id;
 | 
				
			||||||
 | 
								$this->maps['client_ids'][ $client->public_id ] = $client->id;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if ( $client->contacts->count() ) {
 | 
				
			||||||
 | 
								$contact = $client->contacts[0];
 | 
				
			||||||
 | 
								if ( $email = strtolower( trim( $contact->email ) ) ) {
 | 
				
			||||||
 | 
									$this->maps['client'][ $email ] = $client->id;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if ( $name = strtolower( trim( $contact->first_name . ' ' . $contact->last_name ) ) ) {
 | 
				
			||||||
 | 
									$this->maps['client'][ $name ] = $client->id;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								$this->maps['client_ids'][ $client->public_id ] = $client->id;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param ClientContact $contact
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						private function addContactToMaps( ClientContact $contact ) {
 | 
				
			||||||
 | 
							if ( $key = strtolower( trim( $contact->email ) ) ) {
 | 
				
			||||||
 | 
								$this->maps['contact'][ $key ] = $contact;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param Product $product
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						private function addProductToMaps( Product $product ) {
 | 
				
			||||||
 | 
							if ( $key = strtolower( trim( $product->product_key ) ) ) {
 | 
				
			||||||
 | 
								$this->maps['product'][ $key ] = $product;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param Project $project
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						private function addProjectToMaps( Project $project ) {
 | 
				
			||||||
 | 
							if ( $key = strtolower( trim( $project->name ) ) ) {
 | 
				
			||||||
 | 
								$this->maps['project'][ $key ] = $project;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private function addVendorToMaps( Vendor $vendor ) {
 | 
				
			||||||
 | 
							$this->maps['vendor'][ strtolower( $vendor->name ) ] = $vendor->id;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private function addExpenseCategoryToMaps( ExpenseCategory $category ) {
 | 
				
			||||||
 | 
							if ( $name = strtolower( $category->name ) ) {
 | 
				
			||||||
 | 
								$this->maps['expense_category'][ $name ] = $category->id;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function setUser($record)
 | 
						private function getUserIDForRecord( $record ) {
 | 
				
			||||||
    {
 | 
							if ( ! empty( $record['user_id'] ) ) {
 | 
				
			||||||
        $user_key_exists = array_search('client.user_id', $this->column_map);
 | 
								return $this->findUser( $record['user_id'] );
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($user_key_exists) {
 | 
					 | 
				
			||||||
            return $this->findUser($record[$user_key_exists]);
 | 
					 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			return $this->company->owner()->id;
 | 
								return $this->company->owner()->id;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function findUser($user_hash)
 | 
						private function findUser( $user_hash ) {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
		$user = User::where( 'company_id', $this->company->id )
 | 
							$user = User::where( 'company_id', $this->company->id )
 | 
				
			||||||
					->where( \DB::raw( 'CONCAT_WS(" ", first_name, last_name)' ), 'like', '%' . $user_hash . '%' )
 | 
										->where( \DB::raw( 'CONCAT_WS(" ", first_name, last_name)' ), 'like', '%' . $user_hash . '%' )
 | 
				
			||||||
					->first();
 | 
										->first();
 | 
				
			||||||
@ -342,9 +577,12 @@ class CSVImport implements ShouldQueue
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function getCsvData()
 | 
						private function getCsvData( $entityType ) {
 | 
				
			||||||
    {
 | 
							$base64_encoded_csv = Cache::get( $this->hash . '-' . $entityType );
 | 
				
			||||||
        $base64_encoded_csv = Cache::get($this->hash);
 | 
							if ( empty( $base64_encoded_csv ) ) {
 | 
				
			||||||
 | 
								return null;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$csv = base64_decode( $base64_encoded_csv );
 | 
							$csv = base64_decode( $base64_encoded_csv );
 | 
				
			||||||
		$csv = Reader::createFromString( $csv );
 | 
							$csv = Reader::createFromString( $csv );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -355,7 +593,7 @@ class CSVImport implements ShouldQueue
 | 
				
			|||||||
			$headers = $data[0];
 | 
								$headers = $data[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Remove Invoice Ninja headers
 | 
								// Remove Invoice Ninja headers
 | 
				
			||||||
            if (count($headers) && count($data) > 4) {
 | 
								if ( count( $headers ) && count( $data ) > 4 && $this->import_type === 'csv' ) {
 | 
				
			||||||
				$firstCell = $headers[0];
 | 
									$firstCell = $headers[0];
 | 
				
			||||||
				if ( strstr( $firstCell, config( 'ninja.app_name' ) ) ) {
 | 
									if ( strstr( $firstCell, config( 'ninja.app_name' ) ) ) {
 | 
				
			||||||
					array_shift( $data ); // Invoice Ninja...
 | 
										array_shift( $data ); // Invoice Ninja...
 | 
				
			||||||
 | 
				
			|||||||
@ -11,10 +11,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Jobs\Invoice;
 | 
					namespace App\Jobs\Invoice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Jobs\Mail\BaseMailerJob;
 | 
					use App\Jobs\Mail\NinjaMailerJob;
 | 
				
			||||||
 | 
					use App\Jobs\Mail\NinjaMailerObject;
 | 
				
			||||||
use App\Jobs\Util\UnlinkFile;
 | 
					use App\Jobs\Util\UnlinkFile;
 | 
				
			||||||
use App\Mail\DownloadInvoices;
 | 
					use App\Mail\DownloadInvoices;
 | 
				
			||||||
use App\Models\Company;
 | 
					use App\Models\Company;
 | 
				
			||||||
 | 
					use App\Models\User;
 | 
				
			||||||
use App\Utils\TempFile;
 | 
					use App\Utils\TempFile;
 | 
				
			||||||
use Illuminate\Bus\Queueable;
 | 
					use Illuminate\Bus\Queueable;
 | 
				
			||||||
use Illuminate\Contracts\Queue\ShouldQueue;
 | 
					use Illuminate\Contracts\Queue\ShouldQueue;
 | 
				
			||||||
@ -26,7 +28,7 @@ use Illuminate\Support\Facades\Storage;
 | 
				
			|||||||
use ZipStream\Option\Archive;
 | 
					use ZipStream\Option\Archive;
 | 
				
			||||||
use ZipStream\ZipStream;
 | 
					use ZipStream\ZipStream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ZipInvoices extends BaseMailerJob implements ShouldQueue
 | 
					class ZipInvoices implements ShouldQueue
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 | 
					    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -34,7 +36,7 @@ class ZipInvoices extends BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private $company;
 | 
					    private $company;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private $email;
 | 
					    private $user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public $settings;
 | 
					    public $settings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -46,13 +48,13 @@ class ZipInvoices extends BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
     * Create a new job instance.
 | 
					     * Create a new job instance.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function __construct($invoices, Company $company, $email)
 | 
					    public function __construct($invoices, Company $company, User $user)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->invoices = $invoices;
 | 
					        $this->invoices = $invoices;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->company = $company;
 | 
					        $this->company = $company;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->email = $email;
 | 
					        $this->user = $user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->settings = $company->settings;
 | 
					        $this->settings = $company->settings;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -90,14 +92,13 @@ class ZipInvoices extends BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        fclose($tempStream);
 | 
					        fclose($tempStream);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->setMailDriver();
 | 
					        $nmo = new NinjaMailerObject;
 | 
				
			||||||
 | 
					        $nmo->mailable = new DownloadInvoices(Storage::disk(config('filesystems.default'))->url($path.$file_name), $this->company);
 | 
				
			||||||
 | 
					        $nmo->to_user = $this->user;
 | 
				
			||||||
 | 
					        $nmo->settings = $this->settings;
 | 
				
			||||||
 | 
					        $nmo->company = $this->company;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        try {
 | 
					        NinjaMailerJob::dispatch($nmo);
 | 
				
			||||||
            Mail::to($this->email)
 | 
					 | 
				
			||||||
                ->send(new DownloadInvoices(Storage::disk(config('filesystems.default'))->url($path.$file_name), $this->company));
 | 
					 | 
				
			||||||
        } catch (\Exception $e) {
 | 
					 | 
				
			||||||
            // //$this->failed($e);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        UnlinkFile::dispatch(config('filesystems.default'), $path.$file_name)->delay(now()->addHours(1));
 | 
					        UnlinkFile::dispatch(config('filesystems.default'), $path.$file_name)->delay(now()->addHours(1));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,120 +0,0 @@
 | 
				
			|||||||
<?php
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Invoice Ninja (https://invoiceninja.com).
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @license https://opensource.org/licenses/AAL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace App\Jobs\Mail;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use App\DataMapper\Analytics\EmailFailure;
 | 
					 | 
				
			||||||
use App\Jobs\Util\SystemLogger;
 | 
					 | 
				
			||||||
use App\Libraries\Google\Google;
 | 
					 | 
				
			||||||
use App\Models\SystemLog;
 | 
					 | 
				
			||||||
use App\Models\User;
 | 
					 | 
				
			||||||
use App\Providers\MailServiceProvider;
 | 
					 | 
				
			||||||
use App\Utils\Ninja;
 | 
					 | 
				
			||||||
use App\Utils\Traits\MakesHash;
 | 
					 | 
				
			||||||
use Illuminate\Bus\Queueable;
 | 
					 | 
				
			||||||
use Illuminate\Contracts\Queue\ShouldQueue;
 | 
					 | 
				
			||||||
use Illuminate\Foundation\Bus\Dispatchable;
 | 
					 | 
				
			||||||
use Illuminate\Queue\InteractsWithQueue;
 | 
					 | 
				
			||||||
use Illuminate\Queue\SerializesModels;
 | 
					 | 
				
			||||||
use Illuminate\Support\Facades\App;
 | 
					 | 
				
			||||||
use Illuminate\Support\Facades\Config;
 | 
					 | 
				
			||||||
use Illuminate\Support\Facades\Lang;
 | 
					 | 
				
			||||||
use Turbo124\Beacon\Facades\LightLogs;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
Multi Mailer implemented
 | 
					 | 
				
			||||||
@Deprecated 14/02/2021
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class BaseMailerJob implements ShouldQueue
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, MakesHash;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public $tries = 5; //number of retries
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public $backoff = 5; //seconds to wait until retry
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public $deleteWhenMissingModels = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function setMailDriver()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        /* Singletons need to be rebooted each time just in case our Locale is changing*/
 | 
					 | 
				
			||||||
        App::forgetInstance('translator');
 | 
					 | 
				
			||||||
        App::forgetInstance('mail.manager'); //singletons must be destroyed!
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* Inject custom translations if any exist */
 | 
					 | 
				
			||||||
        Lang::replace(Ninja::transformTranslations($this->settings));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        switch ($this->settings->email_sending_method) {
 | 
					 | 
				
			||||||
            case 'default':
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            case 'gmail':
 | 
					 | 
				
			||||||
                $this->setGmailMailer();
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            default:
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function setGmailMailer()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $sending_user = $this->settings->gmail_sending_user_id;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $user = User::find($this->decodePrimaryKey($sending_user));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $google = (new Google())->init();
 | 
					 | 
				
			||||||
        $google->getClient()->setAccessToken(json_encode($user->oauth_user_token));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($google->getClient()->isAccessTokenExpired()) {
 | 
					 | 
				
			||||||
            $google->refreshToken($user);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /*
 | 
					 | 
				
			||||||
         *  Now that our token is refreshed and valid we can boot the
 | 
					 | 
				
			||||||
         *  mail driver at runtime and also set the token which will persist
 | 
					 | 
				
			||||||
         *  just for this request.
 | 
					 | 
				
			||||||
        */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // config(['mail.driver' => 'gmail']);
 | 
					 | 
				
			||||||
        // config(['services.gmail.token' => $user->oauth_user_token->access_token]);
 | 
					 | 
				
			||||||
        // config(['mail.from.address' => $user->email]);
 | 
					 | 
				
			||||||
        // config(['mail.from.name' => $user->present()->name()]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //(new MailServiceProvider(app()))->register();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        nlog("after registering mail service provider");
 | 
					 | 
				
			||||||
        nlog(config('services.gmail.token'));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function logMailError($errors, $recipient_object)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        SystemLogger::dispatch(
 | 
					 | 
				
			||||||
            $errors,
 | 
					 | 
				
			||||||
            SystemLog::CATEGORY_MAIL,
 | 
					 | 
				
			||||||
            SystemLog::EVENT_MAIL_SEND,
 | 
					 | 
				
			||||||
            SystemLog::TYPE_FAILURE,
 | 
					 | 
				
			||||||
            $recipient_object
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function failed($exception = null)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        nlog('mailer job failed');
 | 
					 | 
				
			||||||
        nlog($exception->getMessage());
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        $job_failure = new EmailFailure();
 | 
					 | 
				
			||||||
        $job_failure->string_metric5 = get_parent_class($this);
 | 
					 | 
				
			||||||
        $job_failure->string_metric6 = $exception->getMessage();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        LightLogs::create($job_failure)
 | 
					 | 
				
			||||||
                 ->batch();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,83 +0,0 @@
 | 
				
			|||||||
<?php
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Invoice Ninja (https://invoiceninja.com).
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @license https://opensource.org/licenses/AAL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace App\Jobs\Mail;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use App\Libraries\MultiDB;
 | 
					 | 
				
			||||||
use App\Models\ClientContact;
 | 
					 | 
				
			||||||
use App\Models\Company;
 | 
					 | 
				
			||||||
use App\Models\User;
 | 
					 | 
				
			||||||
use Illuminate\Bus\Queueable;
 | 
					 | 
				
			||||||
use Illuminate\Contracts\Queue\ShouldQueue;
 | 
					 | 
				
			||||||
use Illuminate\Foundation\Bus\Dispatchable;
 | 
					 | 
				
			||||||
use Illuminate\Mail\Mailable;
 | 
					 | 
				
			||||||
use Illuminate\Queue\InteractsWithQueue;
 | 
					 | 
				
			||||||
use Illuminate\Queue\SerializesModels;
 | 
					 | 
				
			||||||
use Illuminate\Support\Facades\Mail;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*Multi Mailer Router implemented*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class MailRouter extends BaseMailerJob implements ShouldQueue
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public $mailable;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public $company;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public $to_user; //User or ClientContact
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public $sending_method; //not sure if we even need this
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public $settings;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function __construct(Mailable $mailable, Company $company, $to_user, $sending_method = null)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->mailable = $mailable;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->company = $company;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->to_user = $to_user;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->sending_method = $sending_method;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($to_user instanceof ClientContact) {
 | 
					 | 
				
			||||||
            $this->settings = $to_user->client->getMergedSettings();
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            $this->settings = $this->company->settings;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function handle()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        /*If we are migrating data we don't want to fire these notification*/
 | 
					 | 
				
			||||||
        if ($this->company->is_disabled) {
 | 
					 | 
				
			||||||
            return true;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        MultiDB::setDb($this->company->db);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //if we need to set an email driver do it now
 | 
					 | 
				
			||||||
        $this->setMailDriver();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //send email
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            Mail::to($this->to_user->email)
 | 
					 | 
				
			||||||
                ->send($this->mailable);
 | 
					 | 
				
			||||||
        } catch (\Exception $e) {
 | 
					 | 
				
			||||||
            //$this->failed($e);
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            if ($this->to_user instanceof ClientContact) {
 | 
					 | 
				
			||||||
                $this->logMailError($e->getMessage(), $this->to_user->client);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -13,17 +13,21 @@ namespace App\Jobs\Mail;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use App\DataMapper\Analytics\EmailFailure;
 | 
					use App\DataMapper\Analytics\EmailFailure;
 | 
				
			||||||
use App\Events\Invoice\InvoiceWasEmailedAndFailed;
 | 
					use App\Events\Invoice\InvoiceWasEmailedAndFailed;
 | 
				
			||||||
 | 
					use App\Events\Payment\PaymentWasEmailedAndFailed;
 | 
				
			||||||
use App\Jobs\Mail\NinjaMailerObject;
 | 
					use App\Jobs\Mail\NinjaMailerObject;
 | 
				
			||||||
use App\Jobs\Util\SystemLogger;
 | 
					use App\Jobs\Util\SystemLogger;
 | 
				
			||||||
use App\Libraries\Google\Google;
 | 
					use App\Libraries\Google\Google;
 | 
				
			||||||
use App\Libraries\MultiDB;
 | 
					use App\Libraries\MultiDB;
 | 
				
			||||||
use App\Mail\TemplateEmail;
 | 
					use App\Mail\TemplateEmail;
 | 
				
			||||||
use App\Models\ClientContact;
 | 
					use App\Models\ClientContact;
 | 
				
			||||||
 | 
					use App\Models\Invoice;
 | 
				
			||||||
 | 
					use App\Models\Payment;
 | 
				
			||||||
use App\Models\SystemLog;
 | 
					use App\Models\SystemLog;
 | 
				
			||||||
use App\Models\User;
 | 
					use App\Models\User;
 | 
				
			||||||
use App\Providers\MailServiceProvider;
 | 
					use App\Providers\MailServiceProvider;
 | 
				
			||||||
use App\Utils\Ninja;
 | 
					use App\Utils\Ninja;
 | 
				
			||||||
use App\Utils\Traits\MakesHash;
 | 
					use App\Utils\Traits\MakesHash;
 | 
				
			||||||
 | 
					use Dacastro4\LaravelGmail\Facade\LaravelGmail;
 | 
				
			||||||
use Illuminate\Bus\Queueable;
 | 
					use Illuminate\Bus\Queueable;
 | 
				
			||||||
use Illuminate\Contracts\Queue\ShouldQueue;
 | 
					use Illuminate\Contracts\Queue\ShouldQueue;
 | 
				
			||||||
use Illuminate\Foundation\Bus\Dispatchable;
 | 
					use Illuminate\Foundation\Bus\Dispatchable;
 | 
				
			||||||
@ -34,7 +38,6 @@ use Illuminate\Support\Facades\Config;
 | 
				
			|||||||
use Illuminate\Support\Facades\Lang;
 | 
					use Illuminate\Support\Facades\Lang;
 | 
				
			||||||
use Illuminate\Support\Facades\Mail;
 | 
					use Illuminate\Support\Facades\Mail;
 | 
				
			||||||
use Turbo124\Beacon\Facades\LightLogs;
 | 
					use Turbo124\Beacon\Facades\LightLogs;
 | 
				
			||||||
use Dacastro4\LaravelGmail\Facade\LaravelGmail;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*Multi Mailer implemented*/
 | 
					/*Multi Mailer implemented*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -77,11 +80,9 @@ class NinjaMailerJob implements ShouldQueue
 | 
				
			|||||||
        } catch (\Exception $e) {
 | 
					        } catch (\Exception $e) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            nlog("error failed with {$e->getMessage()}");
 | 
					            nlog("error failed with {$e->getMessage()}");
 | 
				
			||||||
 | 
					            nlog($e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($this->nmo->to_user instanceof ClientContact) 
 | 
					            if($this->nmo->entity)
 | 
				
			||||||
                $this->logMailError($e->getMessage(), $this->nmo->to_user->client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if($this->nmo->entity_string)
 | 
					 | 
				
			||||||
                $this->entityEmailFailed($e->getMessage());
 | 
					                $this->entityEmailFailed($e->getMessage());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -89,15 +90,22 @@ class NinjaMailerJob implements ShouldQueue
 | 
				
			|||||||
    /* Switch statement to handle failure notifications */
 | 
					    /* Switch statement to handle failure notifications */
 | 
				
			||||||
    private function entityEmailFailed($message)
 | 
					    private function entityEmailFailed($message)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        switch ($this->nmo->entity_string) {
 | 
					        $class = get_class($this->nmo->entity);
 | 
				
			||||||
            case 'invoice':
 | 
					
 | 
				
			||||||
 | 
					        switch ($class) {
 | 
				
			||||||
 | 
					            case Invoice::class:
 | 
				
			||||||
                event(new InvoiceWasEmailedAndFailed($this->nmo->invitation, $this->nmo->company, $message, $this->nmo->reminder_template, Ninja::eventVars()));
 | 
					                event(new InvoiceWasEmailedAndFailed($this->nmo->invitation, $this->nmo->company, $message, $this->nmo->reminder_template, Ninja::eventVars()));
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
 | 
					            case Payment::class:
 | 
				
			||||||
 | 
					                event(new PaymentWasEmailedAndFailed($this->nmo->entity, $this->nmo->company, $message, Ninja::eventVars()));
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
                # code...
 | 
					                # code...
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($this->nmo->to_user instanceof ClientContact) 
 | 
				
			||||||
 | 
					            $this->logMailError($message, $this->nmo->to_user->client);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function setMailDriver()
 | 
					    private function setMailDriver()
 | 
				
			||||||
@ -113,7 +121,7 @@ class NinjaMailerJob implements ShouldQueue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        switch ($this->nmo->settings->email_sending_method) {
 | 
					        switch ($this->nmo->settings->email_sending_method) {
 | 
				
			||||||
            case 'default':
 | 
					            case 'default':
 | 
				
			||||||
                config(['mail.driver' => config('mail.default')]);
 | 
					                //config(['mail.driver' => config('mail.default')]);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case 'gmail':
 | 
					            case 'gmail':
 | 
				
			||||||
                $this->setGmailMailer();
 | 
					                $this->setGmailMailer();
 | 
				
			||||||
 | 
				
			|||||||
@ -35,4 +35,7 @@ class NinjaMailerObject
 | 
				
			|||||||
    public $invitation = FALSE;
 | 
					    public $invitation = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public $template = FALSE;
 | 
					    public $template = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $entity = FALSE;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -28,7 +28,7 @@ use Illuminate\Support\Facades\Mail;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/*Multi Mailer implemented*/
 | 
					/*Multi Mailer implemented*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PaymentFailureMailer extends BaseMailerJob implements ShouldQueue
 | 
					class PaymentFailureMailer implements ShouldQueue
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, UserNotifies;
 | 
					    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, UserNotifies;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,8 @@ namespace App\Jobs\Payment;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use App\Events\Payment\PaymentWasEmailed;
 | 
					use App\Events\Payment\PaymentWasEmailed;
 | 
				
			||||||
use App\Events\Payment\PaymentWasEmailedAndFailed;
 | 
					use App\Events\Payment\PaymentWasEmailedAndFailed;
 | 
				
			||||||
use App\Jobs\Mail\BaseMailerJob;
 | 
					use App\Jobs\Mail\NinjaMailerJob;
 | 
				
			||||||
 | 
					use App\Jobs\Mail\NinjaMailerObject;
 | 
				
			||||||
use App\Libraries\MultiDB;
 | 
					use App\Libraries\MultiDB;
 | 
				
			||||||
use App\Mail\Engine\PaymentEmailEngine;
 | 
					use App\Mail\Engine\PaymentEmailEngine;
 | 
				
			||||||
use App\Mail\TemplateEmail;
 | 
					use App\Mail\TemplateEmail;
 | 
				
			||||||
@ -28,7 +29,7 @@ use Illuminate\Queue\InteractsWithQueue;
 | 
				
			|||||||
use Illuminate\Queue\SerializesModels;
 | 
					use Illuminate\Queue\SerializesModels;
 | 
				
			||||||
use Illuminate\Support\Facades\Mail;
 | 
					use Illuminate\Support\Facades\Mail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class EmailPayment extends BaseMailerJob implements ShouldQueue
 | 
					class EmailPayment implements ShouldQueue
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 | 
					    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -66,27 +67,24 @@ class EmailPayment extends BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function handle()
 | 
					    public function handle()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ($this->company->is_disabled) {
 | 
					        if ($this->company->is_disabled) 
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					        
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if ($this->contact->email) {
 | 
					        if ($this->contact->email) {
 | 
				
			||||||
            MultiDB::setDb($this->company->db);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //if we need to set an email driver do it now
 | 
					            MultiDB::setDb($this->company->db);
 | 
				
			||||||
            $this->setMailDriver();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $email_builder = (new PaymentEmailEngine($this->payment, $this->contact))->build();
 | 
					            $email_builder = (new PaymentEmailEngine($this->payment, $this->contact))->build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            try {
 | 
					            $nmo = new NinjaMailerObject;
 | 
				
			||||||
                $mail = Mail::to($this->contact->email, $this->contact->present()->name());
 | 
					            $nmo->mailable = new TemplateEmail($email_builder, $this->contact);
 | 
				
			||||||
                $mail->send(new TemplateEmail($email_builder, $this->contact));
 | 
					            $nmo->to_user = $this->contact;
 | 
				
			||||||
            } catch (\Exception $e) {
 | 
					            $nmo->settings = $this->settings;
 | 
				
			||||||
                nlog("mailing failed with message " . $e->getMessage());
 | 
					            $nmo->company = $this->company;
 | 
				
			||||||
                event(new PaymentWasEmailedAndFailed($this->payment, $this->company, Mail::failures(), Ninja::eventVars()));
 | 
					            $nmo->entity = $this->payment;
 | 
				
			||||||
                //$this->failed($e);
 | 
					
 | 
				
			||||||
                return $this->logMailError($e->getMessage(), $this->payment->client);
 | 
					            NinjaMailerJob::dispatch($nmo);
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            event(new PaymentWasEmailed($this->payment, $this->payment->company, Ninja::eventVars()));
 | 
					            event(new PaymentWasEmailed($this->payment, $this->payment->company, Ninja::eventVars()));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -11,10 +11,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Jobs\User;
 | 
					namespace App\Jobs\User;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use App\Jobs\Mail\BaseMailerJob;
 | 
					use App\Jobs\Mail\NinjaMailerJob;
 | 
				
			||||||
 | 
					use App\Jobs\Mail\NinjaMailerObject;
 | 
				
			||||||
use App\Libraries\MultiDB;
 | 
					use App\Libraries\MultiDB;
 | 
				
			||||||
use App\Mail\User\UserNotificationMailer;
 | 
					use App\Mail\User\UserNotificationMailer;
 | 
				
			||||||
use App\Models\Company;
 | 
					use App\Models\Company;
 | 
				
			||||||
 | 
					use App\Models\User;
 | 
				
			||||||
use Illuminate\Bus\Queueable;
 | 
					use Illuminate\Bus\Queueable;
 | 
				
			||||||
use Illuminate\Contracts\Queue\ShouldQueue;
 | 
					use Illuminate\Contracts\Queue\ShouldQueue;
 | 
				
			||||||
use Illuminate\Foundation\Bus\Dispatchable;
 | 
					use Illuminate\Foundation\Bus\Dispatchable;
 | 
				
			||||||
@ -23,13 +25,13 @@ use Illuminate\Queue\SerializesModels;
 | 
				
			|||||||
use Illuminate\Support\Facades\Mail;
 | 
					use Illuminate\Support\Facades\Mail;
 | 
				
			||||||
use stdClass;
 | 
					use stdClass;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UserEmailChanged extends BaseMailerJob implements ShouldQueue
 | 
					class UserEmailChanged implements ShouldQueue
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 | 
					    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected $new_email;
 | 
					    protected $new_user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected $old_email;
 | 
					    protected $old_user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected $company;
 | 
					    protected $company;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -42,26 +44,24 @@ class UserEmailChanged extends BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
     * @param string $old_email
 | 
					     * @param string $old_email
 | 
				
			||||||
     * @param Company $company
 | 
					     * @param Company $company
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function __construct(string $new_email, string $old_email, Company $company)
 | 
					    public function __construct(User $new_user, $old_user, Company $company)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->new_email = $new_email;
 | 
					        $this->new_user = $new_user;
 | 
				
			||||||
        $this->old_email = $old_email;
 | 
					        $this->old_user = $old_user;
 | 
				
			||||||
        $this->company = $company;
 | 
					        $this->company = $company;
 | 
				
			||||||
        $this->settings = $this->company->settings;
 | 
					        $this->settings = $this->company->settings;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function handle()
 | 
					    public function handle()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ($this->company->is_disabled) {
 | 
					        nlog("notifying user of email change");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($this->company->is_disabled) 
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        //Set DB
 | 
					        //Set DB
 | 
				
			||||||
        MultiDB::setDb($this->company->db);
 | 
					        MultiDB::setDb($this->company->db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //If we need to set an email driver do it now
 | 
					 | 
				
			||||||
        $this->setMailDriver();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /*Build the object*/
 | 
					        /*Build the object*/
 | 
				
			||||||
        $mail_obj = new stdClass;
 | 
					        $mail_obj = new stdClass;
 | 
				
			||||||
        $mail_obj->subject = ctrans('texts.email_address_changed');
 | 
					        $mail_obj->subject = ctrans('texts.email_address_changed');
 | 
				
			||||||
@ -71,17 +71,19 @@ class UserEmailChanged extends BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
        $mail_obj->data = $this->getData();
 | 
					        $mail_obj->data = $this->getData();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //Send email via a Mailable class
 | 
					        //Send email via a Mailable class
 | 
				
			||||||
        //
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            Mail::to($this->old_email)
 | 
					 | 
				
			||||||
            ->send(new UserNotificationMailer($mail_obj));
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
            Mail::to($this->new_email)
 | 
					        $nmo = new NinjaMailerObject;
 | 
				
			||||||
            ->send(new UserNotificationMailer($mail_obj));
 | 
					        $nmo->mailable = new UserNotificationMailer($mail_obj);
 | 
				
			||||||
        } catch (\Exception $e) {
 | 
					        $nmo->settings = $this->settings;
 | 
				
			||||||
            //$this->failed($e);
 | 
					        $nmo->company = $this->company;
 | 
				
			||||||
            $this->logMailError($e->getMessage(), $this->company->owner());
 | 
					        $nmo->to_user = $this->old_user;
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					        NinjaMailerJob::dispatch($nmo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $nmo->to_user = $this->new_user;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        NinjaMailerJob::dispatch($nmo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function getData()
 | 
					    private function getData()
 | 
				
			||||||
@ -90,8 +92,8 @@ class UserEmailChanged extends BaseMailerJob implements ShouldQueue
 | 
				
			|||||||
            'title' => ctrans('texts.email_address_changed'),
 | 
					            'title' => ctrans('texts.email_address_changed'),
 | 
				
			||||||
            'message' => ctrans(
 | 
					            'message' => ctrans(
 | 
				
			||||||
                'texts.email_address_changed_message',
 | 
					                'texts.email_address_changed_message',
 | 
				
			||||||
                ['old_email' => $this->old_email,
 | 
					                ['old_email' => $this->old_user->email,
 | 
				
			||||||
                'new_email' => $this->new_email,
 | 
					                'new_email' => $this->new_user->email,
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            'url' => config('ninja.app_url'),
 | 
					            'url' => config('ninja.app_url'),
 | 
				
			||||||
 | 
				
			|||||||
@ -52,7 +52,7 @@ class CreditEmailedNotification implements ShouldQueue
 | 
				
			|||||||
        foreach ($event->invitation->company->company_users as $company_user) {
 | 
					        foreach ($event->invitation->company->company_users as $company_user) {
 | 
				
			||||||
            $user = $company_user->user;
 | 
					            $user = $company_user->user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $notification = new EntitySentNotification($event->invitation, 'credit');
 | 
					            // $notification = new EntitySentNotification($event->invitation, 'credit');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $methods = $this->findUserNotificationTypes($event->invitation, $company_user, 'credit', ['all_notifications', 'credit_sent']);
 | 
					            $methods = $this->findUserNotificationTypes($event->invitation, $company_user, 'credit', ['all_notifications', 'credit_sent']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -66,9 +66,9 @@ class CreditEmailedNotification implements ShouldQueue
 | 
				
			|||||||
                $first_notification_sent = false;
 | 
					                $first_notification_sent = false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $notification->method = $methods;
 | 
					            // $notification->method = $methods;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $user->notify($notification);
 | 
					            // $user->notify($notification);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -57,7 +57,7 @@ class InvoiceEmailedNotification implements ShouldQueue
 | 
				
			|||||||
            $user = $company_user->user;
 | 
					            $user = $company_user->user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* This is only here to handle the alternate message channels - ie Slack */
 | 
					            /* This is only here to handle the alternate message channels - ie Slack */
 | 
				
			||||||
            $notification = new EntitySentNotification($event->invitation, 'invoice');
 | 
					            // $notification = new EntitySentNotification($event->invitation, 'invoice');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* Returns an array of notification methods */
 | 
					            /* Returns an array of notification methods */
 | 
				
			||||||
            $methods = $this->findUserNotificationTypes($event->invitation, $company_user, 'invoice', ['all_notifications', 'invoice_sent']);
 | 
					            $methods = $this->findUserNotificationTypes($event->invitation, $company_user, 'invoice', ['all_notifications', 'invoice_sent']);
 | 
				
			||||||
@ -76,10 +76,10 @@ class InvoiceEmailedNotification implements ShouldQueue
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* Override the methods in the Notification Class */
 | 
					            /* Override the methods in the Notification Class */
 | 
				
			||||||
            $notification->method = $methods;
 | 
					            // $notification->method = $methods;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* Notify on the alternate channels */
 | 
					            //  Notify on the alternate channels 
 | 
				
			||||||
            $user->notify($notification);
 | 
					            // $user->notify($notification);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,7 @@ use App\Notifications\Admin\EntitySentNotification;
 | 
				
			|||||||
use App\Utils\Traits\Notifications\UserNotifies;
 | 
					use App\Utils\Traits\Notifications\UserNotifies;
 | 
				
			||||||
use Illuminate\Contracts\Queue\ShouldQueue;
 | 
					use Illuminate\Contracts\Queue\ShouldQueue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class InvoiceFailedEmailNotification implements ShouldQueue
 | 
					class InvoiceFailedEmailNotification
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    use UserNotifies;
 | 
					    use UserNotifies;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -54,7 +54,7 @@ class InvoiceFailedEmailNotification implements ShouldQueue
 | 
				
			|||||||
        foreach ($event->invitation->company->company_users as $company_user) {
 | 
					        foreach ($event->invitation->company->company_users as $company_user) {
 | 
				
			||||||
            $user = $company_user->user;
 | 
					            $user = $company_user->user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $notification = new EntitySentNotification($event->invitation, 'invoice');
 | 
					            // $notification = new EntitySentNotification($event->invitation, 'invoice');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $methods = $this->findUserNotificationTypes($event->invitation, $company_user, 'invoice', ['all_notifications', 'invoice_sent']);
 | 
					            $methods = $this->findUserNotificationTypes($event->invitation, $company_user, 'invoice', ['all_notifications', 'invoice_sent']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -68,9 +68,9 @@ class InvoiceFailedEmailNotification implements ShouldQueue
 | 
				
			|||||||
                $first_notification_sent = false;
 | 
					                $first_notification_sent = false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $notification->method = $methods;
 | 
					            // $notification->method = $methods;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $user->notify($notification);
 | 
					            // $user->notify($notification);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -47,7 +47,7 @@ class InvitationViewedListener implements ShouldQueue
 | 
				
			|||||||
        $entity_name = lcfirst(class_basename($event->entity));
 | 
					        $entity_name = lcfirst(class_basename($event->entity));
 | 
				
			||||||
        $invitation = $event->invitation;
 | 
					        $invitation = $event->invitation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $notification = new EntityViewedNotification($invitation, $entity_name);
 | 
					        // $notification = new EntityViewedNotification($invitation, $entity_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $nmo = new NinjaMailerObject;
 | 
					        $nmo = new NinjaMailerObject;
 | 
				
			||||||
        $nmo->mailable = new NinjaMailer( (new EntityViewedObject($invitation, $entity_name))->build() );
 | 
					        $nmo->mailable = new NinjaMailer( (new EntityViewedObject($invitation, $entity_name))->build() );
 | 
				
			||||||
@ -68,16 +68,16 @@ class InvitationViewedListener implements ShouldQueue
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $notification->method = $methods;
 | 
					            // $notification->method = $methods;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $company_user->user->notify($notification);
 | 
					            // $company_user->user->notify($notification);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (isset($invitation->company->slack_webhook_url)) {
 | 
					        // if (isset($invitation->company->slack_webhook_url)) {
 | 
				
			||||||
            $notification->method = ['slack'];
 | 
					        //     $notification->method = ['slack'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Notification::route('slack', $invitation->company->slack_webhook_url)
 | 
					            // Notification::route('slack', $invitation->company->slack_webhook_url)
 | 
				
			||||||
            //             ->notify($notification);
 | 
					            //             ->notify($notification);
 | 
				
			||||||
        }
 | 
					        // }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -69,19 +69,19 @@ class PaymentNotification implements ShouldQueue
 | 
				
			|||||||
                NinjaMailerJob::dispatch($nmo);
 | 
					                NinjaMailerJob::dispatch($nmo);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $notification = new NewPaymentNotification($payment, $payment->company);
 | 
					            // $notification = new NewPaymentNotification($payment, $payment->company);
 | 
				
			||||||
            $notification->method = $methods;
 | 
					            // $notification->method = $methods;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($user) {
 | 
					            // if ($user) {
 | 
				
			||||||
                $user->notify($notification);
 | 
					            //     $user->notify($notification);
 | 
				
			||||||
            }
 | 
					            // }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /*Company Notifications*/
 | 
					        /*Company Notifications*/
 | 
				
			||||||
        if (isset($payment->company->slack_webhook_url)) {
 | 
					        // if (isset($payment->company->slack_webhook_url)) {
 | 
				
			||||||
            Notification::route('slack', $payment->company->slack_webhook_url)
 | 
					        //     Notification::route('slack', $payment->company->slack_webhook_url)
 | 
				
			||||||
                ->notify(new NewPaymentNotification($payment, $payment->company, true));
 | 
					        //         ->notify(new NewPaymentNotification($payment, $payment->company, true));
 | 
				
			||||||
        }
 | 
					        // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /*Google Analytics Track Revenue*/
 | 
					        /*Google Analytics Track Revenue*/
 | 
				
			||||||
        if (isset($payment->company->google_analytics_key)) {
 | 
					        if (isset($payment->company->google_analytics_key)) {
 | 
				
			||||||
 | 
				
			|||||||
@ -53,7 +53,7 @@ class QuoteEmailedNotification implements ShouldQueue
 | 
				
			|||||||
        foreach ($event->invitation->company->company_users as $company_user) {
 | 
					        foreach ($event->invitation->company->company_users as $company_user) {
 | 
				
			||||||
            $user = $company_user->user;
 | 
					            $user = $company_user->user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $notification = new EntitySentNotification($event->invitation, 'quote');
 | 
					            // $notification = new EntitySentNotification($event->invitation, 'quote');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $methods = $this->findUserNotificationTypes($event->invitation, $company_user, 'quote', ['all_notifications', 'quote_sent']);
 | 
					            $methods = $this->findUserNotificationTypes($event->invitation, $company_user, 'quote', ['all_notifications', 'quote_sent']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -68,9 +68,9 @@ class QuoteEmailedNotification implements ShouldQueue
 | 
				
			|||||||
                $first_notification_sent = false;
 | 
					                $first_notification_sent = false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $notification->method = $methods;
 | 
					            // $notification->method = $methods;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $user->notify($notification);
 | 
					            // $user->notify($notification);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -131,6 +131,7 @@ class EntityFailedSendObject
 | 
				
			|||||||
                    'client' => $this->contact->present()->name(),
 | 
					                    'client' => $this->contact->present()->name(),
 | 
				
			||||||
                    'invoice' => $this->entity->number,
 | 
					                    'invoice' => $this->entity->number,
 | 
				
			||||||
                    'error' => $this->message,
 | 
					                    'error' => $this->message,
 | 
				
			||||||
 | 
					                    'contact' => $this->contact->present()->name(),
 | 
				
			||||||
                ]
 | 
					                ]
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            'url' => $this->invitation->getAdminLink(),
 | 
					            'url' => $this->invitation->getAdminLink(),
 | 
				
			||||||
 | 
				
			|||||||
@ -24,9 +24,6 @@ class DownloadInvoices extends Mailable
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Build the message.
 | 
					     * Build the message.
 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return $this
 | 
					 | 
				
			||||||
     * @throws \Laracasts\Presenter\Exceptions\PresenterException
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function build()
 | 
					    public function build()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,14 @@ use Illuminate\Database\Eloquent\Model;
 | 
				
			|||||||
use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException;
 | 
					use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException;
 | 
				
			||||||
use Illuminate\Support\Carbon;
 | 
					use Illuminate\Support\Carbon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class BaseModel
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @method scope() static
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @package App\Models
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class BaseModel extends Model
 | 
					class BaseModel extends Model
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    use MakesHash;
 | 
					    use MakesHash;
 | 
				
			||||||
 | 
				
			|||||||
@ -27,6 +27,13 @@ use Illuminate\Notifications\Notifiable;
 | 
				
			|||||||
use Illuminate\Support\Facades\Cache;
 | 
					use Illuminate\Support\Facades\Cache;
 | 
				
			||||||
use Laracasts\Presenter\PresentableTrait;
 | 
					use Laracasts\Presenter\PresentableTrait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class ClientContact
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @method scope() static
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @package App\Models
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class ClientContact extends Authenticatable implements HasLocalePreference
 | 
					class ClientContact extends Authenticatable implements HasLocalePreference
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    use Notifiable;
 | 
					    use Notifiable;
 | 
				
			||||||
@ -88,6 +95,27 @@ class ClientContact extends Authenticatable implements HasLocalePreference
 | 
				
			|||||||
        'client_id',
 | 
					        'client_id',
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						V2 type of scope
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function scopeCompany($query)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							$query->where('company_id', auth()->user()->companyId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return $query;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 V1 type of scope
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function scopeScope($query)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							$query->where($this->getTable().'.company_id', '=', auth()->user()->company()->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return $query;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function getEntityType()
 | 
					    public function getEntityType()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return self::class;
 | 
					        return self::class;
 | 
				
			||||||
 | 
				
			|||||||
@ -131,4 +131,9 @@ class Document extends BaseModel
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        return Storage::disk($this->disk)->url($this->url);
 | 
					        return Storage::disk($this->disk)->url($this->url);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function diskPath(): string
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return Storage::disk($this->disk)->path($this->url);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -22,9 +22,8 @@ use Illuminate\Queue\InteractsWithQueue;
 | 
				
			|||||||
use Illuminate\Queue\SerializesModels;
 | 
					use Illuminate\Queue\SerializesModels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//@deprecated
 | 
					//@deprecated
 | 
				
			||||||
class EntitySentNotification extends Notification implements ShouldQueue
 | 
					class EntitySentNotification extends Notification
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    //use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Create a new notification instance.
 | 
					     * Create a new notification instance.
 | 
				
			||||||
 | 
				
			|||||||
@ -21,9 +21,8 @@ use Illuminate\Notifications\Notification;
 | 
				
			|||||||
use Illuminate\Queue\InteractsWithQueue;
 | 
					use Illuminate\Queue\InteractsWithQueue;
 | 
				
			||||||
use Illuminate\Queue\SerializesModels;
 | 
					use Illuminate\Queue\SerializesModels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class EntityViewedNotification extends Notification implements ShouldQueue
 | 
					class EntityViewedNotification extends Notification
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    //use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Create a new notification instance.
 | 
					     * Create a new notification instance.
 | 
				
			||||||
 | 
				
			|||||||
@ -21,9 +21,8 @@ use Illuminate\Notifications\Notification;
 | 
				
			|||||||
use Illuminate\Queue\InteractsWithQueue;
 | 
					use Illuminate\Queue\InteractsWithQueue;
 | 
				
			||||||
use Illuminate\Queue\SerializesModels;
 | 
					use Illuminate\Queue\SerializesModels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NewPaymentNotification extends Notification implements ShouldQueue
 | 
					class NewPaymentNotification extends Notification
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  //  use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Create a new notification instance.
 | 
					     * Create a new notification instance.
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,7 @@ class BaseRepository
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    use MakesHash;
 | 
					    use MakesHash;
 | 
				
			||||||
    use SavesDocuments;
 | 
					    use SavesDocuments;
 | 
				
			||||||
 | 
						public    $import_mode = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @param $entity
 | 
					     * @param $entity
 | 
				
			||||||
 | 
				
			|||||||
@ -28,15 +28,13 @@ use Illuminate\Support\Carbon;
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * PaymentRepository.
 | 
					 * PaymentRepository.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class PaymentRepository extends BaseRepository
 | 
					class PaymentRepository extends BaseRepository {
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	use MakesHash;
 | 
						use MakesHash;
 | 
				
			||||||
	use SavesDocuments;
 | 
						use SavesDocuments;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected $credit_repo;
 | 
						protected $credit_repo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function __construct(CreditRepository $credit_repo)
 | 
						public function __construct( CreditRepository $credit_repo ) {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
		$this->credit_repo = $credit_repo;
 | 
							$this->credit_repo = $credit_repo;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -152,7 +150,7 @@ class PaymentRepository extends BaseRepository
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!$is_existing_payment) {
 | 
							if ( ! $is_existing_payment && ! $this->import_mode ) {
 | 
				
			||||||
			event( new PaymentWasCreated( $payment, $payment->company, Ninja::eventVars() ) );
 | 
								event( new PaymentWasCreated( $payment, $payment->company, Ninja::eventVars() ) );
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * client Ninja (https://clientninja.com).
 | 
					 * Invoice Ninja (https://invoiceninja.com).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @link https://github.com/clientninja/clientninja source repository
 | 
					 * @link https://github.com/invoiceninja/invoiceninja source repository
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
 | 
					 * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @license https://opensource.org/licenses/AAL
 | 
					 * @license https://opensource.org/licenses/AAL
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
				
			|||||||
@ -421,6 +421,10 @@ class Design extends BaseDesign
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function tableTotals(): array
 | 
					    public function tableTotals(): array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        $_variables = array_key_exists('variables', $this->context)
 | 
				
			||||||
 | 
					            ? $this->context['variables']
 | 
				
			||||||
 | 
					            : ['values' => ['$entity.public_notes' => nl2br($this->entity->public_notes), '$entity.terms' => $this->entity->terms, '$entity_footer' => $this->entity->footer], 'labels' => []];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($this->type == 'delivery_note') {
 | 
					        if ($this->type == 'delivery_note') {
 | 
				
			||||||
            return [];
 | 
					            return [];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -429,10 +433,11 @@ class Design extends BaseDesign
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $elements = [
 | 
					        $elements = [
 | 
				
			||||||
            ['element' => 'div', 'properties' => ['style' => 'display: flex; flex-direction: column;'], 'elements' => [
 | 
					            ['element' => 'div', 'properties' => ['style' => 'display: flex; flex-direction: column;'], 'elements' => [
 | 
				
			||||||
                ['element' => 'p', 'content' => '$entity.public_notes', 'properties' => ['data-ref' => 'total_table-public_notes', 'style' => 'text-align: left;']],
 | 
					                ['element' => 'p', 'content' => strtr($_variables['values']['$entity.public_notes'], $_variables), 'properties' => ['data-ref' => 'total_table-public_notes', 'style' => 'text-align: left;']],
 | 
				
			||||||
                ['element' => 'p', 'content' => '', 'properties' => ['style' => 'text-align: left; display: flex; flex-direction: column;'], 'elements' => [
 | 
					                ['element' => 'p', 'content' => '', 'properties' => ['style' => 'text-align: left; display: flex; flex-direction: column;'], 'elements' => [
 | 
				
			||||||
                    ['element' => 'span', 'content' => '$entity.terms_label: ', 'properties' => ['hidden' => $this->entityVariableCheck('$entity.terms'), 'data-ref' => 'total_table-terms-label', 'style' => 'font-weight: bold; text-align: left;']],
 | 
					                    ['element' => 'span', 'content' => '$entity.terms_label: ', 'properties' => ['hidden' => $this->entityVariableCheck('$entity.terms'), 'data-ref' => 'total_table-terms-label', 'style' => 'font-weight: bold; text-align: left;']],
 | 
				
			||||||
                    ['element' => 'span', 'content' => '$entity.terms', 'properties' => ['data-ref' => 'total_table-terms', 'style' => 'text-align: left;']],
 | 
					                    ['element' => 'span', 'content' => strtr($_variables['values']['$entity.terms'], $_variables), 'properties' => ['data-ref' => 'total_table-terms', 'style' => 'text-align: left;']],
 | 
				
			||||||
 | 
					                    ['element' => 'span', 'content' => strtr($_variables['values']['$entity_footer'], $_variables), 'properties' => ['data-ref' => 'total_table-footer', 'style' => 'text-align: left;']],
 | 
				
			||||||
                ]],
 | 
					                ]],
 | 
				
			||||||
                ['element' => 'img', 'properties' => ['hidden' => $this->client->getSetting('signature_on_pdf'), 'style' => 'max-width: 50%; height: auto;', 'src' => '$contact.signature']],
 | 
					                ['element' => 'img', 'properties' => ['hidden' => $this->client->getSetting('signature_on_pdf'), 'style' => 'max-width: 50%; height: auto;', 'src' => '$contact.signature']],
 | 
				
			||||||
                ['element' => 'div', 'properties' => ['style' => 'margin-top: 1.5rem; display: flex; align-items: flex-start;'], 'elements' => [
 | 
					                ['element' => 'div', 'properties' => ['style' => 'margin-top: 1.5rem; display: flex; align-items: flex-start;'], 'elements' => [
 | 
				
			||||||
 | 
				
			|||||||
@ -121,7 +121,7 @@ class HtmlEngine
 | 
				
			|||||||
        if ($this->entity_string == 'invoice' || $this->entity_string == 'recurring_invoice') {
 | 
					        if ($this->entity_string == 'invoice' || $this->entity_string == 'recurring_invoice') {
 | 
				
			||||||
            $data['$entity'] = ['value' => '', 'label' => ctrans('texts.invoice')];
 | 
					            $data['$entity'] = ['value' => '', 'label' => ctrans('texts.invoice')];
 | 
				
			||||||
            $data['$number'] = ['value' => $this->entity->number ?: ' ', 'label' => ctrans('texts.invoice_number')];
 | 
					            $data['$number'] = ['value' => $this->entity->number ?: ' ', 'label' => ctrans('texts.invoice_number')];
 | 
				
			||||||
            $data['$entity.terms'] = ['value' => $this->entity->terms ?: ' ', 'label' => ctrans('texts.invoice_terms')];
 | 
					            $data['$entity.terms'] = ['value' => $this->entity->terms ?: '', 'label' => ctrans('texts.invoice_terms')];
 | 
				
			||||||
            $data['$terms'] = &$data['$entity.terms'];
 | 
					            $data['$terms'] = &$data['$entity.terms'];
 | 
				
			||||||
            $data['$view_link'] = ['value' => '<a class="button" href="'.$this->invitation->getLink().'">'.ctrans('texts.view_invoice').'</a>', 'label' => ctrans('texts.view_invoice')];
 | 
					            $data['$view_link'] = ['value' => '<a class="button" href="'.$this->invitation->getLink().'">'.ctrans('texts.view_invoice').'</a>', 'label' => ctrans('texts.view_invoice')];
 | 
				
			||||||
            $data['$view_url'] = ['value' => $this->invitation->getLink(), 'label' => ctrans('texts.view_invoice')];
 | 
					            $data['$view_url'] = ['value' => $this->invitation->getLink(), 'label' => ctrans('texts.view_invoice')];
 | 
				
			||||||
@ -129,8 +129,8 @@ class HtmlEngine
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if ($this->entity_string == 'quote') {
 | 
					        if ($this->entity_string == 'quote') {
 | 
				
			||||||
            $data['$entity'] = ['value' => '', 'label' => ctrans('texts.quote')];
 | 
					            $data['$entity'] = ['value' => '', 'label' => ctrans('texts.quote')];
 | 
				
			||||||
            $data['$number'] = ['value' => $this->entity->number ?: ' ', 'label' => ctrans('texts.quote_number')];
 | 
					            $data['$number'] = ['value' => $this->entity->number ?: '', 'label' => ctrans('texts.quote_number')];
 | 
				
			||||||
            $data['$entity.terms'] = ['value' => $this->entity->terms ?: ' ', 'label' => ctrans('texts.quote_terms')];
 | 
					            $data['$entity.terms'] = ['value' => $this->entity->terms ?: '', 'label' => ctrans('texts.quote_terms')];
 | 
				
			||||||
            $data['$terms'] = &$data['$entity.terms'];
 | 
					            $data['$terms'] = &$data['$entity.terms'];
 | 
				
			||||||
            $data['$view_link'] = ['value' => '<a class="button" href="'.$this->invitation->getLink().'">'.ctrans('texts.view_quote').'</a>', 'label' => ctrans('texts.view_quote')];
 | 
					            $data['$view_link'] = ['value' => '<a class="button" href="'.$this->invitation->getLink().'">'.ctrans('texts.view_quote').'</a>', 'label' => ctrans('texts.view_quote')];
 | 
				
			||||||
            $data['$view_url'] = ['value' => $this->invitation->getLink(), 'label' => ctrans('texts.view_quote')];
 | 
					            $data['$view_url'] = ['value' => $this->invitation->getLink(), 'label' => ctrans('texts.view_quote')];
 | 
				
			||||||
@ -138,8 +138,8 @@ class HtmlEngine
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if ($this->entity_string == 'credit') {
 | 
					        if ($this->entity_string == 'credit') {
 | 
				
			||||||
            $data['$entity'] = ['value' => '', 'label' => ctrans('texts.credit')];
 | 
					            $data['$entity'] = ['value' => '', 'label' => ctrans('texts.credit')];
 | 
				
			||||||
            $data['$number'] = ['value' => $this->entity->number ?: ' ', 'label' => ctrans('texts.credit_number')];
 | 
					            $data['$number'] = ['value' => $this->entity->number ?: '', 'label' => ctrans('texts.credit_number')];
 | 
				
			||||||
            $data['$entity.terms'] = ['value' => $this->entity->terms ?: ' ', 'label' => ctrans('texts.credit_terms')];
 | 
					            $data['$entity.terms'] = ['value' => $this->entity->terms ?: '', 'label' => ctrans('texts.credit_terms')];
 | 
				
			||||||
            $data['$terms'] = &$data['$entity.terms'];
 | 
					            $data['$terms'] = &$data['$entity.terms'];
 | 
				
			||||||
            $data['$view_link'] = ['value' => '<a class="button" href="'.$this->invitation->getLink().'">'.ctrans('texts.view_credit').'</a>', 'label' => ctrans('texts.view_credit')];
 | 
					            $data['$view_link'] = ['value' => '<a class="button" href="'.$this->invitation->getLink().'">'.ctrans('texts.view_credit').'</a>', 'label' => ctrans('texts.view_credit')];
 | 
				
			||||||
            $data['$view_url'] = ['value' => $this->invitation->getLink(), 'label' => ctrans('texts.view_credit')];
 | 
					            $data['$view_url'] = ['value' => $this->invitation->getLink(), 'label' => ctrans('texts.view_credit')];
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@ 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', ''),
 | 
					    'app_domain' => env('APP_DOMAIN', ''),
 | 
				
			||||||
    'app_version' => '5.1.6',
 | 
					    'app_version' => '5.1.7',
 | 
				
			||||||
    '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', false),
 | 
					    'api_secret' => env('API_SECRET', false),
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										3134
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3134
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										16
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								package.json
									
									
									
									
									
								
							@ -13,23 +13,23 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "devDependencies": {
 | 
					    "devDependencies": {
 | 
				
			||||||
        "@babel/compat-data": "7.9.0",
 | 
					        "@babel/compat-data": "7.9.0",
 | 
				
			||||||
        "@babel/plugin-proposal-class-properties": "^7.10.4",
 | 
					        "@babel/plugin-proposal-class-properties": "^7.12.13",
 | 
				
			||||||
        "cypress": "^4.12.1",
 | 
					        "cypress": "^4.12.1",
 | 
				
			||||||
        "laravel-mix-purgecss": "^5.0.0",
 | 
					        "laravel-mix-purgecss": "^5.0.0",
 | 
				
			||||||
        "vue-template-compiler": "^2.6.11"
 | 
					        "vue-template-compiler": "^2.6.12"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "dependencies": {
 | 
					    "dependencies": {
 | 
				
			||||||
        "@tailwindcss/ui": "^0.1.4",
 | 
					        "@tailwindcss/ui": "^0.7",
 | 
				
			||||||
        "axios": "^0.19",
 | 
					        "axios": "^0.21.1",
 | 
				
			||||||
        "card-js": "^1.0.13",
 | 
					        "card-js": "^1.0.13",
 | 
				
			||||||
        "card-validator": "^6.2.0",
 | 
					        "card-validator": "^6.2.0",
 | 
				
			||||||
        "cross-env": "^7.0",
 | 
					        "cross-env": "^7.0.3",
 | 
				
			||||||
        "jsignature": "^2.1.3",
 | 
					        "jsignature": "^2.1.3",
 | 
				
			||||||
        "laravel-mix": "^5.0.7",
 | 
					        "laravel-mix": "^5.0.9",
 | 
				
			||||||
        "lodash": "^4.17.20",
 | 
					        "lodash": "^4.17.20",
 | 
				
			||||||
        "resolve-url-loader": "^3.1.2",
 | 
					        "resolve-url-loader": "^3.1.2",
 | 
				
			||||||
        "sass": "^1.26.10",
 | 
					        "sass": "^1.32.7",
 | 
				
			||||||
        "sass-loader": "^8.0.0",
 | 
					        "sass-loader": "^8.0.0",
 | 
				
			||||||
        "tailwindcss": "^1.6.2"
 | 
					        "tailwindcss": "^1.9.6"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -15918,38 +15918,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			|||||||
--------------------------------------------------------------------------------
 | 
					--------------------------------------------------------------------------------
 | 
				
			||||||
skia
 | 
					skia
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Copyright 2012 Intel Inc.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Redistribution and use in source and binary forms, with or without
 | 
					 | 
				
			||||||
modification, are permitted provided that the following conditions are
 | 
					 | 
				
			||||||
met:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  * Redistributions of source code must retain the above copyright
 | 
					 | 
				
			||||||
    notice, this list of conditions and the following disclaimer.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  * Redistributions in binary form must reproduce the above copyright
 | 
					 | 
				
			||||||
    notice, this list of conditions and the following disclaimer in
 | 
					 | 
				
			||||||
    the documentation and/or other materials provided with the
 | 
					 | 
				
			||||||
    distribution.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  * Neither the name of the copyright holder nor the names of its
 | 
					 | 
				
			||||||
    contributors may be used to endorse or promote products derived
 | 
					 | 
				
			||||||
    from this software without specific prior written permission.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
					 | 
				
			||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
					 | 
				
			||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
					 | 
				
			||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
					 | 
				
			||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
					 | 
				
			||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
					 | 
				
			||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
					 | 
				
			||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
					 | 
				
			||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
					 | 
				
			||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
					 | 
				
			||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
					 | 
				
			||||||
--------------------------------------------------------------------------------
 | 
					 | 
				
			||||||
skia
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Copyright 2012 The Android Open Source Project
 | 
					Copyright 2012 The Android Open Source Project
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Redistribution and use in source and binary forms, with or without
 | 
					Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
@ -16881,6 +16849,38 @@ skia
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Copyright 2021 Google LLC.
 | 
					Copyright 2021 Google LLC.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					met:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					    notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					    notice, this list of conditions and the following disclaimer in
 | 
				
			||||||
 | 
					    the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					    distribution.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Neither the name of the copyright holder nor the names of its
 | 
				
			||||||
 | 
					    contributors may be used to endorse or promote products derived
 | 
				
			||||||
 | 
					    from this software without specific prior written permission.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					--------------------------------------------------------------------------------
 | 
				
			||||||
 | 
					skia
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright 2021 Google, LLC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Redistribution and use in source and binary forms, with or without
 | 
					Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
modification, are permitted provided that the following conditions are
 | 
					modification, are permitted provided that the following conditions are
 | 
				
			||||||
met:
 | 
					met:
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								public/css/app.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								public/css/app.css
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										6
									
								
								public/flutter_service_worker.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								public/flutter_service_worker.js
									
									
									
									
										vendored
									
									
								
							@ -3,11 +3,11 @@ 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 = {
 | 
				
			||||||
  "main.dart.js": "a36ad0c3c8bb9aa6c244bdfd4c7fdb2b",
 | 
					  "main.dart.js": "5e63c564cc944e8930bd80a70ea4e156",
 | 
				
			||||||
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
 | 
					"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
 | 
				
			||||||
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
 | 
					"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
 | 
				
			||||||
"favicon.ico": "51636d3a390451561744c42188ccd628",
 | 
					"favicon.ico": "51636d3a390451561744c42188ccd628",
 | 
				
			||||||
"assets/NOTICES": "3bf182b8c943ec950bd5bfa72a82c6e0",
 | 
					"assets/NOTICES": "1c2603c5ad0cd648934fe488850b4dea",
 | 
				
			||||||
"assets/fonts/MaterialIcons-Regular.otf": "1288c9e28052e028aba623321f7826ac",
 | 
					"assets/fonts/MaterialIcons-Regular.otf": "1288c9e28052e028aba623321f7826ac",
 | 
				
			||||||
"assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f",
 | 
					"assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f",
 | 
				
			||||||
"assets/AssetManifest.json": "659dcf9d1baf3aed3ab1b9c42112bf8f",
 | 
					"assets/AssetManifest.json": "659dcf9d1baf3aed3ab1b9c42112bf8f",
 | 
				
			||||||
@ -49,7 +49,7 @@ self.addEventListener("install", (event) => {
 | 
				
			|||||||
  return event.waitUntil(
 | 
					  return event.waitUntil(
 | 
				
			||||||
    caches.open(TEMP).then((cache) => {
 | 
					    caches.open(TEMP).then((cache) => {
 | 
				
			||||||
      return cache.addAll(
 | 
					      return cache.addAll(
 | 
				
			||||||
        CORE.map((value) => new Request(value + '?revision=' + RESOURCES[value], {'cache': 'reload'})));
 | 
					        CORE.map((value) => new Request(value, {'cache': 'reload'})));
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								public/js/app.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								public/js/app.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								public/js/setup/setup.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								public/js/setup/setup.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										207274
									
								
								public/main.dart.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										207274
									
								
								public/main.dart.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    "/js/app.js": "/js/app.js?id=1ee684e58f9f6eb754d5",
 | 
					    "/js/app.js": "/js/app.js?id=696e8203d5e8e7cf5ff5",
 | 
				
			||||||
    "/css/app.css": "/css/app.css?id=599b11149976e86c83a3",
 | 
					    "/css/app.css": "/css/app.css?id=1ea5400f7ae7b45f050c",
 | 
				
			||||||
    "/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=a09bb529b8e1826f13b4",
 | 
					    "/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=a09bb529b8e1826f13b4",
 | 
				
			||||||
    "/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=8ce8955ba775ea5f47d1",
 | 
					    "/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=8ce8955ba775ea5f47d1",
 | 
				
			||||||
    "/js/clients/payment_methods/authorize-authorize-card.js": "/js/clients/payment_methods/authorize-authorize-card.js?id=206d7de4ac97612980ff",
 | 
					    "/js/clients/payment_methods/authorize-authorize-card.js": "/js/clients/payment_methods/authorize-authorize-card.js?id=206d7de4ac97612980ff",
 | 
				
			||||||
@ -15,6 +15,6 @@
 | 
				
			|||||||
    "/js/clients/quotes/approve.js": "/js/clients/quotes/approve.js?id=85bcae0a646882e56b12",
 | 
					    "/js/clients/quotes/approve.js": "/js/clients/quotes/approve.js?id=85bcae0a646882e56b12",
 | 
				
			||||||
    "/js/clients/shared/multiple-downloads.js": "/js/clients/shared/multiple-downloads.js?id=5c35d28cf0a3286e7c45",
 | 
					    "/js/clients/shared/multiple-downloads.js": "/js/clients/shared/multiple-downloads.js?id=5c35d28cf0a3286e7c45",
 | 
				
			||||||
    "/js/clients/shared/pdf.js": "/js/clients/shared/pdf.js?id=fa54bb4229aba6b0817c",
 | 
					    "/js/clients/shared/pdf.js": "/js/clients/shared/pdf.js?id=fa54bb4229aba6b0817c",
 | 
				
			||||||
    "/js/setup/setup.js": "/js/setup/setup.js?id=8cb5e2bb0d404725c20a",
 | 
					    "/js/setup/setup.js": "/js/setup/setup.js?id=44bc4a71fc1d3606fc8e",
 | 
				
			||||||
    "/css/card-js.min.css": "/css/card-js.min.css?id=62afeb675235451543ad"
 | 
					    "/css/card-js.min.css": "/css/card-js.min.css?id=62afeb675235451543ad"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -4140,7 +4140,9 @@ $LANG = array(
 | 
				
			|||||||
     'start_migration' => 'Start Migration',
 | 
					     'start_migration' => 'Start Migration',
 | 
				
			||||||
     'recurring_cancellation_request' => 'Request for recurring invoice cancellation from :contact',
 | 
					     'recurring_cancellation_request' => 'Request for recurring invoice cancellation from :contact',
 | 
				
			||||||
     'recurring_cancellation_request_body' => ':contact from Client :client requested to cancel Recurring Invoice :invoice',
 | 
					     'recurring_cancellation_request_body' => ':contact from Client :client requested to cancel Recurring Invoice :invoice',
 | 
				
			||||||
 | 
					     'hello' => 'Hello',
 | 
				
			||||||
 | 
					     'group_documents' => 'Group documents',
 | 
				
			||||||
 | 
					     'quote_approval_confirmation_label' => 'Are you sure you want to approve this quote?',
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
return $LANG;
 | 
					return $LANG;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
@component('email.template.master', ['design' => 'light', 'settings' => $settings])
 | 
					@component('email.template.master', ['design' => 'light', 'settings' => $company->settings])
 | 
				
			||||||
    @slot('header')
 | 
					    @slot('header')
 | 
				
			||||||
        @include('email.components.header', ['logo' => 'https://www.invoiceninja.com/wp-content/uploads/2015/10/logo-white-horizontal-1.png'])
 | 
					        @include('email.components.header', ['logo' => 'https://www.invoiceninja.com/wp-content/uploads/2015/10/logo-white-horizontal-1.png'])
 | 
				
			||||||
    @endslot
 | 
					    @endslot
 | 
				
			||||||
@ -74,18 +74,34 @@
 | 
				
			|||||||
    @endif
 | 
					    @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <p><b>Data Quality:</b></p>
 | 
					    <p><b>Data Quality:</b></p>
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    <p> {!! $check_data !!} </p>
 | 
					    <p> {!! $check_data !!} </p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @if(!empty($errors) )
 | 
				
			||||||
 | 
					        <p>The following import errors occurred:</p>
 | 
				
			||||||
 | 
					        <table>
 | 
				
			||||||
 | 
					            <thead>
 | 
				
			||||||
 | 
					            <tr>
 | 
				
			||||||
 | 
					                <th>Type</th>
 | 
				
			||||||
 | 
					                <th>Data</th>
 | 
				
			||||||
 | 
					                <th>Error</th>
 | 
				
			||||||
 | 
					            </tr>
 | 
				
			||||||
 | 
					            </thead>
 | 
				
			||||||
 | 
					            <tbody>
 | 
				
			||||||
 | 
					            @foreach($errors as $entityType=>$entityErrors)
 | 
				
			||||||
 | 
					                @foreach($entityErrors as $error)
 | 
				
			||||||
 | 
					                    <tr>
 | 
				
			||||||
 | 
					                        <td>{{$entityType}}</td>
 | 
				
			||||||
 | 
					                        <td>{{json_encode($error[$entityType]??null)}}</td>
 | 
				
			||||||
 | 
					                        <td>{{json_encode($error['error'])}}</td>
 | 
				
			||||||
 | 
					                    </tr>
 | 
				
			||||||
 | 
					                @endforeach
 | 
				
			||||||
 | 
					                @endforeach
 | 
				
			||||||
 | 
					            </tbody>
 | 
				
			||||||
 | 
					        </table>
 | 
				
			||||||
 | 
					    @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <a href="{{ url('/') }}" target="_blank" class="button">{{ ctrans('texts.account_login')}}</a>
 | 
					    <a href="{{ url('/') }}" target="_blank" class="button">{{ ctrans('texts.account_login')}}</a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <p>{{ ctrans('texts.email_signature')}}<br/> {{ ctrans('texts.email_from') }}</p>
 | 
					    <p>{{ ctrans('texts.email_signature')}}<br/> {{ ctrans('texts.email_from') }}</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@if(!$whitelabel)
 | 
					 | 
				
			||||||
    @slot('footer')
 | 
					 | 
				
			||||||
        @component('email.components.footer', ['url' => 'https://invoiceninja.com', 'url_text' => '© InvoiceNinja'])
 | 
					 | 
				
			||||||
            For any info, please visit InvoiceNinja.
 | 
					 | 
				
			||||||
        @endcomponent
 | 
					 | 
				
			||||||
    @endslot
 | 
					 | 
				
			||||||
@endif
 | 
					 | 
				
			||||||
@endcomponent
 | 
					@endcomponent
 | 
				
			||||||
@ -259,4 +259,4 @@
 | 
				
			|||||||
    <table id="delivery-note-table" cellspacing="0"></table>
 | 
					    <table id="delivery-note-table" cellspacing="0"></table>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div id="footer">$entity_footer</div>
 | 
					<div id="footer"></div>
 | 
				
			||||||
 | 
				
			|||||||
@ -217,4 +217,4 @@
 | 
				
			|||||||
    <table id="delivery-note-table" cellspacing="0"></table>
 | 
					    <table id="delivery-note-table" cellspacing="0"></table>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div id="footer">$entity_footer</div>
 | 
					<div id="footer"></div>
 | 
				
			||||||
 | 
				
			|||||||
@ -215,4 +215,4 @@
 | 
				
			|||||||
    <table id="delivery-note-table" cellspacing="0"></table>
 | 
					    <table id="delivery-note-table" cellspacing="0"></table>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div id="footer">$entity_footer</div>
 | 
					<div id="footer"></div>
 | 
				
			||||||
 | 
				
			|||||||
@ -215,5 +215,5 @@
 | 
				
			|||||||
    <table id="delivery-note-table" cellspacing="0"></table>
 | 
					    <table id="delivery-note-table" cellspacing="0"></table>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div id="footer">$entity_footer</div>
 | 
					<div id="footer"></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -249,4 +249,4 @@
 | 
				
			|||||||
    <table id="delivery-note-table" cellspacing="0"></table>
 | 
					    <table id="delivery-note-table" cellspacing="0"></table>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div id="footer">$entity_footer</div>
 | 
					<div id="footer"></div>
 | 
				
			||||||
 | 
				
			|||||||
@ -235,7 +235,7 @@
 | 
				
			|||||||
                <div style="margin-top: 195px"></div>
 | 
					                <div style="margin-top: 195px"></div>
 | 
				
			||||||
                <div class="footer-wrapper" id="footer">
 | 
					                <div class="footer-wrapper" id="footer">
 | 
				
			||||||
                    <div class="footer-content">
 | 
					                    <div class="footer-content">
 | 
				
			||||||
                        <div>$entity_footer</div>
 | 
					                        <div></div>
 | 
				
			||||||
                        <div id="company-details"></div>
 | 
					                        <div id="company-details"></div>
 | 
				
			||||||
                        <div id="company-address"></div>
 | 
					                        <div id="company-address"></div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -180,4 +180,4 @@
 | 
				
			|||||||
    <table id="delivery-note-table" cellspacing="0"></table>
 | 
					    <table id="delivery-note-table" cellspacing="0"></table>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div id="footer">$entity_footer</div>
 | 
					<div id="footer"></div>
 | 
				
			||||||
 | 
				
			|||||||
@ -285,7 +285,7 @@
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div id="footer">
 | 
					<div id="footer">
 | 
				
			||||||
    $entity_footer
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div style="background-color: #00968B"><!-- 1 --></div>
 | 
					    <div style="background-color: #00968B"><!-- 1 --></div>
 | 
				
			||||||
    <div style="background-color: #1D756E"><!-- 2 --></div>
 | 
					    <div style="background-color: #1D756E"><!-- 2 --></div>
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            <div class="col-span-6 sm:col-span-3">
 | 
					            <div class="col-span-6 sm:col-span-3">
 | 
				
			||||||
                <label for="website" class="input-label">{{ ctrans('texts.website') }}</label>
 | 
					                <label for="website" class="input-label">{{ ctrans('texts.website') }}</label>
 | 
				
			||||||
                <input id="website" class="input w-full" name="last_name" />
 | 
					                <input id="website" class="input w-full" name="website" />
 | 
				
			||||||
                @error('website')
 | 
					                @error('website')
 | 
				
			||||||
                    <div class="validation validation-fail">
 | 
					                    <div class="validation validation-fail">
 | 
				
			||||||
                        {{ $message }}
 | 
					                        {{ $message }}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@section('body')
 | 
					@section('body')
 | 
				
			||||||
    <div class="grid lg:grid-cols-12 py-8">
 | 
					    <div class="grid lg:grid-cols-12 py-8">
 | 
				
			||||||
        <div class="col-span-4 col-start-5">
 | 
					        <div class="lg:col-span-4 lg:col-start-5 px-6">
 | 
				
			||||||
            <div class="flex justify-center">
 | 
					            <div class="flex justify-center">
 | 
				
			||||||
                <img class="h-32 w-auto" src="{{ $company->present()->logo() }}" alt="{{ ctrans('texts.logo') }}">
 | 
					                <img class="h-32 w-auto" src="{{ $company->present()->logo() }}" alt="{{ ctrans('texts.logo') }}">
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
@ -36,7 +36,7 @@
 | 
				
			|||||||
                        </span>
 | 
					                        </span>
 | 
				
			||||||
                    </span>
 | 
					                    </span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <button class="button button-primary bg-blue-600">{{ ctrans('texts.save') }}</button>
 | 
					                    <button class="button button-primary bg-blue-600">{{ ctrans('texts.register') }}</button>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </form>
 | 
					            </form>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -15,16 +15,6 @@
 | 
				
			|||||||
                <svg class="md:hidden" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="8 17 12 21 16 17"></polyline><line x1="12" y1="12" x2="12" y2="21"></line><path d="M20.88 18.09A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.29"></path></svg>
 | 
					                <svg class="md:hidden" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="8 17 12 21 16 17"></polyline><line x1="12" y1="12" x2="12" y2="21"></line><path d="M20.88 18.09A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.29"></path></svg>
 | 
				
			||||||
            </button>
 | 
					            </button>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="flex items-center">
 | 
					 | 
				
			||||||
            <div class="mr-3">
 | 
					 | 
				
			||||||
                <input wire:click="statusChange('resources')" type="checkbox" class="form-checkbox cursor-pointer" id="resources-checkbox" checked>
 | 
					 | 
				
			||||||
                <label for="resources-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.resources') }}</label>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <div class="mr-3">
 | 
					 | 
				
			||||||
                <input wire:click="statusChange('client')" type="checkbox" class="form-checkbox cursor-pointer" id="client-checkbox">
 | 
					 | 
				
			||||||
                <label for="client-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.client') }}</label>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
 | 
					    <div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
 | 
				
			||||||
        <div class="align-middle inline-block min-w-full overflow-hidden rounded">
 | 
					        <div class="align-middle inline-block min-w-full overflow-hidden rounded">
 | 
				
			||||||
@ -37,11 +27,6 @@
 | 
				
			|||||||
                                {{ ctrans('texts.name') }}
 | 
					                                {{ ctrans('texts.name') }}
 | 
				
			||||||
                            </span>
 | 
					                            </span>
 | 
				
			||||||
                        </th>
 | 
					                        </th>
 | 
				
			||||||
                        <th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider">
 | 
					 | 
				
			||||||
                            <span role="button" wire:click="sortBy('documentable_type')" class="cursor-pointer">
 | 
					 | 
				
			||||||
                                {{ ctrans('texts.resource') }}
 | 
					 | 
				
			||||||
                            </span>
 | 
					 | 
				
			||||||
                        </th>
 | 
					 | 
				
			||||||
                        <th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider">
 | 
					                        <th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider">
 | 
				
			||||||
                            <span role="button" wire:click="sortBy('type')" class="cursor-pointer">
 | 
					                            <span role="button" wire:click="sortBy('type')" class="cursor-pointer">
 | 
				
			||||||
                                {{ ctrans('texts.type') }}
 | 
					                                {{ ctrans('texts.type') }}
 | 
				
			||||||
@ -55,7 +40,7 @@
 | 
				
			|||||||
                        <th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider">
 | 
					                        <th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider">
 | 
				
			||||||
                            {{ ctrans('texts.download') }}
 | 
					                            {{ ctrans('texts.download') }}
 | 
				
			||||||
                        </th>
 | 
					                        </th>
 | 
				
			||||||
                        <th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider" />
 | 
					                        <th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider"></th>
 | 
				
			||||||
                    </tr>
 | 
					                    </tr>
 | 
				
			||||||
                </thead>
 | 
					                </thead>
 | 
				
			||||||
                <tbody>
 | 
					                <tbody>
 | 
				
			||||||
@ -67,9 +52,6 @@
 | 
				
			|||||||
                            <td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
 | 
					                            <td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
 | 
				
			||||||
                                {{ Illuminate\Support\Str::limit($document->name, 20) }}
 | 
					                                {{ Illuminate\Support\Str::limit($document->name, 20) }}
 | 
				
			||||||
                            </td>
 | 
					                            </td>
 | 
				
			||||||
                            <td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
 | 
					 | 
				
			||||||
                                {{ ((new \ReflectionClass($document->documentable))->getShortName()) }}
 | 
					 | 
				
			||||||
                            </td>
 | 
					 | 
				
			||||||
                            <td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
 | 
					                            <td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
 | 
				
			||||||
                                {{ App\Models\Document::$types[$document->type]['mime'] }}
 | 
					                                {{ App\Models\Document::$types[$document->type]['mime'] }}
 | 
				
			||||||
                            </td>
 | 
					                            </td>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,5 +12,102 @@
 | 
				
			|||||||
@endsection
 | 
					@endsection
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@section('body')
 | 
					@section('body')
 | 
				
			||||||
    Coming soon.
 | 
					    <div>
 | 
				
			||||||
 | 
					        <h3 class="text-lg leading-6 font-medium text-gray-900">
 | 
				
			||||||
 | 
					            {{ ctrans('texts.hello') }}, {{ $contact->first_name }}
 | 
				
			||||||
 | 
					        </h3>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <div class="mt-5 grid grid-cols-1 gap-5 sm:grid-cols-2">
 | 
				
			||||||
 | 
					            <div class="bg-white overflow-hidden shadow rounded">
 | 
				
			||||||
 | 
					                <div class="px-4 py-5 sm:p-6">
 | 
				
			||||||
 | 
					                    <dl>
 | 
				
			||||||
 | 
					                        <dt class="text-sm leading-5 font-medium text-gray-500 truncate">
 | 
				
			||||||
 | 
					                            {{ ctrans('texts.paid_to_date') }}
 | 
				
			||||||
 | 
					                        </dt>
 | 
				
			||||||
 | 
					                        <dd class="mt-1 text-3xl leading-9 font-semibold text-gray-900">
 | 
				
			||||||
 | 
					                            {{ App\Utils\Number::formatMoney($client->paid_to_date, $client) }}
 | 
				
			||||||
 | 
					                        </dd>
 | 
				
			||||||
 | 
					                    </dl>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="bg-white overflow-hidden shadow rounded">
 | 
				
			||||||
 | 
					                <div class="px-4 py-5 sm:p-6">
 | 
				
			||||||
 | 
					                    <dl>
 | 
				
			||||||
 | 
					                        <dt class="text-sm leading-5 font-medium text-gray-500 truncate">
 | 
				
			||||||
 | 
					                            {{ ctrans('texts.open_balance') }}
 | 
				
			||||||
 | 
					                        </dt>
 | 
				
			||||||
 | 
					                        <dd class="mt-1 text-3xl leading-9 font-semibold text-gray-900">
 | 
				
			||||||
 | 
					                            {{ App\Utils\Number::formatMoney($client->balance, $client) }}
 | 
				
			||||||
 | 
					                        </dd>
 | 
				
			||||||
 | 
					                    </dl>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="grid md:grid-cols-12 gap-4 mt-6">
 | 
				
			||||||
 | 
					        <div class="col-span-6">
 | 
				
			||||||
 | 
					            <div class="bg-white rounded shadow px-4 py-5 border-b border-gray-200 sm:px-6">
 | 
				
			||||||
 | 
					                <div class="-ml-4 -mt-4 flex justify-between items-center flex-wrap sm:flex-no-wrap">
 | 
				
			||||||
 | 
					                    <div class="ml-4 mt-4 w-full">
 | 
				
			||||||
 | 
					                        <h3 class="text-lg leading-6 font-medium text-gray-900 mb-4 capitalize">
 | 
				
			||||||
 | 
					                            {{ ctrans('texts.group_documents') }}
 | 
				
			||||||
 | 
					                        </h3>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        <div class="flex flex-col h-auto overflow-y-auto">
 | 
				
			||||||
 | 
					                            @if($client->group_settings)
 | 
				
			||||||
 | 
					                                @forelse($client->group_settings->documents as $document)
 | 
				
			||||||
 | 
					                                    <a href="{{ route('client.documents.show', $document->hashed_id) }}" target="_blank"
 | 
				
			||||||
 | 
					                                       class="block inline-flex items-center text-sm button-link text-primary">
 | 
				
			||||||
 | 
					                                        <span>{{ Illuminate\Support\Str::limit($document->name, 40) }}</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
 | 
				
			||||||
 | 
					                                             fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
 | 
				
			||||||
 | 
					                                             stroke-linejoin="round" class="ml-2 text-primary h-6 w-4">
 | 
				
			||||||
 | 
					                                            <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
 | 
				
			||||||
 | 
					                                            <polyline points="15 3 21 3 21 9"></polyline>
 | 
				
			||||||
 | 
					                                            <line x1="10" y1="14" x2="21" y2="3"></line>
 | 
				
			||||||
 | 
					                                        </svg>
 | 
				
			||||||
 | 
					                                    </a>
 | 
				
			||||||
 | 
					                                @empty
 | 
				
			||||||
 | 
					                                    <p class="text-sm">{{ ctrans('texts.no_records_found') }}.</p>
 | 
				
			||||||
 | 
					                                @endforelse
 | 
				
			||||||
 | 
					                            @endif
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <div class="col-span-6">
 | 
				
			||||||
 | 
					            <div class="bg-white rounded shadow px-4 py-5 border-b border-gray-200 sm:px-6">
 | 
				
			||||||
 | 
					                <div class="-ml-4 -mt-4 flex justify-between items-center flex-wrap sm:flex-no-wrap">
 | 
				
			||||||
 | 
					                    <div class="ml-4 mt-4 w-full">
 | 
				
			||||||
 | 
					                        <h3 class="text-lg leading-6 font-medium text-gray-900 mb-4 capitalize">
 | 
				
			||||||
 | 
					                            {{ ctrans('texts.default_documents') }}
 | 
				
			||||||
 | 
					                        </h3>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        <div class="flex flex-col h-auto overflow-y-auto">
 | 
				
			||||||
 | 
					                            @forelse($client->company->documents as $document)
 | 
				
			||||||
 | 
					                                <a href="{{ route('client.documents.show', $document->hashed_id) }}" target="_blank"
 | 
				
			||||||
 | 
					                                   class="block inline-flex items-center text-sm button-link text-primary">
 | 
				
			||||||
 | 
					                                    <span>{{ Illuminate\Support\Str::limit($document->name, 40) }}</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
 | 
				
			||||||
 | 
					                                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
 | 
				
			||||||
 | 
					                                         stroke-linejoin="round" class="ml-2 text-primary h-6 w-4">
 | 
				
			||||||
 | 
					                                        <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
 | 
				
			||||||
 | 
					                                        <polyline points="15 3 21 3 21 9"></polyline>
 | 
				
			||||||
 | 
					                                        <line x1="10" y1="14" x2="21" y2="3"></line>
 | 
				
			||||||
 | 
					                                    </svg>
 | 
				
			||||||
 | 
					                                </a>
 | 
				
			||||||
 | 
					                            @empty
 | 
				
			||||||
 | 
					                                <p class="text-sm">{{ ctrans('texts.no_records_found') }}.</p>
 | 
				
			||||||
 | 
					                            @endforelse
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
@endsection
 | 
					@endsection
 | 
				
			||||||
 | 
				
			|||||||
@ -13,5 +13,6 @@
 | 
				
			|||||||
    <form action="{{ route('client.documents.download_multiple') }}" method="post" id="multiple-downloads">
 | 
					    <form action="{{ route('client.documents.download_multiple') }}" method="post" id="multiple-downloads">
 | 
				
			||||||
        @csrf
 | 
					        @csrf
 | 
				
			||||||
    </form>
 | 
					    </form>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    @livewire('documents-table', ['client' => $client])
 | 
					    @livewire('documents-table', ['client' => $client])
 | 
				
			||||||
@endsection
 | 
					@endsection
 | 
				
			||||||
@ -43,7 +43,7 @@
 | 
				
			|||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        </form>
 | 
					        </form>
 | 
				
			||||||
    @else
 | 
					    @else
 | 
				
			||||||
    <div class="bg-white shadow sm:rounded-lg mb-4" translate>
 | 
					    <div class="bg-white shadow sm:rounded-lg mb-4">
 | 
				
			||||||
    <div class="px-4 py-5 sm:p-6">
 | 
					    <div class="px-4 py-5 sm:p-6">
 | 
				
			||||||
        <div class="sm:flex sm:items-start sm:justify-between">
 | 
					        <div class="sm:flex sm:items-start sm:justify-between">
 | 
				
			||||||
            <div>
 | 
					            <div>
 | 
				
			||||||
@ -57,7 +57,37 @@
 | 
				
			|||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    @endif
 | 
					    @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div class="flex items-center justify-between">
 | 
					    @if($invoice->documents->count() > 0)
 | 
				
			||||||
 | 
					        <div class="bg-white shadow sm:rounded-lg mb-4">
 | 
				
			||||||
 | 
					            <div class="px-4 py-5 sm:p-6">
 | 
				
			||||||
 | 
					                <div class="sm:flex sm:items-start sm:justify-between">
 | 
				
			||||||
 | 
					                    <div>
 | 
				
			||||||
 | 
					                        <p class="text-lg leading-6 font-medium text-gray-900">{{ ctrans('texts.attachments') }}:</p>
 | 
				
			||||||
 | 
					                        @foreach($invoice->documents as $document)
 | 
				
			||||||
 | 
					                            <div class="inline-flex items-center space-x-1">
 | 
				
			||||||
 | 
					                                <a href="{{ route('client.documents.show', $document->hashed_id) }}" target="_blank"
 | 
				
			||||||
 | 
					                                   class="block text-sm button-link text-primary">{{ Illuminate\Support\Str::limit($document->name, 40) }}</a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
 | 
				
			||||||
 | 
					                                     fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
 | 
				
			||||||
 | 
					                                     stroke-linejoin="round" class="text-primary h-6 w-4">
 | 
				
			||||||
 | 
					                                    <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
 | 
				
			||||||
 | 
					                                    <polyline points="15 3 21 3 21 9"></polyline>
 | 
				
			||||||
 | 
					                                    <line x1="10" y1="14" x2="21" y2="3"></line>
 | 
				
			||||||
 | 
					                                </svg>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                @if(!$loop->last)
 | 
				
			||||||
 | 
					                                    <span>—</span>
 | 
				
			||||||
 | 
					                                @endif
 | 
				
			||||||
 | 
					                            </div>
 | 
				
			||||||
 | 
					                        @endforeach
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="flex items-center justify-between mt-4">
 | 
				
			||||||
        <section class="flex items-center">
 | 
					        <section class="flex items-center">
 | 
				
			||||||
            <div class="items-center" style="display: none" id="pagination-button-container">
 | 
					            <div class="items-center" style="display: none" id="pagination-button-container">
 | 
				
			||||||
                <button class="input-label focus:outline-none hover:text-blue-600 transition ease-in-out duration-300" id="previous-page-button" title="Previous page">
 | 
					                <button class="input-label focus:outline-none hover:text-blue-600 transition ease-in-out duration-300" id="previous-page-button" title="Previous page">
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
<form action="{{ route('client.quotes.bulk') }}" method="post">
 | 
					<form action="{{ route('client.quotes.bulk') }}" method="post" onsubmit="return confirm('{{ ctrans('texts.quote_approval_confirmation_label') }}')">
 | 
				
			||||||
    @csrf
 | 
					    @csrf
 | 
				
			||||||
    <input type="hidden" name="action" value="approve">
 | 
					    <input type="hidden" name="action" value="approve">
 | 
				
			||||||
 | 
					    <input type="hidden" name="process" value="true">
 | 
				
			||||||
    <input type="hidden" name="quotes[]" value="{{ $quote->hashed_id }}">
 | 
					    <input type="hidden" name="quotes[]" value="{{ $quote->hashed_id }}">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div class="bg-white shadow sm:rounded-lg">
 | 
					    <div class="bg-white shadow sm:rounded-lg">
 | 
				
			||||||
@ -11,7 +12,7 @@
 | 
				
			|||||||
                        {{ ctrans('texts.waiting_for_approval') }}
 | 
					                        {{ ctrans('texts.waiting_for_approval') }}
 | 
				
			||||||
                    </h3>
 | 
					                    </h3>
 | 
				
			||||||
                    <div class="mt-2 max-w-xl text-sm leading-5 text-gray-500">
 | 
					                    <div class="mt-2 max-w-xl text-sm leading-5 text-gray-500">
 | 
				
			||||||
                        <p translate>
 | 
					                        <p>
 | 
				
			||||||
                            {{ ctrans('texts.quote_still_not_approved') }}
 | 
					                            {{ ctrans('texts.quote_still_not_approved') }}
 | 
				
			||||||
                        </p>
 | 
					                        </p>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
 | 
				
			|||||||
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