This commit is contained in:
Mekan1206
2026-04-29 22:26:04 +05:00
parent 9b95087b94
commit dd633ef7da
19 changed files with 314 additions and 35 deletions

View File

@@ -11,6 +11,10 @@ trait HasShipping
*/
public function shippingPrice(): int
{
if ($this->shippingMethod) {
return intval($this->shipping_price) ?: $this->shippingMethod->price;
}
return intval($this->shipping_price) ?: OrderShipping::priceFor($this->shipping_method);
}
@@ -19,6 +23,10 @@ trait HasShipping
*/
public function formattedShippingMethod(): string
{
if ($this->shippingMethod) {
return $this->shippingMethod->name;
}
return OrderShipping::formattedShippingMethod($this->shipping_method);
}

View File

@@ -12,6 +12,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use App\Models\Ecommerce\Product\Order\Shipping\OrderShippingMethod;
use Illuminate\Database\Eloquent\SoftDeletes;
class Order extends Model
@@ -31,6 +32,7 @@ class Order extends Model
'number',
'status',
'shipping_method',
'shipping_method_id',
'shipping_price',
'payment_type_id',
'notes',
@@ -85,4 +87,12 @@ class Order extends Model
{
return $this->belongsTo(PaymentType::class, 'payment_type_id');
}
/**
* Shipping method
*/
public function shippingMethod(): BelongsTo
{
return $this->belongsTo(OrderShippingMethod::class, 'shipping_method_id');
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace App\Models\Ecommerce\Product\Order\Shipping;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;
use Spatie\Translatable\HasTranslations;
class OrderShippingMethod extends Model
{
use HasFactory;
use HasSlug;
use HasTranslations;
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'order_shipping_methods';
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'slug',
'description',
'price',
'is_active',
];
/**
* Translatable fields
*
* @var array<int, string>
*/
public $translatable = [
'name',
'description',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'is_active' => 'boolean',
];
/**
* Get the options for generating the slug.
*/
public function getSlugOptions(): SlugOptions
{
return SlugOptions::create()
->generateSlugsFrom('name')
->saveSlugsTo('slug');
}
}

View File

@@ -73,7 +73,7 @@ class ExportOrderInvoiceAction extends Action
'created_at' => $order->created_at->format('H:i, d.m.Y'),
'order_shipping_method' => $order->formattedShippingMethod(),
'shipping_price' => $order->shipping_method === OrderShipping::SELF_PICKUP
'shipping_price' => ($order->shippingMethod && $order->shippingMethod->slug === 'self_pickup') || $order->shipping_method === OrderShipping::SELF_PICKUP
? 'Özüm baryp aljak'
: (string) $order->shippingPrice().' TMT',

View File

