diff --git a/VERSION.txt b/VERSION.txt index 23ed8f2834..184f305de1 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.5.9 \ No newline at end of file +5.5.10 \ No newline at end of file diff --git a/app/Factory/CloneQuoteToProjectFactory.php b/app/Factory/CloneQuoteToProjectFactory.php new file mode 100644 index 0000000000..7c95e19b25 --- /dev/null +++ b/app/Factory/CloneQuoteToProjectFactory.php @@ -0,0 +1,40 @@ +company_id = $quote->company_id; + $project->user_id = $user_id; + $project->client_id = $quote->client_id; + + $project->public_notes = $quote->public_notes; + $project->private_notes = $quote->private_notes; + $project->budgeted_hours = 0; + $project->task_rate = 0; + $project->name = ctrans('texts.quote_number_short') . " " . $quote->number; + $project->custom_value1 = ''; + $project->custom_value2 = ''; + $project->custom_value3 = ''; + $project->custom_value4 = ''; + $project->is_deleted = 0; + + return $project; + } +} diff --git a/app/Http/Controllers/QuoteController.php b/app/Http/Controllers/QuoteController.php index b89d9a77ad..de549bdccc 100644 --- a/app/Http/Controllers/QuoteController.php +++ b/app/Http/Controllers/QuoteController.php @@ -15,6 +15,7 @@ use App\Events\Quote\QuoteWasCreated; use App\Events\Quote\QuoteWasUpdated; use App\Factory\CloneQuoteFactory; use App\Factory\CloneQuoteToInvoiceFactory; +use App\Factory\CloneQuoteToProjectFactory; use App\Factory\QuoteFactory; use App\Filters\QuoteFilters; use App\Http\Requests\Quote\ActionQuoteRequest; @@ -31,12 +32,15 @@ use App\Jobs\Quote\ZipQuotes; use App\Models\Account; use App\Models\Client; use App\Models\Invoice; +use App\Models\Project; use App\Models\Quote; use App\Repositories\QuoteRepository; use App\Transformers\InvoiceTransformer; +use App\Transformers\ProjectTransformer; use App\Transformers\QuoteTransformer; use App\Utils\Ninja; use App\Utils\TempFile; +use App\Utils\Traits\GeneratesCounter; use App\Utils\Traits\MakesHash; use App\Utils\Traits\SavesDocuments; use Illuminate\Http\Request; @@ -50,6 +54,7 @@ class QuoteController extends BaseController { use MakesHash; use SavesDocuments; + use GeneratesCounter; protected $entity_type = Quote::class; @@ -556,6 +561,28 @@ class QuoteController extends BaseController return $this->listResponse(Quote::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()); } + + if($action == 'convert_to_project') + { + + $quotes->each(function ($quote, $key) use ($action) { + if (auth()->user()->can('edit', $quote)) + { + $project = CloneQuoteToProjectFactory::create($quote, auth()->user()->id); + + if (empty($project->number)) { + $project->number = $this->getNextProjectNumber($project); + + } + $project->save(); + $quote->project_id = $project->id; + $quote->save(); + } + }); + + return $this->listResponse(Quote::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()); + } + /* * Send the other actions to the switch */ @@ -661,6 +688,7 @@ class QuoteController extends BaseController return $this->itemResponse($quote->service()->convertToInvoice()); break; + case 'clone_to_invoice': $this->entity_type = Invoice::class; diff --git a/app/Http/Livewire/BillingPortalPurchase.php b/app/Http/Livewire/BillingPortalPurchase.php index e4cfaaeef9..c24f013941 100644 --- a/app/Http/Livewire/BillingPortalPurchase.php +++ b/app/Http/Livewire/BillingPortalPurchase.php @@ -265,6 +265,9 @@ class BillingPortalPurchase extends Component } } +// nlog($this->subscription->group_settings->settings); +// nlog($this->subscription->group_settings->settings->currency_id); + if(array_key_exists('currency_id', $this->request_data)) { $currency = Cache::get('currencies')->filter(function ($item){ @@ -274,6 +277,16 @@ class BillingPortalPurchase extends Component if($currency) $data['settings']->currency_id = $currency->id; + } + elseif($this->subscription->group_settings && property_exists($this->subscription->group_settings->settings, 'currency_id')) { + + $currency = Cache::get('currencies')->filter(function ($item){ + return $item->id == $this->subscription->group_settings->settings->currency_id; + })->first(); + + if($currency) + $data['settings']->currency_id = $currency->id; + } if (array_key_exists('locale', $this->request_data)) { diff --git a/app/Models/Subscription.php b/app/Models/Subscription.php index da92f7add0..6bac62e443 100644 --- a/app/Models/Subscription.php +++ b/app/Models/Subscription.php @@ -83,6 +83,11 @@ class Subscription extends BaseModel return $this->belongsTo(User::class)->withTrashed(); } + public function group_settings() + { + return $this->belongsTo(GroupSetting::class, 'group_id', 'id'); + } + public function nextDateByInterval($date, $frequency_id) { switch ($frequency_id) { diff --git a/app/PaymentDrivers/CheckoutComPaymentDriver.php b/app/PaymentDrivers/CheckoutComPaymentDriver.php index 210e231149..a75e93a007 100644 --- a/app/PaymentDrivers/CheckoutComPaymentDriver.php +++ b/app/PaymentDrivers/CheckoutComPaymentDriver.php @@ -44,6 +44,7 @@ use Checkout\Payments\PaymentRequest as PaymentsPaymentRequest; use Checkout\Payments\RefundRequest; use Checkout\Payments\Source\RequestIdSource; use Exception; +use Illuminate\Support\Facades\Auth; class CheckoutComPaymentDriver extends BaseDriver { @@ -407,9 +408,16 @@ class CheckoutComPaymentDriver extends BaseDriver public function process3dsConfirmation(Checkout3dsRequest $request) { + $this->init(); $this->setPaymentHash($request->getPaymentHash()); + //11-08-2022 check the user is autenticated + if (!Auth::guard('contact')->check()) { + $client = $request->getClient(); + auth()->guard('contact')->loginUsingId($client->contacts()->first()->id, true); + } + try { $payment = $this->gateway->getPaymentsClient()->getPaymentDetails( $request->query('cko-session-id') diff --git a/app/PaymentDrivers/PayTrace/CreditCard.php b/app/PaymentDrivers/PayTrace/CreditCard.php index 7b5797990f..b80f3f03ca 100644 --- a/app/PaymentDrivers/PayTrace/CreditCard.php +++ b/app/PaymentDrivers/PayTrace/CreditCard.php @@ -47,14 +47,6 @@ class CreditCard return render('gateways.paytrace.authorize', $data); } - // +"success": true - // +"response_code": 160 - // +"status_message": "The customer profile for PLS5U60OoLUfQXzcmtJYNefPA0gTthzT/11 was successfully created." - // +"customer_id": "PLS5U60OoLUfQXzcmtJYNefPA0gTthzT" - - //if(!$response->success) - //handle failure - public function authorizeResponse($request) { $data = $request->all(); @@ -64,27 +56,6 @@ class CreditCard return redirect()->route('client.payment_methods.index'); } - // "_token" => "Vl1xHflBYQt9YFSaNCPTJKlY5x3rwcFE9kvkw71I" - // "company_gateway_id" => "1" - // "HPF_Token" => "e484a92c-90ed-4468-ac4d-da66824c75de" - // "enc_key" => "zqz6HMHCXALWdX5hyBqrIbSwU7TBZ0FTjjLB3Cp0FQY=" - // "amount" => "Amount" - // "q" => "/client/payment_methods" - // "method" => "1" - // ] - - // "customer_id":"customer789", - // "hpf_token":"e369847e-3027-4174-9161-fa0d4e98d318", - // "enc_key":"lI785yOBMet4Rt9o4NLXEyV84WBU3tdStExcsfoaOoo=", - // "integrator_id":"xxxxxxxxxx", - // "billing_address":{ - // "name":"Mark Smith", - // "street_address":"8320 E. West St.", - // "city":"Spokane", - // "state":"WA", - // "zip":"85284" - // } - private function createCustomer($data) { $post_data = [ @@ -193,8 +164,6 @@ class CreditCard 'invoice_id' => $this->harvestInvoiceId(), ]; -nlog($data); - $response = $this->paytrace->gatewayRequest('/v1/transactions/sale/pt_protect', $data); if ($response->success) { diff --git a/app/Transformers/ActivityTransformer.php b/app/Transformers/ActivityTransformer.php index 7cfaf47941..a977a0c72d 100644 --- a/app/Transformers/ActivityTransformer.php +++ b/app/Transformers/ActivityTransformer.php @@ -55,6 +55,8 @@ class ActivityTransformer extends EntityTransformer 'client_id' => $activity->client_id ? (string) $this->encodePrimaryKey($activity->client_id) : '', 'recurring_invoice_id' => $activity->recurring_invoice_id ? (string) $this->encodePrimaryKey($activity->recurring_invoice_id) : '', 'recurring_expense_id' => $activity->recurring_expense_id ? (string) $this->encodePrimaryKey($activity->recurring_expense_id) : '', + 'purchase_order_id' => $activity->purchase_order_id ? (string) $this->encodePrimaryKey($activity->purchase_order_id) : '', + 'vendor_contact_id' => $activity->vendor_contact_id ? (string) $this->encodePrimaryKey($activity->vendor_contact_id) : '', 'company_id' => $activity->company_id ? (string) $this->encodePrimaryKey($activity->company_id) : '', 'user_id' => (string) $this->encodePrimaryKey($activity->user_id), 'invoice_id' => $activity->invoice_id ? (string) $this->encodePrimaryKey($activity->invoice_id) : '', diff --git a/config/ninja.php b/config/ninja.php index 2522296cca..7db45a89e5 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.9', - 'app_tag' => '5.5.9', + 'app_version' => '5.5.10', + 'app_tag' => '5.5.10', 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', ''), diff --git a/tests/Feature/QuoteTest.php b/tests/Feature/QuoteTest.php index 81bbe46e19..a6072ade4f 100644 --- a/tests/Feature/QuoteTest.php +++ b/tests/Feature/QuoteTest.php @@ -13,6 +13,7 @@ namespace Tests\Feature; use App\Models\Client; use App\Models\ClientContact; +use App\Models\Project; use App\Models\Quote; use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\Model; @@ -49,6 +50,26 @@ class QuoteTest extends TestCase ); } + + + public function testQuoteConvertToProject() + { + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/quotes/bulk',['action' => 'convert_to_project', 'ids' => [$this->quote->hashed_id]]); + + $response->assertStatus(200); + + $res = $response->json(); + + $this->assertNotNull($res['data'][0]['project_id']); + + $project = Project::find($this->decodePrimaryKey($res['data'][0]['project_id'])); + + $this->assertEquals($project->name, ctrans('texts.quote_number_short') . " " . $this->quote->number); + } + public function testQuoteList() { $response = $this->withHeaders([ @@ -139,4 +160,5 @@ class QuoteTest extends TestCase $response->assertStatus(200); } + }