diff --git a/innopacks/common/database/migrations/2024_04_01_161034_init_innoshop_table.php b/innopacks/common/database/migrations/2024_04_01_161034_init_innoshop_table.php
index 42bf584a..e64a6385 100644
--- a/innopacks/common/database/migrations/2024_04_01_161034_init_innoshop_table.php
+++ b/innopacks/common/database/migrations/2024_04_01_161034_init_innoshop_table.php
@@ -700,6 +700,7 @@ public function up(): void
$table->unsignedInteger('product_video_id')->default(0)->index('p_pv_id')->comment('Video ID');
$table->unsignedInteger('product_sku_id')->default(0)->index('p_ps_id')->comment('SKU ID');
$table->unsignedInteger('tax_class_id')->default(0)->index('p_tc_id')->comment('Tax Class ID');
+ $table->string('spu_code', 128)->nullable()->unique()->comment('SPU Code');
$table->string('slug', 128)->nullable()->unique()->comment('URL Slug');
$table->json('variables')->nullable()->comment('Product variables for sku with variants');
$table->boolean('is_virtual')->default(false)->comment('Is Virtual');
diff --git a/innopacks/common/src/Models/Attribute/Translation.php b/innopacks/common/src/Models/Attribute/Translation.php
index 54b14656..d60b94ae 100644
--- a/innopacks/common/src/Models/Attribute/Translation.php
+++ b/innopacks/common/src/Models/Attribute/Translation.php
@@ -9,6 +9,8 @@
namespace InnoShop\Common\Models\Attribute;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use InnoShop\Common\Models\Attribute;
use InnoShop\Common\Models\BaseModel;
class Translation extends BaseModel
@@ -18,4 +20,12 @@ class Translation extends BaseModel
protected $fillable = [
'locale', 'name',
];
+
+ /**
+ * @return BelongsTo
+ */
+ public function attribute(): BelongsTo
+ {
+ return $this->belongsTo(Attribute::class, 'attribute_id');
+ }
}
diff --git a/innopacks/common/src/Models/Category/Translation.php b/innopacks/common/src/Models/Category/Translation.php
index 6383a511..bfef7b37 100644
--- a/innopacks/common/src/Models/Category/Translation.php
+++ b/innopacks/common/src/Models/Category/Translation.php
@@ -9,7 +9,9 @@
namespace InnoShop\Common\Models\Category;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
use InnoShop\Common\Models\BaseModel;
+use InnoShop\Common\Models\Category;
class Translation extends BaseModel
{
@@ -18,4 +20,12 @@ class Translation extends BaseModel
protected $fillable = [
'category_id', 'locale', 'name', 'content', 'meta_title', 'meta_description', 'meta_keywords',
];
+
+ /**
+ * @return BelongsTo
+ */
+ public function category(): BelongsTo
+ {
+ return $this->belongsTo(Category::class, 'category_id');
+ }
}
diff --git a/innopacks/common/src/Models/Product.php b/innopacks/common/src/Models/Product.php
index d22f93f7..af5dadcd 100644
--- a/innopacks/common/src/Models/Product.php
+++ b/innopacks/common/src/Models/Product.php
@@ -28,8 +28,8 @@ class Product extends BaseModel
use HasPackageFactory, Replicate, Translatable;
protected $fillable = [
- 'brand_id', 'product_image_id', 'product_video_id', 'product_sku_id', 'tax_class_id', 'slug', 'is_virtual',
- 'variables', 'position', 'active', 'weight', 'weight_class', 'sales', 'viewed',
+ 'brand_id', 'product_image_id', 'product_video_id', 'product_sku_id', 'tax_class_id', 'spu_code', 'slug',
+ 'is_virtual', 'variables', 'position', 'active', 'weight', 'weight_class', 'sales', 'viewed',
];
protected $casts = [
diff --git a/innopacks/common/src/Repositories/Attribute/ValueRepo.php b/innopacks/common/src/Repositories/Attribute/ValueRepo.php
index 86bc5f13..d116588c 100644
--- a/innopacks/common/src/Repositories/Attribute/ValueRepo.php
+++ b/innopacks/common/src/Repositories/Attribute/ValueRepo.php
@@ -9,6 +9,7 @@
namespace InnoShop\Common\Repositories\Attribute;
+use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use InnoShop\Common\Models\Attribute\Value;
@@ -21,15 +22,17 @@ class ValueRepo extends BaseRepo
/**
* @param $attributeID
* @param $translations
- * @return void
+ * @return mixed
*/
- public function createAttribute($attributeID, $translations): void
+ public function createAttribute($attributeID, $translations): mixed
{
if (empty($attributeID) || empty($translations)) {
- return;
+ return null;
}
$attrValue = Value::query()->create(['attribute_id' => $attributeID]);
$this->updateTranslations($attrValue, $translations);
+
+ return $attrValue;
}
/**
@@ -70,6 +73,48 @@ public function all(array $filters = []): Collection
return $this->builder($filters)->get();
}
+ /**
+ * @param $name
+ * @param string $locale
+ * @return mixed
+ * @throws Exception
+ */
+ public function findByName($name, string $locale = ''): mixed
+ {
+ if (empty($locale)) {
+ $locale = locale_code();
+ }
+
+ $translation = Value\Translation::query()
+ ->where('name', $name)
+ ->where('locale', $locale)
+ ->first();
+
+ return $translation->value ?? null;
+ }
+
+ /**
+ * @param $attributeRow
+ * @param $name
+ * @param string $locale
+ * @return mixed
+ * @throws Exception
+ */
+ public function findOrCreateByName($attributeRow, $name, string $locale = ''): mixed
+ {
+ $attributeValue = $this->findByName($name, $locale);
+ if ($attributeValue) {
+ return $attributeValue;
+ }
+
+ $data = [];
+ foreach (locales() as $locale) {
+ $data[$locale->code] = $name;
+ }
+
+ return $this->createAttribute($attributeRow->id, $data);
+ }
+
/**
* @param array $filters
* @return Builder
diff --git a/innopacks/common/src/Repositories/AttributeRepo.php b/innopacks/common/src/Repositories/AttributeRepo.php
index 9035c9fe..12e34365 100644
--- a/innopacks/common/src/Repositories/AttributeRepo.php
+++ b/innopacks/common/src/Repositories/AttributeRepo.php
@@ -41,6 +41,47 @@ public function all(array $filters = []): Collection
return $this->builder($filters)->get();
}
+ /**
+ * @param $name
+ * @param string $locale
+ * @return mixed
+ * @throws Exception
+ */
+ public function findByName($name, string $locale = ''): mixed
+ {
+ if (empty($locale)) {
+ $locale = locale_code();
+ }
+
+ $translation = Attribute\Translation::query()->where('name', $name)->where('locale', $locale)->first();
+
+ return $translation->attribute ?? null;
+ }
+
+ /**
+ * @param $name
+ * @param string $locale
+ * @return mixed
+ * @throws Throwable
+ */
+ public function findOrCreateByName($name, string $locale = ''): mixed
+ {
+ $attribute = $this->findByName($name, $locale);
+ if ($attribute) {
+ return $attribute;
+ }
+
+ $data = [];
+ foreach (locales() as $locale) {
+ $data['translations'][] = [
+ 'locale' => $locale->code,
+ 'name' => $name,
+ ];
+ }
+
+ return $this->create($data);
+ }
+
/**
* @param array $filters
* @return Builder
diff --git a/innopacks/common/src/Repositories/CategoryRepo.php b/innopacks/common/src/Repositories/CategoryRepo.php
index b15bcb05..e2e3bef0 100644
--- a/innopacks/common/src/Repositories/CategoryRepo.php
+++ b/innopacks/common/src/Repositories/CategoryRepo.php
@@ -9,6 +9,7 @@
namespace InnoShop\Common\Repositories;
+use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use InnoShop\Common\Models\Category;
@@ -161,7 +162,7 @@ private function createOrUpdate(Category $category, $data): void
$category->translations()->createMany($translations);
DB::commit();
- } catch (\Exception $e) {
+ } catch (Exception $e) {
DB::rollBack();
throw $e;
}
@@ -175,10 +176,10 @@ private function handleCategoryData($data): array
{
return [
'parent_id' => $data['parent_id'] ?? 0,
- 'slug' => $data['slug'],
- 'image' => $data['image'] ?? '',
- 'position' => $data['position'] ?? 0,
- 'active' => $data['active'] ?? true,
+ 'slug' => $data['slug'] ?? null,
+ 'image' => $data['image'] ?? '',
+ 'position' => $data['position'] ?? 0,
+ 'active' => $data['active'] ?? true,
];
}
@@ -280,4 +281,45 @@ public function getNameByID($id): string
{
return Category::query()->find($id)->description->name ?? '';
}
+
+ /**
+ * @param $name
+ * @param string $locale
+ * @return mixed
+ * @throws Exception
+ */
+ public function findByName($name, string $locale = ''): mixed
+ {
+ if (empty($locale)) {
+ $locale = locale_code();
+ }
+
+ $translation = Category\Translation::query()->where('name', $name)->where('locale', $locale)->first();
+
+ return $translation->category ?? null;
+ }
+
+ /**
+ * @param $name
+ * @param string $locale
+ * @return mixed
+ * @throws Throwable
+ */
+ public function findOrCreateByName($name, string $locale = ''): mixed
+ {
+ $category = $this->findByName($name, $locale);
+ if ($category) {
+ return $category;
+ }
+
+ $data = [];
+ foreach (locales() as $locale) {
+ $data['translations'][] = [
+ 'locale' => $locale->code,
+ 'name' => $name,
+ ];
+ }
+
+ return $this->create($data);
+ }
}
diff --git a/innopacks/common/src/Repositories/ProductRepo.php b/innopacks/common/src/Repositories/ProductRepo.php
index ff7c1ace..bd0566ef 100644
--- a/innopacks/common/src/Repositories/ProductRepo.php
+++ b/innopacks/common/src/Repositories/ProductRepo.php
@@ -231,6 +231,7 @@ public function handleProductData($data): array
}
return [
+ 'spu_code' => $data['spu_code'],
'slug' => $data['slug'],
'brand_id' => $data['brand_id'] ?? 0,
'product_image_id' => $data['product_image_id'] ?? 0,
@@ -556,6 +557,32 @@ public function getListByProductIDs(mixed $productIDs): mixed
->get();
}
+ /**
+ * @param $spuCode
+ * @return ?Product
+ */
+ public function findBySpuCode($spuCode): ?Product
+ {
+ if (empty($spuCode)) {
+ return null;
+ }
+
+ return Product::query()->where('spu_code', $spuCode)->first();
+ }
+
+ /**
+ * @param $slug
+ * @return ?Product
+ */
+ public function findBySlug($slug): ?Product
+ {
+ if (empty($spuCode)) {
+ return null;
+ }
+
+ return Product::query()->where('slug', $slug)->first();
+ }
+
/**
* @param $keyword
* @param int $limit
diff --git a/innopacks/common/src/Services/CheckoutService.php b/innopacks/common/src/Services/CheckoutService.php
index e0ecb4fe..c72191f2 100644
--- a/innopacks/common/src/Services/CheckoutService.php
+++ b/innopacks/common/src/Services/CheckoutService.php
@@ -30,11 +30,11 @@
class CheckoutService extends BaseService
{
- private int $customerID;
+ protected int $customerID;
- private string $guestID;
+ protected string $guestID;
- private array $cartList = [];
+ protected array $cartList = [];
private array $addressList = [];
@@ -78,7 +78,7 @@ public function __construct(int $customerID = 0, string $guestID = '')
*/
public static function getInstance(int $customerID = 0, string $guestID = ''): static
{
- return new self($customerID, $guestID);
+ return new static($customerID, $guestID);
}
/**
diff --git a/innopacks/front/resources/views/products/show.blade.php b/innopacks/front/resources/views/products/show.blade.php
index f3b97c97..54766ca6 100644
--- a/innopacks/front/resources/views/products/show.blade.php
+++ b/innopacks/front/resources/views/products/show.blade.php
@@ -1,6 +1,19 @@
@extends('layouts.app')
@section('body-class', 'page-product')
+@if($product->translation->meta_title ?? '')
+ @section('title', $product->translation->meta_title ?? '')
+@endif
+
+@if($product->translation->meta_description ?? '')
+ @section('description', $product->translation->meta_description ?? '')
+@endif
+
+@if($product->translation->meta_keywords ?? '')
+ @section('keywords', $product->translation->meta_keywords ?? '')
+@endif
+
+
@push('header')
diff --git a/innopacks/panel/resources/css/page-product-form.scss b/innopacks/panel/resources/css/page-product-form.scss
index 51c7bb8a..bc860250 100644
--- a/innopacks/panel/resources/css/page-product-form.scss
+++ b/innopacks/panel/resources/css/page-product-form.scss
@@ -313,4 +313,51 @@ body.page-product-form {
}
}
}
-}
\ No newline at end of file
+ .variant-skus-table th {
+ padding-top: 0;
+ vertical-align: bottom;
+ }
+
+ .variant-skus-table .batch-input-item {
+ margin: 0;
+ padding: 10px 0;
+ }
+
+ .variant-skus-table .batch-input-item .input-group {
+ width: 100%;
+ min-width: 120px;
+ }
+
+ .variant-skus-table .batch-input-item .form-control {
+ height: 31px;
+ font-size: 13px;
+ border-right: 0;
+ }
+
+ .variant-skus-table .batch-input-item .btn {
+ border-color: #ced4da;
+ background: #fff;
+ font-size: 13px;
+ padding: 4px 8px;
+ }
+
+ .variant-skus-table .batch-input-item .btn:hover {
+ background: #8446df;
+ border-color: #8446df;
+ color: #fff;
+ }
+
+ .variant-skus-table thead th {
+ background: #f8f9fa;
+ border-bottom: 2px solid #dee2e6;
+ }
+
+ .variant-skus-table tbody td .form-control {
+ font-size: 13px;
+ }
+
+ /* Remove old batch input styles */
+ .batch-input-area {
+ display: none;
+ }
+}
diff --git a/innopacks/panel/resources/views/orders/printing.blade.php b/innopacks/panel/resources/views/orders/printing.blade.php
index 431512e0..329cab47 100755
--- a/innopacks/panel/resources/views/orders/printing.blade.php
+++ b/innopacks/panel/resources/views/orders/printing.blade.php
@@ -34,7 +34,7 @@ class="printer">{{ __("panel/order.print") }}
{{ __("panel/order.telephone") }}: {{ $order['shipping_telephone'] }}
{{ __("panel/order.email") }}: {{ $order['email'] }}
{{ __("panel/order.shipping_address") }}:
- {{ $order['shipping_customer_name'] . "(" . $order['shipping_telephone'] . ")". ' ' . $order['shipping_address_1'] . ' ' . $order['shipping_address_2'] . ' ' . $order['shipping_city'] . ' ' . $order['shipping_zone'] . ' ' . $order['shipping_country'] }}
+ {{ $order['shipping_customer_name'] . "(" . $order['shipping_telephone'] . ")". ' ', $order['shipping_address_1'] . ' ' . $order['shipping_address_2'] . ' ' . $order['shipping_city'] . ' ' . $order['shipping_zone'] . ' ' . $order['shipping_country'] }}