@@ -8,8 +8,11 @@ use App\Models\Ecommerce\Product\Order\Status\OrderStatus;
use App\Models\System\Settings\Location\Province;
use App\Models\System\Settings\Location\Region;
use App\Models\System\Settings\OS;
use App\Nova\Resources\Ecommerce\Product\Order\OrderShippingMethod;
use App\Models\Ecommerce\Product\Order\Shipping\OrderShippingMethod as OrderShippingMethodModel;
use App\Repositories\Ecommerce\Order\NovaOrderRepository;
use Illuminate\Support\Str;
use Laravel\Nova\Fields\BelongsTo;
use Laravel\Nova\Fields\Date;
use Laravel\Nova\Fields\Hidden;
use Laravel\Nova\Fields\ID;
@@ -62,18 +65,16 @@ class OrderFieldsForCreate
->options(OrderPayment::values())
->default(OrderPayment::default()),
Select::make(__('Shipping method'), 'shipping_method')
->displayUsingLabels()
->searchable()
->options(OrderShipping::values())
->default(OrderShipping::default())
->sortable(),
BelongsTo::make(__('Shipping method'), 'shippingMethod', OrderShippingMethod::class),
Text::make(__('Shipping price'), 'shipping_price')
->rules('required', 'numeric')
->dependsOn('shipping_method', function ($field, $request, $formData) {
if ($formData->shipping_method) {
$field->setValue(OrderShipping::priceFor($formData->shipping_method));
->dependsOn('shippingMethod', function ($field, $request, $formData) {
if ($formData->shippingMethod) {
$method = OrderShippingMethodModel::query()->find($formData->shippingMethod);
if ($method) {
$field->setValue($method->price);
}
}
}),

View File

@@ -7,7 +7,9 @@ use App\Models\Ecommerce\Product\Order\Status\OrderStatus;
use App\Models\System\Settings\Location\Region;
use App\Models\System\Settings\OS;
use App\Nova\Fields\FieldHelpers;
use App\Nova\Resources\Ecommerce\Product\Order\OrderShippingMethod;
use Laravel\Nova\Fields\Badge;
use Laravel\Nova\Fields\BelongsTo;
use Laravel\Nova\Fields\Date;
use Laravel\Nova\Fields\DateTime;
use Laravel\Nova\Fields\ID;
@@ -49,10 +51,7 @@ class OrderFieldsForIndex
->displayUsing(FieldHelpers::tmDate())
->sortable(),
Select::make(__('Shipping method'), 'shipping_method')
->displayUsingLabels()
->options(OrderShipping::values())
->default(OrderShipping::default())
BelongsTo::make(__('Shipping method'), 'shippingMethod', OrderShippingMethod::class)
->sortable(),
Select::make(__('Source'), 'source_app')

View File

@@ -7,7 +7,10 @@ use App\Models\Ecommerce\Product\Order\Shipping\OrderShipping;
use App\Models\Ecommerce\Product\Order\Status\OrderStatus;
use App\Models\System\Settings\Location\Province;
use App\Models\System\Settings\Location\Region;
use App\Nova\Resources\Ecommerce\Product\Order\OrderShippingMethod;
use App\Models\Ecommerce\Product\Order\Shipping\OrderShippingMethod as OrderShippingMethodModel;
use App\Repositories\Ecommerce\Order\NovaOrderRepository;
use Laravel\Nova\Fields\BelongsTo;
use Laravel\Nova\Fields\Date;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Select;
@@ -54,22 +57,16 @@ class OrderFieldsForUpdate
->options(OrderPayment::values())
->default(OrderPayment::default()),
Select::make(__('Shipping method'), 'shipping_method')
->displayUsingLabels()
->searchable()
->options(OrderShipping::values())
->default(OrderShipping::default())
->sortable(),
BelongsTo::make(__('Shipping method'), 'shippingMethod', OrderShippingMethod::class),
Text::make(__('Shipping price'), 'shipping_price')
->rules('required', 'numeric')
->dependsOn('shipping_method', function ($field, $request, $formData) use ($resource) {
if ($formData->shipping_price) {
return;
->dependsOn('shippingMethod', function ($field, $request, $formData) {
if ($formData->shippingMethod) {
$method = OrderShippingMethodModel::query()->find($formData->shippingMethod);
if ($method) {
$field->setValue($method->price);
}
if ($formData->shipping_method) {
$field->setValue(OrderShipping::orderShippingPrice($resource));
}
}),

View File

@@ -69,7 +69,7 @@ class Order extends Resource
*
* @var array
*/
public static $with = ['items'];
public static $with = ['items', 'shippingMethod'];
/**
* Indicates whether the resource should automatically poll for new resources.

View File

@@ -0,0 +1,84 @@
<?php
namespace App\Nova\Resources\Ecommerce\Product\Order;
use App\Models\Ecommerce\Product\Order\Shipping\OrderShippingMethod as OrderShippingMethodModel;
use App\Nova\Resource;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Number;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Fields\Textarea;
use Laravel\Nova\Http\Requests\NovaRequest;
use Trin4ik\NovaSwitcher\NovaSwitcher;
class OrderShippingMethod extends Resource
{
/**
* The model the resource corresponds to.
*
* @var class-string<OrderShippingMethodModel>
*/
public static $model = OrderShippingMethodModel::class;
/**
* The single value that should be used to represent the resource when being displayed.
*
* @var string
*/
public static $title = 'name';
/**
* The columns that should be searched.
*
* @var array
*/
public static $search = [
'id', 'name', 'slug',
];
/**
* Get the displayable label of the resource.
*/
public static function label(): string
{
return __('Shipping methods');
}
/**
* Get the displayable singular label of the resource.
*/
public static function singularLabel(): string
{
return __('Shipping method');
}
/**
* Get the fields displayed by the resource.
*/
public function fields(NovaRequest $request): array
{
return [
ID::make()->sortable(),
Text::make(__('Name'), 'name')
->translatable()
->rules('required', 'max:255'),
Text::make(__('Slug'), 'slug')
->hideWhenCreating()
->hideWhenUpdating()
->rules('nullable', 'string', 'max:255'),
Textarea::make(__('Description'), 'description')
->translatable()
->rules('nullable', 'max:1000'),
Number::make(__('Price'), 'price')
->step(0.01)
->rules('required', 'numeric', 'min:0'),
NovaSwitcher::make(__('Is active'), 'is_active')
->default(true),
];
}
}

View File

@@ -21,6 +21,7 @@ use App\Nova\Resources\Ecommerce\Product\Inventory\Inventory;
use App\Nova\Resources\Ecommerce\Product\Inventory\InventoryHistoryRemovedResource;
use App\Nova\Resources\Ecommerce\Product\Inventory\InventoryHistoryResource;
use App\Nova\Resources\Ecommerce\Product\Order\Order;
use App\Nova\Resources\Ecommerce\Product\Order\OrderShippingMethod;
use App\Nova\Resources\Ecommerce\Product\Product\Product;
use App\Nova\Resources\Ecommerce\Product\Review\Review;
use App\Nova\Resources\Legal\LegalPage;
@@ -211,6 +212,10 @@ class NovaServiceProvider extends NovaApplicationServiceProvider
MenuItem::resource(PaymentType::class),
])->collapsedByDefault(),
MenuGroup::make(__('Shipping methods'), [
MenuItem::resource(OrderShippingMethod::class),
])->collapsedByDefault(),
MenuGroup::make(__('App'), [
MenuItem::resource(AppVersion::class),
])->collapsedByDefault(),

View File

@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('order_shipping_methods', function (Blueprint $table) {
$table->id();
$table->json('name');
$table->string('slug')->unique();
$table->json('description')->nullable();
$table->string('price')->default(0);
$table->boolean('is_active')->default(true);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('order_shipping_methods');
}
};

View File

@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('orders', function (Blueprint $table) {
$table->foreignId('shipping_method_id')->nullable()->constrained('order_shipping_methods')->nullOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('orders', function (Blueprint $table) {
$table->dropForeign(['shipping_method_id']);
$table->dropColumn('shipping_method_id');
});
}
};

View File

@@ -2,9 +2,9 @@
namespace Database\Seeders;
use Illuminate\Support\Facades\File;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
class BrandTableSeeder extends Seeder
{

View File

@@ -3,9 +3,9 @@
namespace Database\Seeders;
use App\Models\Ecommerce\Channel\Channel;
use Illuminate\Support\Facades\File;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
class ChannelTableSeeder extends Seeder
{

View File

@@ -4,9 +4,9 @@ namespace Database\Seeders;
use App\Models\Legal\LegalPage;
use Exception;
use Illuminate\Support\Facades\File;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
class LegalPageTableSeeder extends Seeder
{

View File

@@ -0,0 +1,49 @@
<?php
namespace Database\Seeders;
use App\Models\Ecommerce\Product\Order\Shipping\OrderShippingMethod;
use Illuminate\Database\Seeder;
class OrderShippingMethodSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$methods = [
[
'slug' => 'standart',
'name' => ['en' => 'Standart', 'tk' => 'Standart', 'ru' => 'Стандарт'],
'price' => 20,
'is_active' => true,
],
[
'slug' => 'express',
'name' => ['en' => 'Express', 'tk' => 'Express', 'ru' => 'Экспресс'],
'price' => 30,
'is_active' => true,
],
[
'slug' => 'self_pickup',
'name' => ['en' => 'Self Pickup', 'tk' => 'Öz-özüňi almak', 'ru' => 'Самовывоз'],
'price' => 0,
'is_active' => true,
],
[
'slug' => 'region',
'name' => ['en' => 'Region', 'tk' => 'Welaýat', 'ru' => 'Регион'],
'price' => 40,
'is_active' => true,
],
];
foreach ($methods as $method) {
OrderShippingMethod::firstOrCreate(
['slug' => $method['slug']],
$method
);
}
}
}

View File

@@ -3,9 +3,9 @@
namespace Database\Seeders;
use Exception;
use Illuminate\Support\Facades\File;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
class ProvinceTableSeeder extends Seeder
{

View File

@@ -36,7 +36,7 @@ class UserTableSeeder extends Seeder
'last_name' => 'Admin',
'email' => 'admin@smartelektronika.com',
'password' => bcrypt('PuteraSeroja'),
]
],
])->each(function ($data) {
$user = User::create($data);

View File

@@ -1,4 +1,4 @@
<span class="link-default">
{{ $model->shipping_price ?: App\Models\Ecommerce\Product\Order\Shipping\OrderShipping::priceFor($model->shipping_method) }} TMT,
{{ App\Models\Ecommerce\Product\Order\Shipping\OrderShipping::formattedShippingMethod($model->shipping_method) }}
{{ $model->shippingPrice() }} TMT,
{{ $model->formattedShippingMethod() }}
</span>