diff --git a/app/Http/Controllers/AccountApiController.php b/app/Http/Controllers/AccountApiController.php index 91184eb68183..88d0b3d1cfe7 100644 --- a/app/Http/Controllers/AccountApiController.php +++ b/app/Http/Controllers/AccountApiController.php @@ -36,7 +36,12 @@ class AccountApiController extends BaseAPIController { $headers = Utils::getApiHeaders(); - return Response::make(RESULT_SUCCESS, 200, $headers); + // Legacy support for Zapier + if (request()->v2) { + return $this->response(RESULT_SUCCESS); + } else { + return Response::make(RESULT_SUCCESS, 200, $headers); + } } public function register(RegisterRequest $request) @@ -92,7 +97,7 @@ class AccountApiController extends BaseAPIController return $this->response($data); } - + public function show(Request $request) { $account = Auth::user()->account; @@ -249,7 +254,7 @@ class AccountApiController extends BaseAPIController public function iosSubscriptionStatus() { //stubbed for iOS callbacks - + } } diff --git a/app/Http/Controllers/IntegrationController.php b/app/Http/Controllers/IntegrationController.php index 07728dd54eea..44bf0ae63305 100644 --- a/app/Http/Controllers/IntegrationController.php +++ b/app/Http/Controllers/IntegrationController.php @@ -11,7 +11,7 @@ use Utils; /** * Class IntegrationController. */ -class IntegrationController extends Controller +class IntegrationController extends BaseAPIController { /** * @return \Illuminate\Http\JsonResponse @@ -33,6 +33,14 @@ class IntegrationController extends Controller return Response::json('Failed to create subscription', 500); } - return Response::json(['id' => $subscription->id], 201); + return Response::json(['id' => $subscription->public_id], 201); + } + + public function unsubscribe($publicId) + { + $subscription = Subscription::scope($publicId)->firstOrFail(); + $subscription->delete(); + + return $this->response(RESULT_SUCCESS); } } diff --git a/app/Http/Controllers/InvoiceApiController.php b/app/Http/Controllers/InvoiceApiController.php index cd56867d8348..0f3407252d57 100644 --- a/app/Http/Controllers/InvoiceApiController.php +++ b/app/Http/Controllers/InvoiceApiController.php @@ -73,6 +73,10 @@ class InvoiceApiController extends BaseAPIController $invoices->where('invoice_status_id', '>=', $statusId); } + if (request()->has('is_recurring')) { + $invoices->where('is_recurring', '=', request()->is_recurring); + } + return $this->listResponse($invoices); } @@ -241,8 +245,6 @@ class InvoiceApiController extends BaseAPIController 'po_number' => '', 'invoice_design_id' => $account->invoice_design_id, 'invoice_items' => [], - 'custom_value1' => 0, - 'custom_value2' => 0, 'custom_taxes1' => false, 'custom_taxes2' => false, 'tax_name1' => '', @@ -274,7 +276,7 @@ class InvoiceApiController extends BaseAPIController } // initialize the line items - if (isset($data['product_key']) || isset($data['cost']) || isset($data['notes']) || isset($data['qty'])) { + if (! isset($data['invoice_items']) && (isset($data['product_key']) || isset($data['cost']) || isset($data['notes']) || isset($data['qty']))) { $data['invoice_items'] = [self::prepareItem($data)]; // make sure the tax isn't applied twice (for the invoice and the line item) unset($data['invoice_items'][0]['tax_name1']); @@ -337,6 +339,13 @@ class InvoiceApiController extends BaseAPIController } } + // Workaround to support line item taxes w/Zapier + foreach (['tax_rate1', 'tax_name1', 'tax_rate2', 'tax_name2'] as $field) { + if (! empty($item['item_' . $field])) { + $item[$field] = $item['item_' . $field]; + } + } + return $item; } diff --git a/app/Http/Controllers/TaskApiController.php b/app/Http/Controllers/TaskApiController.php index 117c9bc63218..b950ec265954 100644 --- a/app/Http/Controllers/TaskApiController.php +++ b/app/Http/Controllers/TaskApiController.php @@ -110,6 +110,24 @@ class TaskApiController extends BaseAPIController $data['client'] = $data['client_id']; } + if (! empty($data['time_details'])) { + $timeLog = []; + foreach ($data['time_details'] as $detail) { + $startTime = strtotime($detail['start_datetime']); + $endTime = false; + if (! empty($detail['end_datetime'])) { + $endTime = strtotime($detail['end_datetime']); + } elseif (! empty($detail['duration_minutes'])) { + $endTime = $startTime + ($detail['duration_minutes'] * 60); + } + $timeLog[] = [$startTime, $endTime]; + if (! $endTime) { + $data['is_running'] = true; + } + } + $data['time_log'] = json_encode($timeLog); + } + $task = $this->taskRepo->save($taskId, $data); $task = Task::scope($task->public_id)->with('client')->first(); @@ -152,9 +170,9 @@ class TaskApiController extends BaseAPIController if ($request->action) { return $this->handleAction($request); } - + $task = $request->entity(); - + $task = $this->taskRepo->save($task->public_id, \Illuminate\Support\Facades\Input::all()); return $this->itemResponse($task); diff --git a/app/Models/Client.php b/app/Models/Client.php index 9541e4c9dddf..d50372dde1bb 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -340,9 +340,17 @@ class Client extends EntityModel */ public function getPrimaryContact() { - return $this->contacts() - ->whereIsPrimary(true) - ->first(); + if (! $this->relationLoaded('contacts')) { + $this->load('contacts'); + } + + foreach ($this->contacts as $contact) { + if ($contact->is_primary) { + return $contact; + } + } + + return false; } /** @@ -352,15 +360,9 @@ class Client extends EntityModel { if ($this->name) { return $this->name; + } else if ($contact = $this->getPrimaryContact()) { + return $contact->getDisplayName(); } - - if (! $this->contacts->count()) { - return ''; - } - - $contact = $this->contacts[0]; - - return $contact->getDisplayName(); } /** diff --git a/app/Ninja/Repositories/ClientRepository.php b/app/Ninja/Repositories/ClientRepository.php index a4ea88091b44..a1e3d89ca2dd 100644 --- a/app/Ninja/Repositories/ClientRepository.php +++ b/app/Ninja/Repositories/ClientRepository.php @@ -124,6 +124,17 @@ class ClientRepository extends BaseRepository } } + // convert shipping country code to id + if (isset($data['shipping_country_code'])) { + $countryCode = strtolower($data['shipping_country_code']); + $country = Cache::get('countries')->filter(function ($item) use ($countryCode) { + return strtolower($item->iso_3166_2) == $countryCode || strtolower($item->iso_3166_3) == $countryCode; + })->first(); + if ($country) { + $data['shipping_country_id'] = $country->id; + } + } + // set default payment terms if (auth()->check() && ! isset($data['payment_terms'])) { $data['payment_terms'] = auth()->user()->account->payment_terms; diff --git a/app/Ninja/Repositories/TaskRepository.php b/app/Ninja/Repositories/TaskRepository.php index e021628bfa9f..08fb09e79ad6 100644 --- a/app/Ninja/Repositories/TaskRepository.php +++ b/app/Ninja/Repositories/TaskRepository.php @@ -161,14 +161,16 @@ class TaskRepository extends BaseRepository $task->fill($data); - if (isset($data['client'])) { - $task->client_id = $data['client'] ? Client::getPrivateId($data['client']) : null; - } elseif (isset($data['client_id'])) { - $task->client_id = $data['client_id'] ? Client::getPrivateId($data['client_id']) : null; - } - - if (isset($data['project_id'])) { - $task->project_id = $data['project_id'] ? Project::getPrivateId($data['project_id']) : null; + if (! empty($data['project_id'])) { + $project = Project::scope($data['project_id'])->firstOrFail(); + $task->project_id = $project->id; + $task->client_id = $project->client_id; + } else { + if (isset($data['client'])) { + $task->client_id = $data['client'] ? Client::getPrivateId($data['client']) : null; + } elseif (isset($data['client_id'])) { + $task->client_id = $data['client_id'] ? Client::getPrivateId($data['client_id']) : null; + } } if (isset($data['description'])) { diff --git a/app/Ninja/Transformers/ClientTransformer.php b/app/Ninja/Transformers/ClientTransformer.php index 7da62cf1a64d..0d4aa4e8f336 100644 --- a/app/Ninja/Transformers/ClientTransformer.php +++ b/app/Ninja/Transformers/ClientTransformer.php @@ -118,6 +118,7 @@ class ClientTransformer extends EntityTransformer return array_merge($this->getDefaults($client), [ 'id' => (int) $client->public_id, 'name' => $client->name, + 'display_name' => $client->getDisplayName(), 'balance' => (float) $client->balance, 'paid_to_date' => (float) $client->paid_to_date, 'updated_at' => $this->getTimestamp($client->updated_at), diff --git a/routes/api.php b/routes/api.php index daac865cabb9..6246b12aa9bf 100644 --- a/routes/api.php +++ b/routes/api.php @@ -17,6 +17,7 @@ Route::resource('payments', 'PaymentApiController'); Route::resource('tasks', 'TaskApiController'); Route::resource('credits', 'CreditApiController'); Route::post('hooks', 'IntegrationController@subscribe'); +Route::delete('hooks/{subscription_id}', 'IntegrationController@unsubscribe'); Route::post('email_invoice', 'InvoiceApiController@emailInvoice'); Route::get('user_accounts', 'AccountApiController@getUserAccounts'); Route::resource('products', 'ProductApiController');