!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:
mengwb 2023-03-24 10:23:55 +00:00 committed by Edward Yang
parent d233cd2fca
commit 86b3d33d6d
25 changed files with 158 additions and 10 deletions

View File

@ -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()),
],

View File

@ -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())]));

View File

@ -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];
}
}

View File

@ -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',

View File

@ -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)) {

View File

@ -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,

View File

@ -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');
});
}
};

View File

@ -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" => "运动户外"],

View File

@ -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 " />

View File

@ -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?',

View File

@ -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',

View File

@ -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? ',

View File

@ -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',

View File

@ -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?',

View File

@ -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? ',

View File

@ -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?',

View File

@ -39,6 +39,8 @@ return [
'add_variable_image' => '仕様画像追加',
'default_main_product' => 'デフォルトのメイン製品',
'modify_order' => 'ダブルクリックして変更、ドラッグして順序を調整',
'weight_text' => '重さ',
'weight_class' => '重量単位',
'confirm_batch_product' => '選択した製品をまとめて削除しますか? ',
'confirm_batch_status' => 'バッチで選択した製品のステータスを変更することを確認しますか? ',

View File

@ -39,6 +39,8 @@ return [
'add_variable_image' => 'Добавить изображение спецификации',
'default_main_product' => 'Основной продукт по умолчанию',
'modify_order' => 'Дважды щелкните, чтобы изменить, перетащите, чтобы настроить порядок',
'weight_text' => 'вес',
'weight_class' => 'единица веса',
'confirm_batch_product' => 'Вы уверены, что хотите удалить выбранные элементы сразу?',
'confirm_batch_status' => 'Вы уверены, что хотите массово изменить статус выбранных элементов?',

View File

@ -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' => '创建属性组',

View File

@ -39,6 +39,8 @@ return [
'add_variable_image' => '添加规格图片',
'default_main_product' => '默认主商品',
'modify_order' => '双击修改、拖动调整顺序',
'weight_text' => '重量',
'weight_class' => '重量单位',
'confirm_batch_product' => '确认要批量删除选中的商品吗?',
'confirm_batch_status' => '确认要批量修改选中的商品的状态吗?',

View File

@ -20,6 +20,10 @@ return [
'model' => '型号',
'quantity' => '库存',
'image' => '图片',
'kg' => '千克',
'g' => '克',
'oz' => '盎司',
'lb' => '磅',
'active' => '上架',
'inactive' => '下架',

View File

@ -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' => '創建屬性組',

View File

@ -39,6 +39,8 @@ return [
'add_variable_image' => '添加規格圖片',
'default_main_product' => '默認主商品',
'modify_order' => '雙擊修改、拖動調整順序',
'weight_text' => '重量',
'weight_class' => '重量單位',
'confirm_batch_product' => '確認要批量刪除選中的商品嗎? ',
'confirm_batch_status' => '確認要批量修改選中的商品的狀態嗎? ',

View File

@ -20,6 +20,10 @@ return [
'model' => '型號',
'quantity' => '庫存',
'image' => '圖片',
'kg' => '千克',
'g' => '克',
'oz' => '盎司',
'lb' => '磅',
'active' => '上架',
'inactive' => '下架',

View File

@ -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') }}');