Skip to content
Open
Show file tree
Hide file tree
Changes from 9 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
1 change: 1 addition & 0 deletions src/backend/app/Models/MpmPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class MpmPlugin extends BaseModelCentral {
public const TEXTBEE_SMS_GATEWAY = 26;
public const ECREEE_E_TENDER = 27;
public const SPARK_SHS = 28;
public const SMS_TRANSACTION_PARSER = 29;

protected $table = 'mpm_plugins';

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace App\Plugins\SmsTransactionParser\Console\Commands;

use App\Plugins\SmsTransactionParser\Services\SmsParsingRuleService;
use Illuminate\Console\Command;

class InstallPackage extends Command {
protected $signature = 'sms-transaction-parser:install';
protected $description = 'Install SmsTransactionParser Package';

public function __construct(
private SmsParsingRuleService $smsParsingRuleService,
) {
parent::__construct();
}

public function handle(): void {
$this->info('Installing SmsTransactionParser Integration Package\n');

$this->smsParsingRuleService->installDefaults();

$this->info('Package installed successfully..');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

declare(strict_types=1);

namespace App\Plugins\SmsTransactionParser\Http\Controllers;

use App\Plugins\SmsTransactionParser\Http\Requests\SmsParsingRuleRequest;
use App\Plugins\SmsTransactionParser\Services\SmsParsingRuleService;
use App\Plugins\SmsTransactionParser\SmsParsing\TemplateToRegexConverter;
use Illuminate\Http\JsonResponse;
use Illuminate\Routing\Controller;

class SmsParsingRuleController extends Controller {
public function __construct(
private SmsParsingRuleService $smsParsingRuleService,
private TemplateToRegexConverter $templateToRegexConverter,
) {}

public function index(): JsonResponse {
return response()->json([
'data' => $this->smsParsingRuleService->getAll(),
]);
}

public function store(SmsParsingRuleRequest $request): JsonResponse {
$data = $request->validated();
$data['pattern'] = $this->templateToRegexConverter->convert($data['template']);
$rule = $this->smsParsingRuleService->create($data);

return response()->json([
'data' => $rule,
], 201);
}

public function update(int $id, SmsParsingRuleRequest $request): JsonResponse {
$rule = $this->smsParsingRuleService->getById($id);
$data = $request->validated();
$data['pattern'] = $this->templateToRegexConverter->convert($data['template']);
$updatedRule = $this->smsParsingRuleService->update($rule, $data);

return response()->json([
'data' => $updatedRule,
]);
}

public function destroy(int $id): JsonResponse {
$rule = $this->smsParsingRuleService->getById($id);
$this->smsParsingRuleService->delete($rule);

return response()->json(null, 204);
}

public function install(): JsonResponse {
$rules = $this->smsParsingRuleService->installDefaults();

return response()->json([
'data' => $rules,
]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace App\Plugins\SmsTransactionParser\Http\Controllers;

use App\Plugins\SmsTransactionParser\Services\SmsTransactionService;
use Illuminate\Http\JsonResponse;
use Illuminate\Routing\Controller;

class SmsTransactionController extends Controller {
public function __construct(
private SmsTransactionService $smsTransactionService,
) {}

public function index(): JsonResponse {
return response()->json(
$this->smsTransactionService->getAll(),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace App\Plugins\SmsTransactionParser\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class SmsParsingRuleRequest extends FormRequest {
public function authorize(): bool {
return true;
}

/**
* @return array<string, mixed>
*/
public function rules(): array {
$ruleId = $this->route('id');

return [
'provider_name' => 'required|string|max:255|unique:tenant.sms_parsing_rules,provider_name'.($ruleId ? ','.$ruleId : ''),
'template' => ['required', 'string'],
'sender_pattern' => ['nullable', 'string'],
'enabled' => ['boolean'],
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace App\Plugins\SmsTransactionParser\Listeners;

use App\Events\SmsStoredEvent;
use App\Plugins\SmsTransactionParser\Models\SmsTransaction;
use App\Plugins\SmsTransactionParser\Services\SmsTransactionService;
use Illuminate\Support\Facades\Log;

class SmsStoredListener {
public function __construct(
private SmsTransactionService $smsTransactionService,
) {}

public function handle(SmsStoredEvent $event): void {
$result = $this->smsTransactionService->processIncomingSms(
$event->message,
$event->sender,
);

if ($result instanceof SmsTransaction) {
Log::info('SMS transaction created from incoming SMS', [
'reference' => $result->transaction_reference,
'provider' => $result->provider_name,
]);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace App\Plugins\SmsTransactionParser\Models;

use App\Models\Base\BaseModel;
use Illuminate\Support\Carbon;

/**
* @property int $id
* @property string $provider_name
* @property string $template
* @property string $pattern
* @property string|null $sender_pattern
* @property bool $enabled
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*/
class SmsParsingRule extends BaseModel {
protected $table = 'sms_parsing_rules';

protected function casts(): array {
return [
'enabled' => 'boolean',
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

declare(strict_types=1);

namespace App\Plugins\SmsTransactionParser\Models;

use App\Models\Transaction\BasePaymentProviderTransaction;
use App\Models\Transaction\Transaction;
use App\Models\Transaction\TransactionConflicts;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Support\Carbon;

/**
* @property int $id
* @property string $provider_name
* @property string $transaction_reference
* @property float $amount
* @property string $sender_phone
* @property string|null $device_serial
* @property string $raw_message
* @property int $status
* @property string|null $manufacturer_transaction_type
* @property int|null $manufacturer_transaction_id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property-read Collection<int, TransactionConflicts> $conflicts
* @property-read Model|null $manufacturerTransaction
* @property-read Transaction|null $transaction
*/
class SmsTransaction extends BasePaymentProviderTransaction {
protected $table = 'sms_transactions';
public const RELATION_NAME = 'sms_transaction';
public const STATUS_FAILED = -1;
public const STATUS_PENDING = 0;
public const STATUS_SUCCESS = 1;

public function getTransactionReference(): string {
return $this->transaction_reference;
}

public function getSenderPhone(): string {
return $this->sender_phone;
}

public function getDeviceSerial(): ?string {
return $this->device_serial;
}

public function getAmount(): float {
return $this->amount;
}

public function getRawMessage(): string {
return $this->raw_message;
}

public function getProviderName(): string {
return $this->provider_name;
}

public function setStatus(int $status): void {
$this->status = $status;
}

/**
* @return MorphMany<TransactionConflicts, $this>
*/
public function conflicts(): MorphMany {
return $this->morphMany(TransactionConflicts::class, 'transaction');
}

public function getManufacturerTransferType(): ?string {
return 'SmsTransaction';
}

public function getDescription(): ?string {
return $this->raw_message;
}

public static function getTransactionName(): string {
return self::RELATION_NAME;
}

public function getId(): int {
return $this->id;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace App\Plugins\SmsTransactionParser\Providers;

use App\Events\SmsStoredEvent;
use App\Plugins\SmsTransactionParser\Listeners\SmsStoredListener;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider {
/** @var array<class-string, array<int, class-string>> */
protected $listen = [
SmsStoredEvent::class => [
SmsStoredListener::class,
],
];

/**
* @var array<class-string>
*/
protected $subscribe = [];

/**
* Register any events for your application.
*/
public function boot(): void {
parent::boot();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace App\Plugins\SmsTransactionParser\Providers;

use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class ObserverServiceProvider extends ServiceProvider {
/**
* Register any events for your application.
*/
public function boot(): void {
parent::boot();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace App\Plugins\SmsTransactionParser\Providers;

use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Route;

class RouteServiceProvider extends ServiceProvider {
protected $namespace = 'App\Plugins\SmsTransactionParser\Http\Controllers';

public function boot(): void {
parent::boot();
}

public function map(): void {
$this->mapApiRoutes();
}

protected function mapApiRoutes(): void {
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(__DIR__.'/../routes/api.php');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace App\Plugins\SmsTransactionParser\Providers;

use App\Plugins\SmsTransactionParser\Console\Commands\InstallPackage;
use App\Plugins\SmsTransactionParser\Models\SmsTransaction;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\ServiceProvider;

class SmsTransactionParserServiceProvider extends ServiceProvider {
public function boot(): void {
$this->app->register(RouteServiceProvider::class);
$this->commands([InstallPackage::class]);
Relation::morphMap([
SmsTransaction::RELATION_NAME => SmsTransaction::class,
]);
}

public function register(): void {
$this->app->register(EventServiceProvider::class);
$this->app->register(ObserverServiceProvider::class);
$this->app->bind(SmsTransactionProvider::class);
$this->app->alias(SmsTransactionProvider::class, 'SmsTransactionParser');
}
}
Loading
Loading