mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-05-04 05:05:58 +00:00
record daily usage
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use Domain\Sharing\Models\Share;
|
||||||
|
use Domain\Traffic\Models\Traffic;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
class TrafficFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name of the factory's corresponding model.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $model = Traffic::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function definition()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->faker->uuid,
|
||||||
|
'user_id' => $this->faker->uuid,
|
||||||
|
'upload' => rand(11111111, 99999999),
|
||||||
|
'download' => rand(11111111, 99999999),
|
||||||
|
'created_at' => $this->faker->dateTimeBetween('-month'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ use Support\Scheduler\Actions\DeleteFailedFilesAction;
|
|||||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||||
use Support\Scheduler\Actions\DeleteUnverifiedUsersAction;
|
use Support\Scheduler\Actions\DeleteUnverifiedUsersAction;
|
||||||
use Support\Scheduler\Actions\DeleteExpiredShareLinksAction;
|
use Support\Scheduler\Actions\DeleteExpiredShareLinksAction;
|
||||||
|
use Support\Scheduler\Actions\ReportUsageAction;
|
||||||
|
|
||||||
class Kernel extends ConsoleKernel
|
class Kernel extends ConsoleKernel
|
||||||
{
|
{
|
||||||
@@ -26,7 +27,7 @@ class Kernel extends ConsoleKernel
|
|||||||
*/
|
*/
|
||||||
protected function schedule(Schedule $schedule): void
|
protected function schedule(Schedule $schedule): void
|
||||||
{
|
{
|
||||||
if (! is_storage_driver(['local'])) {
|
if (! is_storage_driver('local')) {
|
||||||
$schedule->call(
|
$schedule->call(
|
||||||
fn () => resolve(DeleteFailedFilesAction::class)()
|
fn () => resolve(DeleteFailedFilesAction::class)()
|
||||||
)->everySixHours();
|
)->everySixHours();
|
||||||
@@ -38,7 +39,11 @@ class Kernel extends ConsoleKernel
|
|||||||
|
|
||||||
$schedule->call(
|
$schedule->call(
|
||||||
fn () => resolve(DeleteUnverifiedUsersAction::class)()
|
fn () => resolve(DeleteUnverifiedUsersAction::class)()
|
||||||
)->daily();
|
)->daily()->at('00:05');
|
||||||
|
|
||||||
|
$schedule->call(
|
||||||
|
fn () => resolve(ReportUsageAction::class)()
|
||||||
|
)->daily()->at('00:10');
|
||||||
|
|
||||||
// Run queue jobs every minute
|
// Run queue jobs every minute
|
||||||
$schedule->command('queue:work --stop-when-empty')
|
$schedule->command('queue:work --stop-when-empty')
|
||||||
@@ -48,10 +53,10 @@ class Kernel extends ConsoleKernel
|
|||||||
// Backup app database daily
|
// Backup app database daily
|
||||||
$schedule->command('backup:clean')
|
$schedule->command('backup:clean')
|
||||||
->daily()
|
->daily()
|
||||||
->at('01:00');
|
->at('00:15');
|
||||||
$schedule->command('backup:run --only-db')
|
$schedule->command('backup:run --only-db')
|
||||||
->daily()
|
->daily()
|
||||||
->at('01:30');
|
->at('00:20');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class UploadFileAction
|
|||||||
$disk_local->move("chunks/$chunkName", "files/$user_id/$fileName");
|
$disk_local->move("chunks/$chunkName", "files/$user_id/$fileName");
|
||||||
|
|
||||||
// Move files to external storage
|
// Move files to external storage
|
||||||
if (! is_storage_driver(['local'])) {
|
if (! is_storage_driver('local')) {
|
||||||
($this->moveFileToExternalStorage)($fileName, $user_id);
|
($this->moveFileToExternalStorage)($fileName, $user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ class File extends Model
|
|||||||
$links = [];
|
$links = [];
|
||||||
|
|
||||||
// Generate thumbnail link for external storage service
|
// Generate thumbnail link for external storage service
|
||||||
if ($this->type === 'image' && ! is_storage_driver(['local'])) {
|
if ($this->type === 'image' && ! is_storage_driver('local')) {
|
||||||
foreach (config('vuefilemanager.image_sizes') as $item) {
|
foreach (config('vuefilemanager.image_sizes') as $item) {
|
||||||
$filePath = "files/{$this->user_id}/{$item['name']}-{$this->basename}";
|
$filePath = "files/{$this->user_id}/{$item['name']}-{$this->basename}";
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ class File extends Model
|
|||||||
public function getFileUrlAttribute(): string
|
public function getFileUrlAttribute(): string
|
||||||
{
|
{
|
||||||
// Get file from external storage
|
// Get file from external storage
|
||||||
if (! is_storage_driver(['local'])) {
|
if (! is_storage_driver('local')) {
|
||||||
$file_pretty_name = is_storage_driver('backblaze')
|
$file_pretty_name = is_storage_driver('backblaze')
|
||||||
? Str::snake(mb_strtolower($this->attributes['name']))
|
? Str::snake(mb_strtolower($this->attributes['name']))
|
||||||
: get_pretty_name($this->attributes['basename'], $this->attributes['name'], $this->attributes['mimetype']);
|
: get_pretty_name($this->attributes['basename'], $this->attributes['name'], $this->attributes['mimetype']);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Domain\Traffic\Models;
|
namespace Domain\Traffic\Models;
|
||||||
|
|
||||||
|
use Database\Factories\TrafficFactory;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
@@ -22,6 +23,11 @@ class Traffic extends Model
|
|||||||
|
|
||||||
protected $keyType = 'string';
|
protected $keyType = 'string';
|
||||||
|
|
||||||
|
protected static function newFactory(): TrafficFactory
|
||||||
|
{
|
||||||
|
return TrafficFactory::new();
|
||||||
|
}
|
||||||
|
|
||||||
public function scopeCurrentDay($query): Builder
|
public function scopeCurrentDay($query): Builder
|
||||||
{
|
{
|
||||||
return $query->whereDate('created_at', today());
|
return $query->whereDate('created_at', today());
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Support\Scheduler\Actions;
|
||||||
|
|
||||||
|
use DB;
|
||||||
|
use VueFileManager\Subscription\Domain\Subscriptions\Models\Subscription;
|
||||||
|
|
||||||
|
class ReportUsageAction
|
||||||
|
{
|
||||||
|
public function __invoke()
|
||||||
|
{
|
||||||
|
Subscription::whereIn('type', ['pre-paid', 'auto-renew'])
|
||||||
|
->where('status', 'active')
|
||||||
|
->cursor()
|
||||||
|
->each(function($subscription) {
|
||||||
|
$this->recordBandwidth($subscription);
|
||||||
|
$this->recordStorageCapacity($subscription);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private function recordStorageCapacity(Subscription $subscription): void
|
||||||
|
{
|
||||||
|
// Sum all file size
|
||||||
|
$filesize = DB::table('files')
|
||||||
|
->where('user_id', $subscription->user->id)
|
||||||
|
->sum('filesize');
|
||||||
|
|
||||||
|
// We count storage size in GB, e.g. 0.15 is 150mb
|
||||||
|
$amount = $filesize / 1000000000;
|
||||||
|
|
||||||
|
// Record storage capacity usage
|
||||||
|
$subscription->recordUsage('storage', $amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function recordBandwidth(Subscription $subscription): void
|
||||||
|
{
|
||||||
|
// We count storage size in GB, e.g. 0.15 is 150mb
|
||||||
|
$record = $subscription
|
||||||
|
->user
|
||||||
|
->traffics()
|
||||||
|
->where('created_at', today()->subDay())
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$amount = ($record->download ?? 0) / 1000000000;
|
||||||
|
|
||||||
|
// Record storage capacity usage
|
||||||
|
$subscription->recordUsage('bandwidth', $amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Domain\Traffic;
|
namespace Tests\Domain\Traffic;
|
||||||
|
|
||||||
|
use Domain\Traffic\Models\Traffic;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Storage;
|
use Storage;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
use App\Users\Models\User;
|
use App\Users\Models\User;
|
||||||
@@ -9,12 +12,11 @@ use Domain\Files\Models\File;
|
|||||||
use Domain\Sharing\Models\Share;
|
use Domain\Sharing\Models\Share;
|
||||||
use Domain\Folders\Models\Folder;
|
use Domain\Folders\Models\Folder;
|
||||||
use Illuminate\Http\UploadedFile;
|
use Illuminate\Http\UploadedFile;
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
|
|
||||||
class TrafficTest extends TestCase
|
class TrafficTest extends TestCase
|
||||||
{
|
{
|
||||||
public UploadedFile $file;
|
public UploadedFile $file;
|
||||||
public User $user;
|
public Model $user;
|
||||||
|
|
||||||
public function setUp(): void
|
public function setUp(): void
|
||||||
{
|
{
|
||||||
@@ -193,13 +195,10 @@ class TrafficTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function it_get_user_traffic_test()
|
public function it_get_user_traffic_test()
|
||||||
{
|
{
|
||||||
$user = User::factory()
|
|
||||||
->create();
|
|
||||||
|
|
||||||
foreach (range(0, 30) as $day) {
|
foreach (range(0, 30) as $day) {
|
||||||
DB::table('traffic')->insert([
|
Traffic::factory()
|
||||||
'id' => Str::uuid(),
|
->create([
|
||||||
'user_id' => $user->id,
|
'user_id' => $this->user->id,
|
||||||
'upload' => 10000 * $day,
|
'upload' => 10000 * $day,
|
||||||
'download' => 1000000 * $day,
|
'download' => 1000000 * $day,
|
||||||
'created_at' => now()->subDays($day),
|
'created_at' => now()->subDays($day),
|
||||||
@@ -207,7 +206,7 @@ class TrafficTest extends TestCase
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->actingAs($user)
|
$this->actingAs($this->user)
|
||||||
->get('/api/user/storage')
|
->get('/api/user/storage')
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertJsonFragment([
|
->assertJsonFragment([
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Support\Scheduler;
|
namespace Tests\Support\Scheduler;
|
||||||
|
|
||||||
|
use Domain\Files\Models\File;
|
||||||
|
use Domain\Traffic\Models\Traffic;
|
||||||
use Storage;
|
use Storage;
|
||||||
|
use Support\Scheduler\Actions\ReportUsageAction;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
use App\Users\Models\User;
|
use App\Users\Models\User;
|
||||||
use Domain\Sharing\Models\Share;
|
use Domain\Sharing\Models\Share;
|
||||||
@@ -9,9 +13,71 @@ use Illuminate\Http\UploadedFile;
|
|||||||
use Support\Scheduler\Actions\DeleteFailedFilesAction;
|
use Support\Scheduler\Actions\DeleteFailedFilesAction;
|
||||||
use Support\Scheduler\Actions\DeleteUnverifiedUsersAction;
|
use Support\Scheduler\Actions\DeleteUnverifiedUsersAction;
|
||||||
use Support\Scheduler\Actions\DeleteExpiredShareLinksAction;
|
use Support\Scheduler\Actions\DeleteExpiredShareLinksAction;
|
||||||
|
use VueFileManager\Subscription\Domain\Plans\Models\Plan;
|
||||||
|
use VueFileManager\Subscription\Domain\Plans\Models\PlanMeteredFeature;
|
||||||
|
use VueFileManager\Subscription\Domain\Subscriptions\Models\Subscription;
|
||||||
|
|
||||||
class SchedulerTest extends TestCase
|
class SchedulerTest extends TestCase
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function it_report_usage_of_subscription()
|
||||||
|
{
|
||||||
|
$user = User::factory()
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$plan = Plan::factory()
|
||||||
|
->create([
|
||||||
|
'type' => 'metered',
|
||||||
|
]);
|
||||||
|
|
||||||
|
PlanMeteredFeature::factory()
|
||||||
|
->count(2)
|
||||||
|
->sequence(
|
||||||
|
['key' => 'storage'],
|
||||||
|
['key' => 'bandwidth'],
|
||||||
|
)
|
||||||
|
->create([
|
||||||
|
'plan_id' => $plan->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$subscription = Subscription::factory()
|
||||||
|
->create([
|
||||||
|
'status' => 'active',
|
||||||
|
'type' => 'pre-paid',
|
||||||
|
'plan_id' => $plan->id,
|
||||||
|
'user_id' => $user->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
File::factory()
|
||||||
|
->create([
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'filesize' => 125000000,
|
||||||
|
]);
|
||||||
|
|
||||||
|
Traffic::factory()
|
||||||
|
->create([
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'download' => 155000000,
|
||||||
|
'created_at' => now()->subDay(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
resolve(ReportUsageAction::class)();
|
||||||
|
|
||||||
|
$this
|
||||||
|
->assertDatabaseHas('usages', [
|
||||||
|
'metered_feature_id' => $plan->meteredFeatures()->get()[0]->id,
|
||||||
|
'subscription_id' => $subscription->id,
|
||||||
|
'quantity' => 0.125,
|
||||||
|
])
|
||||||
|
->assertDatabaseHas('usages', [
|
||||||
|
'metered_feature_id' => $plan->meteredFeatures()->get()[1]->id,
|
||||||
|
'subscription_id' => $subscription->id,
|
||||||
|
'quantity' => 0.155,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user