diff --git a/app/Http/Controllers/Admin/PaymentController.php b/app/Http/Controllers/Admin/PaymentController.php index a7001427..4c52a310 100644 --- a/app/Http/Controllers/Admin/PaymentController.php +++ b/app/Http/Controllers/Admin/PaymentController.php @@ -27,6 +27,7 @@ use PayPalHttp\HttpException; class PaymentController extends Controller { + /** * @return Application|Factory|View */ @@ -45,7 +46,10 @@ class PaymentController extends Controller public function checkOut(Request $request, PaypalProduct $paypalProduct) { return view('store.checkout')->with([ - 'product' => $paypalProduct + 'product' => $paypalProduct, + 'taxvalue' => $paypalProduct->getTaxValue(), + 'taxpercent' => $paypalProduct->getTaxPercent(), + 'total' => $paypalProduct->getTotalPrice() ]); } @@ -65,8 +69,20 @@ class PaymentController extends Controller "reference_id" => uniqid(), "description" => $paypalProduct->description, "amount" => [ - "value" => $paypalProduct->price, - "currency_code" => strtoupper($paypalProduct->currency_code) + "value" => $paypalProduct->getTotalPrice(), + 'currency_code' => strtoupper($paypalProduct->currency_code), + 'breakdown' =>[ + 'item_total' => + [ + 'currency_code' => strtoupper($paypalProduct->currency_code), + 'value' => $paypalProduct->price, + ], + 'tax_total' => + [ + 'currency_code' => strtoupper($paypalProduct->currency_code), + 'value' => $paypalProduct->getTaxValue(), + ] + ] ] ] ], @@ -76,6 +92,8 @@ class PaymentController extends Controller 'brand_name' => config('app.name', 'Laravel'), 'shipping_preference' => 'NO_SHIPPING' ] + + ]; @@ -161,6 +179,9 @@ class PaymentController extends Controller 'status' => $response->result->status, 'amount' => $paypalProduct->quantity, 'price' => $paypalProduct->price, + 'tax_value' => $paypalProduct->getTaxValue(), + 'tax_percent' => $paypalProduct->getTaxPercent(), + 'total_price' => $paypalProduct->getTotalPrice(), 'currency_code' => $paypalProduct->currency_code, 'payer' => json_encode($response->result->payer), ]); @@ -199,7 +220,7 @@ class PaymentController extends Controller */ public function cancel(Request $request) { - return redirect()->route('store.index')->with('success', 'Payment was Cannceled'); + return redirect()->route('store.index')->with('success', 'Payment was Canceled'); } @@ -216,7 +237,13 @@ class PaymentController extends Controller return $payment->user->name; }) ->editColumn('price', function (Payment $payment) { - return $payment->formatCurrency(); + return $payment->formatToCurrency($payment->price); + }) + ->editColumn('tax_value', function (Payment $payment) { + return $payment->formatToCurrency($payment->tax_value); + }) + ->editColumn('total_price', function (Payment $payment) { + return $payment->formatToCurrency($payment->total_price); }) ->editColumn('created_at', function (Payment $payment) { return $payment->created_at ? $payment->created_at->diffForHumans() : ''; diff --git a/app/Http/Controllers/Admin/PaypalProductController.php b/app/Http/Controllers/Admin/PaypalProductController.php index f7b7f36f..ee4764e4 100644 --- a/app/Http/Controllers/Admin/PaypalProductController.php +++ b/app/Http/Controllers/Admin/PaypalProductController.php @@ -173,7 +173,7 @@ class PaypalProductController extends Controller return $paypalProduct->created_at ? $paypalProduct->created_at->diffForHumans() : ''; }) ->editColumn('price', function (PaypalProduct $paypalProduct) { - return $paypalProduct->formatCurrency(); + return $paypalProduct->formatToCurrency($paypalProduct->price); }) ->rawColumns(['actions', 'disabled']) ->make(); diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index c88f8334..33738d52 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -58,13 +58,13 @@ class ProductController extends Controller /** @var Location $location */ $location = $node->location; - if (!$locations->contains('id' , $location->id)){ - $nodeIds = $nodes->map(function ($node){ + if (!$locations->contains('id', $location->id)) { + $nodeIds = $nodes->map(function ($node) { return $node->id; }); $location->nodes = $location->nodes() - ->whereIn('id' , $nodeIds) + ->whereIn('id', $nodeIds) ->get(); $locations->add($location); @@ -76,14 +76,20 @@ class ProductController extends Controller /** * @param Node $node + * @param Egg $egg * @return Collection|JsonResponse */ - public function getProductsBasedOnNode(Node $node) + public function getProductsBasedOnNode(Egg $egg, Node $node) { - if (is_null($node->id)) return response()->json('Node ID is required', '400'); + if (is_null($egg->id) || is_null($node->id)) return response()->json('node and egg id is required', '400'); - return Product::query()->whereHas('nodes', function (Builder $builder) use ($node) { - $builder->where('id', '=', $node->id); - })->get(); + return Product::query() + ->whereHas('nodes', function (Builder $builder) use ($node) { + $builder->where('id', '=', $node->id); + }) + ->whereHas('eggs', function (Builder $builder) use ($egg) { + $builder->where('id', '=', $egg->id); + }) + ->get(); } } diff --git a/app/Models/Payment.php b/app/Models/Payment.php index 85bb4b0d..2fb1db0e 100644 --- a/app/Models/Payment.php +++ b/app/Models/Payment.php @@ -29,6 +29,9 @@ class Payment extends Model 'type', 'amount', 'price', + 'tax_value', + 'total_price', + 'tax_percent', 'currency_code', ]; @@ -51,9 +54,15 @@ class Payment extends Model return $this->belongsTo(User::class); } - public function formatCurrency($locale = 'en_US') + /** + * @param mixed $value + * @param string $locale + * + * @return float + */ + public function formatToCurrency($value,$locale = 'en_US') { $formatter = new NumberFormatter($locale, NumberFormatter::CURRENCY); - return $formatter->formatCurrency($this->price, $this->currency_code); + return $formatter->formatCurrency($value, $this->currency_code); } } diff --git a/app/Models/PaypalProduct.php b/app/Models/PaypalProduct.php index c39c0f8e..2463bf00 100644 --- a/app/Models/PaypalProduct.php +++ b/app/Models/PaypalProduct.php @@ -6,6 +6,7 @@ use Hidehalo\Nanoid\Client; use Illuminate\Database\Eloquent\Model; use NumberFormatter; use Spatie\Activitylog\Traits\LogsActivity; +use App\Models\Configuration; class PaypalProduct extends Model { @@ -40,12 +41,45 @@ class PaypalProduct extends Model } /** + * @param mixed $value * @param string $locale - * @return string + * + * @return float */ - public function formatCurrency($locale = 'en_US') + public function formatToCurrency($value,$locale = 'en_US') { $formatter = new NumberFormatter($locale, NumberFormatter::CURRENCY); - return $formatter->formatCurrency($this->price, $this->currency_code); + return $formatter->formatCurrency($value, $this->currency_code); + } + + /** + * @description Returns the tax in % taken from the Configuration + * + * @return int + */ + public function getTaxPercent() + { + $tax = Configuration::getValueByKey("SALES_TAX"); + return $tax < 0 ? 0 : $tax; + } + + /** + * @description Returns the tax as Number + * + * @return float + */ + public function getTaxValue() + { + return $this->price*$this->getTaxPercent()/100; + } + + /** + * @description Returns the full price of a Product including tax + * + * @return float + */ + public function getTotalPrice() + { + return $this->price+($this->getTaxValue()); } } diff --git a/database/migrations/2021_11_05_071456_add_tax_to_paymentlogs.php b/database/migrations/2021_11_05_071456_add_tax_to_paymentlogs.php new file mode 100644 index 00000000..3796ee9e --- /dev/null +++ b/database/migrations/2021_11_05_071456_add_tax_to_paymentlogs.php @@ -0,0 +1,36 @@ +decimal('tax_value',8,2)->after('price')->nullable(); + $table->integer('tax_percent')->after('tax_value')->nullable(); + $table->decimal('total_price',8,2)->after('tax_percent')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('payments', function (Blueprint $table) { + $table->dropColumn('tax_value'); + $table->dropColumn('tax_percent'); + $table->dropColumn('total_price'); + }); + } +} diff --git a/database/seeders/Seeds/ConfigurationSeeder.php b/database/seeders/Seeds/ConfigurationSeeder.php index cce8c991..98d3a57a 100644 --- a/database/seeders/Seeds/ConfigurationSeeder.php +++ b/database/seeders/Seeds/ConfigurationSeeder.php @@ -136,6 +136,14 @@ class ConfigurationSeeder extends Seeder 'type' => 'boolean', 'description' => 'Charges the first hour worth of credits upon creating a server.' ]); + //sales tax + Configuration::firstOrCreate([ + 'key' => 'SALES_TAX', + ], [ + 'value' => '0', + 'type' => 'integer', + 'description' => 'The %-value of tax that will be added to the product price on checkout' + ]); } } diff --git a/resources/views/admin/payments/index.blade.php b/resources/views/admin/payments/index.blade.php index d22b2788..b6765901 100644 --- a/resources/views/admin/payments/index.blade.php +++ b/resources/views/admin/payments/index.blade.php @@ -37,7 +37,10 @@ User Type Amount - Price + Product Price + Tax + Tax(%) + Total Price Payment_ID Payer_ID Created at @@ -68,6 +71,9 @@ {data: 'type'}, {data: 'amount'}, {data: 'price'}, + {data: 'tax_value'}, + {data: 'tax_percent'}, + {data: 'total_price'}, {data: 'payment_id'}, {data: 'payer_id'}, {data: 'created_at'}, diff --git a/resources/views/mail/payment/confirmed.blade.php b/resources/views/mail/payment/confirmed.blade.php index e8a30931..2ba7c487 100644 --- a/resources/views/mail/payment/confirmed.blade.php +++ b/resources/views/mail/payment/confirmed.blade.php @@ -6,7 +6,7 @@ Your payment has been confirmed; Your credit balance has been updated.
___ ### Payment ID: **{{$payment->id}}**
### Status: **{{$payment->status}}**
-### Price: **{{$payment->formatCurrency()}}**
+### Price: **{{$payment->formatToCurrency($payment->total_price)}}**
### Type: **{{$payment->type}}**
### Amount: **{{$payment->amount}}**
### Balance: **{{$payment->user->credits}}**
diff --git a/resources/views/servers/create.blade.php b/resources/views/servers/create.blade.php index e22b2148..b516c98a 100644 --- a/resources/views/servers/create.blade.php +++ b/resources/views/servers/create.blade.php @@ -101,7 +101,7 @@ name="nest" id="nest" x-model="selectedNest" - @change="setNests();"> + @change="setEggs();"> @foreach ($nests as $nest) @@ -229,33 +229,39 @@ + @@ -319,7 +325,7 @@ * @note called whenever a nest is selected * @see selectedNest */ - setNests() { + async setEggs() { this.fetchedLocations = false; this.fetchedProducts = false; this.locations = []; @@ -329,6 +335,14 @@ this.selectedProduct = 'null'; this.eggs = this.eggsSave.filter(egg => egg.nest_id == this.selectedNest) + + //automatically select the first entry if there is only 1 + if (this.eggs.length === 1) { + this.selectedEgg = this.eggs[0].id; + await this.fetchLocations(); + return; + } + this.updateSelectedObjects() }, @@ -351,6 +365,14 @@ this.fetchedLocations = true; this.locations = response.data + + //automatically select the first entry if there is only 1 + if (this.locations.length === 1 && this.locations[0]?.nodes?.length === 1) { + this.selectedNode = this.locations[0].id; + await this.fetchProducts(); + return; + } + this.loading = false; this.updateSelectedObjects() }, @@ -366,11 +388,17 @@ this.products = []; this.selectedProduct = 'null'; - let response = await axios.get(`{{route('products.products.node')}}/${this.selectedNode}`) + let response = await axios.get(`{{route('products.products.node')}}/${this.selectedEgg}/${this.selectedNode}`) .catch(console.error) this.fetchedProducts = true; this.products = response.data + + //automatically select the first entry if there is only 1 + if (this.products.length === 1) { + this.selectedProduct = this.products[0].id; + } + this.loading = false; this.updateSelectedObjects() }, diff --git a/resources/views/store/checkout.blade.php b/resources/views/store/checkout.blade.php index d6401374..f2bce40a 100644 --- a/resources/views/store/checkout.blade.php +++ b/resources/views/store/checkout.blade.php @@ -83,7 +83,7 @@ 1 {{$product->quantity}} {{strtolower($product->type) == 'credits' ? CREDITS_DISPLAY_NAME : $product->type}} {{$product->description}} - {{$product->formatCurrency()}} + {{$product->formatToCurrency($product->price)}} @@ -111,11 +111,11 @@ - + - - + + @@ -123,7 +123,7 @@ - +
Subtotal:{{$product->formatCurrency()}}{{$product->formatToCurrency($product->price)}}
Tax (0%)0.00Tax ({{$taxpercent}}%){{$product->formatToCurrency($taxvalue)}}
Quantity:
Total:{{$product->formatCurrency()}}{{$product->formatToCurrency($total)}}
diff --git a/resources/views/store/index.blade.php b/resources/views/store/index.blade.php index 8bc3f077..880d83a4 100644 --- a/resources/views/store/index.blade.php +++ b/resources/views/store/index.blade.php @@ -50,7 +50,7 @@ @foreach($products as $product) - {{$product->formatCurrency()}} + {{$product->formatToCurrency($product->price)}} {{strtolower($product->type) == 'credits' ? CREDITS_DISPLAY_NAME : $product->type}} {{$product->display}} Purchase diff --git a/routes/web.php b/routes/web.php index d107930d..18cadf8d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -58,7 +58,7 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () { #routes made for server create page to fetch product info Route::get('/products/nodes/egg/{egg?}', [FrontProductController::class, 'getNodesBasedOnEgg'])->name('products.nodes.egg'); Route::get('/products/locations/egg/{egg?}', [FrontProductController::class, 'getLocationsBasedOnEgg'])->name('products.locations.egg'); - Route::get('/products/products/node/{node?}', [FrontProductController::class, 'getProductsBasedOnNode'])->name('products.products.node'); + Route::get('/products/products/{egg?}/{node?}', [FrontProductController::class, 'getProductsBasedOnNode'])->name('products.products.node'); #payments Route::get('checkout/{paypalProduct}', [PaymentController::class, 'checkOut'])->name('checkout');