Skip to content

Commit

Permalink
patched creating customer with order, and loading order relations in …
Browse files Browse the repository at this point in the history
…json resources
  • Loading branch information
roncodes committed Oct 17, 2024
1 parent 27558ad commit da38905
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 18 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fleetbase/fleetops-api",
"version": "0.5.11",
"version": "0.5.12",
"description": "Fleet & Transport Management Extension for Fleetbase",
"keywords": [
"fleetbase-extension",
Expand Down
2 changes: 1 addition & 1 deletion extension.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Fleet-Ops",
"version": "0.5.11",
"version": "0.5.12",
"description": "Fleet & Transport Management Extension for Fleetbase",
"repository": "https://github.com/fleetbase/fleetops",
"license": "AGPL-3.0-or-later",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@fleetbase/fleetops-engine",
"version": "0.5.11",
"version": "0.5.12",
"description": "Fleet & Transport Management Extension for Fleetbase",
"fleetbase": {
"route": "fleet-ops"
Expand Down
43 changes: 43 additions & 0 deletions server/src/Exceptions/UserAlreadyExistsException.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,49 @@

namespace Fleetbase\FleetOps\Exceptions;

use Fleetbase\Models\User;

/**
* Class UserAlreadyExistsException.
*
* Exception thrown when attempting to create or register a user that already exists in the system.
*
* This exception provides additional context by including the existing user object, allowing
* developers to access details about the duplicate user that triggered the exception.
*/
class UserAlreadyExistsException extends \Exception
{
/**
* The user that already exists in the system.
*/
private ?User $user;

/**
* UserAlreadyExistsException constructor.
*
* Initializes a new instance of the UserAlreadyExistsException.
*
* @param string $message the exception message describing the error
* @param User|null $user The existing user that caused the exception. Optional.
* @param int $code The exception code. Default is 0.
* @param \Throwable|null $previous The previous throwable used for exception chaining. Optional.
*/
public function __construct(string $message = '', ?User $user = null, int $code = 0, ?\Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
$this->user = $user;
}

/**
* Retrieves the user that already exists.
*
* This method returns the `User` instance that triggered the exception, providing access
* to the user's details such as ID, name, email, etc.
*
* @return User|null the existing user object, or null if not provided
*/
public function getUser(): ?User
{
return $this->user;
}
}
20 changes: 17 additions & 3 deletions server/src/Http/Controllers/Api/v1/OrderController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Fleetbase\FleetOps\Events\OrderDispatchFailed;
use Fleetbase\FleetOps\Events\OrderReady;
use Fleetbase\FleetOps\Events\OrderStarted;
use Fleetbase\FleetOps\Exceptions\UserAlreadyExistsException;
use Fleetbase\FleetOps\Flow\Activity;
use Fleetbase\FleetOps\Http\Requests\CreateOrderRequest;
use Fleetbase\FleetOps\Http\Requests\ScheduleOrderRequest;
Expand Down Expand Up @@ -226,16 +227,29 @@ public function create(CreateOrderRequest $request)
try {
$customer = Contact::firstOrCreate(
[
'email' => $customer['email'],
'type' => 'customer',
'company_uuid' => session('company'),
'email' => $customer['email'],
'type' => 'customer',
],
[
...$customer,
'type' => 'customer',
'company_uuid' => session('company'),
'type' => 'customer',
]
);
} catch (\Exception $e) {
return response()->apiError('Failed to find or create customer for order.');
} catch (UserAlreadyExistsException $e) {
try {
// If user already exist then assign user to this customer and the company
$existingUser = $e->getUser();
// Assign user to customer
if ($existingUser && $customer) {
$customer->assignUser($existingUser);
}
} catch (\Exception $e) {
return response()->apiError('Failed to find or create customer for order.');
}
}

if ($customer instanceof Contact) {
Expand Down
14 changes: 12 additions & 2 deletions server/src/Http/Resources/v1/PurchaseRate.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,18 @@ public function toWebhookPayload()
*/
public function serviceQuote()
{
$this->loadMissing('serviceQuote');
if ($this->resource && method_exists($this->resource, 'loadMissing')) {
$this->resource->loadMissing('serviceQuote');

return $this->serviceQuote ? new ServiceQuote($this->serviceQuote) : null;
return $this->resource->serviceQuote ? new ServiceQuote($this->resource->serviceQuote) : null;
}

if (method_exists($this, 'loadMissing')) {
$this->loadMissing('serviceQuote');

return $this->serviceQuote ? new ServiceQuote($this->serviceQuote) : null;
}

return null;
}
}
14 changes: 12 additions & 2 deletions server/src/Http/Resources/v1/TrackingStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,18 @@ public function toWebhookPayload()
*/
public function trackingNumber()
{
$this->loadMissing('trackingNumber');
if ($this->resource && method_exists($this->resource, 'loadMissing')) {
$this->resource->loadMissing('trackingNumber');

return $this->trackingNumber ? new TrackingNumber($this->trackingNumber) : null;
return $this->resource->trackingNumber ? new TrackingNumber($this->resource->trackingNumber) : null;
}

if (method_exists($this, 'loadMissing')) {
$this->loadMissing('trackingNumber');

return $this->trackingNumber ? new TrackingNumber($this->trackingNumber) : null;
}

return null;
}
}
74 changes: 66 additions & 8 deletions server/src/Models/Contact.php
Original file line number Diff line number Diff line change
Expand Up @@ -262,21 +262,23 @@ public static function createFromImport(array $row, bool $saveInstance = false):
* user to the contact. Optionally, it sends an invitation to the newly created user via email.
*
* @param Contact $contact the contact instance from which the user should be created
* @param bool $sendInvite (optional) Whether to send an invitation to the newly created user. Default is true.
* @param bool $sendInvite (optional) Whether to send an invitation to the newly created user. Default is false.
*
* @return User the newly created user instance
*
* @throws UserAlreadyExistsException if a user with the same email or phone number already exists
*/
public static function createUserFromContact(Contact $contact, bool $sendInvite = true): User
public static function createUserFromContact(Contact $contact, bool $sendInvite = false): User
{
// Check if user already exist with email or phone number
$userAlreadyExists = User::where(function ($query) use ($contact) {
$existingUser = User::where(function ($query) use ($contact) {
$query->where('email', $contact->email);
$query->orWhere('phone', $contact->phone);
if ($contact->phone) {
$query->orWhere('phone', $contact->phone);
}
})->first();
if ($userAlreadyExists) {
throw new UserAlreadyExistsException('User already exists, try to assigning the user to this contact.');
if ($existingUser) {
throw new UserAlreadyExistsException('User already exists, try to assigning the user to this contact.', $existingUser);
}

// Load company
Expand Down Expand Up @@ -330,6 +332,62 @@ public static function createUserFromContact(Contact $contact, bool $sendInvite
return $user;
}

/**
* Assigns a user to the company and optionally sends an invitation email.
*
* This method performs the following actions:
* 1. Associates the provided user with the current company, assigning them a role based on the
* company's type (e.g., 'Fleet-Ops Customer' or 'Fleet-Ops Contact').
* 2. If the user is of type 'customer', assigns the 'Fleet-Ops Customer' role specifically.
* 3. Updates the current entity's `user_uuid` to reference the assigned user.
* 4. Optionally sends an invitation email to the user, inviting them to join the company.
*
* @param User $user the user to be assigned to the company
* @param bool $sendInvite Determines whether to send an invitation email to the user. Defaults to false.
*
* @return self returns the current instance to allow method chaining
*
* @throws \Exception if an error occurs during user assignment or while sending the invitation
*/
public function assignUser(User $user, bool $sendInvite = false): self
{
// Load company
$this->loadMissing('copmany');

// Assing to company
$user->assignCompany($this->company, $this->type === 'customer' ? 'Fleet-Ops Customer' : 'Fleet-Ops Contact');

// Get the company user instance
$companyUser = $user->getCompanyUser($this->company);

// Assign customer role
$companyUser->assignSingleRole('Fleet-Ops Customer');

// Set user to contact
$this->update(['user_uuid' => $user->uuid]);

// Optionally, send invite
if ($sendInvite) {
// send invitation to user
$invitation = Invite::create([
'company_uuid' => $user->company_uuid,
'created_by_uuid' => session('user'),
'subject_uuid' => $user->company_uuid,
'subject_type' => Utils::getMutationType('company'),
'protocol' => 'email',
'recipients' => [$user->email],
'reason' => 'join_company',
]);

// notify user
$user->notify(new UserInvited($invitation));
}

$this->setRelation('user', $user);

return $this;
}

public function syncWithUser(): bool
{
$updates = [];
Expand Down Expand Up @@ -364,11 +422,11 @@ public function syncWithUser(): bool
* This method is a wrapper around the createUserFromContact method. It allows creating a user directly
* from a contact instance and, optionally, sending an invitation to the newly created user.
*
* @param bool $sendInvite (optional) Whether to send an invitation to the newly created user. Default is true.
* @param bool $sendInvite (optional) Whether to send an invitation to the newly created user. Default is false.
*
* @return User the newly created user instance
*/
public function createUser(bool $sendInvite = true): User
public function createUser(bool $sendInvite = false): User
{
return static::createUserFromContact($this, $sendInvite);
}
Expand Down

0 comments on commit da38905

Please sign in to comment.