From c86af4ab91ed788cfd48cf3d13c007fd5c148a76 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Wed, 17 Jun 2026 23:18:06 +0700 Subject: [PATCH] feat: add tiktok_order_id and shopee_order_id fields to order management, including validation, display, and search functionality --- .../Requests/Admin/Manage/OrderRequest.php | 4 ++ app/Services/Manage/OrderService.php | 6 +++ .../2026_06_12_100001_create_orders_table.php | 2 + .../admin/manage/orders/OrderGroupedTable.vue | 14 +++++-- .../admin/manage/orders/OrderPosForm.vue | 41 +++++++++++++++++-- resources/js/constants/order-channel.ts | 4 ++ .../js/pages/admin/manage/orders/Edit.vue | 2 + resources/js/types/order.ts | 4 ++ 8 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 resources/js/constants/order-channel.ts diff --git a/app/Http/Requests/Admin/Manage/OrderRequest.php b/app/Http/Requests/Admin/Manage/OrderRequest.php index 6102ae2..ef733f4 100644 --- a/app/Http/Requests/Admin/Manage/OrderRequest.php +++ b/app/Http/Requests/Admin/Manage/OrderRequest.php @@ -31,6 +31,8 @@ public function rules(): array 'marketing_id' => ['nullable', 'integer', Rule::exists('users', 'id')->whereNull('deleted_at')], 'channel' => ['required', Rule::enum(OrderChannel::class)], 'price_type' => ['required', Rule::enum(PriceType::class)], + 'tiktok_order_id' => [Rule::requiredIf(fn () => $this->channel === OrderChannel::TIKTOK->value), 'string', 'max:100'], + 'shopee_order_id' => [Rule::requiredIf(fn () => $this->channel === OrderChannel::SHOPEE->value), 'string', 'max:100'], 'discount' => ['nullable', 'integer', 'min:0'], 'notes' => ['nullable', 'string'], ]; @@ -58,6 +60,8 @@ public function attributes(): array 'marketing_id' => 'marketing', 'channel' => 'channel', 'price_type' => 'tipe harga', + 'tiktok_order_id' => 'ID pesanan TikTok Shop', + 'shopee_order_id' => 'ID pesanan Shopee', 'discount' => 'diskon', 'notes' => 'keterangan', 'items' => 'produk', diff --git a/app/Services/Manage/OrderService.php b/app/Services/Manage/OrderService.php index 75dc1b0..478a37e 100644 --- a/app/Services/Manage/OrderService.php +++ b/app/Services/Manage/OrderService.php @@ -46,6 +46,8 @@ public function paginateForIndex(array $tableQuery, User $user): LengthAwarePagi $search = $tableQuery['search']; $query->where(function (Builder $query) use ($search): void { $query->where('order_number', 'like', "%{$search}%") + ->orWhere('tiktok_order_id', 'like', "%{$search}%") + ->orWhere('shopee_order_id', 'like', "%{$search}%") ->orWhere('notes', 'like', "%{$search}%") ->orWhereHas('customer', fn (Builder $query) => $query->where('name', 'like', "%{$search}%")) ->orWhereHas('items.productVariant', function (Builder $query) use ($search): void { @@ -324,6 +326,8 @@ public function create(array $validated, User $user): Order 'channel' => $channel, 'price_type' => $priceType, 'status' => OrderStatus::PENDING, + 'tiktok_order_id' => $validated['tiktok_order_id'] ?? null, + 'shopee_order_id' => $validated['shopee_order_id'] ?? null, 'created_by_id' => $user->id, 'subtotal' => $subtotal, 'discount' => $discount, @@ -397,6 +401,8 @@ public function update(Order $order, array $validated): void $order->marketing_id = $validated['marketing_id'] ?? null; $order->channel = $channel; $order->price_type = $priceType; + $order->tiktok_order_id = $validated['tiktok_order_id'] ?? null; + $order->shopee_order_id = $validated['shopee_order_id'] ?? null; $order->subtotal = $subtotal; $order->discount = $discount; $order->marketplace_settings_snapshot = $this->marketplaceService->buildOrderSnapshot( diff --git a/database/migrations/2026_06_12_100001_create_orders_table.php b/database/migrations/2026_06_12_100001_create_orders_table.php index 4a4577e..4490f75 100644 --- a/database/migrations/2026_06_12_100001_create_orders_table.php +++ b/database/migrations/2026_06_12_100001_create_orders_table.php @@ -21,6 +21,8 @@ public function up(): void $table->enum('channel', array_column(OrderChannel::cases(), 'value')); $table->enum('price_type', array_column(PriceType::cases(), 'value')); $table->enum('status', array_column(OrderStatus::cases(), 'value'))->default(OrderStatus::PENDING->value); + $table->string('tiktok_order_id', 100)->nullable(); + $table->string('shopee_order_id', 100)->nullable(); $table->unsignedBigInteger('subtotal'); $table->unsignedBigInteger('discount')->default(0); $table->json('marketplace_settings_snapshot')->nullable(); diff --git a/resources/js/components/admin/manage/orders/OrderGroupedTable.vue b/resources/js/components/admin/manage/orders/OrderGroupedTable.vue index 09363a2..ea11cf8 100644 --- a/resources/js/components/admin/manage/orders/OrderGroupedTable.vue +++ b/resources/js/components/admin/manage/orders/OrderGroupedTable.vue @@ -98,6 +98,12 @@ function statusVariant(status: string): 'default' | 'secondary' | 'destructive' {{ order.channel_label }} + + ID Pesanan: {{ order.tiktok_order_id }} + + + ID Pesanan: {{ order.shopee_order_id }} +

@@ -108,13 +114,13 @@ function statusVariant(status: string): 'default' | 'secondary' | 'destructive'

Tipe Harga {{ order.price_type_label - }} + }} Subtotal {{ order.subtotal_formatted - }} + }} Diskon {{ order.discount_formatted - }} + }} Total {{ order.total_amount_formatted - }} + }}

