diff --git a/src/app/Console/Commands/DomainList.php b/src/app/Console/Commands/DomainDelete.php copy from src/app/Console/Commands/DomainList.php copy to src/app/Console/Commands/DomainDelete.php --- a/src/app/Console/Commands/DomainList.php +++ b/src/app/Console/Commands/DomainDelete.php @@ -2,24 +2,23 @@ namespace App\Console\Commands; -use App\Domain; use Illuminate\Console\Command; -class DomainList extends Command +class DomainDelete extends Command { /** * The name and signature of the console command. * * @var string */ - protected $signature = 'domain:list'; + protected $signature = 'domain:delete {domain}'; /** * The console command description. * * @var string */ - protected $description = 'List domains'; + protected $description = 'Delete a domain'; /** * Create a new command instance. @@ -38,10 +37,12 @@ */ public function handle() { - $domains = Domain::withTrashed()->orderBy('namespace')->each( - function ($domain) { - $this->info($domain->namespace); - } - ); + $domain = \App\Domain::where('id', $this->argument('domain'))->first(); + + if (!$domain) { + return 1; + } + + $domain->delete(); } } diff --git a/src/app/Console/Commands/DomainList.php b/src/app/Console/Commands/DomainList.php --- a/src/app/Console/Commands/DomainList.php +++ b/src/app/Console/Commands/DomainList.php @@ -12,7 +12,7 @@ * * @var string */ - protected $signature = 'domain:list'; + protected $signature = 'domain:list {--deleted}'; /** * The console command description. @@ -38,9 +38,21 @@ */ public function handle() { - $domains = Domain::withTrashed()->orderBy('namespace')->each( + if ($this->option('deleted')) { + $domains = Domain::withTrashed()->orderBy('namespace'); + } else { + $domains = Domain::orderBy('namespace'); + } + + $domains->each( function ($domain) { - $this->info($domain->namespace); + $msg = $domain->namespace; + + if ($domain->deleted_at) { + $msg .= " (deleted at {$domain->deleted_at})"; + } + + $this->info($msg); } ); } diff --git a/src/app/Console/Commands/DomainListUsers.php b/src/app/Console/Commands/DomainListUsers.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/DomainListUsers.php @@ -0,0 +1,83 @@ +argument('domain'))->first(); + + if (!$domain) { + return 1; + } + + if ($domain->isPublic()) { + $this->error("This domain is a public registration domain."); + return 1; + } + + // TODO: actually implement listing users + $wallet = $domain->wallet(); + + if (!$wallet) { + $this->error("This domain isn't billed to a wallet."); + return 1; + } + + $mailboxSKU = \App\Sku::where('title', 'mailbox')->first(); + + if (!$mailboxSKU) { + $this->error("No mailbox SKU available."); + } + + $entitlements = $wallet->entitlements() + ->where('entitleable_type', \App\User::class) + ->where('sku_id', $mailboxSKU->id)->get(); + + $users = []; + + foreach ($entitlements as $entitlement) { + $users[] = $entitlement->entitleable; + } + + usort($users, function ($a, $b) { + return $a->email > $b->email; + }); + + foreach ($users as $user) { + $this->info($user->email); + } + } +} diff --git a/src/app/Console/Commands/DomainList.php b/src/app/Console/Commands/UserDelete.php copy from src/app/Console/Commands/DomainList.php copy to src/app/Console/Commands/UserDelete.php --- a/src/app/Console/Commands/DomainList.php +++ b/src/app/Console/Commands/UserDelete.php @@ -2,24 +2,23 @@ namespace App\Console\Commands; -use App\Domain; use Illuminate\Console\Command; -class DomainList extends Command +class UserDelete extends Command { /** * The name and signature of the console command. * * @var string */ - protected $signature = 'domain:list'; + protected $signature = 'user:delete {user}'; /** * The console command description. * * @var string */ - protected $description = 'List domains'; + protected $description = 'Delete a user'; /** * Create a new command instance. @@ -38,10 +37,12 @@ */ public function handle() { - $domains = Domain::withTrashed()->orderBy('namespace')->each( - function ($domain) { - $this->info($domain->namespace); - } - ); + $user = \App\User::where('email', $this->argument('user'))->first(); + + if (!$user) { + return 1; + } + + $user->delete(); } } diff --git a/src/app/Console/Commands/UserDomains.php b/src/app/Console/Commands/UserDomains.php --- a/src/app/Console/Commands/UserDomains.php +++ b/src/app/Console/Commands/UserDomains.php @@ -42,10 +42,12 @@ { $user = User::where('email', $this->argument('userid'))->first(); - $this->info("Found user: {$user->id}"); + if (!$user) { + return 1; + } foreach ($user->domains() as $domain) { - $this->info("Domain: {$domain->namespace}"); + $this->info("{$domain->namespace}"); } } } diff --git a/src/app/Console/Commands/UserEntitlements.php b/src/app/Console/Commands/UserEntitlements.php --- a/src/app/Console/Commands/UserEntitlements.php +++ b/src/app/Console/Commands/UserEntitlements.php @@ -41,6 +41,10 @@ { $user = User::where('email', $this->argument('userid'))->first(); + if (!$user) { + return 1; + } + $this->info("Found user: {$user->id}"); $skus_counted = []; diff --git a/src/app/Console/Commands/WalletBalances.php b/src/app/Console/Commands/WalletBalances.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/WalletBalances.php @@ -0,0 +1,65 @@ +each( + function ($wallet) { + if ($wallet->balance == 0) { + return; + } + + $user = \App\User::where('id', $wallet->user_id)->first(); + + if (!$user) { + return; + } + + $this->info( + sprintf( + "%s: %8s (account: %s/%s (%s))", + $wallet->id, + $wallet->balance, + "https://kolabnow.com/cockpit/admin/accounts/show", + $user->id, + $user->email + ) + ); + } + ); + } +} diff --git a/src/app/Console/Commands/WalletExpected.php b/src/app/Console/Commands/WalletExpected.php --- a/src/app/Console/Commands/WalletExpected.php +++ b/src/app/Console/Commands/WalletExpected.php @@ -11,14 +11,14 @@ * * @var string */ - protected $signature = 'wallet:expected'; + protected $signature = 'wallet:expected {--user=} {--non-zero}'; /** * The console command description. * * @var string */ - protected $description = 'Show expected charges to wallets'; + protected $description = 'Show expected charges to wallets (for user)'; /** * Create a new command instance. @@ -37,15 +37,40 @@ */ public function handle() { - $wallets = \App\Wallet::all(); + if ($this->option('user')) { + $user = \App\User::where('email', $this->option('user')) + ->orWhere('id', $this->option('user'))->first(); + + if (!$user) { + return 1; + } + + $wallets = $user->wallets; + } else { + $wallets = \App\Wallet::all(); + } foreach ($wallets as $wallet) { $charge = 0; $expected = $wallet->expectedCharges(); - if ($expected > 0) { - $this->info("expect charging wallet {$wallet->id} for user {$wallet->owner->email} with {$expected}"); + if (!$wallet->owner) { + \Log::debug("{$wallet->id} has no owner: {$wallet->user_id}"); + continue; } + + if ($this->option('non-zero') && $expected < 1) { + continue; + } + + $this->info( + sprintf( + "expect charging wallet %s for user %s with %d", + $wallet->id, + $wallet->owner->email, + $expected + ) + ); } } } diff --git a/src/app/Console/Commands/DomainList.php b/src/app/Console/Commands/WalletGetBalance.php copy from src/app/Console/Commands/DomainList.php copy to src/app/Console/Commands/WalletGetBalance.php --- a/src/app/Console/Commands/DomainList.php +++ b/src/app/Console/Commands/WalletGetBalance.php @@ -2,24 +2,23 @@ namespace App\Console\Commands; -use App\Domain; use Illuminate\Console\Command; -class DomainList extends Command +class WalletGetBalance extends Command { /** * The name and signature of the console command. * * @var string */ - protected $signature = 'domain:list'; + protected $signature = 'wallet:get-balance {wallet}'; /** * The console command description. * * @var string */ - protected $description = 'List domains'; + protected $description = 'Display the balance of a wallet'; /** * Create a new command instance. @@ -38,10 +37,12 @@ */ public function handle() { - $domains = Domain::withTrashed()->orderBy('namespace')->each( - function ($domain) { - $this->info($domain->namespace); - } - ); + $wallet = \App\Wallet::find($this->argument('wallet')); + + if (!$wallet) { + return 1; + } + + $this->info($wallet->balance); } } diff --git a/src/app/Console/Commands/UserDomains.php b/src/app/Console/Commands/WalletGetDiscount.php copy from src/app/Console/Commands/UserDomains.php copy to src/app/Console/Commands/WalletGetDiscount.php --- a/src/app/Console/Commands/UserDomains.php +++ b/src/app/Console/Commands/WalletGetDiscount.php @@ -2,26 +2,23 @@ namespace App\Console\Commands; -use App\Domain; -use App\User; use Illuminate\Console\Command; -use Illuminate\Support\Facades\DB; -class UserDomains extends Command +class WalletGetDiscount extends Command { /** * The name and signature of the console command. * * @var string */ - protected $signature = 'user:domains {userid}'; + protected $signature = 'wallet:get-discount {wallet}'; /** * The console command description. * * @var string */ - protected $description = 'Command description'; + protected $description = 'Display the existing discount to a wallet, if any.'; /** * Create a new command instance. @@ -40,12 +37,17 @@ */ public function handle() { - $user = User::where('email', $this->argument('userid'))->first(); + $wallet = \App\Wallet::find($this->argument('wallet')); - $this->info("Found user: {$user->id}"); + if (!$wallet) { + return 1; + } - foreach ($user->domains() as $domain) { - $this->info("Domain: {$domain->namespace}"); + if (!$wallet->discount) { + $this->info("No discount on this wallet."); + return 0; } + + $this->info($wallet->discount->discount); } } diff --git a/src/app/Console/Commands/DomainList.php b/src/app/Console/Commands/WalletSetBalance.php copy from src/app/Console/Commands/DomainList.php copy to src/app/Console/Commands/WalletSetBalance.php --- a/src/app/Console/Commands/DomainList.php +++ b/src/app/Console/Commands/WalletSetBalance.php @@ -2,24 +2,23 @@ namespace App\Console\Commands; -use App\Domain; use Illuminate\Console\Command; -class DomainList extends Command +class WalletSetBalance extends Command { /** * The name and signature of the console command. * * @var string */ - protected $signature = 'domain:list'; + protected $signature = 'wallet:set-balance {wallet} {balance}'; /** * The console command description. * * @var string */ - protected $description = 'List domains'; + protected $description = 'Set the balance of a wallet'; /** * Create a new command instance. @@ -38,10 +37,13 @@ */ public function handle() { - $domains = Domain::withTrashed()->orderBy('namespace')->each( - function ($domain) { - $this->info($domain->namespace); - } - ); + $wallet = \App\Wallet::find($this->argument('wallet')); + + if (!$wallet) { + return 1; + } + + $wallet->balance = (int)($this->argument('balance')); + $wallet->save(); } } diff --git a/src/app/Console/Commands/WalletSetDiscount.php b/src/app/Console/Commands/WalletSetDiscount.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/WalletSetDiscount.php @@ -0,0 +1,62 @@ +argument('wallet'))->first(); + + if (!$wallet) { + return 1; + } + + // FIXME: Using '0' for delete might be not that obvious + + if ($this->argument('discount') === '0') { + $wallet->discount()->dissociate(); + } else { + $discount = \App\Discount::find($this->argument('discount')); + + if (!$discount) { + return 1; + } + + $wallet->discount()->associate($discount); + } + + $wallet->save(); + } +} diff --git a/src/app/Discount.php b/src/app/Discount.php --- a/src/app/Discount.php +++ b/src/app/Discount.php @@ -40,8 +40,14 @@ { $discount = (int) $discount; - if ($discount < 0 || $discount > 100) { - throw new \Exception("Invalid discount value, expected integer in range of 0-100"); + if ($discount < 0) { + \Log::warning("Expecting a discount rate >= 0"); + $discount = 0; + } + + if ($discount > 100) { + \Log::warning("Expecting a discount rate <= 100"); + $discount = 100; } $this->attributes['discount'] = $discount; diff --git a/src/app/Domain.php b/src/app/Domain.php --- a/src/app/Domain.php +++ b/src/app/Domain.php @@ -61,6 +61,22 @@ */ public function assignPackage($package, $user) { + // If this domain is public it can not be assigned to a user. + if ($this->isPublic()) { + return $this; + } + + // See if this domain is already owned by another user. + $wallet = $this->wallet(); + + if ($wallet) { + \Log::error( + "Domain {$this->namespace} is already assigned to {$wallet->owner->email}" + ); + + return $this; + } + $wallet_id = $user->wallets()->first()->id; foreach ($package->skus as $sku) { @@ -80,7 +96,6 @@ return $this; } - public function entitlement() { return $this->morphOne('App\Entitlement', 'entitleable'); @@ -198,6 +213,14 @@ } /** + * Ensure the namespace is appropriately cased. + */ + public function setNamespaceAttribute($namespace) + { + $this->attributes['namespace'] = strtolower($namespace); + } + + /** * Domain status mutator * * @throws \Exception diff --git a/src/tests/Feature/DiscountTest.php b/src/tests/Feature/DiscountTest.php --- a/src/tests/Feature/DiscountTest.php +++ b/src/tests/Feature/DiscountTest.php @@ -12,10 +12,10 @@ */ public function testDiscountValueLessThanZero(): void { - $this->expectException(\Exception::class); - $discount = new Discount(); $discount->discount = -1; + + $this->assertTrue($discount->discount == 0); } /** @@ -23,9 +23,9 @@ */ public function testDiscountValueMoreThanHundred(): void { - $this->expectException(\Exception::class); - $discount = new Discount(); $discount->discount = 101; + + $this->assertTrue($discount->discount == 100); } }