wip
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace App\Nova\Resources\Ecommerce\Product\Order\Actions;
|
||||
|
||||
use App\Models\Ecommerce\Payouts\Payout;
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Nova\Actions\Action;
|
||||
use Laravel\Nova\Fields\ActionFields;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use PhpOffice\PhpWord\SimpleType\TblWidth;
|
||||
|
||||
class ExportEvidenceForProducts extends Action
|
||||
{
|
||||
use InteractsWithQueue, Queueable;
|
||||
|
||||
/**
|
||||
* The displayable name of the action.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public function name(): string
|
||||
{
|
||||
return __('Evidence for products');
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the action on the given models.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(ActionFields $fields, Collection $models)
|
||||
{
|
||||
$payout = $models->first();
|
||||
$orderItems = $payout->orderItems;
|
||||
$channel = $payout->channel;
|
||||
$user = $channel->user;
|
||||
|
||||
exec('rm -rf app-docs/*');
|
||||
|
||||
$documentsPath = 'app-docs/'.Str::random();
|
||||
exec("mkdir {$documentsPath}");
|
||||
|
||||
$this->generatePriceNegotiationDocument($user, $payout, $orderItems, $documentsPath);
|
||||
$this->generateEvidenceForProductsDocument($user, $payout, $orderItems, $documentsPath);
|
||||
|
||||
return Action::openInNewTab(route('user.docs', ['folder' => $documentsPath]));
|
||||
}
|
||||
|
||||
protected function generatePriceNegotiationDocument(User $user, Payout $payout, Collection $orderItems, string $folder): void
|
||||
{
|
||||
$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor(resource_path('docs/order/evidence-price-negotiation.docx'));
|
||||
$templateProcessor->setValues([
|
||||
'year' => date('Y'),
|
||||
'product_owner' => $user->companyName(),
|
||||
]);
|
||||
|
||||
$table = new \PhpOffice\PhpWord\Element\Table([
|
||||
'borderSize' => 2,
|
||||
'borderColor' => 'black',
|
||||
'width' => 5000,
|
||||
'width' => 6000,
|
||||
'unit' => TblWidth::TWIP,
|
||||
]);
|
||||
$table->addRow();
|
||||
$table->addCell()->addText('');
|
||||
$table->addCell()->addText('Harydyň ady');
|
||||
$table->addCell()->addText('Komitentiň satyş bahasy, manat');
|
||||
$table->addCell()->addText('Komissioneriň satyş bahasy, manat');
|
||||
|
||||
$i = 0;
|
||||
$total_cost_amount = 0;
|
||||
$total_unit_price_amount = 0;
|
||||
foreach ($orderItems as $orderItem) {
|
||||
$i++;
|
||||
$table->addRow();
|
||||
|
||||
$table->addCell()->addText($i);
|
||||
$table->addCell()->addText($orderItem->product_name);
|
||||
$table->addCell()->addText($orderItem->unit_cost_amount);
|
||||
$table->addCell()->addText($orderItem->unit_price_amount);
|
||||
|
||||
$total_cost_amount += $orderItem->unit_cost_amount;
|
||||
$total_unit_price_amount += $orderItem->unit_price_amount;
|
||||
}
|
||||
|
||||
$table->addRow();
|
||||
$table->addCell()->addText();
|
||||
$table->addCell()->addText('Jemi');
|
||||
$table->addCell()->addText($total_cost_amount);
|
||||
$table->addCell()->addText($total_unit_price_amount);
|
||||
|
||||
$templateProcessor->setComplexBlock('products_table', $table);
|
||||
|
||||
$documentPath = "{$folder}/hasaplashyk-{$payout->id}-{$user->companyName()}-baha-ylalashyk.docx";
|
||||
$templateProcessor->saveAs(public_path($documentPath));
|
||||
}
|
||||
|
||||
public function generateEvidenceForProductsDocument(User $user, Payout $payout, Collection $orderItems, string $folder): void
|
||||
{
|
||||
$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor(resource_path('docs/order/evidence.docx'));
|
||||
$templateProcessor->setValues([
|
||||
'date' => date('Y'),
|
||||
'o_date' => $payout->created_at->format('d.m.Y'),
|
||||
'product_owner' => $user->companyName(),
|
||||
]);
|
||||
|
||||
$table = new \PhpOffice\PhpWord\Element\Table([
|
||||
'borderSize' => 2,
|
||||
'borderColor' => 'black',
|
||||
'width' => 5000,
|
||||
'width' => 6000,
|
||||
'unit' => TblWidth::TWIP,
|
||||
]);
|
||||
$table->addRow();
|
||||
$table->addCell()->addText('No');
|
||||
$table->addCell()->addText('Harydyň ady');
|
||||
$table->addCell()->addText('Mukdary, san');
|
||||
$table->addCell()->addText('Biriniň bahasy, manat');
|
||||
$table->addCell()->addText('Jemi bahasy, manat');
|
||||
|
||||
$i = 0;
|
||||
$total_price = 0;
|
||||
foreach ($orderItems as $orderItem) {
|
||||
$i++;
|
||||
$table->addRow();
|
||||
|
||||
$table->addCell()->addText($i);
|
||||
$table->addCell()->addText($orderItem->product_name);
|
||||
$table->addCell()->addText($orderItem->quantity);
|
||||
$table->addCell()->addText($orderItem->unit_cost_amount);
|
||||
$table->addCell()->addText($orderItem->unit_cost_amount * $orderItem->quantity);
|
||||
|
||||
$total_price += $orderItem->unit_cost_amount * $orderItem->quantity;
|
||||
}
|
||||
|
||||
$table->addRow();
|
||||
$table->addCell()->addText('');
|
||||
$table->addCell()->addText('Jemi');
|
||||
$table->addCell()->addText($i);
|
||||
$table->addCell()->addText();
|
||||
$table->addCell()->addText($total_price);
|
||||
|
||||
$templateProcessor->setComplexBlock('products_table', $table);
|
||||
|
||||
$documentPath = "{$folder}/sargyt-{$payout->id}-{$user->companyName()}-delilnama.docx";
|
||||
$templateProcessor->saveAs(public_path($documentPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fields available on the action.
|
||||
*/
|
||||
public function fields(NovaRequest $request): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
namespace App\Nova\Resources\Ecommerce\Product\Order\Actions;
|
||||
|
||||
use App\Models\Ecommerce\Product\Order\Order;
|
||||
use App\Models\Ecommerce\Product\Order\Shipping\OrderShipping;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Support\Collection;
|
||||
use Laravel\Nova\Actions\Action;
|
||||
use Laravel\Nova\Actions\ActionResponse;
|
||||
use Laravel\Nova\Fields\ActionFields;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use PhpOffice\PhpWord\Element\Table;
|
||||
use PhpOffice\PhpWord\SimpleType\TblWidth;
|
||||
use PhpOffice\PhpWord\TemplateProcessor;
|
||||
|
||||
class ExportOrderInvoiceAction extends Action
|
||||
{
|
||||
use InteractsWithQueue, Queueable;
|
||||
|
||||
/**
|
||||
* The displayable name of the action.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public function name(): string
|
||||
{
|
||||
return __('Invoice');
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the action on the given models.
|
||||
*/
|
||||
public function handle(ActionFields $fields, Collection $models): mixed
|
||||
{
|
||||
if ($models->count() !== 1) {
|
||||
return Action::danger(
|
||||
__('Please run this on only one user resource')
|
||||
);
|
||||
}
|
||||
|
||||
$order = $models->first();
|
||||
$products = $order
|
||||
->items()
|
||||
->with(['channel', 'product'])
|
||||
->get();
|
||||
|
||||
$documentPath = $this->generateDocument(
|
||||
order: $order,
|
||||
products: $products,
|
||||
templatePath: resource_path('docs/order/invoice.docx'),
|
||||
productsTotal: $products->sum('total')
|
||||
);
|
||||
|
||||
return ActionResponse::download(
|
||||
name: sprintf('sargyt-%s.docx', $order->id),
|
||||
url: url($documentPath)
|
||||
);
|
||||
}
|
||||
|
||||
private function generateDocument(
|
||||
Order $order,
|
||||
Collection $products,
|
||||
string $templatePath,
|
||||
float $productsTotal
|
||||
): string {
|
||||
$templateProcessor = new TemplateProcessor($templatePath);
|
||||
|
||||
$templateProcessor->setValues([
|
||||
'id' => $order->id,
|
||||
'payment_type' => $order->formattedPaymentType(),
|
||||
'created_at' => $order->created_at->format('H:i, d.m.Y'),
|
||||
'order_shipping_method' => $order->formattedShippingMethod(),
|
||||
|
||||
'shipping_price' => $order->shipping_method === OrderShipping::SELF_PICKUP
|
||||
? 'Özüm baryp aljak'
|
||||
: (string) $order->shippingPrice().' TMT',
|
||||
|
||||
'order_name' => $order->customer_name,
|
||||
'order_address' => $order->fullAddress(),
|
||||
'order_phone' => $order->customer_phone,
|
||||
'p_t' => $productsTotal,
|
||||
't' => $productsTotal + $order->shippingPrice(),
|
||||
'notes' => $order->notes,
|
||||
'adt_tax' => $order->additional_tax ?: '0.0',
|
||||
]);
|
||||
|
||||
$table = $this->generateTable($products);
|
||||
$templateProcessor->setComplexBlock('products_table', $table);
|
||||
|
||||
$documentPath = public_path(
|
||||
sprintf('app-docs/sargyt-%s.docx', $order->id)
|
||||
);
|
||||
$templateProcessor->saveAs($documentPath);
|
||||
|
||||
return sprintf('app-docs/sargyt-%s.docx', $order->id);
|
||||
}
|
||||
|
||||
private function generateTable(Collection $products): Table
|
||||
{
|
||||
$table = new Table([
|
||||
'borderSize' => 2,
|
||||
'borderColor' => 'black',
|
||||
'width' => 5000,
|
||||
'unit' => TblWidth::PERCENT,
|
||||
]);
|
||||
|
||||
$table->addRow();
|
||||
$table->addCell()->addText('№');
|
||||
$table->addCell()->addText('HARYDYŇ ADY');
|
||||
$table->addCell()->addText('BAHASY');
|
||||
$table->addCell()->addText('SATYJY');
|
||||
$table->addCell()->addText('MUKDARY');
|
||||
$table->addCell()->addText('ARZANLADYŞ');
|
||||
$table->addCell()->addText('JEMI BAHASY');
|
||||
|
||||
$products->each(function ($product, $index) use ($table) {
|
||||
$table->addRow();
|
||||
$table->addCell()->addText($index + 1);
|
||||
$table->addCell()->addText($product->product->name);
|
||||
$table->addCell()->addText($product->unit_price_amount);
|
||||
$table
|
||||
->addCell()
|
||||
->addText($product->channel?->name ?? 'Türkmenpoçta PAK');
|
||||
$table->addCell()->addText($product->quantity);
|
||||
$table
|
||||
->addCell()
|
||||
->addText(
|
||||
$product->product->caluculateDiscountDifference(
|
||||
$product->unit_price_amount
|
||||
)
|
||||
);
|
||||
$table
|
||||
->addCell()
|
||||
->addText($product->quantity * $product->unit_price_amount);
|
||||
});
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fields available on the action.
|
||||
*/
|
||||
public function fields(NovaRequest $request): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Nova\Resources\Ecommerce\Product\Order\Actions;
|
||||
|
||||
use App\Exports\Ecommerce\Product\Order\ExportOrderReport;
|
||||
use App\Nova\Fields\FieldHelpers;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Laravel\Nova\Actions\Action;
|
||||
use Laravel\Nova\Fields\ActionFields;
|
||||
use Laravel\Nova\Fields\Date;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
class ExportOrderReportAction extends Action
|
||||
{
|
||||
use InteractsWithQueue, Queueable;
|
||||
|
||||
/**
|
||||
* Get the displayable name of the action.
|
||||
*/
|
||||
public function name(): string
|
||||
{
|
||||
return __('Export Order Report');
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the action on the given models.
|
||||
*/
|
||||
public function handle(ActionFields $fields, Collection $models): mixed
|
||||
{
|
||||
$start_date = Carbon::createFromFormat('Y-m-d', $fields->start_date)->format('d.m.Y');
|
||||
$end_date = Carbon::createFromFormat('Y-m-d', $fields->end_date)->format('d.m.Y');
|
||||
|
||||
(new ExportOrderReport(
|
||||
start_date: $fields->start_date,
|
||||
end_date: $fields->end_date
|
||||
))->store('order-reports.xlsx', 'order_reports');
|
||||
|
||||
return Action::download(
|
||||
url: Storage::disk('order_reports')->url('order-reports.xlsx'),
|
||||
name: sprintf('Hasabat %s - %s.xlsx', $start_date, $end_date)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fields available on the action.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function fields(NovaRequest $request)
|
||||
{
|
||||
return [
|
||||
Date::make(__('Start date'), 'start_date')
|
||||
->rules('required')
|
||||
->displayUsing(FieldHelpers::tmDate()),
|
||||
|
||||
Date::make(__('End date'), 'end_date')
|
||||
->rules('required')
|
||||
->displayUsing(FieldHelpers::tmDate()),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Nova\Resources\Ecommerce\Product\Order\Concerns;
|
||||
|
||||
use App\Models\Ecommerce\Product\Order\Shipping\OrderShipping;
|
||||
use App\Models\Ecommerce\Product\Order\Status\OrderStatus;
|
||||
use App\Models\System\Settings\Location\Region;
|
||||
use App\Nova\Fields\FieldHelpers;
|
||||
use Laravel\Nova\Fields\Badge;
|
||||
use Laravel\Nova\Fields\Date;
|
||||
use Laravel\Nova\Fields\ID;
|
||||
use Laravel\Nova\Fields\Select;
|
||||
use Laravel\Nova\Fields\Text;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
trait HasFieldsForIndex
|
||||
{
|
||||
/**
|
||||
* Get the fields displayed by the resource.
|
||||
*/
|
||||
public function fieldsForIndex(NovaRequest $request): array
|
||||
{
|
||||
return [
|
||||
ID::make()->sortable(),
|
||||
|
||||
Text::make(__('Customer'), 'customer_name')
|
||||
->canSeeWhen('systemUser', $this)
|
||||
->sortable(),
|
||||
|
||||
Text::make(__('Phone'), 'customer_phone')
|
||||
->canSeeWhen('systemUser', $this)
|
||||
->sortable(),
|
||||
|
||||
Select::make(__('Welaýat'), 'region')
|
||||
->displayUsingLabels()
|
||||
->options(Region::values())
|
||||
->canSeeWhen('systemUser', $this)
|
||||
->sortable(),
|
||||
|
||||
Select::make(__('Delivery time'), 'delivery_time')
|
||||
->displayUsingLabels()
|
||||
->searchable()
|
||||
->options(OrderShipping::times())
|
||||
->rules('required')
|
||||
->sortable(),
|
||||
|
||||
Date::make(__('Delivery date'), 'delivery_at')
|
||||
->displayUsing(FieldHelpers::tmDate())
|
||||
->sortable(),
|
||||
|
||||
Text::make(__('Total'), fn () => $this->resource->fullPriceWithShipping().' TMT')
|
||||
->canSeeWhen('systemUser', $this)
|
||||
->sortable(),
|
||||
|
||||
Badge::make('Status')->map(OrderStatus::classes())->addTypes([
|
||||
'primary' => 'dark:bg-gray-900 bg-gray-600 text-white',
|
||||
])->labels(OrderStatus::values())->sortable(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace App\Nova\Resources\Ecommerce\Product\Order\Concerns;
|
||||
|
||||
use App\Models\Ecommerce\Product\Order\Payment\OrderPayment;
|
||||
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\Models\System\Settings\OS;
|
||||
use App\Repositories\Ecommerce\Order\NovaOrderRepository;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Nova\Fields\Date;
|
||||
use Laravel\Nova\Fields\Hidden;
|
||||
use Laravel\Nova\Fields\ID;
|
||||
use Laravel\Nova\Fields\Select;
|
||||
use Laravel\Nova\Fields\Text;
|
||||
use Nurmuhammet\NovaInputmask\NovaInputmask;
|
||||
|
||||
class OrderFieldsForCreate
|
||||
{
|
||||
/**
|
||||
* Order fields for create
|
||||
*/
|
||||
public static function make($resource, $request): array
|
||||
{
|
||||
return [
|
||||
Hidden::make('number')->default(Str::random(30)),
|
||||
Hidden::make('user_id')->default($request->user()->id),
|
||||
Hidden::make('source_app')->default(OS::ADMIN),
|
||||
|
||||
ID::make(),
|
||||
|
||||
Text::make(__('Customer name'), 'customer_name')
|
||||
->rules('nullable', 'string', 'max:255')
|
||||
->canSeeWhen('systemUser', $resource)
|
||||
->default('Walk in customer'),
|
||||
|
||||
NovaInputmask::make(__('Customer phone'), 'customer_phone')
|
||||
->mask(phoneMaskFormat())
|
||||
->storeRawValue()
|
||||
->canSeeWhen('systemUser', $resource),
|
||||
|
||||
Select::make(__('Region'), 'region')
|
||||
->displayUsingLabels()
|
||||
->searchable()
|
||||
->options(Region::values())
|
||||
->default(Region::default())
|
||||
->canSeeWhen('systemUser', $resource),
|
||||
|
||||
Select::make(__('Province'), 'province_id')
|
||||
->displayUsingLabels()
|
||||
->searchable()
|
||||
->dependsOn(['region'], NovaOrderRepository::dependsOnWhere('region', Province::class)),
|
||||
|
||||
Text::make(__('Customer address'), 'customer_address')
|
||||
->rules('nullable', 'string', 'max:255'),
|
||||
|
||||
Select::make(__('Payment type'), 'payment_type_id')
|
||||
->displayUsingLabels()
|
||||
->searchable()
|
||||
->options(OrderPayment::values())
|
||||
->default(OrderPayment::default()),
|
||||
|
||||
Select::make(__('Shipping method'), 'shipping_method')
|
||||
->displayUsingLabels()
|
||||
->searchable()
|
||||
->options(OrderShipping::values())
|
||||
->default(OrderShipping::default())
|
||||
->sortable(),
|
||||
|
||||
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));
|
||||
}
|
||||
}),
|
||||
|
||||
Date::make(__('Delivery at'), 'delivery_at')
|
||||
->default(date('Y-m-d'))
|
||||
->rules('required'),
|
||||
|
||||
Select::make(__('Delivery time'), 'delivery_time')
|
||||
->displayUsingLabels()
|
||||
->searchable()
|
||||
->options(OrderShipping::times())
|
||||
->default(OrderShipping::defaultTime()),
|
||||
|
||||
Text::make(__('Additional tax'), 'additional_tax')
|
||||
->rules('nullable', 'numeric'),
|
||||
|
||||
Select::make(__('Status'), 'status')
|
||||
->displayUsingLabels()
|
||||
->searchable()
|
||||
->options(OrderStatus::values())
|
||||
->default(OrderStatus::default()),
|
||||
|
||||
Text::make(__('Notes'), 'notes')
|
||||
->rules('nullable', 'string', 'max:255'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace App\Nova\Resources\Ecommerce\Product\Order\Concerns;
|
||||
|
||||
use App\Models\Ecommerce\Product\Order\Status\OrderStatus;
|
||||
use App\Models\System\Settings\OS;
|
||||
use App\Nova\Resources\Ecommerce\Product\Order\OrderItem;
|
||||
use App\Nova\Resources\System\Payments\PaymentType;
|
||||
use App\Nova\User;
|
||||
use Laravel\Nova\Fields\Badge;
|
||||
use Laravel\Nova\Fields\BelongsTo;
|
||||
use Laravel\Nova\Fields\DateTime;
|
||||
use Laravel\Nova\Fields\HasMany;
|
||||
use Laravel\Nova\Fields\ID;
|
||||
use Laravel\Nova\Fields\Select;
|
||||
use Laravel\Nova\Fields\Text;
|
||||
use Nurmuhammet\NovaInputmask\NovaInputmask;
|
||||
|
||||
class OrderFieldsForDetail
|
||||
{
|
||||
/**
|
||||
* Order fields for detail
|
||||
*/
|
||||
public static function make($resource, $request): array
|
||||
{
|
||||
// nova has a wierd bug, can load detail fields while on Index
|
||||
if (! $request->isResourceDetailRequest()) {
|
||||
if ($request->viaResource && $request->viaRelationship && $request->relationshipType) {
|
||||
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
ID::make()->sortable(),
|
||||
|
||||
Text::make(__('Customer name'), 'customer_name'),
|
||||
|
||||
NovaInputmask::make(__('Customer phone'), 'customer_phone')
|
||||
->mask(phoneMaskFormat())
|
||||
->storeRawValue(),
|
||||
|
||||
Text::make(
|
||||
name: __('Address'),
|
||||
attribute: fn ($model) => view('vendor.nova.resources.order.create-fields.address', [
|
||||
'model' => $model,
|
||||
])->render()
|
||||
)
|
||||
->asHtml(),
|
||||
|
||||
BelongsTo::make(__('Payment type'), 'paymentType', PaymentType::class),
|
||||
|
||||
Text::make(
|
||||
name: __('Shipping'),
|
||||
attribute: fn ($model) => view('vendor.nova.resources.order.create-fields.shipping', [
|
||||
'model' => $model,
|
||||
])->render()
|
||||
)
|
||||
->asHtml(),
|
||||
|
||||
Text::make(
|
||||
name: __('Shipping time'),
|
||||
attribute: fn ($model) => view('vendor.nova.resources.order.create-fields.shipping-time', [
|
||||
'model' => $model,
|
||||
])->render()
|
||||
)
|
||||
->asHtml(),
|
||||
|
||||
Select::make(__('App'), 'source_app')
|
||||
->displayUsingLabels()
|
||||
->options(OS::apps())
|
||||
->sortable(),
|
||||
|
||||
Badge::make('Status')->map(OrderStatus::classes())->addTypes([
|
||||
'primary' => 'dark:bg-gray-900 bg-gray-600 text-white',
|
||||
])->labels(OrderStatus::values())->sortable(),
|
||||
|
||||
Text::make(__('Notes'), 'notes'),
|
||||
|
||||
Text::make(__('Additional tax'), fn () => $resource->additional_tax.' TMT')
|
||||
->canSeeWhen('systemUser', $resource),
|
||||
|
||||
Text::make(__('Products total'), fn () => $resource->total().' TMT')
|
||||
->canSeeWhen('systemUser', $resource),
|
||||
|
||||
Text::make(__('Total'), fn () => $resource->fullPriceWithShipping().' TMT')
|
||||
->canSeeWhen('systemUser', $resource),
|
||||
|
||||
DateTime::make(__('Created at'), 'created_at')
|
||||
->turkmenDate(),
|
||||
|
||||
BelongsTo::make(__('Filled by:'), 'user', User::class),
|
||||
|
||||
HasMany::make(__('Products'), 'items', OrderItem::class),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace App\Nova\Resources\Ecommerce\Product\Order\Concerns;
|
||||
|
||||
use App\Models\Ecommerce\Product\Order\Shipping\OrderShipping;
|
||||
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 Laravel\Nova\Fields\Badge;
|
||||
use Laravel\Nova\Fields\Date;
|
||||
use Laravel\Nova\Fields\DateTime;
|
||||
use Laravel\Nova\Fields\ID;
|
||||
use Laravel\Nova\Fields\Select;
|
||||
use Laravel\Nova\Fields\Text;
|
||||
use Nurmuhammet\NovaInputmask\NovaInputmask;
|
||||
|
||||
class OrderFieldsForIndex
|
||||
{
|
||||
/**
|
||||
* Fields for index
|
||||
*/
|
||||
public static function make($resource, $request): array
|
||||
{
|
||||
return [
|
||||
ID::make()->sortable(),
|
||||
|
||||
Text::make(__('Customer'), 'customer_name')
|
||||
->sortable(),
|
||||
|
||||
NovaInputmask::make(__('Customer phone'), 'customer_phone')
|
||||
->mask(phoneMaskFormat())
|
||||
->storeRawValue()
|
||||
->sortable(),
|
||||
|
||||
Select::make(__('Welaýat'), 'region')
|
||||
->displayUsingLabels()
|
||||
->options(Region::values())
|
||||
->sortable(),
|
||||
|
||||
Select::make(__('Delivery time'), 'delivery_time')
|
||||
->displayUsingLabels()
|
||||
->searchable()
|
||||
->options(OrderShipping::times())
|
||||
->rules('required')
|
||||
->sortable(),
|
||||
|
||||
Date::make(__('Delivery date'), 'delivery_at')
|
||||
->displayUsing(FieldHelpers::tmDate())
|
||||
->sortable(),
|
||||
|
||||
Select::make(__('Shipping method'), 'shipping_method')
|
||||
->displayUsingLabels()
|
||||
->options(OrderShipping::values())
|
||||
->default(OrderShipping::default())
|
||||
->sortable(),
|
||||
|
||||
Select::make(__('Source'), 'source_app')
|
||||
->displayUsingLabels()
|
||||
->options(OS::apps())
|
||||
->sortable(),
|
||||
|
||||
Text::make(__('Total'), fn () => $resource->fullPriceWithShipping().' TMT')
|
||||
->canSeeWhen('systemUser', $resource)
|
||||
->sortable(),
|
||||
|
||||
DateTime::make(__('Created at'), 'created_at')
|
||||
->turkmenDate(),
|
||||
|
||||
Badge::make('Status')
|
||||
->map(OrderStatus::classes())
|
||||
->labels(OrderStatus::values())
|
||||
->addTypes([
|
||||
'primary' => 'dark:bg-gray-900 bg-gray-600 text-white',
|
||||
])
|
||||
->sortable(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace App\Nova\Resources\Ecommerce\Product\Order\Concerns;
|
||||
|
||||
use App\Models\Ecommerce\Product\Order\Payment\OrderPayment;
|
||||
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\Repositories\Ecommerce\Order\NovaOrderRepository;
|
||||
use Laravel\Nova\Fields\Date;
|
||||
use Laravel\Nova\Fields\ID;
|
||||
use Laravel\Nova\Fields\Select;
|
||||
use Laravel\Nova\Fields\Text;
|
||||
use Nurmuhammet\NovaInputmask\NovaInputmask;
|
||||
|
||||
class OrderFieldsForUpdate
|
||||
{
|
||||
/**
|
||||
* Order
|
||||
*/
|
||||
public static function make($resource, $request): array
|
||||
{
|
||||
return [
|
||||
ID::make()->sortable(),
|
||||
|
||||
Text::make(__('Customer name'), 'customer_name')
|
||||
->rules('nullable', 'string', 'max:255')
|
||||
->canSeeWhen('systemUser', $resource),
|
||||
|
||||
NovaInputmask::make(__('Customer phone'), 'customer_phone')
|
||||
->mask(phoneMaskFormat())
|
||||
->storeRawValue()
|
||||
->canSeeWhen('systemUser', $resource),
|
||||
|
||||
Select::make(__('Region'), 'region')
|
||||
->displayUsingLabels()
|
||||
->searchable()
|
||||
->options(Region::values())
|
||||
->default(Region::default())
|
||||
->canSeeWhen('systemUser', $resource),
|
||||
|
||||
Select::make(__('Province'), 'province_id')
|
||||
->displayUsingLabels()
|
||||
->searchable()
|
||||
->dependsOn(['region'], NovaOrderRepository::dependsOnWhere('region', Province::class)),
|
||||
|
||||
Text::make(__('Customer address'), 'customer_address')
|
||||
->rules('nullable', 'string', 'max:255'),
|
||||
|
||||
Select::make(__('Payment type'), 'payment_type_id')
|
||||
->displayUsingLabels()
|
||||
->searchable()
|
||||
->options(OrderPayment::values())
|
||||
->default(OrderPayment::default()),
|
||||
|
||||
Select::make(__('Shipping method'), 'shipping_method')
|
||||
->displayUsingLabels()
|
||||
->searchable()
|
||||
->options(OrderShipping::values())
|
||||
->default(OrderShipping::default())
|
||||
->sortable(),
|
||||
|
||||
Text::make(__('Shipping price'), 'shipping_price')
|
||||
->rules('required', 'numeric')
|
||||
->dependsOn('shipping_method', function ($field, $request, $formData) use ($resource) {
|
||||
if ($formData->shipping_price) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($formData->shipping_method) {
|
||||
$field->setValue(OrderShipping::orderShippingPrice($resource));
|
||||
}
|
||||
}),
|
||||
|
||||
Text::make(__('Additional tax'), 'additional_tax')
|
||||
->rules('nullable', 'numeric'),
|
||||
|
||||
Date::make(__('Delivery at'), 'delivery_at')
|
||||
->default(date('Y-m-d'))
|
||||
->rules('required'),
|
||||
|
||||
Select::make(__('Delivery time'), 'delivery_time')
|
||||
->displayUsingLabels()
|
||||
->searchable()
|
||||
->options(OrderShipping::times())
|
||||
->default(OrderShipping::defaultTime()),
|
||||
|
||||
Select::make(__('Status'), 'status')
|
||||
->displayUsingLabels()
|
||||
->searchable()
|
||||
->options(OrderStatus::values())
|
||||
->default(OrderStatus::default()),
|
||||
|
||||
Text::make(__('Notes'), 'notes')
|
||||
->rules('nullable', 'string', 'max:255'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Nova\Resources\Ecommerce\Product\Order\Metrics;
|
||||
|
||||
use App\Models\Ecommerce\Product\Order\Order;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Metrics\Value;
|
||||
|
||||
class NewOrders extends Value
|
||||
{
|
||||
/**
|
||||
* Calculate the value of the metric.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function calculate(NovaRequest $request)
|
||||
{
|
||||
if ($request->user()->hasRole('vendor')) {
|
||||
$channel = $request->user()->channel();
|
||||
|
||||
$vendor_orders = DB::table('order_items')->where('channel_id', $channel->id)->pluck('order_id');
|
||||
|
||||
return $this->count($request, Order::whereIntegerInRaw('id', $vendor_orders));
|
||||
}
|
||||
|
||||
return $this->count($request, Order::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ranges available for the metric.
|
||||
*/
|
||||
public function ranges(): array
|
||||
{
|
||||
return [
|
||||
'TODAY' => __('Today'),
|
||||
30 => __('30 Days'),
|
||||
60 => __('60 Days'),
|
||||
365 => __('365 Days'),
|
||||
'MTD' => __('Month To Date'),
|
||||
'QTD' => __('Quarter To Date'),
|
||||
'YTD' => __('Year To Date'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the amount of time the results of the metric should be cached.
|
||||
*
|
||||
* @return \DateTimeInterface|\DateInterval|float|int|null
|
||||
*/
|
||||
public function cacheFor()
|
||||
{
|
||||
return now()->addMinutes(5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URI key for the metric.
|
||||
*/
|
||||
public function uriKey(): string
|
||||
{
|
||||
return 'orders-new-orders';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the displayable name of the metric
|
||||
*/
|
||||
public function name(): string
|
||||
{
|
||||
return __('Orders');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Nova\Resources\Ecommerce\Product\Order\Metrics;
|
||||
|
||||
use App\Models\Ecommerce\Product\Order\Order;
|
||||
use App\Models\Ecommerce\Product\Order\Status\OrderStatus;
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Metrics\Partition;
|
||||
|
||||
class OrdersPerStatus extends Partition
|
||||
{
|
||||
/**
|
||||
* Calculate the value of the metric.
|
||||
*/
|
||||
public function calculate(NovaRequest $request): mixed
|
||||
{
|
||||
$model = Order::class;
|
||||
|
||||
if ($request->user()->hasRole('vendor')) {
|
||||
$channel = $request->user()->channel();
|
||||
$vendor_orders = DB::table('order_items')->where('channel_id', $channel->id)->pluck('order_id');
|
||||
|
||||
$model = Order::whereIntegerInRaw('id', $vendor_orders);
|
||||
}
|
||||
|
||||
return $this->count($request, $model, 'status')
|
||||
->colors(OrderStatus::colors())
|
||||
->label(fn ($value) => OrderStatus::formattedStatusFor($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the amount of time the results of the metric should be cached.
|
||||
*
|
||||
* @return \DateTimeInterface|\DateInterval|float|int|null
|
||||
*/
|
||||
public function cacheFor(): DateTimeInterface|DateInterval|float|int|null
|
||||
{
|
||||
return now()->addMinutes(5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URI key for the metric.
|
||||
*/
|
||||
public function uriKey(): string
|
||||
{
|
||||
return 'orders-orders-per-status';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the displayable name of the metric
|
||||
*/
|
||||
public function name(): string
|
||||
{
|
||||
return __('Order Per Status');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace App\Nova\Resources\Ecommerce\Product\Order\Metrics;
|
||||
|
||||
use App\Models\Ecommerce\Product\Order\OrderItem;
|
||||
use DateTimeInterface;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Metrics\Trend;
|
||||
|
||||
class ProductSoldPerDay extends Trend
|
||||
{
|
||||
/**
|
||||
* Calculate the value of the metric.
|
||||
*/
|
||||
public function calculate(NovaRequest $request): mixed
|
||||
{
|
||||
if ($request->user()->hasRole('vendor')) {
|
||||
$channel = $request->user()->channel();
|
||||
|
||||
return $this->countByDays($request, OrderItem::where('channel_id', $channel->id))->showLatestValue();
|
||||
}
|
||||
|
||||
return $this->countByDays($request, OrderItem::class)->showLatestValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ranges available for the metric.
|
||||
*/
|
||||
public function ranges(): array
|
||||
{
|
||||
return [
|
||||
30 => __('30 Days'),
|
||||
60 => __('60 Days'),
|
||||
90 => __('90 Days'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the amount of time the results of the metric should be cached.
|
||||
*
|
||||
* @return \DateTimeInterface|\DateInterval|float|int|null
|
||||
*/
|
||||
public function cacheFor(): DateTimeInterface|DateInterval|float|int|null
|
||||
{
|
||||
return now()->addMinutes(5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URI key for the metric.
|
||||
*/
|
||||
public function uriKey(): string
|
||||
{
|
||||
return 'orders-product-sold-per-day';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the displayable name of the metric
|
||||
*/
|
||||
public function name(): string
|
||||
{
|
||||
return __('Product Sold Per Day');
|
||||
}
|
||||
}
|
||||
214
app/Nova/Resources/Ecommerce/Product/Order/Order.php
Normal file
214
app/Nova/Resources/Ecommerce/Product/Order/Order.php
Normal file
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
namespace App\Nova\Resources\Ecommerce\Product\Order;
|
||||
|
||||
use App\Models\Ecommerce\Product\Order\Order as OrderModel;
|
||||
use App\Models\Ecommerce\Product\Order\Status\OrderStatus;
|
||||
use App\Nova\Filters\RegionFilter;
|
||||
use App\Nova\Filters\StatusFilter;
|
||||
use App\Nova\Resource;
|
||||
use App\Nova\Resources\Ecommerce\Product\Order\Actions\ExportOrderInvoiceAction;
|
||||
use App\Nova\Resources\Ecommerce\Product\Order\Actions\ExportOrderReportAction;
|
||||
use App\Nova\Resources\Ecommerce\Product\Order\Concerns\OrderFieldsForCreate;
|
||||
use App\Nova\Resources\Ecommerce\Product\Order\Concerns\OrderFieldsForDetail;
|
||||
use App\Nova\Resources\Ecommerce\Product\Order\Concerns\OrderFieldsForIndex;
|
||||
use App\Nova\Resources\Ecommerce\Product\Order\Concerns\OrderFieldsForUpdate;
|
||||
use App\Repositories\CMS\Icon\IconRepository;
|
||||
use DigitalCreative\ColumnToggler\ColumnTogglerTrait;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Laravel\Nova\Fields\HasMany;
|
||||
use Laravel\Nova\Fields\ID;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
class Order extends Resource
|
||||
{
|
||||
use ColumnTogglerTrait;
|
||||
|
||||
/**
|
||||
* The model the resource corresponds to.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $model = OrderModel::class;
|
||||
|
||||
/**
|
||||
* The single value that should be used to represent the resource when being displayed.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $title = 'id';
|
||||
|
||||
/**
|
||||
* The columns that should be searched.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $search = [
|
||||
'id', 'customer_name', 'customer_phone',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the displayable label of the resource.
|
||||
*/
|
||||
public static function label(): string
|
||||
{
|
||||
return __('Orders');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the displayable singular label of the resource.
|
||||
*/
|
||||
public static function singularLabel(): string
|
||||
{
|
||||
return __('Order');
|
||||
}
|
||||
|
||||
/**
|
||||
* The relationships that should be eager loaded on index queries.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $with = ['items'];
|
||||
|
||||
/**
|
||||
* Indicates whether the resource should automatically poll for new resources.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $polling = true;
|
||||
|
||||
/**
|
||||
* The interval at which Nova should poll for new resources.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public static $pollingInterval = 120;
|
||||
|
||||
/**
|
||||
* Indicates whether to show the polling toggle button inside Nova.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $showPollingToggle = true;
|
||||
|
||||
/**
|
||||
* Build an "index" query for the given resource.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public static function indexQuery(NovaRequest $request, $query)
|
||||
{
|
||||
$user = $request->user();
|
||||
|
||||
if ($user->hasRole('vendor')) {
|
||||
$order_ids = DB::table('order_items')->where('channel_id', $user->channel()->id)->distinct()->pluck('order_id');
|
||||
|
||||
$query->whereIntegerInRaw('id', $order_ids);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* After order was updated
|
||||
*/
|
||||
public static function afterUpdate(NovaRequest $request, Model $model): void
|
||||
{
|
||||
if ($model->status === OrderStatus::CANCELLED) {
|
||||
$orderItems = $model->items()->with('product')->get(['id', 'product_id', 'order_id', 'quantity']);
|
||||
|
||||
$orderItems->each(function ($item) {
|
||||
$item->product->update([
|
||||
'stock' => intval($item->product->stock) + intval($item->quantity),
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fields for index.
|
||||
*/
|
||||
public function fieldsForIndex(NovaRequest $request): array
|
||||
{
|
||||
return OrderFieldsForIndex::make($this, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fields for create.
|
||||
*/
|
||||
public function fieldsForCreate(NovaRequest $request): array
|
||||
{
|
||||
return OrderFieldsForCreate::make($this, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fields displayed by the resource on detail page.
|
||||
*/
|
||||
public function fieldsForDetail(NovaRequest $request): array
|
||||
{
|
||||
return OrderFieldsForDetail::make($this, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fields displayed by the resource on detail page.
|
||||
*/
|
||||
public function fieldsForUpdate(NovaRequest $request): array
|
||||
{
|
||||
return OrderFieldsForUpdate::make($this, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fields displayed by the resource.
|
||||
*/
|
||||
public function fields(NovaRequest $request): array
|
||||
{
|
||||
return [
|
||||
ID::make()->sortable(),
|
||||
HasMany::make(__('Products'), 'items', OrderItem::class),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the actions available for the resource.
|
||||
*/
|
||||
public function actions(NovaRequest $request): array
|
||||
{
|
||||
return [
|
||||
ExportOrderReportAction::make()
|
||||
->standalone()
|
||||
->canSeeWhen('isAdmin', $this)
|
||||
->onlyOnIndex()
|
||||
->icon(IconRepository::make()->documentReport()),
|
||||
|
||||
ExportOrderInvoiceAction::make()
|
||||
->confirmText(__('Are you sure you want to run this action?'))
|
||||
->confirmButtonText(__('Yes'))
|
||||
->cancelButtonText(__('No'))
|
||||
->exceptOnIndex()
|
||||
->icon(IconRepository::make()->documentDownload()),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filters available for the resource.
|
||||
*/
|
||||
public function filters(NovaRequest $request): array
|
||||
{
|
||||
return [
|
||||
RegionFilter::make(),
|
||||
StatusFilter::make(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lenses available for the resource.
|
||||
*/
|
||||
public function lenses(NovaRequest $request): array
|
||||
{
|
||||
return [
|
||||
|
||||
];
|
||||
}
|
||||
}
|
||||
173
app/Nova/Resources/Ecommerce/Product/Order/OrderItem.php
Normal file
173
app/Nova/Resources/Ecommerce/Product/Order/OrderItem.php
Normal file
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
namespace App\Nova\Resources\Ecommerce\Product\Order;
|
||||
|
||||
use App\Models\Ecommerce\Product\Order\OrderItem as OrderItemModel;
|
||||
use App\Nova\Resource;
|
||||
use App\Nova\Resources\Ecommerce\Product\Order\OrderItem\OrderItemFieldsForCreate;
|
||||
use App\Nova\Resources\Ecommerce\Product\Order\OrderItem\OrderItemFieldsForIndex;
|
||||
use App\Nova\Resources\Ecommerce\Product\Order\OrderItem\OrderItemFieldsForUpdate;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Laravel\Nova\Fields\BelongsTo;
|
||||
use Laravel\Nova\Fields\ID;
|
||||
use Laravel\Nova\Fields\Text;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
class OrderItem extends Resource
|
||||
{
|
||||
/**
|
||||
* The model the resource corresponds to.
|
||||
*
|
||||
* @var class-string<OrderItemModel>
|
||||
*/
|
||||
public static $model = OrderItemModel::class;
|
||||
|
||||
/**
|
||||
* The single value that should be used to represent the resource when being displayed.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $title = 'id';
|
||||
|
||||
/**
|
||||
* The columns that should be searched.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $search = [
|
||||
'id',
|
||||
];
|
||||
|
||||
/**
|
||||
* The relationships that should be eager loaded on index queries.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
// public static $with = ['product', 'product.media'];
|
||||
|
||||
/**
|
||||
* The number of resources to show per page via relationships.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public static $perPageViaRelationship = 20;
|
||||
|
||||
/**
|
||||
* Build an "index" query for the given resource.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
*/
|
||||
public static function indexQuery(NovaRequest $request, $query): Builder
|
||||
{
|
||||
$user = $request->user();
|
||||
|
||||
if ($user->hasRole('vendor')) {
|
||||
$query->with(['product', 'product.media'])
|
||||
->where('channel_id', $request->user()->channel()->id);
|
||||
} else {
|
||||
$query->with(['product', 'product.media', 'channel']);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fields for index.
|
||||
*/
|
||||
public function fieldsForIndex(NovaRequest $request): array
|
||||
{
|
||||
return OrderItemFieldsForIndex::make($this, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fields for create.
|
||||
*/
|
||||
public function fieldsForCreate(NovaRequest $request): array
|
||||
{
|
||||
return OrderItemFieldsForCreate::make($this, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fields displayed by the resource on detail page.
|
||||
*/
|
||||
public function fieldsForUpdate(NovaRequest $request): array
|
||||
{
|
||||
return OrderItemFieldsForUpdate::make($this, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the location to redirect the user after creation.
|
||||
*
|
||||
* @param \Laravel\Nova\Resource $resource
|
||||
* @return \Laravel\Nova\URL|string
|
||||
*/
|
||||
public static function redirectAfterCreate(NovaRequest $request, $resource)
|
||||
{
|
||||
return sprintf('/resources/orders/%s', $resource->order_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the location to redirect the user after update.
|
||||
*
|
||||
* @param \Laravel\Nova\Resource $resource
|
||||
* @return \Laravel\Nova\URL|string
|
||||
*/
|
||||
public static function redirectAfterUpdate(NovaRequest $request, $resource)
|
||||
{
|
||||
return sprintf('/resources/orders/%s', $resource->order_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fields displayed by the resource.
|
||||
*/
|
||||
public function fields(NovaRequest $request): array
|
||||
{
|
||||
return [
|
||||
ID::make()->sortable(),
|
||||
|
||||
Text::make(__('Quantity'), 'quantity'),
|
||||
BelongsTo::make(__('Order'), 'order', Order::class),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cards available for the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function cards(NovaRequest $request)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filters available for the resource.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function filters(NovaRequest $request)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lenses available for the resource.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function lenses(NovaRequest $request)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the actions available for the resource.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function actions(NovaRequest $request)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\Nova\Resources\Ecommerce\Product\Order\OrderItem;
|
||||
|
||||
use App\Models\Ecommerce\Product\Product\Product as ProductModel;
|
||||
use App\Nova\Resources\Ecommerce\Product\Order\Order;
|
||||
use App\Nova\Resources\Ecommerce\Product\Product\Product;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Laravel\Nova\Fields\Hidden;
|
||||
use Laravel\Nova\Fields\ID;
|
||||
use Laravel\Nova\Fields\Number;
|
||||
use Laravel\Nova\Fields\Text;
|
||||
use Outl1ne\MultiselectField\Multiselect;
|
||||
|
||||
class OrderItemFieldsForCreate
|
||||
{
|
||||
/**
|
||||
* Order item fields for create
|
||||
*/
|
||||
public static function make($resource, $request): array
|
||||
{
|
||||
return [
|
||||
ID::make(),
|
||||
|
||||
Hidden::make('order_id')
|
||||
->default($request->viaResource()),
|
||||
|
||||
Multiselect::make(__('Product'), 'product_id')
|
||||
->asyncResource(Product::class)
|
||||
->placeholder(__('Search by id, name, sku, barcode...'))
|
||||
->singleSelect()
|
||||
->rules('required'),
|
||||
|
||||
Number::make(__('Quantity'), 'quantity')
|
||||
->rules('required', 'min:1')
|
||||
->default(1),
|
||||
|
||||
Text::make(__('Price'), 'unit_price_amount')
|
||||
->rules('required')
|
||||
->dependsOn('product_id', function ($field, $request, $formData) {
|
||||
if (! $formData->product_id || ! is_int($formData->product_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$product = DB::table('products')->where('id', $formData->product_id)->first();
|
||||
|
||||
$field->setValue($product->price_amount);
|
||||
})->fillUsing(function ($request, $model, $attribute, $requestAttribute) {
|
||||
$product = ProductModel::find($request->product_id);
|
||||
|
||||
$model->unit_price_amount = $request->unit_price_amount;
|
||||
$model->unit_cost_amount = $product->cost_amount;
|
||||
$model->product_name = $product->name;
|
||||
$model->channel_id = $product->channels()->first()?->id ?? tmpostChannel()->id;
|
||||
}),
|
||||
|
||||
Number::make(__('Total'), 'total')
|
||||
->dependsOn(['quantity', 'unit_price_amount'], function ($field, $request, $formData) {
|
||||
if (! $formData->unit_price_amount || ! $formData->quantity) {
|
||||
return;
|
||||
}
|
||||
|
||||
$field->setValue($formData->unit_price_amount * $formData->quantity);
|
||||
})->readonly(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Nova\Resources\Ecommerce\Product\Order\OrderItem;
|
||||
|
||||
use App\Repositories\Nova\NovaRepo;
|
||||
use Laravel\Nova\Fields\ID;
|
||||
use Laravel\Nova\Fields\Text;
|
||||
use Laravel\Nova\Fields\URL;
|
||||
|
||||
class OrderItemFieldsForIndex
|
||||
{
|
||||
/**
|
||||
* Order item's index fields
|
||||
*/
|
||||
public static function make($resource): array
|
||||
{
|
||||
return [
|
||||
ID::make()->sortable()->hidden(),
|
||||
|
||||
Text::make(
|
||||
name: __('Image'),
|
||||
attribute: fn () => NovaRepo::rawImage(url: $resource->product?->thumbnail())
|
||||
)->asHtml(),
|
||||
|
||||
Text::make(
|
||||
name: __('Product name'),
|
||||
attribute: fn () => $resource->product?->novaDetailPage(),
|
||||
)->displayUsing(function () use ($resource) {
|
||||
$product = $resource->product;
|
||||
|
||||
if (! $product) {
|
||||
return;
|
||||
}
|
||||
|
||||
return sprintf('
|
||||
<a href="%s" target="_blank" class="link-default"> %s <span class="link-default">%s</span> <span class="link-default">%s</span></a>',
|
||||
$product->novaDetailPage(),
|
||||
$product->name,
|
||||
$product->color,
|
||||
$product->size,
|
||||
);
|
||||
})->asHtml(),
|
||||
|
||||
URL::make(
|
||||
name: __('Channel'),
|
||||
attribute: fn () => $resource->channel?->novaDetailPage(),
|
||||
)
|
||||
->displayUsing(fn () => $resource->channel?->name)
|
||||
->canSeeWhen('isAdmin', $resource),
|
||||
|
||||
Text::make(__('Cost amount'), fn () => $resource->product?->cost_amount),
|
||||
Text::make(__('Price'), 'unit_price_amount'),
|
||||
Text::make(__('Quantity'), 'quantity'),
|
||||
Text::make(__('Total'), fn () => intval($resource->quantity) * floatval($resource->unit_price_amount)),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Nova\Resources\Ecommerce\Product\Order\OrderItem;
|
||||
|
||||
use Laravel\Nova\Fields\Hidden;
|
||||
use Laravel\Nova\Fields\ID;
|
||||
use Laravel\Nova\Fields\Number;
|
||||
use Laravel\Nova\Fields\Text;
|
||||
|
||||
class OrderItemFieldsForUpdate
|
||||
{
|
||||
/**
|
||||
* Order item fields for update
|
||||
*/
|
||||
public static function make($resource, $request): array
|
||||
{
|
||||
return [
|
||||
ID::make(),
|
||||
|
||||
Hidden::make('order_id'),
|
||||
|
||||
Text::make(__('Product name'), 'product_name')
|
||||
->readonly(),
|
||||
|
||||
Number::make(__('Quantity'), 'quantity')
|
||||
->rules('required', 'min:1'),
|
||||
|
||||
Text::make(__('Price'), 'unit_price_amount')
|
||||
->rules('required'),
|
||||
|
||||
Number::make(__('Total'), 'total')
|
||||
->dependsOn(['quantity', 'unit_price_amount'], function ($field, $request, $formData) {
|
||||
if (! $formData->unit_price_amount || ! $formData->quantity) {
|
||||
return;
|
||||
}
|
||||
|
||||
$field->setValue($formData->unit_price_amount * $formData->quantity);
|
||||
})->readonly(),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user