{{ order.notes }} diff --git a/resources/js/components/admin/manage/orders/OrderPosForm.vue b/resources/js/components/admin/manage/orders/OrderPosForm.vue index 82acae6..6bce9b7 100644 --- a/resources/js/components/admin/manage/orders/OrderPosForm.vue +++ b/resources/js/components/admin/manage/orders/OrderPosForm.vue @@ -3,7 +3,6 @@ import { useForm, usePage } from '@inertiajs/vue3'; import { Minus, Plus, Save, Search, ShoppingCart, Trash2 } from '@lucide/vue'; import { computed, ref, watch } from 'vue'; import { toast } from 'vue-sonner'; -import type { Auth } from '@/types/auth'; import PosCatalogCard from '@/components/admin/manage/PosCatalogCard.vue'; import PosCatalogVariantThumb from '@/components/admin/manage/PosCatalogVariantThumb.vue'; import { NumberInput } from '@/components/form/number-input'; @@ -34,10 +33,12 @@ import { } from '@/components/ui/select'; import { Separator } from '@/components/ui/separator'; import { Textarea } from '@/components/ui/textarea'; +import { OrderChannel } from '@/constants/order-channel'; import { apiFetch } from '@/lib/api'; import { getFirstCoverImage } from '@/lib/catalog-cover'; import { formErrors } from '@/lib/form'; import { formatRupiah, parseRupiah } from '@/lib/rupiah'; +import type { Auth } from '@/types/auth'; import type { EnumOption, OrderCartItem, OrderCatalogItem, SelectOption } from '@/types/order'; import type { ProductPriceItem, ProductVariantItem } from '@/types/product'; @@ -52,6 +53,8 @@ const props = defineProps<{ marketing_id: string; channel: string; price_type: string; + tiktok_order_id: string; + shopee_order_id: string; discount: string; notes: string; items: OrderCartItem[]; @@ -83,6 +86,8 @@ const form = useForm({ marketing_id: defaultMarketingId.value || 'none', channel: 'store', price_type: 'ecer', + tiktok_order_id: '', + shopee_order_id: '', discount: '', notes: '', }); @@ -98,6 +103,8 @@ function populateForm() { form.marketing_id = props.initialData.marketing_id || 'none'; form.channel = props.initialData.channel; form.price_type = props.initialData.price_type; + form.tiktok_order_id = props.initialData.tiktok_order_id; + form.shopee_order_id = props.initialData.shopee_order_id; form.discount = props.initialData.discount; form.notes = props.initialData.notes; cart.value = props.initialData.items.map((item) => ({ ...item })); @@ -347,6 +354,15 @@ function buildFormData(): FormData { formData.append('channel', form.channel); formData.append('price_type', form.price_type); + + if (form.channel === 'tiktok' && form.tiktok_order_id) { + formData.append('tiktok_order_id', form.tiktok_order_id); + } + + if (form.channel === 'shopee' && form.shopee_order_id) { + formData.append('shopee_order_id', form.shopee_order_id); + } + formData.append('discount', parseRupiah(form.discount)); formData.append('notes', form.notes); @@ -409,8 +425,7 @@ function submit() { Belum ada varian

Tipe Harga
- {{ form.channel === 'shopee' ? 'Shopee' : 'TikTok' }} + {{ form.channel === OrderChannel.SHOPEE ? 'Shopee' : 'TikTok' }}
+ + ID + Pesanan + TikTok Shop + + + + + + ID + Pesanan + Shopee + + + + Pelanggan