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

More Transaction generation to Seeder #422

Merged
merged 2 commits into from
Dec 12, 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
7 changes: 3 additions & 4 deletions docs/development/development-environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,15 @@ password: 123123

The Demo Company protected page password of this company is `123123`.

## Generating transaction data
## Generating ticket data

To generate transaction and ticket for the Demo Company data, run:
To generate ticket for the Demo Company data, run:

```sh
php artisan demo:create-data 250
php artisan demo:create-data --type=ticket 25
```

This commands will create 250 transactions and 25 tickets within the past 30 days respectively.
This commands will generate 25 tickets within the past 365 days respectively.
It can be run multiple times to generate more data as required.

## Reseting the Demo data
Expand Down
253 changes: 4 additions & 249 deletions src/backend/app/Console/Commands/DemoDataCreator.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,21 @@

namespace App\Console\Commands;

use App\Helpers\TokenGenerator;
use App\Models\MainSettings;
use App\Models\MaintenanceUsers;
use App\Models\Meter\Meter;
use App\Models\Meter\MeterToken;
use App\Models\Person\Person;
use App\Models\Token;
use App\Models\Transaction\AgentTransaction;
use App\Models\Transaction\AirtelTransaction;
use App\Models\Transaction\Transaction;
use App\Models\Transaction\VodacomTransaction;
use App\Models\User;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Console\View\Components\Warn;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Inensus\CalinMeter\Models\CalinTransaction;
use Inensus\SwiftaPaymentProvider\Models\SwiftaTransaction;
use Inensus\Ticket\Models\Ticket;
use Inensus\Ticket\Models\TicketCategory;
use Inensus\Ticket\Models\TicketOutsource;
use Inensus\Ticket\Models\TicketUser;
use Inensus\WavecomPaymentProvider\Models\WaveComTransaction;
use Inensus\WaveMoneyPaymentProvider\Models\WaveMoneyTransaction;

