openclaw/projects/glass-v2-migration-detailed-plan.md

13 KiB
Raw Blame History

glass-v2 迁移详细计划

📋 概述

将 glass-v2 的 5 个功能模块迁移到 glass 项目,同时适配:

  1. 多租户架构team_id 隔离)
  2. Spatie Permission 权限系统
  3. Filament 4.x API

🎯 模块清单

1. 产品分类管理ProductCategory

数据库

状态: glass 项目已有 categories 表,需要增强 已创建的迁移:

  • 2026_02_02_140000_add_icon_and_color_to_categories_table.php

模型适配

需要: 创建或更新 app/Models/Category.php

<?php

namespace App\Models;

use App\Models\Concerns\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Category extends Model
{
    use BelongsToTenant;

    protected $fillable = [
        'name',
        'name_en',
        'slug',
        'icon',
        'color',
        'description',
        'sort_order',
        'status',  // 'active' or 'inactive' (改为 is_active)
    ];

    protected $casts = [
        'status' => 'boolean',
        'sort_order' => 'integer',
    ];

    // 添加字段以兼容 v2
    protected $appends = ['is_active'];

    public function getIsActiveAttribute(): bool
    {
        return $this->status === 'active';
    }

    public function products(): HasMany
    {
        return $this->hasMany(Product::class);
    }

    protected static function boot()
    {
        parent::boot();

        static::creating(function ($category) {
            if (empty($category->slug)) {
                $category->slug = \Illuminate\Support\Str::slug($category->name);
            }
        });
    }
}

Filament 资源

需要创建: app/Filament/Resources/Categories/CategoryResource.php 来源: v2 的 ProductCategoryResource.php 适配点:

  1. 修改命名空间:ProductCategoriesCategories
  2. 修改模型:ProductCategoryCategory
  3. 修改权限检查:
    // v2: auth()->user()->is_admin
    // glass: 使用 Gate 或 Policy
    public static function canViewAny(): bool
    {
        return auth()->user()->can('view_any_categories');
    }
    
  4. 修改导航组:'库存与供应链' → 保持
  5. 添加团队范围:默认会应用 BelongsToTenant

Seeder

