diff --git a/app/Factory/CloneQuoteToProjectFactory.php b/app/Factory/CloneQuoteToProjectFactory.php new file mode 100644 index 000000000000..7c95e19b25bf --- /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 b89d9a77ade4..de549bdccccc 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 e4cfaaeef984..c24f0139410c 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 da92f7add006..6bac62e44341 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/PayTrace/CreditCard.php b/app/PaymentDrivers/PayTrace/CreditCard.php index 7b5797990f0c..b80f3f03caa6 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/tests/Feature/QuoteTest.php b/tests/Feature/QuoteTest.php index 81bbe46e196e..a6072ade4f8b 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); } + }