diff --git a/VERSION.txt b/VERSION.txt index 0467d2fb7a5b..b150ab7535f7 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.5.93 \ No newline at end of file +5.5.94 \ No newline at end of file diff --git a/app/Console/Commands/CheckData.php b/app/Console/Commands/CheckData.php index d2548e27e414..8e04496b3782 100644 --- a/app/Console/Commands/CheckData.php +++ b/app/Console/Commands/CheckData.php @@ -174,8 +174,10 @@ class CheckData extends Command CompanyUser::query()->cursor()->each(function ($cu) { if (CompanyToken::where('user_id', $cu->user_id)->where('company_id', $cu->company_id)->where('is_system', 1)->doesntExist()) { - $this->logMessage("Creating missing company token for user # {$cu->user->id} for company id # {$cu->company->id}"); - (new CreateCompanyToken($cu->company, $cu->user, 'System'))->handle(); + $this->logMessage("Creating missing company token for user # {$cu->user_id} for company id # {$cu->company_id}"); + + if($cu->company && $cu->user) + (new CreateCompanyToken($cu->company, $cu->user, 'System'))->handle(); } }); diff --git a/app/DataMapper/CompanySettings.php b/app/DataMapper/CompanySettings.php index d979030514fd..6feca01c1727 100644 --- a/app/DataMapper/CompanySettings.php +++ b/app/DataMapper/CompanySettings.php @@ -471,9 +471,12 @@ class CompanySettings extends BaseSettings public $client_initiated_payments_minimum = 0; + public $client_initiated_payments_recurring = false; + public $sync_invoice_quote_columns = true; public static $casts = [ + 'client_initiated_payments_recurring'=> 'bool', 'client_initiated_payments' => 'bool', 'client_initiated_payments_minimum' => 'float', 'sync_invoice_quote_columns' => 'bool', diff --git a/app/DataMapper/Schedule/ScheduleInvoice.php b/app/DataMapper/Schedule/ScheduleInvoice.php new file mode 100644 index 000000000000..71b57e820b50 --- /dev/null +++ b/app/DataMapper/Schedule/ScheduleInvoice.php @@ -0,0 +1,37 @@ +company = $company; $this->event_vars = $event_vars; } + + /** + * Get the channels the event should broadcast on. + * + * @return PrivateChannel|array + */ + public function broadcastOn() + { + return new PrivateChannel('channel-name'); + } + } diff --git a/app/Http/Controllers/Bank/YodleeController.php b/app/Http/Controllers/Bank/YodleeController.php index 1783d097c904..de2f3cc89b5e 100644 --- a/app/Http/Controllers/Bank/YodleeController.php +++ b/app/Http/Controllers/Bank/YodleeController.php @@ -276,8 +276,6 @@ class YodleeController extends BaseController { //this is the main hook we use for notifications - nlog("data refresh"); - nlog($request->all()); return response()->json(['message' => 'Success'], 200); diff --git a/app/Http/Controllers/ClientPortal/PrePaymentController.php b/app/Http/Controllers/ClientPortal/PrePaymentController.php index 9f62ab3ec962..9c8070e572d4 100644 --- a/app/Http/Controllers/ClientPortal/PrePaymentController.php +++ b/app/Http/Controllers/ClientPortal/PrePaymentController.php @@ -12,11 +12,16 @@ namespace App\Http\Controllers\ClientPortal; +use App\Utils\Number; use Illuminate\View\View; +use App\DataMapper\InvoiceItem; +use App\Factory\InvoiceFactory; use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesDates; use App\Http\Controllers\Controller; use Illuminate\Contracts\View\Factory; +use App\Repositories\InvoiceRepository; +use App\Http\Requests\ClientPortal\PrePayments\StorePrePaymentRequest; /** * Class PrePaymentController. @@ -33,9 +38,80 @@ class PrePaymentController extends Controller */ public function index() { - $data['minimum_amount'] = auth()->guard('contact')->user()->client->getSetting('client_initiated_payments_minimum'); - $data['title'] = ctrans('texts.amount'). " " .auth()->guard('contact')->user()->client->currency()->code." (".auth()->guard('contact')->user()->client->currency()->symbol . ")"; + + $data = [ + 'title' => ctrans('texts.amount'). " " .auth()->guard('contact')->user()->client->currency()->code." (".auth()->guard('contact')->user()->client->currency()->symbol . ")", + 'allows_recurring' => auth()->guard('contact')->user()->client->getSetting('client_initiated_payments_recurring'), + 'allows_recurring' => true, + 'minimum_amount' => auth()->guard('contact')->user()->client->getSetting('client_initiated_payments_minimum'), + ]; + return $this->render('pre_payments.index', $data); } + public function process(StorePrePaymentRequest $request) + { + + $invoice = InvoiceFactory::create(auth()->guard('contact')->user()->company_id, auth()->guard('contact')->user()->user_id); + $invoice->due_date = now()->format('Y-m-d'); + $invoice->is_proforma = true; + $invoice->client_id = auth()->guard('contact')->user()->client_id; + + $line_item = new InvoiceItem(); + $line_item->cost = (float)$request->amount; + $line_item->quantity = 1; + $line_item->product_key = ctrans('texts.pre_payment'); + $line_item->notes = $request->notes; + $line_item->type_id = '1'; + + $items = []; + $items[] = $line_item; + $invoice->line_items = $items; + $invoice->number = ctrans('texts.pre_payment') . " " . now()->format('Y-m-d : H:i:s'); + + $invoice_repo = new InvoiceRepository(); + + $data = [ + 'client_id' => $invoice->client_id, + 'quantity' => 1, + 'date' => now()->format('Y-m-d'), + ]; + + $invoice = $invoice_repo->save($data, $invoice) + ->service() + ->markSent() + ->fillDefaults() + ->save(); + + $total = $invoice->balance; + + //format totals + $formatted_total = Number::formatMoney($invoice->amount, auth()->guard('contact')->user()->client); + + $payment_methods = auth()->guard('contact')->user()->client->service()->getPaymentMethods($request->amount); + + //if there is only one payment method -> lets return straight to the payment page + $invoices = collect(); + $invoices->push($invoice); + + $invoices->map(function ($invoice) { + $invoice->balance = Number::formatValue($invoice->balance, $invoice->client->currency()); + return $invoice; + }); + + $data = [ + 'settings' => auth()->guard('contact')->user()->client->getMergedSettings(), + 'invoices' => $invoices, + 'formatted_total' => $formatted_total, + 'payment_methods' => $payment_methods, + 'hashed_ids' => $invoices->pluck('hashed_id'), + 'total' => $total, + 'pre_payment' => true, + ]; + + + return $this->render('invoices.payment', $data); + + } + } \ No newline at end of file diff --git a/app/Http/Controllers/CompanyController.php b/app/Http/Controllers/CompanyController.php index d5575e4e9753..b12e5c06dcc4 100644 --- a/app/Http/Controllers/CompanyController.php +++ b/app/Http/Controllers/CompanyController.php @@ -11,36 +11,37 @@ namespace App\Http\Controllers; -use App\DataMapper\Analytics\AccountDeleted; -use App\DataMapper\CompanySettings; -use App\Http\Requests\Company\CreateCompanyRequest; -use App\Http\Requests\Company\DefaultCompanyRequest; -use App\Http\Requests\Company\DestroyCompanyRequest; -use App\Http\Requests\Company\EditCompanyRequest; -use App\Http\Requests\Company\ShowCompanyRequest; -use App\Http\Requests\Company\StoreCompanyRequest; -use App\Http\Requests\Company\UpdateCompanyRequest; -use App\Http\Requests\Company\UploadCompanyRequest; -use App\Jobs\Company\CreateCompany; -use App\Jobs\Company\CreateCompanyPaymentTerms; -use App\Jobs\Company\CreateCompanyTaskStatuses; -use App\Jobs\Company\CreateCompanyToken; -use App\Jobs\Mail\NinjaMailerJob; -use App\Jobs\Mail\NinjaMailerObject; -use App\Mail\Company\CompanyDeleted; +use App\Utils\Ninja; use App\Models\Account; use App\Models\Company; use App\Models\CompanyUser; -use App\Repositories\CompanyRepository; -use App\Transformers\CompanyTransformer; -use App\Transformers\CompanyUserTransformer; -use App\Utils\Ninja; -use App\Utils\Traits\MakesHash; -use App\Utils\Traits\SavesDocuments; -use App\Utils\Traits\Uploadable; -use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Http\Response; +use App\Utils\Traits\MakesHash; +use App\Utils\Traits\Uploadable; +use App\Jobs\Mail\NinjaMailerJob; +use App\DataMapper\CompanySettings; +use App\Jobs\Company\CreateCompany; +use App\Jobs\Mail\NinjaMailerObject; +use App\Mail\Company\CompanyDeleted; +use App\Utils\Traits\SavesDocuments; use Turbo124\Beacon\Facades\LightLogs; +use App\Repositories\CompanyRepository; +use Illuminate\Support\Facades\Storage; +use App\Jobs\Company\CreateCompanyToken; +use App\Transformers\CompanyTransformer; +use App\DataMapper\Analytics\AccountDeleted; +use App\Transformers\CompanyUserTransformer; +use Illuminate\Foundation\Bus\DispatchesJobs; +use App\Jobs\Company\CreateCompanyPaymentTerms; +use App\Jobs\Company\CreateCompanyTaskStatuses; +use App\Http\Requests\Company\EditCompanyRequest; +use App\Http\Requests\Company\ShowCompanyRequest; +use App\Http\Requests\Company\StoreCompanyRequest; +use App\Http\Requests\Company\CreateCompanyRequest; +use App\Http\Requests\Company\UpdateCompanyRequest; +use App\Http\Requests\Company\UploadCompanyRequest; +use App\Http\Requests\Company\DefaultCompanyRequest; +use App\Http\Requests\Company\DestroyCompanyRequest; /** * Class CompanyController. @@ -486,6 +487,12 @@ class CompanyController extends BaseController $company_user->forceDelete(); }); + try { + Storage::disk(config('filesystems.default'))->deleteDirectory($company->company_key); + } + catch(\Exception $e) { + } + $account->delete(); if (Ninja::isHosted()) { @@ -494,7 +501,10 @@ class CompanyController extends BaseController LightLogs::create(new AccountDeleted()) ->increment() - ->queue(); + ->batch(); + + + } else { $company_id = $company->id; @@ -511,6 +521,12 @@ class CompanyController extends BaseController $nmo->to_user = auth()->user(); (new NinjaMailerJob($nmo, true))->handle(); + try { + Storage::disk(config('filesystems.default'))->deleteDirectory($company->company_key); + } catch(\Exception $e) { + } + + $company->delete(); //If we are deleting the default companies, we'll need to make a new company the default. diff --git a/app/Http/Controllers/SubdomainController.php b/app/Http/Controllers/SubdomainController.php index 287e5cc819b6..e32f184d3895 100644 --- a/app/Http/Controllers/SubdomainController.php +++ b/app/Http/Controllers/SubdomainController.php @@ -38,6 +38,7 @@ class SubdomainController extends BaseController 'beta', 'prometh', 'license', + 'socket', ]; public function __construct() diff --git a/app/Http/Requests/ClientPortal/PrePayments/StorePrePaymentRequest.php b/app/Http/Requests/ClientPortal/PrePayments/StorePrePaymentRequest.php new file mode 100644 index 000000000000..a591632db413 --- /dev/null +++ b/app/Http/Requests/ClientPortal/PrePayments/StorePrePaymentRequest.php @@ -0,0 +1,34 @@ +guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_INVOICES; + + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'notes' => 'required|bail|', + 'amount' => 'required|bail|', + ]; + } + +} diff --git a/app/Http/ViewComposers/PortalComposer.php b/app/Http/ViewComposers/PortalComposer.php index d1e4134d511e..747cc9572adb 100644 --- a/app/Http/ViewComposers/PortalComposer.php +++ b/app/Http/ViewComposers/PortalComposer.php @@ -138,12 +138,10 @@ class PortalComposer $data[] = ['title' => ctrans('texts.subscriptions'), 'url' => 'client.subscriptions.index', 'icon' => 'calendar']; } - /* - if($this->settings->client_initiated_payments) { + if(property_exists($this->settings, 'client_initiated_payments') && $this->settings->client_initiated_payments) { $data[] = ['title' => ctrans('texts.pre_payment'), 'url' => 'client.pre_payments.index', 'icon' => 'dollar-sign']; } - */ - + return $data; } } diff --git a/app/Jobs/Account/CreateAccount.php b/app/Jobs/Account/CreateAccount.php index a010f8272283..8c7a8d6a42cc 100644 --- a/app/Jobs/Account/CreateAccount.php +++ b/app/Jobs/Account/CreateAccount.php @@ -77,7 +77,7 @@ class CreateAccount $sp794f3f->hosted_company_count = config('ninja.quotas.free.max_companies'); $sp794f3f->account_sms_verified = true; - if (in_array($this->getDomain($this->request['email']), ['givmail.com','yopmail.com','gmail.com', 'hotmail.com', 'outlook.com', 'yahoo.com', 'aol.com', 'mail.ru','brand-app.biz','proton.me','ema-sofia.eu'])) { + if (in_array($this->getDomain($this->request['email']), ['givmail.com','yopmail.com','gmail.com', 'hotmail.com', 'outlook.com', 'yahoo.com', 'aol.com', 'mail.ru','brand-app.biz','proton.me','ema-sofia.eu', 'mail.com'])) { $sp794f3f->account_sms_verified = false; } diff --git a/app/Jobs/Util/Import.php b/app/Jobs/Util/Import.php index 4d12e8948d14..ecfb43a5f96c 100644 --- a/app/Jobs/Util/Import.php +++ b/app/Jobs/Util/Import.php @@ -811,6 +811,10 @@ class Import implements ShouldQueue $modified['updated_at'] = Carbon::parse($modified['updated_at']); } + if(!array_key_exists('currency_id', $modified) || !$modified['currency_id']) { + $modified['currency_id'] = $this->company->settings->currency_id; + } + $vendor = $vendor_repository->save( $modified, VendorFactory::create( diff --git a/app/Jobs/Util/WebhookSingle.php b/app/Jobs/Util/WebhookSingle.php index 7be0f0feeebb..84398b00ee1a 100644 --- a/app/Jobs/Util/WebhookSingle.php +++ b/app/Jobs/Util/WebhookSingle.php @@ -105,7 +105,7 @@ class WebhookSingle implements ShouldQueue $resource = new Item($this->entity, $transformer, $this->entity->getEntityType()); $data = $manager->createData($resource)->toArray(); - $this->postData($subscription, $data, []); + $this->postData($subscription, $data, $subscription->headers); } private function postData($subscription, $data, $headers = []) diff --git a/app/Listeners/Subscription/PlayStoreRenewSubscription.php b/app/Listeners/Subscription/PlayStoreRenewSubscription.php index d03b7111ec9c..1a3bb1684fa8 100644 --- a/app/Listeners/Subscription/PlayStoreRenewSubscription.php +++ b/app/Listeners/Subscription/PlayStoreRenewSubscription.php @@ -28,11 +28,13 @@ class PlayStoreRenewSubscription implements ShouldQueue nlog($notification); $in_app_identifier = $event->getSubscriptionIdentifier(); - MultiDB::findAndSetDbByInappTransactionId($in_app_identifier); + $parts = explode("..", $in_app_identifier); + + MultiDB::findAndSetDbByInappTransactionId($parts[0]); $expirationTime = $event->getSubscription()->getExpiryTime(); - $account = Account::where('inapp_transaction_id', 'like', $in_app_identifier."%")->first(); + $account = Account::where('inapp_transaction_id', 'like', $parts[0]."%")->first(); if ($account) { $account->update(['plan_expires' => Carbon::parse($expirationTime)]); diff --git a/app/Mail/Engine/PaymentEmailEngine.php b/app/Mail/Engine/PaymentEmailEngine.php index 353dfbfb810d..1b274fca2353 100644 --- a/app/Mail/Engine/PaymentEmailEngine.php +++ b/app/Mail/Engine/PaymentEmailEngine.php @@ -362,10 +362,10 @@ class PaymentEmailEngine extends BaseEmailEngine /** * generateLabelsAndValues - * - * @return void + * + * @return array */ - public function generateLabelsAndValues() + public function generateLabelsAndValues(): array { $data = []; diff --git a/app/Models/Account.php b/app/Models/Account.php index 7eb9bd228c5a..5dc6584aef9e 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -130,6 +130,10 @@ use Laracasts\Presenter\PresentableTrait; * @method static \Illuminate\Database\Eloquent\Builder|Account whereUtmMedium($value) * @method static \Illuminate\Database\Eloquent\Builder|Account whereUtmSource($value) * @method static \Illuminate\Database\Eloquent\Builder|Account whereUtmTerm($value) + * @property-read \Illuminate\Database\Eloquent\Collection $bank_integrations + * @property-read \Illuminate\Database\Eloquent\Collection $companies + * @property-read \Illuminate\Database\Eloquent\Collection $company_users + * @property-read \Illuminate\Database\Eloquent\Collection $users * @mixin \Eloquent */ class Account extends BaseModel diff --git a/app/Models/BankAccount.php b/app/Models/BankAccount.php index 7c0ebebdff5a..fd5ea891db41 100644 --- a/app/Models/BankAccount.php +++ b/app/Models/BankAccount.php @@ -32,6 +32,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @method static \Illuminate\Database\Eloquent\Builder|BaseModel scope() * @method static \Illuminate\Database\Eloquent\Builder|BankAccount withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|BankAccount withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $bank_subaccounts * @mixin \Eloquent */ class BankAccount extends BaseModel diff --git a/app/Models/BankIntegration.php b/app/Models/BankIntegration.php index 4c54136ebd1a..b5e414705612 100644 --- a/app/Models/BankIntegration.php +++ b/app/Models/BankIntegration.php @@ -75,6 +75,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @method static \Illuminate\Database\Eloquent\Builder|BankIntegration whereUserId($value) * @method static \Illuminate\Database\Eloquent\Builder|BankIntegration withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|BankIntegration withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $transactions * @mixin \Eloquent */ class BankIntegration extends BaseModel diff --git a/app/Models/Client.php b/app/Models/Client.php index a7d00e361954..a58d7fb450c0 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -166,6 +166,25 @@ use Laracasts\Presenter\PresentableTrait; * @method static \Illuminate\Database\Eloquent\Builder|Client whereWebsite($value) * @method static \Illuminate\Database\Eloquent\Builder|Client withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|Client withoutTrashed() + * @property string $payment_balance + * @property-read \Illuminate\Database\Eloquent\Collection $activities + * @property-read \Illuminate\Database\Eloquent\Collection $company_ledger + * @property-read \Illuminate\Database\Eloquent\Collection $contacts + * @property-read \Illuminate\Database\Eloquent\Collection $credits + * @property-read \Illuminate\Database\Eloquent\Collection $documents + * @property-read \Illuminate\Database\Eloquent\Collection $expenses + * @property-read \Illuminate\Database\Eloquent\Collection $gateway_tokens + * @property-read \Illuminate\Database\Eloquent\Collection $invoices + * @property-read \Illuminate\Database\Eloquent\Collection $ledger + * @property-read \Illuminate\Database\Eloquent\Collection $payments + * @property-read \Illuminate\Database\Eloquent\Collection $primary_contact + * @property-read \Illuminate\Database\Eloquent\Collection $projects + * @property-read \Illuminate\Database\Eloquent\Collection $quotes + * @property-read \Illuminate\Database\Eloquent\Collection $recurring_expenses + * @property-read \Illuminate\Database\Eloquent\Collection $recurring_invoices + * @property-read \Illuminate\Database\Eloquent\Collection $system_logs + * @property-read \Illuminate\Database\Eloquent\Collection $tasks + * @method static \Illuminate\Database\Eloquent\Builder|Client wherePaymentBalance($value) * @mixin \Eloquent */ class Client extends BaseModel implements HasLocalePreference diff --git a/app/Models/ClientContact.php b/app/Models/ClientContact.php index c473116f80f3..21bb1c3ba8ac 100644 --- a/app/Models/ClientContact.php +++ b/app/Models/ClientContact.php @@ -123,6 +123,11 @@ use Laracasts\Presenter\PresentableTrait; * @method static \Illuminate\Database\Eloquent\Builder|ClientContact whereUserId($value) * @method static \Illuminate\Database\Eloquent\Builder|ClientContact withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|ClientContact withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $credit_invitations + * @property-read \Illuminate\Database\Eloquent\Collection $invoice_invitations + * @property-read \Illuminate\Notifications\DatabaseNotificationCollection $notifications + * @property-read \Illuminate\Database\Eloquent\Collection $quote_invitations + * @property-read \Illuminate\Database\Eloquent\Collection $recurring_invoice_invitations * @mixin \Eloquent */ class ClientContact extends Authenticatable implements HasLocalePreference diff --git a/app/Models/Company.php b/app/Models/Company.php index 49531af286ce..bdc442937101 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -282,6 +282,50 @@ use Laracasts\Presenter\PresentableTrait; * @method static \Illuminate\Database\Eloquent\Builder|Company whereUpdatedAt($value) * @method static \Illuminate\Database\Eloquent\Builder|Company whereUseCommaAsDecimalPlace($value) * @method static \Illuminate\Database\Eloquent\Builder|Company whereUseQuoteTermsOnConversion($value) + * @property-read \Illuminate\Database\Eloquent\Collection $activities + * @property-read \Illuminate\Database\Eloquent\Collection $all_activities + * @property-read \Illuminate\Database\Eloquent\Collection $all_documents + * @property-read \Illuminate\Database\Eloquent\Collection $bank_integrations + * @property-read \Illuminate\Database\Eloquent\Collection $bank_transaction_rules + * @property-read \Illuminate\Database\Eloquent\Collection $bank_transactions + * @property-read \Illuminate\Database\Eloquent\Collection $client_contacts + * @property-read \Illuminate\Database\Eloquent\Collection $client_gateway_tokens + * @property-read \Illuminate\Database\Eloquent\Collection $clients + * @property-read \Illuminate\Database\Eloquent\Collection $company_gateways + * @property-read \Illuminate\Database\Eloquent\Collection $company_users + * @property-read \Illuminate\Database\Eloquent\Collection $contacts + * @property-read \Illuminate\Database\Eloquent\Collection $credits + * @property-read \Illuminate\Database\Eloquent\Collection $designs + * @property-read \Illuminate\Database\Eloquent\Collection $documents + * @property-read \Illuminate\Database\Eloquent\Collection $expense_categories + * @property-read \Illuminate\Database\Eloquent\Collection $expenses + * @property-read \Illuminate\Database\Eloquent\Collection $group_settings + * @property-read \Illuminate\Database\Eloquent\Collection $groups + * @property-read \Illuminate\Database\Eloquent\Collection $invoices + * @property-read \Illuminate\Database\Eloquent\Collection $ledger + * @property-read \Illuminate\Database\Eloquent\Collection $payment_terms + * @property-read \Illuminate\Database\Eloquent\Collection $payments + * @property-read \Illuminate\Database\Eloquent\Collection $products + * @property-read \Illuminate\Database\Eloquent\Collection $projects + * @property-read \Illuminate\Database\Eloquent\Collection $purchase_orders + * @property-read \Illuminate\Database\Eloquent\Collection $quotes + * @property-read \Illuminate\Database\Eloquent\Collection $recurring_expenses + * @property-read \Illuminate\Database\Eloquent\Collection $recurring_invoices + * @property-read \Illuminate\Database\Eloquent\Collection $schedulers + * @property-read \Illuminate\Database\Eloquent\Collection $subscriptions + * @property-read \Illuminate\Database\Eloquent\Collection $system_log_relation + * @property-read \Illuminate\Database\Eloquent\Collection $system_logs + * @property-read \Illuminate\Database\Eloquent\Collection $task_schedulers + * @property-read \Illuminate\Database\Eloquent\Collection $task_statuses + * @property-read \Illuminate\Database\Eloquent\Collection $tasks + * @property-read \Illuminate\Database\Eloquent\Collection $tax_rates + * @property-read \Illuminate\Database\Eloquent\Collection $tokens + * @property-read \Illuminate\Database\Eloquent\Collection $tokens_hashed + * @property-read \Illuminate\Database\Eloquent\Collection $user_designs + * @property-read \Illuminate\Database\Eloquent\Collection $user_payment_terms + * @property-read \Illuminate\Database\Eloquent\Collection $users + * @property-read \Illuminate\Database\Eloquent\Collection $vendors + * @property-read \Illuminate\Database\Eloquent\Collection $webhooks * @mixin \Eloquent */ class Company extends BaseModel diff --git a/app/Models/CompanyGateway.php b/app/Models/CompanyGateway.php index edaaa02e0968..4013bf1f006d 100644 --- a/app/Models/CompanyGateway.php +++ b/app/Models/CompanyGateway.php @@ -92,6 +92,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @method static \Illuminate\Database\Eloquent\Builder|CompanyGateway whereUserId($value) * @method static \Illuminate\Database\Eloquent\Builder|CompanyGateway withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|CompanyGateway withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $client_gateway_tokens * @mixin \Eloquent */ class CompanyGateway extends BaseModel diff --git a/app/Models/CompanyUser.php b/app/Models/CompanyUser.php index 0a18f541245d..ed785efffefe 100644 --- a/app/Models/CompanyUser.php +++ b/app/Models/CompanyUser.php @@ -67,6 +67,9 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @method static \Illuminate\Database\Eloquent\Builder|CompanyUser whereUserId($value) * @method static \Illuminate\Database\Eloquent\Builder|CompanyUser withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|CompanyUser withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $token + * @property-read \Illuminate\Database\Eloquent\Collection $tokens + * @property-read \Illuminate\Database\Eloquent\Collection $users * @mixin \Eloquent */ class CompanyUser extends Pivot diff --git a/app/Models/Credit.php b/app/Models/Credit.php index c8c9fc5f0252..752618b450c1 100644 --- a/app/Models/Credit.php +++ b/app/Models/Credit.php @@ -185,6 +185,13 @@ use Laracasts\Presenter\PresentableTrait; * @method static \Illuminate\Database\Eloquent\Builder|Credit whereVendorId($value) * @method static \Illuminate\Database\Eloquent\Builder|Credit withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|Credit withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $activities + * @property-read \Illuminate\Database\Eloquent\Collection $company_ledger + * @property-read \Illuminate\Database\Eloquent\Collection $documents + * @property-read \Illuminate\Database\Eloquent\Collection $history + * @property-read \Illuminate\Database\Eloquent\Collection $invitations + * @property-read \Illuminate\Database\Eloquent\Collection $invoices + * @property-read \Illuminate\Database\Eloquent\Collection $payments * @mixin \Eloquent */ class Credit extends BaseModel diff --git a/app/Models/Expense.php b/app/Models/Expense.php index 3ec8f0b5780c..2ff2a9483126 100644 --- a/app/Models/Expense.php +++ b/app/Models/Expense.php @@ -130,6 +130,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @method static \Illuminate\Database\Eloquent\Builder|Expense whereVendorId($value) * @method static \Illuminate\Database\Eloquent\Builder|Expense withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|Expense withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $documents * @mixin \Eloquent */ class Expense extends BaseModel diff --git a/app/Models/GatewayType.php b/app/Models/GatewayType.php index c359fdbee48c..fa5e08a7a477 100644 --- a/app/Models/GatewayType.php +++ b/app/Models/GatewayType.php @@ -28,6 +28,7 @@ namespace App\Models; * @method static \Illuminate\Database\Eloquent\Builder|GatewayType whereAlias($value) * @method static \Illuminate\Database\Eloquent\Builder|GatewayType whereId($value) * @method static \Illuminate\Database\Eloquent\Builder|GatewayType whereName($value) + * @property-read \Illuminate\Database\Eloquent\Collection $payment_methods * @mixin \Eloquent */ class GatewayType extends StaticModel diff --git a/app/Models/GroupSetting.php b/app/Models/GroupSetting.php index fb8de1203187..afa61135a2eb 100644 --- a/app/Models/GroupSetting.php +++ b/app/Models/GroupSetting.php @@ -54,6 +54,8 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @method static \Illuminate\Database\Eloquent\Builder|GroupSetting whereUserId($value) * @method static \Illuminate\Database\Eloquent\Builder|GroupSetting withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|GroupSetting withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $clients + * @property-read \Illuminate\Database\Eloquent\Collection $documents * @mixin \Eloquent */ class GroupSetting extends StaticModel diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 84cb253604fa..4b897ff62181 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -203,6 +203,15 @@ use Laracasts\Presenter\PresentableTrait; * @method static \Illuminate\Database\Eloquent\Builder|Invoice whereVendorId($value) * @method static \Illuminate\Database\Eloquent\Builder|Invoice withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|Invoice withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $activities + * @property-read \Illuminate\Database\Eloquent\Collection $company_ledger + * @property-read \Illuminate\Database\Eloquent\Collection $credits + * @property-read \Illuminate\Database\Eloquent\Collection $documents + * @property-read \Illuminate\Database\Eloquent\Collection $expenses + * @property-read \Illuminate\Database\Eloquent\Collection $history + * @property-read \Illuminate\Database\Eloquent\Collection $invitations + * @property-read \Illuminate\Database\Eloquent\Collection $payments + * @property-read \Illuminate\Database\Eloquent\Collection $tasks * @mixin \Eloquent */ class Invoice extends BaseModel diff --git a/app/Models/License.php b/app/Models/License.php index bc4f20b70d8d..d2af140651e3 100644 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -13,6 +13,43 @@ namespace App\Models; use Illuminate\Database\Eloquent\SoftDeletes; +/** + * App\Models\License + * + * @property int $id + * @property int|null $created_at + * @property int|null $updated_at + * @property int|null $deleted_at + * @property string|null $first_name + * @property string|null $last_name + * @property string|null $email + * @property string|null $license_key + * @property int|null $is_claimed + * @property string|null $transaction_reference + * @property int|null $product_id + * @property int|null $recurring_invoice_id + * @method static \Illuminate\Database\Eloquent\Builder|StaticModel company() + * @method static \Illuminate\Database\Eloquent\Builder|StaticModel exclude($columns) + * @method static \Illuminate\Database\Eloquent\Builder|License newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|License newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|License onlyTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|License query() + * @method static \Illuminate\Database\Eloquent\Builder|License whereCreatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereDeletedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereEmail($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereFirstName($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereIsClaimed($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereLastName($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereLicenseKey($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereProductId($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereRecurringInvoiceId($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereTransactionReference($value) + * @method static \Illuminate\Database\Eloquent\Builder|License whereUpdatedAt($value) + * @method static \Illuminate\Database\Eloquent\Builder|License withTrashed() + * @method static \Illuminate\Database\Eloquent\Builder|License withoutTrashed() + * @mixin \Eloquent + */ class License extends StaticModel { use SoftDeletes; diff --git a/app/Models/Payment.php b/app/Models/Payment.php index b6f8296a4c3d..70da83de1bdd 100644 --- a/app/Models/Payment.php +++ b/app/Models/Payment.php @@ -132,6 +132,11 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @method static \Illuminate\Database\Eloquent\Builder|Payment whereVendorId($value) * @method static \Illuminate\Database\Eloquent\Builder|Payment withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|Payment withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $company_ledger + * @property-read \Illuminate\Database\Eloquent\Collection $credits + * @property-read \Illuminate\Database\Eloquent\Collection $documents + * @property-read \Illuminate\Database\Eloquent\Collection $invoices + * @property-read \Illuminate\Database\Eloquent\Collection $paymentables * @mixin \Eloquent */ class Payment extends BaseModel diff --git a/app/Models/Product.php b/app/Models/Product.php index 80e64f57d0d5..ac34c8f43cb2 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -96,6 +96,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @method static \Illuminate\Database\Eloquent\Builder|Product whereVendorId($value) * @method static \Illuminate\Database\Eloquent\Builder|Product withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|Product withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $documents * @mixin \Eloquent */ class Product extends BaseModel diff --git a/app/Models/Project.php b/app/Models/Project.php index 30b3e82f5677..42a53c0c756f 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -72,6 +72,8 @@ use Laracasts\Presenter\PresentableTrait; * @method static \Illuminate\Database\Eloquent\Builder|Project whereUserId($value) * @method static \Illuminate\Database\Eloquent\Builder|Project withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|Project withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $documents + * @property-read \Illuminate\Database\Eloquent\Collection $tasks * @mixin \Eloquent */ class Project extends BaseModel diff --git a/app/Models/Proposal.php b/app/Models/Proposal.php index 041d907d56db..f2d75f539937 100644 --- a/app/Models/Proposal.php +++ b/app/Models/Proposal.php @@ -28,6 +28,7 @@ use App\Utils\Traits\MakesHash; * @method static \Illuminate\Database\Eloquent\Builder|Proposal newQuery() * @method static \Illuminate\Database\Eloquent\Builder|Proposal query() * @method static \Illuminate\Database\Eloquent\Builder|BaseModel scope() + * @property-read \Illuminate\Database\Eloquent\Collection $documents * @mixin \Eloquent */ class Proposal extends BaseModel diff --git a/app/Models/PurchaseOrder.php b/app/Models/PurchaseOrder.php index 8d9551541055..dc35fcb5f2e6 100644 --- a/app/Models/PurchaseOrder.php +++ b/app/Models/PurchaseOrder.php @@ -180,6 +180,12 @@ use Illuminate\Support\Facades\Storage; * @method static \Illuminate\Database\Eloquent\Builder|PurchaseOrder whereVendorId($value) * @method static \Illuminate\Database\Eloquent\Builder|PurchaseOrder withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|PurchaseOrder withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $activities + * @property-read \Illuminate\Database\Eloquent\Collection $documents + * @property-read \Illuminate\Database\Eloquent\Collection $history + * @property-read \Illuminate\Database\Eloquent\Collection $invitations + * @property-read \Illuminate\Database\Eloquent\Collection $invoices + * @property-read \Illuminate\Database\Eloquent\Collection $payments * @mixin \Eloquent */ class PurchaseOrder extends BaseModel diff --git a/app/Models/Quote.php b/app/Models/Quote.php index c27d0d6b64be..f62d1d5f59bc 100644 --- a/app/Models/Quote.php +++ b/app/Models/Quote.php @@ -181,6 +181,10 @@ use Laracasts\Presenter\PresentableTrait; * @method static \Illuminate\Database\Eloquent\Builder|Quote whereVendorId($value) * @method static \Illuminate\Database\Eloquent\Builder|Quote withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|Quote withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $activities + * @property-read \Illuminate\Database\Eloquent\Collection $documents + * @property-read \Illuminate\Database\Eloquent\Collection $history + * @property-read \Illuminate\Database\Eloquent\Collection $invitations * @mixin \Eloquent */ class Quote extends BaseModel diff --git a/app/Models/RecurringExpense.php b/app/Models/RecurringExpense.php index 841be99b7afe..d3668a34d1e6 100644 --- a/app/Models/RecurringExpense.php +++ b/app/Models/RecurringExpense.php @@ -139,6 +139,7 @@ use Illuminate\Support\Carbon; * @method static \Illuminate\Database\Eloquent\Builder|RecurringExpense whereVendorId($value) * @method static \Illuminate\Database\Eloquent\Builder|RecurringExpense withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|RecurringExpense withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $documents * @mixin \Eloquent */ class RecurringExpense extends BaseModel diff --git a/app/Models/RecurringInvoice.php b/app/Models/RecurringInvoice.php index 4a5de7fc39aa..34cc53715fea 100644 --- a/app/Models/RecurringInvoice.php +++ b/app/Models/RecurringInvoice.php @@ -177,6 +177,11 @@ use Laracasts\Presenter\PresentableTrait; * @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereVendorId($value) * @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $activities + * @property-read \Illuminate\Database\Eloquent\Collection $documents + * @property-read \Illuminate\Database\Eloquent\Collection $history + * @property-read \Illuminate\Database\Eloquent\Collection $invitations + * @property-read \Illuminate\Database\Eloquent\Collection $invoices * @mixin \Eloquent */ class RecurringInvoice extends BaseModel diff --git a/app/Models/RecurringQuote.php b/app/Models/RecurringQuote.php index ce68c134dd50..569f57d7445f 100644 --- a/app/Models/RecurringQuote.php +++ b/app/Models/RecurringQuote.php @@ -171,6 +171,11 @@ use Laracasts\Presenter\PresentableTrait; * @method static \Illuminate\Database\Eloquent\Builder|RecurringQuote whereVendorId($value) * @method static \Illuminate\Database\Eloquent\Builder|RecurringQuote withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|RecurringQuote withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $activities + * @property-read \Illuminate\Database\Eloquent\Collection $documents + * @property-read \Illuminate\Database\Eloquent\Collection $history + * @property-read \Illuminate\Database\Eloquent\Collection $invitations + * @property-read \Illuminate\Database\Eloquent\Collection $quotes * @mixin \Eloquent */ class RecurringQuote extends BaseModel diff --git a/app/Models/Task.php b/app/Models/Task.php index 6f52ff2a8745..4a1829c98eae 100644 --- a/app/Models/Task.php +++ b/app/Models/Task.php @@ -91,6 +91,7 @@ use Illuminate\Support\Carbon; * @method static \Illuminate\Database\Eloquent\Builder|Task whereUserId($value) * @method static \Illuminate\Database\Eloquent\Builder|Task withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|Task withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $documents * @mixin \Eloquent */ class Task extends BaseModel diff --git a/app/Models/User.php b/app/Models/User.php index fc57697d5e10..eabc9eb07bc8 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -139,6 +139,13 @@ use Laracasts\Presenter\PresentableTrait; * @method static \Illuminate\Database\Eloquent\Builder|User whereVerifiedPhoneNumber($value) * @method static \Illuminate\Database\Eloquent\Builder|User withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|User withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $clients + * @property-read \Illuminate\Database\Eloquent\Collection $companies + * @property-read \Illuminate\Database\Eloquent\Collection $company_users + * @property-read \Illuminate\Database\Eloquent\Collection $contacts + * @property-read \Illuminate\Database\Eloquent\Collection $documents + * @property-read \Illuminate\Notifications\DatabaseNotificationCollection $notifications + * @property-read \Illuminate\Database\Eloquent\Collection $tokens * @mixin \Eloquent */ class User extends Authenticatable implements MustVerifyEmail diff --git a/app/Models/Vendor.php b/app/Models/Vendor.php index 51f998ab5826..1508a5944a19 100644 --- a/app/Models/Vendor.php +++ b/app/Models/Vendor.php @@ -104,6 +104,10 @@ use Laracasts\Presenter\PresentableTrait; * @method static \Illuminate\Database\Eloquent\Builder|Vendor whereWebsite($value) * @method static \Illuminate\Database\Eloquent\Builder|Vendor withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|Vendor withoutTrashed() + * @property-read \Illuminate\Database\Eloquent\Collection $activities + * @property-read \Illuminate\Database\Eloquent\Collection $contacts + * @property-read \Illuminate\Database\Eloquent\Collection $documents + * @property-read \Illuminate\Database\Eloquent\Collection $primary_contact * @mixin \Eloquent */ class Vendor extends BaseModel diff --git a/app/Models/VendorContact.php b/app/Models/VendorContact.php index 5026bbdc9625..fe9b61caff53 100644 --- a/app/Models/VendorContact.php +++ b/app/Models/VendorContact.php @@ -110,6 +110,8 @@ use Laracasts\Presenter\PresentableTrait; * @method static \Illuminate\Database\Eloquent\Builder|VendorContact whereVendorId($value) * @method static \Illuminate\Database\Eloquent\Builder|VendorContact withTrashed() * @method static \Illuminate\Database\Eloquent\Builder|VendorContact withoutTrashed() + * @property-read \Illuminate\Notifications\DatabaseNotificationCollection $notifications + * @property-read \Illuminate\Database\Eloquent\Collection $purchase_order_invitations * @mixin \Eloquent */ class VendorContact extends Authenticatable implements HasLocalePreference diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 15d441ec2e29..73b6e6a118b0 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -24,7 +24,6 @@ class RouteServiceProvider extends ServiceProvider { use MakesHash; - private int $default_rate_limit = 5000; /** * Define your route model bindings, pattern filters, etc. * diff --git a/app/Repositories/InvoiceRepository.php b/app/Repositories/InvoiceRepository.php index 1490cfaec06f..f88c5a295776 100644 --- a/app/Repositories/InvoiceRepository.php +++ b/app/Repositories/InvoiceRepository.php @@ -83,6 +83,9 @@ class InvoiceRepository extends BaseRepository */ public function restore($invoice) :Invoice { + if($invoice->is_proforma) + return $invoice; + //if we have just archived, only perform a soft restore if (! $invoice->is_deleted) { parent::restore($invoice); diff --git a/app/Services/ClientPortal/InstantPayment.php b/app/Services/ClientPortal/InstantPayment.php index 359d1e9b8b73..6dcae4a17921 100644 --- a/app/Services/ClientPortal/InstantPayment.php +++ b/app/Services/ClientPortal/InstantPayment.php @@ -214,7 +214,7 @@ class InstantPayment $credit_totals = 0; } - $hash_data = ['invoices' => $payable_invoices->toArray(), 'credits' => $credit_totals, 'amount_with_fee' => max(0, (($invoice_totals + $fee_totals) - $credit_totals))]; + $hash_data = ['invoices' => $payable_invoices->toArray(), 'credits' => $credit_totals, 'amount_with_fee' => max(0, (($invoice_totals + $fee_totals) - $credit_totals)), 'pre_payment' => $this->request->pre_payment]; if ($this->request->query('hash')) { $hash_data['billing_context'] = Cache::get($this->request->query('hash')); diff --git a/app/Services/Email/EmailDefaults.php b/app/Services/Email/EmailDefaults.php index 2aa356a4d85c..c76575e0a7a4 100644 --- a/app/Services/Email/EmailDefaults.php +++ b/app/Services/Email/EmailDefaults.php @@ -168,6 +168,12 @@ class EmailDefaults */ private function setBody(): self { + + if ($this->template == 'email.template.custom') { + $this->email->email_object->body = (str_replace('$body', $this->email->email_object->body, $this->email->email_object->settings->email_style_custom)); + return $this; + } + if ($this->email->email_object->body) { // A Custom Message has been set in the email screen. return $this; @@ -179,10 +185,6 @@ class EmailDefaults $this->email->email_object->body = EmailTemplateDefaults::getDefaultTemplate($this->email->email_object->email_template_body, $this->locale); } - if ($this->template == 'email.template.custom') { - $this->email->email_object->body = (str_replace('$body', $this->email->email_object->body, $this->email->email_object->settings->email_style_custom)); - } - return $this; } diff --git a/app/Services/Email/EmailMailable.php b/app/Services/Email/EmailMailable.php index 08c8a54dc2ae..8cbb990e36c5 100644 --- a/app/Services/Email/EmailMailable.php +++ b/app/Services/Email/EmailMailable.php @@ -39,7 +39,7 @@ class EmailMailable extends Mailable * @return \Illuminate\Mail\Mailables\Envelope */ public function envelope() - {nlog($this->email_object->cc); + { return new Envelope( subject: $this->email_object->subject, tags: [$this->email_object->company_key], diff --git a/app/Services/Payment/UpdateInvoicePayment.php b/app/Services/Payment/UpdateInvoicePayment.php index 9ffdbe5b02d2..0fe1a9001edc 100644 --- a/app/Services/Payment/UpdateInvoicePayment.php +++ b/app/Services/Payment/UpdateInvoicePayment.php @@ -82,10 +82,22 @@ class UpdateInvoicePayment ->save(); if ($invoice->is_proforma) { - if (strlen($invoice->number) > 1 && str_starts_with($invoice->number, "####")) { - $invoice->number = ''; + + //keep proforma's hidden + if(property_exists($this->payment_hash->data, 'pre_payment') && $this->payment_hash->data->pre_payment == "1"){ + + $invoice->payments()->each(function ($p) { + $p->pivot->forceDelete(); + }); + + $invoice->is_deleted = true; + $invoice->deleted_at = now(); + $invoice->saveQuietly(); + return; } - + + if (strlen($invoice->number) > 1 && str_starts_with($invoice->number, "####")) + $invoice->number = ''; $invoice->is_proforma = false; diff --git a/app/Utils/HtmlEngine.php b/app/Utils/HtmlEngine.php index 3872ef95666e..c889bd675f58 100644 --- a/app/Utils/HtmlEngine.php +++ b/app/Utils/HtmlEngine.php @@ -683,8 +683,6 @@ class HtmlEngine $data['labels'][$key.'_label'] = $value['label']; } - // nlog($data); - return $data; } diff --git a/app/Utils/TemplateEngine.php b/app/Utils/TemplateEngine.php index ca10200a882e..778a0083fcfc 100644 --- a/app/Utils/TemplateEngine.php +++ b/app/Utils/TemplateEngine.php @@ -12,27 +12,28 @@ namespace App\Utils; -use App\DataMapper\EmailTemplateDefaults; -use App\Mail\Engine\PaymentEmailEngine; -use App\Models\Client; -use App\Models\ClientContact; -use App\Models\Invoice; -use App\Models\InvoiceInvitation; -use App\Models\Payment; -use App\Models\PurchaseOrder; -use App\Models\PurchaseOrderInvitation; -use App\Models\Quote; -use App\Models\QuoteInvitation; -use App\Models\Vendor; -use App\Models\VendorContact; -use App\Services\PdfMaker\Designs\Utilities\DesignHelpers; -use App\Utils\Traits\MakesHash; -use App\Utils\Traits\MakesInvoiceHtml; -use App\Utils\Traits\MakesTemplateData; use DB; -use Illuminate\Support\Facades\App; +use App\Models\Quote; +use App\Models\Client; +use App\Models\Vendor; +use App\Models\Invoice; +use App\Models\Payment; use Illuminate\Support\Str; +use App\Models\ClientContact; +use App\Models\PurchaseOrder; +use App\Models\VendorContact; +use App\Services\Pdf\PdfMock; +use App\Models\QuoteInvitation; +use App\Utils\Traits\MakesHash; +use App\Models\InvoiceInvitation; +use Illuminate\Support\Facades\App; +use App\Utils\Traits\MakesInvoiceHtml; +use App\Mail\Engine\PaymentEmailEngine; +use App\Models\PurchaseOrderInvitation; +use App\Utils\Traits\MakesTemplateData; +use App\DataMapper\EmailTemplateDefaults; use League\CommonMark\CommonMarkConverter; +use App\Services\PdfMaker\Designs\Utilities\DesignHelpers; class TemplateEngine { @@ -96,7 +97,19 @@ class TemplateEngine if (strlen($this->entity) > 1 && strlen($this->entity_id) > 1) { $class = 'App\Models\\' . ucfirst(Str::camel($this->entity)); $this->entity_obj = $class::withTrashed()->where('id', $this->decodePrimaryKey($this->entity_id))->company()->first(); - } else { + } + elseif(stripos($this->template, 'quote') !== false && $quote = Quote::whereHas('invitations')->withTrashed()->company()->first()){ + $this->entity = 'quote'; + $this->entity_obj = $quote; + } + elseif(stripos($this->template, 'purchase') !== false && $purchase_order = PurchaseOrder::whereHas('invitations')->withTrashed()->company()->first()){ + $this->entity = 'purchase_order'; + $this->entity_obj = $purchase_order; + } + elseif ($invoice = Invoice::whereHas('invitations')->withTrashed()->company()->first()){ + $this->entity_obj = $invoice; + } + else { $this->mockEntity(); } @@ -183,6 +196,7 @@ class TemplateEngine private function entityValues($contact) { + if (in_array($this->entity, ['purchaseOrder', 'purchase_order'])) { $this->labels_and_values = (new VendorHtmlEngine($this->entity_obj->invitations->first()))->generateLabelsAndValues(); } elseif ($this->entity == 'payment') { @@ -323,6 +337,8 @@ class TemplateEngine 'user_id' => auth()->user()->id, 'company_id' => auth()->user()->company()->id, 'client_id' => $client->id, + 'amount' => '10', + 'balance' => '10', ]); $invitation = InvoiceInvitation::factory()->create([ @@ -391,6 +407,7 @@ class TemplateEngine $this->entity_obj->load('client'); $client->setRelation('company', auth()->user()->company()); $client->load('company'); + } } diff --git a/app/Utils/VendorHtmlEngine.php b/app/Utils/VendorHtmlEngine.php index 4eac57ac59bc..aab9b9fb3302 100644 --- a/app/Utils/VendorHtmlEngine.php +++ b/app/Utils/VendorHtmlEngine.php @@ -511,7 +511,7 @@ class VendorHtmlEngine $data['values'][$key] = $value['value']; $data['labels'][$key.'_label'] = $value['label']; } -nlog($data); + return $data; } diff --git a/composer.json b/composer.json index c85baeeb4327..eb24cf0460f1 100644 --- a/composer.json +++ b/composer.json @@ -74,7 +74,7 @@ "omnipay/paypal": "^3.0", "payfast/payfast-php-sdk": "^1.1", "pragmarx/google2fa": "^8.0", - "turbo124/predis": "1.1.11", + "pusher/pusher-php-server": "^7.2", "razorpay/razorpay": "2.*", "sentry/sentry-laravel": "^3", "setasign/fpdf": "^1.8", @@ -88,6 +88,7 @@ "symfony/mailgun-mailer": "^6.1", "symfony/postmark-mailer": "^6.1", "turbo124/beacon": "^1.4", + "turbo124/predis": "1.1.11", "twilio/sdk": "^6.40", "webpatser/laravel-countries": "dev-master#75992ad", "wepay/php-sdk": "^0.3" diff --git a/composer.lock b/composer.lock index 6cf928a7b942..d3c2b6033f11 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5aa22a61531e67324395d207a7c94e27", + "content-hash": "9f936d7b92dfacb4e28eda9197563c32", "packages": [ { "name": "afosto/yaac", @@ -6369,6 +6369,92 @@ }, "time": "2020-10-15T08:29:30+00:00" }, + { + "name": "paragonie/sodium_compat", + "version": "v1.19.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/sodium_compat.git", + "reference": "cb15e403ecbe6a6cc515f855c310eb6b1872a933" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/cb15e403ecbe6a6cc515f855c310eb6b1872a933", + "reference": "cb15e403ecbe6a6cc515f855c310eb6b1872a933", + "shasum": "" + }, + "require": { + "paragonie/random_compat": ">=1", + "php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7|^8" + }, + "require-dev": { + "phpunit/phpunit": "^3|^4|^5|^6|^7|^8|^9" + }, + "suggest": { + "ext-libsodium": "PHP < 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security.", + "ext-sodium": "PHP >= 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security." + }, + "type": "library", + "autoload": { + "files": [ + "autoload.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com" + }, + { + "name": "Frank Denis", + "email": "jedisct1@pureftpd.org" + } + ], + "description": "Pure PHP implementation of libsodium; uses the PHP extension if it exists", + "keywords": [ + "Authentication", + "BLAKE2b", + "ChaCha20", + "ChaCha20-Poly1305", + "Chapoly", + "Curve25519", + "Ed25519", + "EdDSA", + "Edwards-curve Digital Signature Algorithm", + "Elliptic Curve Diffie-Hellman", + "Poly1305", + "Pure-PHP cryptography", + "RFC 7748", + "RFC 8032", + "Salpoly", + "Salsa20", + "X25519", + "XChaCha20-Poly1305", + "XSalsa20-Poly1305", + "Xchacha20", + "Xsalsa20", + "aead", + "cryptography", + "ecdh", + "elliptic curve", + "elliptic curve cryptography", + "encryption", + "libsodium", + "php", + "public-key cryptography", + "secret-key cryptography", + "side-channel resistant" + ], + "support": { + "issues": "https://github.com/paragonie/sodium_compat/issues", + "source": "https://github.com/paragonie/sodium_compat/tree/v1.19.0" + }, + "time": "2022-09-26T03:40:35+00:00" + }, { "name": "payfast/payfast-php-sdk", "version": "v1.1.4", @@ -7645,6 +7731,67 @@ }, "time": "2023-01-29T21:24:40+00:00" }, + { + "name": "pusher/pusher-php-server", + "version": "7.2.2", + "source": { + "type": "git", + "url": "https://github.com/pusher/pusher-http-php.git", + "reference": "4ace4873873b06c25cecb2dd6d9fdcbf2f20b640" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pusher/pusher-http-php/zipball/4ace4873873b06c25cecb2dd6d9fdcbf2f20b640", + "reference": "4ace4873873b06c25cecb2dd6d9fdcbf2f20b640", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "guzzlehttp/guzzle": "^7.2", + "paragonie/sodium_compat": "^1.6", + "php": "^7.3|^8.0", + "psr/log": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "overtrue/phplint": "^2.3", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Pusher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Library for interacting with the Pusher REST API", + "keywords": [ + "events", + "messaging", + "php-pusher-server", + "publish", + "push", + "pusher", + "real time", + "real-time", + "realtime", + "rest", + "trigger" + ], + "support": { + "issues": "https://github.com/pusher/pusher-http-php/issues", + "source": "https://github.com/pusher/pusher-http-php/tree/7.2.2" + }, + "time": "2022-12-20T19:52:36+00:00" + }, { "name": "ralouphie/getallheaders", "version": "3.0.3", diff --git a/config/ninja.php b/config/ninja.php index 234559067aa9..e847e0c1d386 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -14,8 +14,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => '5.5.93', - 'app_tag' => '5.5.93', + 'app_version' => '5.5.94', + 'app_tag' => '5.5.94', 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', ''), diff --git a/database/seeders/RandomDataSeeder.php b/database/seeders/RandomDataSeeder.php index 6ecc2b535c3a..13a0e89c091d 100644 --- a/database/seeders/RandomDataSeeder.php +++ b/database/seeders/RandomDataSeeder.php @@ -110,6 +110,7 @@ class RandomDataSeeder extends Seeder 'account_id' => $account->id, 'name' => 'test token', 'token' => \Illuminate\Support\Str::random(64), + 'is_system' => 1 ]); $user->companies()->attach($company->id, [ @@ -157,6 +158,7 @@ class RandomDataSeeder extends Seeder 'account_id' => $account->id, 'name' => 'test token', 'token' => \Illuminate\Support\Str::random(64), + 'is_system' => 1, ]); $user->companies()->attach($company->id, [ @@ -200,6 +202,7 @@ class RandomDataSeeder extends Seeder 'account_id' => $account->id, 'name' => 'test token', 'token' => \Illuminate\Support\Str::random(64), + 'is_system' => 1, ]); diff --git a/lang/en/texts.php b/lang/en/texts.php index 0c91c98bcd70..19230f5b0211 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -5021,6 +5021,7 @@ $LANG = array( 'payment_type_Klarna' => 'Klarna', 'payment_type_Interac E Transfer' => 'Interac E Transfer', 'pre_payment' => 'Pre Payment', + 'client_remaining_cycles_helper' => 'The number of times this invoice will be generated', ); diff --git a/resources/views/portal/ninja2020/invoices/payment.blade.php b/resources/views/portal/ninja2020/invoices/payment.blade.php index b45fd4435575..adc7b32c90b6 100644 --- a/resources/views/portal/ninja2020/invoices/payment.blade.php +++ b/resources/views/portal/ninja2020/invoices/payment.blade.php @@ -13,6 +13,7 @@ +
@@ -110,7 +111,6 @@ type="text" class="input mt-0 mr-4 relative" name="payable_invoices[{{$key}}][amount]" - dusk="underpayment-input" value="{{ $invoice->partial > 0 ? $invoice->partial : $invoice->balance }}"/>
diff --git a/resources/views/portal/ninja2020/payments/show.blade.php b/resources/views/portal/ninja2020/payments/show.blade.php index 80c443d700ad..91f68b79dbbc 100644 --- a/resources/views/portal/ninja2020/payments/show.blade.php +++ b/resources/views/portal/ninja2020/payments/show.blade.php @@ -14,6 +14,18 @@
+ + @if(!empty($payment->status_id) && !is_null($payment->status_id)) +
+
+ {{ ctrans('texts.status') }} +
+
+ {!! \App\Models\Payment::badgeForStatus($payment->status_id) !!} +
+
+ @endif + @if(!empty($payment->clientPaymentDate()) && !is_null($payment->clientPaymentDate()))
@@ -72,14 +84,6 @@ @endif @if(!empty($payment->status_id) && !is_null($payment->status_id)) -
-
- {{ ctrans('texts.status') }} -
-
- {!! \App\Models\Payment::badgeForStatus($payment->status_id) !!} -
-
@if($payment->refunded > 0)
@@ -91,6 +95,18 @@
@endif + + @if($payment->applied != $payment->amount) +
+
+ {{ ctrans('texts.remaining') }} +
+
+ {{ \App\Utils\Number::formatMoney($payment->amount - $payment->applied, $payment->client) }} +
+
+ @endif + @endif @@ -107,6 +123,7 @@
@foreach($payment->invoices as $invoice) + @if(!$invoice->is_proforma)
{{ ctrans('texts.invoice_number') }} @@ -119,6 +136,7 @@ - {{ \App\Utils\Number::formatMoney($payment->invoices->where('id', $invoice->id)->sum('pivot.amount') - $payment->invoices->where('id', $invoice->id)->sum('pivot.refunded'), $payment->client) }}
+ @endif @endforeach diff --git a/resources/views/portal/ninja2020/pre_payments/index.blade.php b/resources/views/portal/ninja2020/pre_payments/index.blade.php new file mode 100644 index 000000000000..50acf0fa0ad6 --- /dev/null +++ b/resources/views/portal/ninja2020/pre_payments/index.blade.php @@ -0,0 +1,101 @@ +@extends('portal.ninja2020.layout.app') +@section('meta_title', ctrans('texts.pre_payment')) + +@push('head') + +@endpush +@section('body') +
+ @csrf + + + + +
+
+
+
+
+ +
+
+

+ {{ ctrans('texts.payment') }} +

+
+ + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_details')]) + + + @if($errors->has('notes')) +

{{ $errors->first('notes') }}

+ @endif + @endcomponent + + + @component('portal.ninja2020.components.general.card-element', ['title' => $title]) + + + @if($errors->has('amount')) +

{{ $errors->first('amount') }}

+ @endif + + @endcomponent + + @if($allows_recurring) +
+ @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.enable_recurring')]) + + @endcomponent + +
+ @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.cycles_remaining')]) + + + + + @endcomponent + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.frequency')]) + + @endcomponent +
+ +
+ + @endif + +
+ +
+
+ +
+
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/portal/ninja2020/recurring_invoices/show.blade.php b/resources/views/portal/ninja2020/recurring_invoices/show.blade.php index 4cdf71849e08..df9a8c59bf9d 100644 --- a/resources/views/portal/ninja2020/recurring_invoices/show.blade.php +++ b/resources/views/portal/ninja2020/recurring_invoices/show.blade.php @@ -76,6 +76,40 @@ @endif +
+
+