class DemoDataCreator extends AbstractSharedCommand {
protected $signature = 'demo:create-data {amount} {--company-id=} {--type=}';
protected $description = 'Creates transaction and ticket data for Demo Company';

private $transactionTypes = [
SwiftaTransaction::class,
WaveComTransaction::class,
WaveMoneyTransaction::class,
AgentTransaction::class,
VodacomTransaction::class,
AirtelTransaction::class,
];

public function handle() {
$companyId = $this->option('company-id');
$type = $this->option('type') ?? 'transaction';
Expand All @@ -55,7 +33,9 @@ public function handle() {
try {
DB::connection('shard')->beginTransaction();
if ($type == 'transaction') {
$this->generateTransaction();
(new Warn($this->getOutput()))->render(
'Generating Transaction data using script is no longer supported. Use `artisan db:seed --TransactionSeeder` instead.`'
);
} else {
$this->generateTicket();
}
Expand All @@ -68,231 +48,6 @@ public function handle() {
}
}

private function generateTransaction(): void {
try {
// get randomly a user
$randomMeter = Meter::inRandomOrder()->with([
'device',
'tariff',
])->limit(1)->firstOrFail();
} catch (ModelNotFoundException $x) {
echo 'failed to find a random meter';

return;
} catch (\Exception $x) {
echo 'boom';

return;
}

$demoDate = date('Y-m-d', strtotime('-'.mt_rand(0, 365).' days'));

try {
$meterOwnerPhoneNumber = $randomMeter->device->person->addresses()->firstOrFail();
} catch (\Exception $x) {
echo 'failed to get meter owner address';

return;
}

try {
$amount = random_int(1000, 20000);
} catch (\Exception $e) {
$amount = 300;
}

$randomTransactionType = $this->getTransactionTypeRandomlyFromTransactionTypes();
$transactionType = app()->make($randomTransactionType);

$transaction = Transaction::query()->make([
'amount' => $amount,
'type' => 'energy',
'message' => $randomMeter['serial_number'],
'sender' => $meterOwnerPhoneNumber['phone'],
'created_at' => $demoDate,
'updated_at' => $demoDate,
]);
$subTransaction = null;

// FIXME: What is this?
$manufacturerTransaction = CalinTransaction::query()->create([]);

if ($transactionType instanceof AgentTransaction) {
$city = $randomMeter->device->person->addresses()->first()->city()->first();
$miniGrid = $city->miniGrid()->first();
$agent = $miniGrid->agent()->first();
$subTransaction = AgentTransaction::query()->create([
'agent_id' => $agent->id,
'device_id' => 'test-device',
'status' => 1,
'manufacturer_transaction_id' => $manufacturerTransaction->id,
'manufacturer_transaction_type' => 'calin_transaction',
'created_at' => $demoDate,
'updated_at' => $demoDate,
]);
}

if ($transactionType instanceof SwiftaTransaction) {
$subTransaction = SwiftaTransaction::query()->create([
'transaction_reference' => Str::random(10),
'status' => 1,
'amount' => $amount,
'cipher' => Str::random(10),
'timestamp' => strval(time()),
'manufacturer_transaction_id' => $manufacturerTransaction->id,
'manufacturer_transaction_type' => 'calin_transaction',
'created_at' => $demoDate,
'updated_at' => $demoDate,
]);
}

if ($transactionType instanceof WaveMoneyTransaction) {
$mainSettings = MainSettings::query()->first();
$subTransaction = WaveMoneyTransaction::query()->create([
'transaction_reference' => Str::random(10),
'status' => 1,
'amount' => $amount,
'order_id' => Str::random(10),
'reference_id' => Str::random(10),
'currency' => $mainSettings ? $mainSettings->currency : '$',
'customer_id' => $randomMeter->device->person->id,
'meter_serial' => $randomMeter['serial_number'],
'external_transaction_id' => Str::random(10),
'attempts' => 1,
'created_at' => $demoDate,
'updated_at' => $demoDate,
'manufacturer_transaction_id' => $manufacturerTransaction->id,
'manufacturer_transaction_type' => 'calin_transaction',
]);
}

if ($transactionType instanceof WaveComTransaction) {
$subTransaction = WaveComTransaction::query()->create([
'transaction_id' => Str::random(10),
'sender' => $meterOwnerPhoneNumber['phone'],
'message' => $randomMeter['serial_number'],
'status' => 1,
'amount' => $amount,
'manufacturer_transaction_id' => $manufacturerTransaction->id,
'manufacturer_transaction_type' => 'calin_transaction',
'created_at' => $demoDate,
'updated_at' => $demoDate,
]);
}

if ($transactionType instanceof VodacomTransaction) {
$subTransaction = VodacomTransaction::query()->create([
'conversation_id' => Str::random(20),
'originator_conversation_id' => Str::random(20),
'mpesa_receipt' => Str::random(10),
'transaction_date' => $demoDate,
'transaction_id' => Str::random(10),
'status' => 1,
'manufacturer_transaction_id' => $manufacturerTransaction->id,
'manufacturer_transaction_type' => 'calin_transaction',
'created_at' => $demoDate,
'updated_at' => $demoDate,
]);
}

if ($transactionType instanceof AirtelTransaction) {
$subTransaction = AirtelTransaction::query()->create([
'interface_id' => Str::random(20),
'business_number' => Str::random(20),
'trans_id' => Str::random(10),
'tr_id' => Str::random(10),
'status' => 1,
'manufacturer_transaction_id' => $manufacturerTransaction->id,
'manufacturer_transaction_type' => 'calin_transaction',
'created_at' => $demoDate,
'updated_at' => $demoDate,
]);
}

$transaction->originalTransaction()->associate($subTransaction);
$transaction->save();

try {
// create an object for the token job
$transactionData = \App\Misc\TransactionDataContainer::initialize($transaction);
} catch (\Exception $exception) {
event('transaction.failed', [$transaction, $exception->getMessage()]);
throw $exception;
}

// pay access rate
$accessRatePayer = resolve('AccessRatePayer');
$accessRatePayer->initialize($transactionData);
$transactionData = $accessRatePayer->pay();

// pay appliance installments
$applianceInstallmentPayer = resolve('ApplianceInstallmentPayer');
$applianceInstallmentPayer->initialize($transactionData);
$transactionData->transaction->amount = $applianceInstallmentPayer->payInstallments();
$transactionData->totalAmount = $transactionData->transaction->amount;
$transactionData->paidRates = $applianceInstallmentPayer->paidRates;
$transactionData->shsLoan = $applianceInstallmentPayer->shsLoan;

// generate random token
if ($transactionData->transaction->amount > 0) {
$tokenData = [
'token' => TokenGenerator::generate(),
'load' => round(
$transactionData->transaction->amount /
$randomMeter['tariff']['price'],
2
),
];
$token = Token::query()->make([
'token' => $tokenData['token'],
'load' => $tokenData['load'],
]);
$token->transaction()->associate($transaction);
$token->save();
$transactionData->token = $token;

// generate meter_token
$meterTokenData = [
'meter_id' => $randomMeter->id,
'token' => TokenGenerator::generate(),
'energy' => round(
$transactionData->transaction->amount /
$randomMeter['tariff']['price'],
2
),
'transaction_id' => $transaction->id,
];
$meterToken = MeterToken::query()->make([
'meter_id' => $meterTokenData['meter_id'],
'token' => $meterTokenData['token'],
'energy' => $meterTokenData['energy'],
'transaction_id' => $meterTokenData['transaction_id'],
]);
$meterToken->save();

// payment event
event(
'payment.successful',
[
'amount' => $transactionData->transaction->amount,
'paymentService' => $transactionData->transaction->original_transaction_type,
'paymentType' => 'energy',
'sender' => $transactionData->transaction->sender,
'paidFor' => $token,
'payer' => $transactionData->device->person,
'transaction' => $transactionData->transaction,
]
);

// TODO: This currently doesn't work, it throws error that SMS is not configured.
// event('transaction.successful', [$transactionData->transaction]);
}
}

private function getTransactionTypeRandomlyFromTransactionTypes() {
return $this->transactionTypes[array_rand($this->transactionTypes)];
}

private function generateTicket() {
$randomCategory = TicketCategory::query()->inRandomOrder()->first();
$fakeSentence = $this->generateFakeSentence();
Expand Down
3 changes: 2 additions & 1 deletion src/backend/database/seeders/DatabaseSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ public function run() {
CustomerSeeder::class,
MeterSeeder::class,
SolarHomeSystemSeeder::class,
TicketSeeder::class,
AgentSeeder::class,
TicketSeeder::class,
TransactionSeeder::class,
]);
} else {
// If the database already includes the Demo data we don't throw an error,
Expand Down
Loading
Loading