!66 默认属性组不可删除
* 默认数据增加id为1的默认属性组,并且默认属性组后台不能删除 * migrations/2023_03_20_091423_product_weight.php * 商品重量 * add weight blade * bugfix * 商品重量,用于计算flex shipping运费;地址变化后配送方式变化,需要重新显示新的配送方式 * Placeholder Image Backend Settings * 商品重量,用于计算flex shipping运费;地址变化后配送方式变化,需要重新显示新的配送方式 * 增加hook
This commit is contained in:
parent
d233cd2fca
commit
86b3d33d6d
|
|
@ -7,6 +7,7 @@ use Beike\Admin\Http\Resources\ProductAttributeResource;
|
|||
use Beike\Admin\Http\Resources\ProductResource;
|
||||
use Beike\Admin\Repositories\TaxClassRepo;
|
||||
use Beike\Admin\Services\ProductService;
|
||||
use Beike\Libraries\Weight;
|
||||
use Beike\Models\Product;
|
||||
use Beike\Repositories\CategoryRepo;
|
||||
use Beike\Repositories\LanguageRepo;
|
||||
|
|
@ -152,6 +153,7 @@ class ProductController extends Controller
|
|||
'relations' => ProductResource::collection($product->relations)->resource,
|
||||
'languages' => LanguageRepo::all(),
|
||||
'tax_classes' => $taxClasses,
|
||||
'weight_classes' => Weight::getWeightUnits(),
|
||||
'source' => [
|
||||
'categories' => CategoryRepo::flatten(locale()),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -68,6 +68,9 @@ class AttributeGroupRepo
|
|||
|
||||
public static function delete($id)
|
||||
{
|
||||
if ($id == 1) {
|
||||
throw new \Exception(trans('admin/attribute_group.error_cannot_delete_default_group'));
|
||||
}
|
||||
$group = AttributeGroup::query()->findOrFail($id);
|
||||
if ($group->attributes->count()) {
|
||||
throw new \Exception(trans('admin/attribute_group.error_cannot_delete_attribute_used', ['attributes' => implode(', ', $group->attributes->pluck('id')->toArray())]));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
/**
|
||||
* Weight.php
|
||||
*
|
||||
* @copyright 2023 beikeshop.com - All Rights Reserved
|
||||
* @link https://beikeshop.com
|
||||
* @author TL <mengwb@guangda.work>
|
||||
* @created 2023-03-21 16:29:54
|
||||
* @modified 2023-03-21 16:29:54
|
||||
*/
|
||||
|
||||
namespace Beike\Libraries;
|
||||
|
||||
class Weight
|
||||
{
|
||||
public const WEIGHT_CLASS = [
|
||||
'kg' => 0.001,
|
||||
'g' => 1,
|
||||
'oz' => 0.035,
|
||||
'lb' => 0.0022046,
|
||||
];
|
||||
public const DEFAULT_CLASS = 'g';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static function getWeightUnits() : array
|
||||
{
|
||||
return array_keys(self::WEIGHT_CLASS);
|
||||
}
|
||||
|
||||
public static function convert($weight, $from, $to = '')
|
||||
{
|
||||
if (!$to) {
|
||||
$to = self::DEFAULT_CLASS;
|
||||
}
|
||||
if (empty($weight)) {
|
||||
return 0;
|
||||
}
|
||||
return $weight * self::WEIGHT_CLASS[$to] / self::WEIGHT_CLASS[$from];
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ class Product extends Base
|
|||
use HasFactory;
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = ['images', 'video', 'position', 'brand_id', 'tax_class_id', 'active', 'variables'];
|
||||
protected $fillable = ['images', 'video', 'position', 'brand_id', 'tax_class_id', 'weight', 'weight_class', 'active', 'variables'];
|
||||
|
||||
protected $casts = [
|
||||
'active' => 'boolean',
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class ImageService
|
|||
|
||||
private $imagePath;
|
||||
|
||||
public const PLACEHOLDER_IMAGE = 'catalog/placeholder.png';
|
||||
private $placeholderImage = 'catalog/placeholder.png';
|
||||
|
||||
/**
|
||||
* @param $image
|
||||
|
|
@ -28,8 +28,9 @@ class ImageService
|
|||
*/
|
||||
public function __construct($image)
|
||||
{
|
||||
$this->image = $image ?: self::PLACEHOLDER_IMAGE;
|
||||
$this->image = $image ?: $this->placeholderImage;
|
||||
$this->imagePath = public_path($this->image);
|
||||
$this->placeholderImage = system_setting('base.placeholder');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -40,7 +41,7 @@ class ImageService
|
|||
public function setPluginDirName($dirName): static
|
||||
{
|
||||
$originImage = $this->image;
|
||||
if ($this->image == self::PLACEHOLDER_IMAGE) {
|
||||
if ($this->image == $this->placeholderImage) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
@ -48,7 +49,7 @@ class ImageService
|
|||
if (file_exists($this->imagePath)) {
|
||||
$this->image = strtolower('plugin/' . $dirName . $originImage);
|
||||
} else {
|
||||
$this->image = self::PLACEHOLDER_IMAGE;
|
||||
$this->image = $this->placeholderImage;
|
||||
$this->imagePath = public_path($this->image);
|
||||
}
|
||||
|
||||
|
|
@ -65,7 +66,7 @@ class ImageService
|
|||
{
|
||||
try {
|
||||
if (! file_exists($this->imagePath)) {
|
||||
$this->image = self::PLACEHOLDER_IMAGE;
|
||||
$this->image = $this->placeholderImage;
|
||||
$this->imagePath = public_path($this->image);
|
||||
}
|
||||
if (! file_exists($this->imagePath)) {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
namespace Beike\Shop\Services;
|
||||
|
||||
use Beike\Libraries\Weight;
|
||||
use Beike\Models\Address;
|
||||
use Beike\Models\Country;
|
||||
use Beike\Models\Customer;
|
||||
|
|
@ -140,7 +141,7 @@ class CheckoutService
|
|||
$weight = 0;
|
||||
$selectedProducts = $this->selectedProducts;
|
||||
foreach ($selectedProducts as $product) {
|
||||
// $weight += $this->weight->convert($product['weight'], $product['weight_class_id'], $this->config->get('config_weight_class_id'));
|
||||
$weight += Weight::convert($product->product['weight'], $product->product['weight_class']);
|
||||
}
|
||||
|
||||
return $weight;
|
||||
|
|
@ -189,11 +190,13 @@ class CheckoutService
|
|||
private function updateShippingAddressId($shippingAddressId)
|
||||
{
|
||||
$this->cart->update(['shipping_address_id' => $shippingAddressId]);
|
||||
$this->cart->load('shippingAddress');
|
||||
}
|
||||
|
||||
private function updatePaymentAddressId($paymentAddressId)
|
||||
{
|
||||
$this->cart->update(['payment_address_id' => $paymentAddressId]);
|
||||
$this->cart->load('paymentAddress');
|
||||
}
|
||||
|
||||
private function updateGuestShippingAddress($guestShippingAddress)
|
||||
|
|
@ -236,6 +239,14 @@ class CheckoutService
|
|||
$shipments = ShippingMethodService::getShippingMethods($this);
|
||||
$payments = PaymentMethodItem::collection(PluginRepo::getPaymentMethods())->jsonSerialize();
|
||||
|
||||
$shipmentCodes = [];
|
||||
foreach ($shipments as $shipment) {
|
||||
$shipmentCodes = array_merge($shipmentCodes, array_column($shipment['quotes'], 'code'));
|
||||
}
|
||||
if (!in_array($currentCart->shipping_method_code, $shipmentCodes)) {
|
||||
$this->updateShippingMethod($shipmentCodes[0]);
|
||||
}
|
||||
|
||||
$data = [
|
||||
'current' => [
|
||||
'shipping_address_id' => $currentCart->shipping_address_id,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if (Schema::hasColumn('products', 'weight')) {
|
||||
return;
|
||||
}
|
||||
|
||||
Schema::table('products', function (Blueprint $table) {
|
||||
$table->float('weight')->comment('重量')->default(0)->after('tax_class_id');
|
||||
$table->string('weight_class')->comment('重量单位')->default('')->after('weight');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
if (!Schema::hasColumn('products', 'weight')) {
|
||||
return;
|
||||
}
|
||||
|
||||
Schema::table('products', function (Blueprint $table) {
|
||||
$table->dropColumn('weight');
|
||||
$table->dropColumn('weight_class');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -111,8 +111,8 @@ class AttributesSeeder extends Seeder
|
|||
private function getGroupDescriptions(): array
|
||||
{
|
||||
return [
|
||||
["attribute_group_id" => 1, "locale" => "zh_cn", "name" => "女装"],
|
||||
["attribute_group_id" => 1, "locale" => "en", "name" => "Women's clothing"],
|
||||
["attribute_group_id" => 1, "locale" => "zh_cn", "name" => "默认"],
|
||||
["attribute_group_id" => 1, "locale" => "en", "name" => "Default"],
|
||||
["attribute_group_id" => 2, "locale" => "zh_cn", "name" => "衣服"],
|
||||
["attribute_group_id" => 2, "locale" => "en", "name" => "Clothing"],
|
||||
["attribute_group_id" => 3, "locale" => "zh_cn", "name" => "运动户外"],
|
||||
|
|
|
|||
|
|
@ -78,6 +78,17 @@
|
|||
{{-- <x-admin-form-input name="video" title="视频" :value="old('video', $product->video ?? '')" /> --}}
|
||||
<x-admin-form-input name="position" :title="__('common.sort_order')" :value="old('position', $product->position ?? '0')" />
|
||||
|
||||
<x-admin::form.row :title="__('admin/product.weight_text')">
|
||||
<div class="d-flex wp-400">
|
||||
<input type="text" name="weight" placeholder="{{ __('admin/product.weight_text') }}" value="{{ old('weight', $product->weight ?? '') }}" class="form-control" style="flex: 0 0 260px" />
|
||||
<select class="form-select ms-4 bg-white" name="weight_class">
|
||||
@foreach ($weight_classes as $item)
|
||||
<option value="{{ $item }}" {{ $product->weight_class == $item ? 'selected' : '' }}>{{ __('product.' . $item) }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</x-admin::form.row>
|
||||
|
||||
@hookwrapper('admin.product.edit.brand')
|
||||
<x-admin::form.row :title="__('admin/brand.index')">
|
||||
<input type="text" value="{{ $product->brand->name ?? '' }}" id="brand-autocomplete" class="form-control wp-400 " />
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ return [
|
|||
'add_variable_image' => 'Spezifikationsbild hinzufügen',
|
||||
'default_main_product' => 'Standard-Hauptprodukt',
|
||||
'modify_order' => 'Zum Ändern doppelklicken, zum Anpassen der Reihenfolge ziehen',
|
||||
'weight_text' => 'Gewicht',
|
||||
'weight_class' => 'Gewichtseinheit',
|
||||
|
||||
'confirm_batch_product' => 'Möchten Sie die ausgewählten Elemente wirklich in großen Mengen löschen?',
|
||||
'confirm_batch_status' => 'Möchten Sie den Status der ausgewählten Artikel wirklich per Bulk-Verfahren bearbeiten?',
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ return [
|
|||
'index' => 'Attribute group',
|
||||
'create_at_groups' => 'Create',
|
||||
'error_cannot_delete_attribute_used' => 'Attribute Group used by attribute (ID: :attributes), can not be deleted!',
|
||||
'error_cannot_delete_default_group' => 'The attribute group with ID 1 is the default attribute group and cannot be deleted.',
|
||||
|
||||
'attribute_groups_index' => 'Index',
|
||||
'attribute_groups_create' => 'Create',
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ return [
|
|||
'add_variable_image' => 'Add Spec Image',
|
||||
'default_main_product' => 'Default main product',
|
||||
'modify_order' => 'Double-click to modify, drag to adjust the order',
|
||||
'weight_text' => 'weight',
|
||||
'weight_class' => 'weight unit',
|
||||
|
||||
'confirm_batch_product' => 'Are you sure you want to delete the selected products in batches? ',
|
||||
'confirm_batch_status' => 'Confirm to modify the status of the selected products in batches? ',
|
||||
|
|
|
|||
|
|
@ -19,7 +19,10 @@ return [
|
|||
'category' => 'Category',
|
||||
'model' => 'Model',
|
||||
'quantity' => 'Quantity',
|
||||
'image' => 'Image',
|
||||
'kg' => 'Kilogram',
|
||||
'g' => 'Gram',
|
||||
'oz' => 'Ounce',
|
||||
'lb' => 'Pound',
|
||||
|
||||
'active' => 'Active',
|
||||
'inactive' => 'Inactive',
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ return [
|
|||
'add_variable_image' => 'Agregar imagen de especificaciones',
|
||||
'default_main_product' => 'Producto principal predeterminado',
|
||||
'modify_order' => 'Haz doble clic para modificar, arrastra para ajustar el orden',
|
||||
'peso_texto' => 'peso',
|
||||
'weight_class' => 'unidad de peso',
|
||||
|
||||
'confirm_batch_product' => '¿Está seguro de que desea eliminar los elementos seleccionados de forma masiva?',
|
||||
'confirm_batch_status' => '¿Está seguro de que desea editar en masa el estado de los elementos seleccionados?',
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ return [
|
|||
'add_variable_image' => 'Ajouter une image de spécification',
|
||||
'default_main_product' => 'produit principal par défaut',
|
||||
'modify_order' => 'Double-cliquez pour modifier, faites glisser pour ajuster la commande',
|
||||
'weight_text' => 'poids',
|
||||
'weight_class' => 'unité de poids',
|
||||
|
||||
'confirm_batch_product' => 'Êtes-vous sûr de vouloir supprimer les produits sélectionnés par lots? ',
|
||||
'confirm_batch_status' => 'Confirmer pour modifier le statut des produits sélectionnés par lots? ',
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ return [
|
|||
'add_variable_image' => 'Aggiungi immagine specifica',
|
||||
'default_main_product' => 'prodotto principale predefinito',
|
||||
'modify_order' => 'Fai doppio clic per modificare, trascina per regolare l\'ordine',
|
||||
'weight_text' => 'peso',
|
||||
'weight_class' => 'unità di peso',
|
||||
|
||||
'confirm_batch_product' => 'Sei sicuro di voler eliminare i prodotti selezionati in batch?',
|
||||
'confirm_batch_status' => 'Conferma per modificare lo stato dei prodotti selezionati in batch?',
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ return [
|
|||
'add_variable_image' => '仕様画像追加',
|
||||
'default_main_product' => 'デフォルトのメイン製品',
|
||||
'modify_order' => 'ダブルクリックして変更、ドラッグして順序を調整',
|
||||
'weight_text' => '重さ',
|
||||
'weight_class' => '重量単位',
|
||||
|
||||
'confirm_batch_product' => '選択した製品をまとめて削除しますか? ',
|
||||
'confirm_batch_status' => 'バッチで選択した製品のステータスを変更することを確認しますか? ',
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ return [
|
|||
'add_variable_image' => 'Добавить изображение спецификации',
|
||||
'default_main_product' => 'Основной продукт по умолчанию',
|
||||
'modify_order' => 'Дважды щелкните, чтобы изменить, перетащите, чтобы настроить порядок',
|
||||
'weight_text' => 'вес',
|
||||
'weight_class' => 'единица веса',
|
||||
|
||||
'confirm_batch_product' => 'Вы уверены, что хотите удалить выбранные элементы сразу?',
|
||||
'confirm_batch_status' => 'Вы уверены, что хотите массово изменить статус выбранных элементов?',
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ return [
|
|||
'index' => '属性组',
|
||||
'create_at_groups' => '创建属性组',
|
||||
'error_cannot_delete_attribute_used' => '属性组不能删除,由于该属性组被属性(属性ID: :attributes)使用',
|
||||
'error_cannot_delete_default_group' => 'ID为1的为默认属性组,不能删除',
|
||||
|
||||
'attribute_groups_index' => '属性组列表',
|
||||
'attribute_groups_create' => '创建属性组',
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ return [
|
|||
'add_variable_image' => '添加规格图片',
|
||||
'default_main_product' => '默认主商品',
|
||||
'modify_order' => '双击修改、拖动调整顺序',
|
||||
'weight_text' => '重量',
|
||||
'weight_class' => '重量单位',
|
||||
|
||||
'confirm_batch_product' => '确认要批量删除选中的商品吗?',
|
||||
'confirm_batch_status' => '确认要批量修改选中的商品的状态吗?',
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ return [
|
|||
'model' => '型号',
|
||||
'quantity' => '库存',
|
||||
'image' => '图片',
|
||||
'kg' => '千克',
|
||||
'g' => '克',
|
||||
'oz' => '盎司',
|
||||
'lb' => '磅',
|
||||
|
||||
'active' => '上架',
|
||||
'inactive' => '下架',
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ return [
|
|||
'index' => '屬性組',
|
||||
'create_at_groups' => '創建屬性組',
|
||||
'error_cannot_delete_attribute_used' => '屬性組不能刪除,由於該屬性組被屬性(屬性ID: :attributes)使用',
|
||||
'error_cannot_delete_default_group' => 'ID為1的為默認屬性組,不能刪除',
|
||||
|
||||
'attribute_groups_index' => '屬性組列表',
|
||||
'attribute_groups_create' => '創建屬性組',
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ return [
|
|||
'add_variable_image' => '添加規格圖片',
|
||||
'default_main_product' => '默認主商品',
|
||||
'modify_order' => '雙擊修改、拖動調整順序',
|
||||
'weight_text' => '重量',
|
||||
'weight_class' => '重量單位',
|
||||
|
||||
'confirm_batch_product' => '確認要批量刪除選中的商品嗎? ',
|
||||
'confirm_batch_status' => '確認要批量修改選中的商品的狀態嗎? ',
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ return [
|
|||
'model' => '型號',
|
||||
'quantity' => '庫存',
|
||||
'image' => '圖片',
|
||||
'kg' => '千克',
|
||||
'g' => '克',
|
||||
'oz' => '盎司',
|
||||
'lb' => '磅',
|
||||
|
||||
'active' => '上架',
|
||||
'inactive' => '下架',
|
||||
|
|
|
|||
|
|
@ -241,6 +241,9 @@
|
|||
this.source.guest_shipping_address = res.current.guest_shipping_address;
|
||||
this.source.guest_payment_address = res.current.guest_payment_address;
|
||||
} else {
|
||||
if (this.same_as_shipping_address) {
|
||||
this.source.guest_payment_address = res.current.guest_shipping_address;
|
||||
}
|
||||
this.source[this.dialogAddress.type] = res.current[this.dialogAddress.type];
|
||||
}
|
||||
this.$message.success('{{ __('common.edit_success') }}');
|
||||
|
|
|
|||
Loading…
Reference in New Issue