Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrations workflows #1971

Merged
merged 19 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ jobs:
run: php artisan kanvas:setup-ecosystem

- name: Setup Kanvas Integrations
run: php artisan kanvas:create-integration kanvas --config='{"client_id":{"type":"text","required":true},"client_secret":{"type":"text","required":true},"shop_url":{"type":"text","required":true}}' --handler='Kanvas\Connectors\Shopify\Handlers\ShopifyHandler'
run: php artisan kanvas:create-integration shopify --config='{"client_id":{"type":"text","required":true},"client_secret":{"type":"text","required":true},"shop_url":{"type":"text","required":true}}' --handler='Kanvas\Connectors\Shopify\Handlers\ShopifyHandler'

- name: create .env file
run: echo '' > .env
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ class CreateIntegrationCommand extends Command

/**
* The name and signature of the console command.
* Specify as option workflow and receiver for future use.
*
* @var string
*/
protected $signature = 'kanvas:create-integration {name} {--app_id=} {--config=} {--handler=}';
protected $signature = 'kanvas:create-integration {name} {--app_id=} {--config=} {--handler=} {--workflow_id=} {--receiver_id=}';

/**
* The console command description.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,14 @@ public function createIntegrationCompany(mixed $rootValue, array $request): Mode
$integration = Integrations::getById((int) $request['input']['integration']['id']);
$company = CompaniesRepository::getById((int) $request['input']['company_id']);
$region = RegionRepository::getById((int) $request['input']['region']['id'], $company);
$user = auth()->user();

CompaniesRepository::userAssociatedToCompany(
$company,
auth()->user()
);
if (! $user->isAppOwner()) {
CompaniesRepository::userAssociatedToCompany(
$company,
$user
);
}

(new ConfigValidation($integration->config, $request['input']))->validate();
$integrationDto = new IntegrationsCompany(
Expand Down Expand Up @@ -69,7 +72,7 @@ public function createIntegrationCompany(mixed $rootValue, array $request): Mode
->first();
}

$integrationCompany = (new CreateIntegrationCompanyAction($integrationDto, auth()->user(), $status))->execute();
$integrationCompany = (new CreateIntegrationCompanyAction($integrationDto, $user, $status))->execute();

return $integrationCompany;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class () extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('integrations', function (Blueprint $table) {
$table->unsignedBigInteger('actions_id')->after('handler')->nullable(true);
$table->unsignedBigInteger('receivers_id')->after('actions_id')->nullable(true);

$table->foreign('actions_id')->references('id')->on('actions');
$table->foreign('receivers_id')->references('id')->on('receiver_webhooks');

$table->index('actions_id', 'actions_id_index');
$table->index('receivers_id', 'receivers_id_index');
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
//
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

declare(strict_types=1);

namespace Kanvas\Connectors\Shopify\Workflows\Activities;

use Kanvas\Apps\Models\Apps;
use Kanvas\Connectors\Shopify\Enums\StatusEnum as ShopifyStatusEnum;
use Kanvas\Connectors\Shopify\Services\ShopifyInventoryService;
use Kanvas\Inventory\Products\Models\Products;
use Kanvas\Workflow\Enums\IntegrationsEnum;
use Kanvas\Workflow\Enums\StatusEnum;
use Kanvas\Workflow\Integrations\Models\IntegrationsCompany;
use Kanvas\Workflow\Integrations\Models\Status;
use Workflow\Activity;

class ExportProductToShopifyActivity extends Activity
{
public $tries = 5;

public function execute(Products $product, Apps $app, array $params): array
{
$response = [];
$status = Status::where('slug', StatusEnum::ACTIVE->value)
->where('apps_id', 0)
->first();


foreach ($product->variants as $variant) {
foreach ($variant->warehouses as $warehouse) {
$integrationCompany = IntegrationsCompany::getByIntegration(
company: $product->company,
status: $status,
region: $warehouse->region,
name: IntegrationsEnum::SHOPIFY->value
);

if ($integrationCompany) {
// Sending warehouses instead of region, until integration is migrated on all the code.
$shopifyService = new ShopifyInventoryService(
app: $app,
company: $product->company,
warehouses: $warehouse
);

$response = $shopifyService->saveProduct($product, ShopifyStatusEnum::ACTIVE);
}
}
}

return [
'company' => $product->company->getId(),
'product' => $product->getId(),
'shopify_response' => $response,
];
}
}
11 changes: 11 additions & 0 deletions src/Domains/Inventory/Products/Actions/CreateProductAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Baka\Users\Contracts\UserInterface;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Kanvas\Apps\Models\Apps;
use Kanvas\Companies\Repositories\CompaniesRepository;
use Kanvas\Inventory\Attributes\Actions\CreateAttribute;
use Kanvas\Inventory\Attributes\DataTransferObject\Attributes as AttributesDto;
Expand All @@ -16,10 +17,13 @@
use Kanvas\Inventory\Products\DataTransferObject\Product as ProductDto;
use Kanvas\Inventory\Products\Models\Products;
use Kanvas\Inventory\Variants\Services\VariantService;
use Kanvas\Workflow\Enums\WorkflowEnum;
use Throwable;

class CreateProductAction
{
protected Apps $app;
protected bool $runWorkflow = true;
/**
* __construct.
*
Expand Down Expand Up @@ -117,6 +121,13 @@ public function execute(): Products
throw $e;
}

if ($this->runWorkflow) {
$products->fireWorkflow(
WorkflowEnum::CREATED->value,
true
);
}

return $products;
}
}
2 changes: 2 additions & 0 deletions src/Domains/Inventory/Products/Models/Products.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
use Kanvas\Inventory\Warehouses\Models\Warehouses;
use Kanvas\Social\Interactions\Traits\LikableTrait;
use Kanvas\Social\Tags\Traits\HasTagsTrait;
use Kanvas\Workflow\Traits\CanUseWorkflow;
use Laravel\Scout\Searchable;

/**
Expand Down Expand Up @@ -65,6 +66,7 @@ class Products extends BaseModel

use CascadeSoftDeletes;
use Compoships;
use CanUseWorkflow;

protected $table = 'products';
protected $guarded = [];
Expand Down
11 changes: 11 additions & 0 deletions src/Domains/Workflow/Enums/IntegrationsEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Kanvas\Workflow\Enums;

enum IntegrationsEnum: string
{
case SHOPIFY = 'shopify';
case KANVAS = 'kanvas';
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace Kanvas\Workflow\Integrations\Actions;

use Baka\Users\Contracts\UserInterface;
use Kanvas\Companies\Repositories\CompaniesRepository;
use Kanvas\Workflow\Integrations\DataTransferObject\IntegrationsCompany;
use Kanvas\Workflow\Integrations\Models\IntegrationsCompany as IntegrationsCompanyModel;
use Kanvas\Workflow\Integrations\Models\Status;
Expand All @@ -31,11 +30,6 @@ public function __construct(
*/
public function execute(): IntegrationsCompanyModel
{
CompaniesRepository::userAssociatedToCompany(
$this->dto->company,
$this->user
);

return IntegrationsCompanyModel::firstOrCreate([
'companies_id' => $this->dto->company->getId(),
'integrations_id' => $this->dto->integration->getId(),
Expand Down
22 changes: 22 additions & 0 deletions src/Domains/Workflow/Integrations/Models/IntegrationsCompany.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

use Baka\Casts\Json;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Kanvas\Companies\Models\Companies;
use Kanvas\Inventory\Regions\Models\Regions;
use Kanvas\Workflow\Enums\StatusEnum;
use Kanvas\Workflow\Models\BaseModel;
use Kanvas\Workflow\Models\Integrations;

Expand Down Expand Up @@ -46,4 +48,24 @@ public function setStatus(Status $status): void
$this->status_id = $status->getId();
$this->saveOrFail();
}

/**
* Get the integration company using the integration name
*
* @param Companies $company
* @param Status $status Current status of the integration company
* @param string $name name of the integration
* @param Region $region The region of the company integration
* @return IntegrationsCompany
*/
public static function getByIntegration(Companies $company, Status $status, string $name, Regions $region): ?IntegrationsCompany
{
$integration = Integrations::where('name', $name)->firstOrFail();

return IntegrationsCompany::fromCompany($company)
->where('integrations_id', $integration->getId())
->where('status_id', $status->getId())
->where('region_id', $region->getId())
->first();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace Tests\Connectors\Integration\Shopify;

use Kanvas\Apps\Models\Apps;
use Kanvas\Connectors\Shopify\Workflows\Activities\ExportProductToShopifyActivity;
use Kanvas\Inventory\Products\Models\Products;
use Kanvas\Workflow\Models\StoredWorkflow;
use Tests\Connectors\Traits\HasShopifyConfiguration;
use Tests\TestCase;

final class ExportProductToShopifyActivityTest extends TestCase
{
use HasShopifyConfiguration;

public function testExportProductWorkflow(): void
{
$product = Products::first();
$variant = $product->variants()->first();
$warehouse = $variant->warehouses()->first();

$this->setupShopifyIntegration($product, $warehouse->region);

$exportActivity = new ExportProductToShopifyActivity(
0,
now()->toDateTimeString(),
StoredWorkflow::make(),
[]
);

$app = app(Apps::class);

$result = $exportActivity->execute(
product: $product,
app: $app,
params: []
);

//We need to DELETE the exported product after the test.
$this->assertArrayHasKey('shopify_response', $result);
$this->assertArrayHasKey('company', $result);
$this->assertArrayHasKey('product', $result);
}
}
33 changes: 33 additions & 0 deletions tests/Connectors/Traits/HasShopifyConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@
namespace Tests\Connectors\Traits;

use Exception;
use Kanvas\Apps\Models\Apps;
use Kanvas\Connectors\Shopify\DataTransferObject\Shopify;
use Kanvas\Connectors\Shopify\Services\ShopifyConfigurationService;
use Kanvas\Inventory\Products\Models\Products;
use Kanvas\Inventory\Regions\Models\Regions;
use Kanvas\Inventory\Warehouses\Models\Warehouses;
use Kanvas\Workflow\Enums\StatusEnum;
use Kanvas\Workflow\Integrations\Actions\CreateIntegrationCompanyAction;
use Kanvas\Workflow\Integrations\DataTransferObject\IntegrationsCompany;
use Kanvas\Workflow\Integrations\Models\Status;
use Kanvas\Workflow\Models\Integrations;

trait HasShopifyConfiguration
{
Expand All @@ -28,4 +34,31 @@ public function setupShopifyConfiguration(Products $product, Warehouses $warehou
getenv('TEST_SHOPIFY_SHOP_URL')
));
}

public function setupShopifyIntegration(Products $product, Regions $region)
{
$credentials = [
'client_id' => getenv('TEST_SHOPIFY_API_KEY'),
'client_secret' => getenv('TEST_SHOPIFY_API_SECRET'),
'shop_url' => getenv('TEST_SHOPIFY_SHOP_URL'),
];

$integration = Integrations::first();

$integrationDto = new IntegrationsCompany(
integration: $integration,
region: $region,
company: $product->company,
config: $credentials,
app: app(Apps::class)
);

$status = Status::where('slug', StatusEnum::ACTIVE->value)
->where('apps_id', 0)
->first();

// for the time being this can only work with shopify integration.
// we need to figure out how to standard is it.
(new CreateIntegrationCompanyAction($integrationDto, auth()->user(), $status))->execute();
}
}
Loading