diff --git a/app/Factory/CompanyFactory.php b/app/Factory/CompanyFactory.php index 0f68ec9418..00f2874ffd 100644 --- a/app/Factory/CompanyFactory.php +++ b/app/Factory/CompanyFactory.php @@ -27,7 +27,7 @@ class CompanyFactory * @param int $account_id * @return Company */ - public function create(int $account_id) :Company + public function create(int $account_id): Company { $company = new Company; $company->account_id = $account_id; @@ -49,6 +49,11 @@ class CompanyFactory $company->markdown_enabled = false; $company->tax_data = new TaxModel(); $company->first_month_of_year = 1; + + // default mailbox + $company->expense_mailbox = config('ninja.inbound_expense.webhook.mailbox_template') != '' ? + str_replace('{{company_key}}', $company->company_key, config('ninja.inbound_expense.webhook.mailbox_template')) : null; + return $company; } } diff --git a/app/Jobs/Mail/ExpenseMailboxJob.php b/app/Jobs/Mail/ExpenseMailboxJob.php index 60dd6a5dc4..956d29c956 100644 --- a/app/Jobs/Mail/ExpenseMailboxJob.php +++ b/app/Jobs/Mail/ExpenseMailboxJob.php @@ -86,14 +86,14 @@ class ExpenseMailboxJob implements ShouldQueue private function getImapCredentials() { - $servers = array_map('trim', explode(",", config('ninja.imap_inbound_expense.servers'))); - $ports = explode(",", config('ninja.imap_inbound_expense.servers')); - $users = explode(",", config('ninja.imap_inbound_expense.servers')); - $passwords = explode(",", config('ninja.imap_inbound_expense.servers')); - $companies = explode(",", config('ninja.imap_inbound_expense.servers')); + $servers = array_map('trim', explode(",", config('ninja.inbound_expense.imap.servers'))); + $ports = explode(",", config('ninja.inbound_expense.imap.servers')); + $users = explode(",", config('ninja.inbound_expense.imap.servers')); + $passwords = explode(",", config('ninja.inbound_expense.imap.servers')); + $companies = explode(",", config('ninja.inbound_expense.imap.servers')); if (sizeOf($servers) != sizeOf($ports) || sizeOf($servers) != sizeOf($users) || sizeOf($servers) != sizeOf($passwords) || sizeOf($servers) != sizeOf($companies)) - throw new \Exception('invalid configuration imap_inbound_expenses (wrong element-count)'); + throw new \Exception('invalid configuration inbound_expense.imap (wrong element-count)'); foreach ($companies as $index => $companyId) { $this->imap_credentials[$companyId] = [ diff --git a/app/Models/Company.php b/app/Models/Company.php index 8f37c7d063..f8b331ba9e 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -111,6 +111,8 @@ use Laracasts\Presenter\PresentableTrait; * @property int $convert_expense_currency * @property int $notify_vendor_when_paid * @property int $invoice_task_hours + * @property boolean $expense_import + * @property string|null $expense_mailbox * @property int $deleted_at * @property-read \App\Models\Account $account * @property-read \Illuminate\Database\Eloquent\Collection $activities @@ -352,6 +354,8 @@ class Company extends BaseModel 'calculate_taxes', 'tax_data', 'e_invoice_certificate_passphrase', + 'expense_import', + 'expense_mailbox', // TODO: @turbo124 custom validation: self-hosted => free change, hosted => not changeable, only changeable with env-mask ]; protected $hidden = [ @@ -404,17 +408,17 @@ class Company extends BaseModel return $this->morphMany(Document::class, 'documentable'); } - public function schedulers() :HasMany + public function schedulers(): HasMany { return $this->hasMany(Scheduler::class); } - public function task_schedulers() :HasMany + public function task_schedulers(): HasMany { return $this->hasMany(Scheduler::class); } - public function all_documents() :HasMany + public function all_documents(): HasMany { return $this->hasMany(Document::class); } @@ -424,22 +428,22 @@ class Company extends BaseModel return self::class; } - public function ledger() :HasMany + public function ledger(): HasMany { return $this->hasMany(CompanyLedger::class); } - public function bank_integrations() :HasMany + public function bank_integrations(): HasMany { return $this->hasMany(BankIntegration::class); } - public function bank_transactions() :HasMany + public function bank_transactions(): HasMany { return $this->hasMany(BankTransaction::class); } - public function bank_transaction_rules() :HasMany + public function bank_transaction_rules(): HasMany { return $this->hasMany(BankTransactionRule::class); } @@ -454,7 +458,7 @@ class Company extends BaseModel return $this->belongsTo(Account::class); } - public function client_contacts() :HasMany + public function client_contacts(): HasMany { return $this->hasMany(ClientContact::class)->withTrashed(); } @@ -467,27 +471,27 @@ class Company extends BaseModel return $this->hasManyThrough(User::class, CompanyUser::class, 'company_id', 'id', 'id', 'user_id')->withTrashed(); } - public function expense_categories() :HasMany + public function expense_categories(): HasMany { return $this->hasMany(ExpenseCategory::class)->withTrashed(); } - public function subscriptions() :HasMany + public function subscriptions(): HasMany { return $this->hasMany(Subscription::class)->withTrashed(); } - public function purchase_orders() :HasMany + public function purchase_orders(): HasMany { return $this->hasMany(PurchaseOrder::class)->withTrashed(); } - public function task_statuses() :HasMany + public function task_statuses(): HasMany { return $this->hasMany(TaskStatus::class)->withTrashed(); } - public function clients() :HasMany + public function clients(): HasMany { return $this->hasMany(Client::class)->withTrashed(); } @@ -495,12 +499,12 @@ class Company extends BaseModel /** * @return HasMany */ - public function tasks() :HasMany + public function tasks(): HasMany { return $this->hasMany(Task::class)->withTrashed(); } - public function webhooks() :HasMany + public function webhooks(): HasMany { return $this->hasMany(Webhook::class); } @@ -508,7 +512,7 @@ class Company extends BaseModel /** * @return HasMany */ - public function projects() :HasMany + public function projects(): HasMany { return $this->hasMany(Project::class)->withTrashed(); } @@ -516,7 +520,7 @@ class Company extends BaseModel /** * @return HasMany */ - public function vendor_contacts() :HasMany + public function vendor_contacts(): HasMany { return $this->hasMany(VendorContact::class)->withTrashed(); } @@ -524,17 +528,17 @@ class Company extends BaseModel /** * @return HasMany */ - public function vendors() :HasMany + public function vendors(): HasMany { return $this->hasMany(Vendor::class)->withTrashed(); } - public function all_activities() :\Illuminate\Database\Eloquent\Relations\HasMany + public function all_activities(): \Illuminate\Database\Eloquent\Relations\HasMany { return $this->hasMany(Activity::class); } - public function activities() :HasMany + public function activities(): HasMany { return $this->hasMany(Activity::class)->orderBy('id', 'DESC')->take(50); } @@ -620,7 +624,7 @@ class Company extends BaseModel { $companies = Cache::get('countries'); - if (! $companies) { + if (!$companies) { $this->buildCache(true); $companies = Cache::get('countries'); @@ -643,7 +647,7 @@ class Company extends BaseModel { $timezones = Cache::get('timezones'); - if (! $timezones) { + if (!$timezones) { $this->buildCache(true); } @@ -679,7 +683,7 @@ class Company extends BaseModel $languages = Cache::get('languages'); //build cache and reinit - if (! $languages) { + if (!$languages) { $this->buildCache(true); $languages = Cache::get('languages'); } @@ -699,7 +703,7 @@ class Company extends BaseModel return isset($this->settings->language_id) && $this->language() ? $this->language()->locale : config('ninja.i18n.locale'); } - public function getLogo() :?string + public function getLogo(): ?string { return $this->settings->company_logo ?: null; } @@ -713,7 +717,7 @@ class Company extends BaseModel { App::setLocale($this->getLocale()); } - + public function getSetting($setting) { //todo $this->setting ?? false @@ -809,7 +813,7 @@ class Company extends BaseModel { return $this->hasMany(CreditInvitation::class); } - + public function purchase_order_invitations(): HasMany { return $this->hasMany(PurchaseOrderInvitation::class); @@ -826,25 +830,25 @@ class Company extends BaseModel public function credit_rules() { return BankTransactionRule::query() - ->where('company_id', $this->id) - ->where('applies_to', 'CREDIT') - ->get(); + ->where('company_id', $this->id) + ->where('applies_to', 'CREDIT') + ->get(); } public function debit_rules() { return BankTransactionRule::query() - ->where('company_id', $this->id) - ->where('applies_to', 'DEBIT') - ->get(); + ->where('company_id', $this->id) + ->where('applies_to', 'DEBIT') + ->get(); } public function resolveRouteBinding($value, $field = null) { return $this->where('id', $this->decodePrimaryKey($value)) - ->where('account_id', auth()->user()->account_id) - ->firstOrFail(); + ->where('account_id', auth()->user()->account_id) + ->firstOrFail(); } public function domain(): string @@ -854,7 +858,7 @@ class Company extends BaseModel return $this->portal_domain; } - return "https://{$this->subdomain}.".config('ninja.app_domain'); + return "https://{$this->subdomain}." . config('ninja.app_domain'); } return config('ninja.app_url'); @@ -872,7 +876,7 @@ class Company extends BaseModel public function file_path(): string { - return $this->company_key.'/'; + return $this->company_key . '/'; } public function rBits() @@ -951,7 +955,7 @@ class Company extends BaseModel { $date_formats = Cache::get('date_formats'); - if (! $date_formats) { + if (!$date_formats) { $this->buildCache(true); } @@ -962,7 +966,7 @@ class Company extends BaseModel public function getInvoiceCert() { - if($this->e_invoice_certificate) { + if ($this->e_invoice_certificate) { return base64_decode($this->e_invoice_certificate); } diff --git a/config/ninja.php b/config/ninja.php index d94ec91a01..25505a49c6 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -228,11 +228,17 @@ return [ 'secret' => env('PAYPAL_SECRET', null), 'client_id' => env('PAYPAL_CLIENT_ID', null), ], - 'imap_inbound_expense' => [ - 'servers' => env('IMAP_INBOUND_EXPENSE_SERVERS', ''), - 'ports' => env('IMAP_INBOUND_EXPENSE_PORTS', ''), - 'users' => env('IMAP_INBOUND_EXPENSE_USERS', ''), - 'passwords' => env('IMAP_INBOUND_EXPENSE_PASSWORDS', ''), - 'companies' => env('IMAP_INBOUND_EXPENSE_COMPANIES', ''), - ] + 'inbound_expense' => [ + 'imap' => [ + 'servers' => env('INBOUND_EXPENSE_IMAP_SERVERS', ''), + 'ports' => env('INBOUND_EXPENSE_IMAP_PORTS', ''), + 'users' => env('INBOUND_EXPENSE_IMAP_USERS', ''), + 'passwords' => env('INBOUND_EXPENSE_IMAP_PASSWORDS', ''), + 'companies' => env('INBOUND_EXPENSE_IMAP_COMPANIES', ''), + ], + 'webhook' => [ + 'mailbox_template' => env('INBOUND_EXPENSE_WEBHOOK_MAILBOXTEMPLATE', null), + 'mailbox_template_enterprise' => env('INBOUND_EXPENSE_WEBHOOK_MAILBOXTEMPLATE_ENTERPRISE', '{{input}}@expense.invoicing.co'), + ], + ], ]; diff --git a/database/migrations/2023_12_10_110951_create_imap_configuration_fields.php b/database/migrations/2023_12_10_110951_create_imap_configuration_fields.php index e5b8a03b3a..f750b9b074 100644 --- a/database/migrations/2023_12_10_110951_create_imap_configuration_fields.php +++ b/database/migrations/2023_12_10_110951_create_imap_configuration_fields.php @@ -1,5 +1,6 @@ string("expense_import")->default(true); + $table->boolean("expense_import")->default(true); + $table->string("expense_mailbox")->nullable(); + }); + Company::query()->cursor()->each(function ($company) { // TODO: @turbo124 check migration on staging environment with real data to ensure, this works as exspected + $company->expense_mailbox = config('ninja.inbound_expense.webhook.mailbox_template') != '' ? + str_replace('{{company_key}}', $company->company_key, config('ninja.inbound_expense.webhook.mailbox_template')) : null; + + $company->save(); }); Schema::table('vendor', function (Blueprint $table) { $table->string("expense_sender_email")->nullable();