+ {{ ctrans('texts.invoices') }} +

+
+
+
+ @foreach($invoice->invoices as $inv) +
+
+ {{ ctrans('texts.invoice_number') }} +
+
+ + {{ $inv->number }} + + - {{ \App\Utils\Number::formatMoney($inv->amount, $invoice->client) }} +
+
+ @endforeach +
+
+ + + + + + + + + + @if($invoice->subscription && $invoice->subscription?->allow_cancellation) {{-- INV2-591 --}} {{-- @if(false) --}} diff --git a/routes/client.php b/routes/client.php index e7439906f6e5..19b0dcd2acc1 100644 --- a/routes/client.php +++ b/routes/client.php @@ -68,7 +68,7 @@ Route::group(['middleware' => ['auth:contact', 'locale', 'domain_db','check_clie Route::get('payments/{payment}', [App\Http\Controllers\ClientPortal\PaymentController::class, 'show'])->name('payments.show'); Route::get('pre_payments', [PrePaymentController::class, 'index'])->name('pre_payments.index')->middleware('portal_enabled'); - Route::get('pre_payments/process', [PrePaymentController::class, 'process'])->name('pre_payments.process')->middleware('portal_enabled'); + Route::post('pre_payments/process', [PrePaymentController::class, 'process'])->name('pre_payments.process')->middleware('portal_enabled'); Route::get('profile/{client_contact}/edit', [App\Http\Controllers\ClientPortal\ProfileController::class, 'edit'])->name('profile.edit'); Route::put('profile/{client_contact}/edit', [App\Http\Controllers\ClientPortal\ProfileController::class, 'update'])->name('profile.update');