需要创建: database/seeders/CategorySeeder.php 预置数据:

  • 镜架 (heroicon-o-eye, 蓝色 #3b82f6)
  • 镜片 (heroicon-o-circle-stack, 绿色 #10b981)
  • 隐形眼镜 (heroicon-o-eye-dropper, 紫色 #8b5cf6)
  • 护理液 (heroicon-o-beaker, 青色 #06b6d4)
  • 配件 (heroicon-o-wrench-screwdriver, 橙色 #f59e0b)

2. 品牌管理Brand

数据库

状态: glass 项目已有 brands 表,需要增强 已创建的迁移:

  • 2026_02_02_140100_add_slug_and_sort_order_to_brands_table.php

模型适配

需要: 创建或更新 app/Models/Brand.php

<?php

namespace App\Models;

use App\Models\Concerns\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Brand extends Model
{
    use BelongsToTenant;

    protected $fillable = [
        'name',
        'name_en',
        'slug',
        'logo',
        'description',
        'website',
        'country',
        'sort_order',
        'status',
    ];

    protected $casts = [
        'status' => 'boolean',
        'sort_order' => 'integer',
    ];

    protected $appends = ['is_active'];

    public function getIsActiveAttribute(): bool
    {
        return $this->status === 'active';
    }

    public function products(): HasMany
    {
        return $this->hasMany(Product::class);
    }

    protected static function boot()
    {
        parent::boot();

        static::creating(function ($brand) {
            if (empty($brand->slug)) {
                $brand->slug = \Illuminate\Support\Str::slug($brand->name);
            }
        });
    }
}

Filament 资源

需要创建: app/Filament/Resources/Brands/BrandResource.php 来源: v2 的 BrandResource.php 适配点:

  1. 模型名称保持不变
  2. 修改权限检查(同上)
  3. 确保 logo 上传目录正确:brands/

Seeder

需要创建: database/seeders/BrandSeeder.php 预置数据:

  • 雷朋 (Ray-Ban, 意大利)
  • 暴龙 (Bolon, 中国)
  • 蔡司 (Zeiss, 德国)
  • 依视路 (Essilor, 法国)
  • 强生 (Johnson, 美国)
  • 博士伦 (Bausch & Lomb, 美国)
  • 海昌 (Hydron, 中国)

3. 采购订单管理PurchaseOrder

数据库

状态: glass 项目没有此表 已创建的迁移:

  • 2026_02_02_140200_create_purchase_orders_table.php
  • 2026_02_02_140300_create_purchase_order_items_table.php

模型

需要创建: app/Models/PurchaseOrder.phpapp/Models/PurchaseOrderItem.php 来源: v2 的模型 适配点:

  1. 添加 BelongsToTenant trait
  2. 确保所有关系正确
  3. 添加团队范围查询

PurchaseOrderItem:

<?php

namespace App\Models;

use App\Models\Concerns\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class PurchaseOrderItem extends Model
{
    use BelongsToTenant;

    protected $fillable = [
        'purchase_order_id',
        'product_id',
        'quantity',
        'received_quantity',
        'unit_cost',
        'total_cost',
        'note',
    ];

    protected $casts = [
        'quantity' => 'integer',
        'received_quantity' => 'integer',
        'unit_cost' => 'decimal:2',
        'total_cost' => 'decimal:2',
    ];

    public function purchaseOrder(): BelongsTo
    {
        return $this->belongsTo(PurchaseOrder::class);
    }

    public function product(): BelongsTo
    {
        return $this->belongsTo(Product::class);
    }

    public function getPendingQuantityAttribute(): int
    {
        return $this->quantity - $this->received_quantity;
    }
}

Filament 资源

需要创建: app/Filament/Resources/PurchaseOrders/PurchaseOrderResource.php 来源: v2 的 PurchaseOrderResource.php 适配点:

  1. 修改权限检查
  2. 确保关联关系正确加载(with()
  3. 状态流转逻辑保持不变

权限配置

需要添加到 RoleAndPermissionSeeder:

$purchasePermissions = [
    'view_any_purchase_orders',
    'view_purchase_orders',
    'create_purchase_orders',
    'update_purchase_orders',
    'delete_purchase_orders',
    'receive_purchase_orders',
    'stock_in_purchase_orders',
];

// 分配角色
$manager->givePermissionTo($purchasePermissions);
$warehouseStaff->givePermissionTo(['view_any_purchase_orders', 'view_purchase_orders', 'create_purchase_orders', 'receive_purchase_orders']);

4. 库存流水管理InventoryTransaction

数据库

状态: glass 项目没有此表 已创建的迁移:

  • 2026_02_02_140400_create_inventory_transactions_table.php

模型

需要创建: app/Models/InventoryTransaction.php 来源: v2 的模型 适配点:

  1. 添加 BelongsToTenant trait
  2. 确保多态关联正确
<?php

namespace App\Models;

use App\Models\Concerns\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;

class InventoryTransaction extends Model
{
    use BelongsToTenant;

    protected $fillable = [
        'product_id',
        'type',  // 'in', 'out', 'adjust'
        'quantity',
        'reference_type',
        'reference_id',
        'staff_id',
        'balance_after',
        'note',
    ];

    protected $casts = [
        'quantity' => 'integer',
        'balance_after' => 'integer',
    ];

    public function product(): BelongsTo
    {
        return $this->belongsTo(Product::class);
    }

    public function staff(): BelongsTo
    {
        return $this->belongsTo(User::class, 'staff_id');
    }

    public function reference(): MorphTo
    {
        return $this->morphTo();
    }
}

Filament 资源

需要创建: app/Filament/Resources/InventoryTransactions/InventoryTransactionResource.php 来源: v2 的 InventoryTransactionResource.php 适配点:

  1. 修改权限检查
  2. 保持只读(表单禁用)
  3. 过滤器适配 Filament 4.x

权限配置

需要添加:

$inventoryPermissions = [
    'view_any_inventory_transactions',
    'view_inventory_transactions',
];

// 所有角色都可以查看库存流水
$allRoles->each(fn($role) => $role->givePermissionTo($inventoryPermissions));

5. 员工排班管理StaffSchedule

数据库

状态: glass 项目没有此表 已创建的迁移:

  • 2026_02_02_140500_create_staff_schedules_table.php

模型

需要创建: app/Models/StaffSchedule.php 来源: v2 的模型 适配点:

  1. 添加 BelongsToTenant trait
  2. 保持所有辅助方法
<?php

namespace App\Models;

use App\Models\Concerns\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class StaffSchedule extends Model
{
    use BelongsToTenant;

    public const SHIFT_MORNING = 'morning';
    public const SHIFT_AFTERNOON = 'afternoon';
    public const SHIFT_FULL_DAY = 'full_day';
    public const SHIFT_CUSTOM = 'custom';

    // ... 其余代码保持不变 ...
}

Filament 资源

需要创建: app/Filament/Resources/StaffSchedules/StaffScheduleResource.php 来源: v2 的 StaffScheduleResource.php 适配点:

  1. 修改权限检查
  2. 移除 v2 特定的导航组(或保持"系统管理"

权限配置

需要添加:

$schedulePermissions = [
    'view_any_staff_schedules',
    'view_staff_schedules',
    'create_staff_schedules',
    'update_staff_schedules',
    'delete_staff_schedules',
];

// 管理权限角色
$manager->givePermissionTo($schedulePermissions);
$shopOwner->givePermissionTo($schedulePermissions);

🔧 全局适配步骤

1. 权限系统扩展

database/seeders/RoleAndPermissionSeeder.php 中添加:

// 产品分类和品牌权限
$categoryAndBrandPermissions = [
    'view_any_categories',
    'view_categories',
    'create_categories',
    'update_categories',
    'delete_categories',
    'view_any_brands',
    'view_brands',
    'create_brands',
    'update_brands',
    'delete_brands',
];

// 采购订单权限(已在上方定义)
// 库存流水权限(已在上方定义)
// 员工排班权限(已在上方定义)

// 分配给角色
$shopOwner->givePermissionTo([...$categoryAndBrandPermissions, ...$purchasePermissions, ...$inventoryPermissions, ...$schedulePermissions]);
$shopAdmin->givePermissionTo([...$categoryAndBrandPermissions, ...$purchasePermissions, ...$inventoryPermissions]);
$manager->givePermissionTo([...$categoryAndBrandPermissions, ...$purchasePermissions, ...$inventoryPermissions]);
$warehouseStaff->givePermissionTo(['view_any_categories', 'view_any_brands', ...$purchasePermissions, ...$inventoryPermissions]);

2. 中文本地化更新

lang/zh_CN.json 中添加:

{
  "resources": {
    "categories": {
      "label": "产品分类",
      "plural_label": "产品分类",
      "navigation_label": "产品分类"
    },
    "brands": {
      "label": "品牌",
      "plural_label": "品牌",
      "navigation_label": "品牌管理"
    },
    "purchase_orders": {
      "label": "采购单",
      "plural_label": "采购管理",
      "navigation_label": "采购订单"
    },
    "inventory_transactions": {
      "label": "库存记录",
      "plural_label": "库存交易记录",
      "navigation_label": "库存"
    },
    "staff_schedules": {
      "label": "排班",
      "plural_label": "员工排班管理",
      "navigation_label": "员工排班"
    }
  },
  "actions": {
    "receive": "收货入库",
    "stock_in": "补入库",
    "duplicate": "复制到明天"
  }
}

3. 导航分组组织

在所有 Resource 中统一导航分组:

  • 产品分类:库存与供应链
  • 品牌管理:库存与供应链
  • 采购订单:库存与供应链
  • 库存流水:库存与供应链
  • 员工排班:系统管理 或保持单独

检查清单

迁移前

  • 备份 glass 项目数据库
  • 确认 glass 项目的数据库连接配置
  • 准备测试数据

数据库迁移

  • 运行所有新迁移文件
  • 验证表结构正确
  • 检查外键约束

模型创建

  • 创建所有模型文件
  • 添加 BelongsToTenant trait
  • 测试模型关系

Filament 资源

  • 创建所有 Resource 文件
  • 适配权限检查
  • 测试表单和表格

Seeder

  • 创建 CategorySeeder
  • 创建 BrandSeeder
  • 运行 Seeder 填充初始数据

测试

  • 测试 CRUD 操作
  • 测试权限隔离
  • 测试跨租户数据隔离
  • 测试采购订单收货流程
  • 测试库存流水自动记录

🚀 执行顺序

第一步数据库结构30 分钟)

# 所有迁移文件已创建,运行迁移
#(需要先配置数据库连接)
php artisan migrate

第二步模型创建45 分钟)

  1. 复制并适配所有模型
  2. 添加 BelongsToTenant trait
  3. 测试关系

第三步Filament 资源1 小时)

  1. 复制所有 Resource 文件
  2. 适配权限检查
  3. 调整导航

第四步:权限和 Seeder30 分钟)

  1. 更新 RoleAndPermissionSeeder
  2. 创建 CategorySeeder 和 BrandSeeder
  3. 运行 Seeder

第五步测试和调试30 分钟)

  1. 测试所有功能
  2. 修复问题

总预计时间: 3 小时


美羊羊 🐑