diff --git a/app/Factory/InvoiceItemFactory.php b/app/Factory/InvoiceItemFactory.php index 5890e5f8feee..012dab417e5b 100644 --- a/app/Factory/InvoiceItemFactory.php +++ b/app/Factory/InvoiceItemFactory.php @@ -64,10 +64,10 @@ class InvoiceItemFactory $item->discount = $faker->numberBetween(1, 10); $item->notes = $faker->realText(50); $item->product_key = $faker->word(); - $item->custom_value1 = $faker->realText(10); - $item->custom_value2 = $faker->realText(10); - $item->custom_value3 = $faker->realText(10); - $item->custom_value4 = $faker->realText(10); + // $item->custom_value1 = $faker->realText(10); + // $item->custom_value2 = $faker->realText(10); + // $item->custom_value3 = $faker->realText(10); + // $item->custom_value4 = $faker->realText(10); $item->tax_name1 = 'GST'; $item->tax_rate1 = 10.00; $item->type_id = "1"; @@ -98,10 +98,10 @@ class InvoiceItemFactory $item->discount = 0; $item->notes = $faker->realText(20); $item->product_key = $faker->word(); - $item->custom_value1 = $faker->realText(10); - $item->custom_value2 = $faker->realText(10); - $item->custom_value3 = $faker->realText(10); - $item->custom_value4 = $faker->realText(10); + // $item->custom_value1 = $faker->realText(10); + // $item->custom_value2 = $faker->realText(10); + // $item->custom_value3 = $faker->realText(10); + // $item->custom_value4 = $faker->realText(10); $item->tax_name1 = ''; $item->tax_rate1 = 0; $item->type_id = "1"; diff --git a/app/Http/Controllers/ClientPortal/PaymentController.php b/app/Http/Controllers/ClientPortal/PaymentController.php index 97dc9c5a1d66..4f2b70846389 100644 --- a/app/Http/Controllers/ClientPortal/PaymentController.php +++ b/app/Http/Controllers/ClientPortal/PaymentController.php @@ -214,7 +214,7 @@ class PaymentController extends Controller $payment_method_id = $request->input('payment_method_id'); $invoice_totals = $payable_invoices->sum('amount'); $first_invoice = $invoices->first(); - $credit_totals = $first_invoice->client->getSetting('use_credits_payment') == 'off' ? 0 : $first_invoice->client->service()->getCreditBalance(); + $credit_totals = $first_invoice->client->getSetting('use_credits_payment') == 'always' ? $first_invoice->client->service()->getCreditBalance() : 0; $starting_invoice_amount = $first_invoice->amount; if ($gateway) { diff --git a/app/Http/Controllers/EmailController.php b/app/Http/Controllers/EmailController.php index 8481a0939ad6..97a325f0fa1e 100644 --- a/app/Http/Controllers/EmailController.php +++ b/app/Http/Controllers/EmailController.php @@ -128,7 +128,11 @@ class EmailController extends BaseController 'body' => $body ]; - EmailEntity::dispatchNow($invitation, $invitation->company, $template, $data); + $entity_obj->service()->markSent()->save(); + + //@TODO why is this dispatchNow instead of just dispatch? + //update - changing to dispatch and see if something breaks. + EmailEntity::dispatch($invitation, $invitation->company, $template, $data)->delay(now()->addSeconds(5)); } }); diff --git a/app/Http/Requests/Expense/StoreExpenseRequest.php b/app/Http/Requests/Expense/StoreExpenseRequest.php index bffb4012c265..828217b4ee63 100644 --- a/app/Http/Requests/Expense/StoreExpenseRequest.php +++ b/app/Http/Requests/Expense/StoreExpenseRequest.php @@ -38,12 +38,9 @@ class StoreExpenseRequest extends Request if (isset($this->number)) { $rules['number'] = Rule::unique('expenses')->where('company_id', auth()->user()->company()->id); } - - // $rules['number'] = 'unique:expenses,number,'.$this->id.',id,company_id,'.auth()->user()->company()->id; - // $rules['contacts.*.email'] = 'nullable|distinct'; - //$rules['number'] = new UniqueExpenseNumberRule($this->all()); - $rules['client_id'] = 'bail|sometimes|exists:clients,id,company_id,'.auth()->user()->company()->id; + if(!empty($this->client_id)) + $rules['client_id'] = 'bail|sometimes|exists:clients,id,company_id,'.auth()->user()->company()->id; return $this->globalRules($rules); } diff --git a/app/Http/Requests/Expense/UpdateExpenseRequest.php b/app/Http/Requests/Expense/UpdateExpenseRequest.php index 3295603f4f1e..71a8a7773a24 100644 --- a/app/Http/Requests/Expense/UpdateExpenseRequest.php +++ b/app/Http/Requests/Expense/UpdateExpenseRequest.php @@ -36,7 +36,7 @@ class UpdateExpenseRequest extends Request /* Ensure we have a client name, and that all emails are unique*/ $rules['country_id'] = 'integer|nullable'; - //$rules['id_number'] = 'unique:clients,id_number,,id,company_id,' . auth()->user()->company()->id; + $rules['contacts.*.email'] = 'nullable|distinct'; if (isset($this->number)) { diff --git a/app/Jobs/Entity/CreateEntityPdf.php b/app/Jobs/Entity/CreateEntityPdf.php index a21fc5d63c4f..04ca27461698 100644 --- a/app/Jobs/Entity/CreateEntityPdf.php +++ b/app/Jobs/Entity/CreateEntityPdf.php @@ -108,7 +108,6 @@ class CreateEntityPdf implements ShouldQueue $entity_design_id = 'credit_design_id'; } - $file_path = $path.$this->entity->number.'.pdf'; $entity_design_id = $this->entity->design_id ? $this->entity->design_id : $this->decodePrimaryKey($this->entity->client->getSetting($entity_design_id)); @@ -145,10 +144,6 @@ class CreateEntityPdf implements ShouldQueue ->design($template) ->build(); - //todo - move this to the client creation stage so we don't keep hitting this unnecessarily - //nlog("make dir => {$path}"); - //Storage::makeDirectory($path, 0775); - $pdf = null; try { diff --git a/app/Jobs/Entity/EmailEntity.php b/app/Jobs/Entity/EmailEntity.php index bcfcb87ae602..0021aad84b88 100644 --- a/app/Jobs/Entity/EmailEntity.php +++ b/app/Jobs/Entity/EmailEntity.php @@ -110,15 +110,11 @@ class EmailEntity extends BaseMailerJob implements ShouldQueue ) ); } catch (\Exception $e) { -// $this->failed($e); + $this->entityEmailFailed($e->getMessage()); $this->logMailError($e->getMessage(), $this->entity->client); } - // if (count(Mail::failures()) == 0) { - // $this->entityEmailSucceeded(); - // } - /* Mark entity sent */ $this->entity->service()->markSent()->save(); } diff --git a/app/Models/Company.php b/app/Models/Company.php index c5fd0465595f..90a266d18e99 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -83,7 +83,6 @@ class Company extends BaseModel 'default_task_is_date_based', 'enable_product_discount', 'expense_inclusive_taxes', - 'expense_amount_is_pretax', ]; protected $hidden = [ diff --git a/app/Models/Expense.php b/app/Models/Expense.php index 6b54ef387364..c50a3f59f7f9 100644 --- a/app/Models/Expense.php +++ b/app/Models/Expense.php @@ -55,7 +55,7 @@ class Expense extends BaseModel 'tax_amount2', 'tax_amount3', 'uses_inclusive_taxes', - 'amount_is_pretax', + 'calculate_tax_by_amount', ]; protected $casts = [ diff --git a/app/Models/RecurringInvoice.php b/app/Models/RecurringInvoice.php index 1c34f6c5e98e..549aa08333ee 100644 --- a/app/Models/RecurringInvoice.php +++ b/app/Models/RecurringInvoice.php @@ -91,6 +91,7 @@ class RecurringInvoice extends BaseModel 'remaining_cycles', 'auto_bill', 'auto_bill_enabled', + 'design_id', ]; protected $casts = [ diff --git a/app/PaymentDrivers/Authorize/AuthorizeCreditCard.php b/app/PaymentDrivers/Authorize/AuthorizeCreditCard.php index 4d431fc3df97..8b3bb046f4dd 100644 --- a/app/PaymentDrivers/Authorize/AuthorizeCreditCard.php +++ b/app/PaymentDrivers/Authorize/AuthorizeCreditCard.php @@ -140,11 +140,6 @@ class AuthorizeCreditCard } - - - - - private function handleResponse($data, $request) { $response = $data['response']; @@ -205,7 +200,12 @@ class AuthorizeCreditCard 'data' => $this->formatGatewayResponse($data, $vars), ]; - SystemLogger::dispatch($logger_message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_AUTHORIZE, $this->authorize->client); + SystemLogger::dispatch( + $logger_message, + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_SUCCESS, + SystemLog::TYPE_AUTHORIZE, + $this->authorize->client); return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); } diff --git a/app/PaymentDrivers/BaseDriver.php b/app/PaymentDrivers/BaseDriver.php index 8366c4f5f627..168d96e435e5 100644 --- a/app/PaymentDrivers/BaseDriver.php +++ b/app/PaymentDrivers/BaseDriver.php @@ -468,4 +468,16 @@ class BaseDriver extends AbstractPaymentDriver { return $this->company_gateway->id; } + + public function logSuccessfulGatewayResponse($response, $gateway_const) + { + + SystemLogger::dispatch( + $response, + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_SUCCESS, + $gateway_const, + $this->client, + ); + } } diff --git a/app/PaymentDrivers/Stripe/CreditCard.php b/app/PaymentDrivers/Stripe/CreditCard.php index fa2755e14d2c..c575f7d03ebf 100644 --- a/app/PaymentDrivers/Stripe/CreditCard.php +++ b/app/PaymentDrivers/Stripe/CreditCard.php @@ -103,6 +103,8 @@ class CreditCard if ($server_response->status == 'succeeded') { $this->stripe->confirmGatewayFee($request); + $this->stripe->logSuccessfulGatewayResponse(['response' => json_decode($request->gateway_response), 'data' => $this->stripe->payment_hash], SystemLog::TYPE_STRIPE); + return $this->processSuccessfulPayment(); } diff --git a/app/Services/Invoice/GetInvoicePdf.php b/app/Services/Invoice/GetInvoicePdf.php index 838511988b0d..4fe48bbaad22 100644 --- a/app/Services/Invoice/GetInvoicePdf.php +++ b/app/Services/Invoice/GetInvoicePdf.php @@ -15,6 +15,7 @@ use App\Jobs\Entity\CreateEntityPdf; use App\Models\ClientContact; use App\Models\Invoice; use App\Services\AbstractService; +use App\Utils\TempFile; use Illuminate\Support\Facades\Storage; class GetInvoicePdf extends AbstractService @@ -46,6 +47,12 @@ class GetInvoicePdf extends AbstractService $file_path = CreateEntityPdf::dispatchNow($invitation); } + + /* Copy from remote disk to local when using cloud file storage. */ + if(config('filesystems.default') == 's3') + return TempFile::path(Storage::disk($disk)->url($file_path)); + + // return Storage::disk($disk)->url($file_path); return Storage::disk($disk)->path($file_path); } } diff --git a/app/Transformers/CompanyTransformer.php b/app/Transformers/CompanyTransformer.php index 0e7158f3235e..b0ea39bb5788 100644 --- a/app/Transformers/CompanyTransformer.php +++ b/app/Transformers/CompanyTransformer.php @@ -131,7 +131,7 @@ class CompanyTransformer extends EntityTransformer 'archived_at' => (int) $company->deleted_at, 'created_at' =>(int) $company->created_at, 'slack_webhook_url' => (string) $company->slack_webhook_url, - 'google_analytics_url' => (string) $company->google_analytics_key, //@deprecate + 'google_analytics_url' => (string) $company->google_analytics_key, //@deprecate 1-2-2021 'google_analytics_key' => (string) $company->google_analytics_key, 'enabled_item_tax_rates' => (int) $company->enabled_item_tax_rates, 'client_can_register' => (bool) $company->client_can_register, @@ -145,13 +145,13 @@ class CompanyTransformer extends EntityTransformer 'auto_start_tasks' => (bool) $company->auto_start_tasks, 'invoice_task_documents' => (bool) $company->invoice_task_documents, 'show_tasks_table' => (bool) $company->show_tasks_table, - 'use_credits_payment' => 'always', //todo remove + 'use_credits_payment' => 'always', // @deprecate 1-2-2021 'default_task_is_date_based' => (bool)$company->default_task_is_date_based, 'enable_product_discount' => (bool)$company->enable_product_discount, 'calculate_expense_tax_by_amount' =>(bool)$company->calculate_expense_tax_by_amount, - 'hide_empty_columns_on_pdf' => false, //@deprecate + 'hide_empty_columns_on_pdf' => false, // @deprecate 1-2-2021 'expense_inclusive_taxes' => (bool)$company->expense_inclusive_taxes, - 'expense_amount_is_pretax' =>( bool)$company->expense_amount_is_pretax, + 'expense_amount_is_pretax' =>(bool)true, //@deprecate 1-2-2021 ]; } diff --git a/app/Transformers/ExpenseTransformer.php b/app/Transformers/ExpenseTransformer.php index 200e4991a5fc..2fca0c6a27d1 100644 --- a/app/Transformers/ExpenseTransformer.php +++ b/app/Transformers/ExpenseTransformer.php @@ -95,7 +95,7 @@ class ExpenseTransformer extends EntityTransformer 'tax_amount2' => (float) $expense->tax_amount2, 'tax_amount3' => (float) $expense->tax_amount3, 'uses_inclusive_taxes' => (bool) $expense->uses_inclusive_taxes, - 'amount_is_pretax' => (bool) $expense->amount_is_pretax, + 'calculate_tax_by_amount' => (bool) $expense->calculate_tax_by_amount, ]; } } diff --git a/app/Utils/TempFile.php b/app/Utils/TempFile.php index 124b3724630b..1907e49d10c7 100644 --- a/app/Utils/TempFile.php +++ b/app/Utils/TempFile.php @@ -15,7 +15,7 @@ class TempFile { public static function path($url) :string { - $temp_path = tempnam(sys_get_temp_dir(), basename($url)); + $temp_path = @tempnam(sys_get_temp_dir() . '/' . sha1(time()), basename($url)); copy($url, $temp_path); return $temp_path; diff --git a/app/Utils/Traits/MakesDates.php b/app/Utils/Traits/MakesDates.php index fb47b1c2cf86..6a908eb3543c 100644 --- a/app/Utils/Traits/MakesDates.php +++ b/app/Utils/Traits/MakesDates.php @@ -95,6 +95,8 @@ trait MakesDates private function convertToDateObject($date) { - return new DateTime($date); + $dt = new DateTime($date); + $dt->setTimezone(new DateTimeZone('UTC')); + return $dt; } } diff --git a/database/migrations/2021_01_11_092056_fix_company_settings_url.php b/database/migrations/2021_01_11_092056_fix_company_settings_url.php index f04d1615b048..1df76cd65b9a 100644 --- a/database/migrations/2021_01_11_092056_fix_company_settings_url.php +++ b/database/migrations/2021_01_11_092056_fix_company_settings_url.php @@ -31,11 +31,17 @@ class FixCompanySettingsUrl extends Migration Schema::table('companies', function (Blueprint $table) { $table->dropColumn('logo'); + $table->dropColumn('expense_amount_is_pretax'); }); Schema::table('tasks', function (Blueprint $table) { $table->dropColumn('start_time'); }); + + Schema::table('expenses', function (Blueprint $table) { + $table->dropColumn('amount_is_pretax'); + $table->boolean('calculate_tax_by_amount')->default(false); + }); } /**