first commit

This commit is contained in:
liu
2026-07-23 12:31:37 +08:00
parent 760c9ba8b6
commit 00a0938a1b
14 changed files with 1442 additions and 3 deletions
@@ -14,14 +14,25 @@ return new class extends Migration
if (! Schema::hasTable('user')) {
Schema::create('user', function (Blueprint $table) {
$table->increments('id')->comment('用户ID');
$table->string('username', 20)->unique()->comment('用户名');
$table->string('password', 100)->comment('密码');
$table->string('username', 20)->nullable()->unique()->comment('用户名(微信注册用户可为空)');
$table->string('password', 100)->nullable()->comment('密码(微信注册用户可为空)');
$table->string('nickname', 20)->default('')->comment('昵称');
$table->string('email', 50)->default('')->comment('邮箱');
$table->timestamp('email_verified_at')->nullable();
// 小程序用户扩展字段(微信授权登录,自动识别门店/供应商身份)
$table->string('openid', 64)->nullable()->unique()->comment('微信OpenID(小程序用户唯一标识)');
$table->string('unionid', 64)->default('')->comment('微信UnionID');
$table->string('phone', 20)->default('')->comment('手机号(微信授权获取,用于匹配门店/供应商)');
$table->string('avatar', 255)->default('')->comment('头像');
$table->integer('type')->default(0)->comment('用户类型(0待绑定 1门店 2供应商)');
$table->integer('store_id')->default(0)->comment('关联门店IDtype=1时有效)');
$table->integer('supplier_id')->default(0)->comment('关联供应商IDtype=2时有效)');
$table->integer('status')->default(1)->comment('状态(1正常 0停用)');
$table->timestamp('last_login_at')->nullable()->comment('最后登录时间');
$table->rememberToken();
$table->timestamps();
$table->comment('APP用户表');
$table->index(['type', 'store_id'], 'user_type_store_index');
$table->comment('APP用户表(含小程序用户)');
});
}
}
@@ -0,0 +1,94 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
* 基础档案:客户等级、门店、供应商、消息通知(小程序用户已并入 user 表)
*/
public function up(): void
{
// 客户等级表(价格体系按等级定价)
if (! Schema::hasTable('customer_level')) {
Schema::create('customer_level', function (Blueprint $table) {
$table->increments('id')->comment('等级ID');
$table->string('name', 50)->comment('等级名称(如:一级客户、二级客户)');
$table->integer('sort')->default(0)->comment('排序');
$table->integer('status')->default(1)->comment('状态(1正常 0停用)');
$table->string('remark', 255)->default('')->comment('备注');
$table->timestamps();
$table->comment('客户等级表');
});
}
// 门店表(小程序下单主体,即客户)
if (! Schema::hasTable('store')) {
Schema::create('store', function (Blueprint $table) {
$table->increments('id')->comment('门店ID');
$table->string('name', 100)->comment('门店名称');
$table->string('code', 50)->unique()->comment('门店编码');
$table->integer('level_id')->default(0)->comment('客户等级ID(决定商品价格)');
$table->string('contact', 50)->default('')->comment('联系人');
$table->string('phone', 20)->default('')->comment('联系电话');
$table->string('address', 255)->default('')->comment('门店地址');
$table->integer('payment_cycle_days')->default(0)->comment('回款周期(天),门店可自行修改,影响对账单应结算日期');
$table->integer('status')->default(1)->comment('状态(1正常 0停用)');
$table->string('remark', 255)->default('')->comment('备注');
$table->timestamps();
$table->softDeletes();
$table->index(['level_id', 'status'], 'store_level_status_index');
$table->comment('门店表');
});
}
// 供应商表
if (! Schema::hasTable('supplier')) {
Schema::create('supplier', function (Blueprint $table) {
$table->increments('id')->comment('供应商ID');
$table->string('name', 100)->comment('供应商名称');
$table->string('contact', 50)->default('')->comment('联系人');
$table->string('phone', 20)->default('')->comment('联系电话');
$table->string('address', 255)->default('')->comment('地址');
$table->string('main_products', 255)->default('')->comment('主营品类');
$table->integer('status')->default(1)->comment('状态(1正常 0停用)');
$table->string('remark', 255)->default('')->comment('备注');
$table->timestamps();
$table->softDeletes();
$table->comment('供应商表');
});
}
// 消息通知表(订单状态变更、价格调整等通知)
// 小程序用户已并入 user 表,不再单独建 mini_user 表
if (! Schema::hasTable('notice')) {
Schema::create('notice', function (Blueprint $table) {
$table->increments('id')->comment('通知ID');
$table->integer('user_id')->default(0)->comment('接收用户IDuser表,0为全员广播)');
$table->string('type', 20)->default('system')->comment('通知类型(order订单 price价格 system系统)');
$table->string('title', 100)->comment('标题');
$table->string('content', 500)->default('')->comment('内容');
$table->json('data')->nullable()->comment('业务关联数据(如订单ID');
$table->integer('is_read')->default(0)->comment('是否已读(1已读 0未读)');
$table->timestamp('read_at')->nullable()->comment('阅读时间');
$table->timestamps();
$table->index(['user_id', 'is_read'], 'notice_user_read_index');
$table->comment('消息通知表');
});
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('customer_level');
Schema::dropIfExists('store');
Schema::dropIfExists('supplier');
Schema::dropIfExists('notice');
}
};
@@ -0,0 +1,74 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
* 商品中心(A1-A3):商品分类、商品档案、客户等级价格体系
*/
public function up(): void
{
// 商品分类表(A3 多级分类:蔬菜/水果/其他,子分类排序)
if (! Schema::hasTable('product_category')) {
Schema::create('product_category', function (Blueprint $table) {
$table->increments('id')->comment('分类ID');
$table->integer('parent_id')->default(0)->comment('父级分类ID0为顶级)');
$table->string('name', 50)->comment('分类名称');
$table->integer('sort')->default(0)->comment('排序(采购单导出按此排序)');
$table->integer('status')->default(1)->comment('状态(1正常 0停用)');
$table->timestamps();
$table->index(['parent_id', 'sort'], 'product_category_parent_sort_index');
$table->comment('商品分类表');
});
}
// 商品表(A1 商品档案:品名、规格/包规、供应商、等级)
if (! Schema::hasTable('product')) {
Schema::create('product', function (Blueprint $table) {
$table->increments('id')->comment('商品ID');
$table->integer('category_id')->default(0)->comment('商品分类ID');
$table->integer('supplier_id')->default(0)->comment('默认供应商ID');
$table->string('name', 100)->comment('品名');
$table->string('spec', 100)->default('')->comment('规格/包规');
$table->string('grade', 50)->default('')->comment('商品等级');
$table->string('unit', 20)->default('斤')->comment('计价单位(斤/件/箱等)');
$table->string('image', 255)->default('')->comment('商品图片');
$table->integer('sort')->default(0)->comment('排序');
$table->integer('status')->default(1)->comment('状态(1上架 0下架)');
$table->string('remark', 255)->default('')->comment('备注');
$table->timestamps();
$table->softDeletes();
$table->index(['category_id', 'status'], 'product_category_status_index');
$table->index(['supplier_id'], 'product_supplier_index');
$table->comment('商品表');
});
}
// 商品等级价格表(A2 价格策略:同一商品对不同客户等级显示不同单价)
if (! Schema::hasTable('product_price')) {
Schema::create('product_price', function (Blueprint $table) {
$table->increments('id')->comment('价格ID');
$table->integer('product_id')->comment('商品ID');
$table->integer('level_id')->comment('客户等级ID');
$table->decimal('price', 10, 2)->default(0)->comment('该等级下的商品单价');
$table->timestamps();
$table->unique(['product_id', 'level_id'], 'product_price_product_level_unique');
$table->comment('商品等级价格表');
});
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('product_category');
Schema::dropIfExists('product');
Schema::dropIfExists('product_price');
}
};
@@ -0,0 +1,64 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
* 门店订货:小程序下单(品名/单价/订货量/重量/单品金额/总金额)
*/
public function up(): void
{
// 门店订货单表
if (! Schema::hasTable('store_order')) {
Schema::create('store_order', function (Blueprint $table) {
$table->increments('id')->comment('订单ID');
$table->string('order_no', 32)->unique()->comment('订单编号');
$table->integer('store_id')->comment('门店ID');
$table->date('order_date')->comment('订货日期');
$table->decimal('total_quantity', 10, 2)->default(0)->comment('订货总量');
$table->decimal('total_weight', 10, 3)->default(0)->comment('总重量');
$table->decimal('total_amount', 10, 2)->default(0)->comment('订单总金额');
$table->integer('status')->default(0)->comment('订单状态(0待汇总 1已汇总 2配送中 3已完成 4已取消)');
$table->string('remark', 255)->default('')->comment('订单备注');
$table->timestamps();
$table->index(['store_id', 'order_date'], 'store_order_store_date_index');
$table->index(['status'], 'store_order_status_index');
$table->comment('门店订货单表');
});
}
// 门店订货明细表(下单时快照等级单价,价格变更不影响历史订单)
if (! Schema::hasTable('store_order_item')) {
Schema::create('store_order_item', function (Blueprint $table) {
$table->increments('id')->comment('明细ID');
$table->integer('order_id')->comment('订单ID');
$table->integer('store_id')->comment('门店ID(冗余,便于按门店筛选)');
$table->integer('product_id')->comment('商品ID');
$table->string('product_name', 100)->comment('品名(快照)');
$table->string('product_spec', 100)->default('')->comment('规格/包规(快照)');
$table->decimal('price', 10, 2)->default(0)->comment('单价(下单时客户等级价快照)');
$table->decimal('quantity', 10, 2)->default(0)->comment('订货量');
$table->decimal('weight', 10, 3)->default(0)->comment('重量');
$table->decimal('amount', 10, 2)->default(0)->comment('单品金额');
$table->string('remark', 255)->default('')->comment('门店下单备注');
$table->timestamps();
$table->index(['order_id'], 'store_order_item_order_index');
$table->index(['store_id', 'product_id'], 'store_order_item_store_product_index');
$table->comment('门店订货明细表');
});
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('store_order');
Schema::dropIfExists('store_order_item');
}
};
@@ -0,0 +1,87 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
* 采购管理(C1-C6):采购单、采购明细(发送供应商)、采购金额分摊(D3)
*/
public function up(): void
{
// 采购单表(C1 基于所有门店订单汇总生成)
if (! Schema::hasTable('purchase_order')) {
Schema::create('purchase_order', function (Blueprint $table) {
$table->increments('id')->comment('采购单ID');
$table->string('purchase_no', 32)->unique()->comment('采购单编号');
$table->date('purchase_date')->comment('采购日期');
$table->integer('status')->default(0)->comment('采购单状态(0草稿 1已确认 2部分发送 3全部发送 4已完成)');
$table->decimal('total_quantity', 10, 2)->default(0)->comment('采购总量');
$table->decimal('total_weight', 10, 3)->default(0)->comment('采购总重量');
$table->decimal('estimate_amount', 10, 2)->default(0)->comment('预估金额(按订货汇总)');
$table->decimal('actual_amount', 10, 2)->default(0)->comment('实际采购金额');
$table->integer('operator_id')->default(0)->comment('采购员(系统用户ID');
$table->string('remark', 255)->default('')->comment('备注');
$table->timestamps();
$table->index(['purchase_date', 'status'], 'purchase_order_date_status_index');
$table->comment('采购单表');
});
}
// 采购单明细表(C2/C3 按分类排序导出,C4 可修改,C5/C6 发送供应商及状态标记)
if (! Schema::hasTable('purchase_order_item')) {
Schema::create('purchase_order_item', function (Blueprint $table) {
$table->increments('id')->comment('明细ID');
$table->integer('purchase_id')->comment('采购单ID');
$table->integer('product_id')->comment('商品ID');
$table->integer('supplier_id')->default(0)->comment('供应商ID');
$table->string('product_name', 100)->comment('品名(快照)');
$table->string('product_spec', 100)->default('')->comment('规格/包规(快照)');
$table->decimal('price', 10, 2)->default(0)->comment('采购单价');
$table->decimal('quantity', 10, 2)->default(0)->comment('采购量');
$table->decimal('weight', 10, 3)->default(0)->comment('实际称重');
$table->decimal('amount', 10, 2)->default(0)->comment('采购金额');
$table->integer('sort')->default(0)->comment('排序(导出用)');
$table->integer('is_sent')->default(0)->comment('是否已发送供应商(1已发送 0未发送)');
$table->timestamp('sent_at')->nullable()->comment('发送时间');
$table->string('remark', 255)->default('')->comment('备注');
$table->timestamps();
$table->index(['purchase_id'], 'purchase_order_item_purchase_index');
$table->index(['supplier_id', 'is_sent'], 'purchase_order_item_supplier_sent_index');
$table->comment('采购单明细表');
});
}
// 采购分摊表(D3 采购金额自动分配到各门店/各单品)
if (! Schema::hasTable('purchase_allocation')) {
Schema::create('purchase_allocation', function (Blueprint $table) {
$table->increments('id')->comment('分摊ID');
$table->integer('purchase_item_id')->comment('采购单明细ID');
$table->integer('order_item_id')->comment('门店订货明细ID');
$table->integer('store_id')->comment('分摊到的门店ID');
$table->integer('product_id')->comment('商品ID');
$table->decimal('quantity', 10, 2)->default(0)->comment('分摊数量');
$table->decimal('weight', 10, 3)->default(0)->comment('分摊重量');
$table->decimal('amount', 10, 2)->default(0)->comment('分摊金额');
$table->timestamps();
$table->index(['purchase_item_id'], 'purchase_allocation_item_index');
$table->index(['order_item_id'], 'purchase_allocation_order_item_index');
$table->index(['store_id'], 'purchase_allocation_store_index');
$table->comment('采购分摊表');
});
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('purchase_order');
Schema::dropIfExists('purchase_order_item');
Schema::dropIfExists('purchase_allocation');
}
};
@@ -0,0 +1,139 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
* 对账管理(D1-D10):财务对账、门店对账单、结算表
*/
public function up(): void
{
// 财务对账单表(D1 按品类对账、D2 按供应商筛选)
if (! Schema::hasTable('reconciliation')) {
Schema::create('reconciliation', function (Blueprint $table) {
$table->increments('id')->comment('对账ID');
$table->string('recon_no', 32)->unique()->comment('对账单编号');
$table->string('title', 100)->comment('对账单标题');
$table->date('period_start')->comment('对账周期开始');
$table->date('period_end')->comment('对账周期结束');
$table->integer('category_id')->default(0)->comment('按品类筛选(0为全部,D1');
$table->integer('supplier_id')->default(0)->comment('按供应商筛选(0为全部,D2');
$table->decimal('publish_amount', 10, 2)->default(0)->comment('公布金额合计(D5');
$table->decimal('actual_amount', 10, 2)->default(0)->comment('实际采购金额合计(D5');
$table->decimal('diff_amount', 10, 2)->default(0)->comment('差额合计(D5');
$table->integer('status')->default(0)->comment('状态(0对账中 1已完成 2已生成结算表)');
$table->integer('operator_id')->default(0)->comment('对账员(系统用户ID');
$table->string('remark', 255)->default('')->comment('备注');
$table->timestamps();
$table->index(['period_start', 'period_end'], 'reconciliation_period_index');
$table->comment('财务对账单表');
});
}
// 财务对账明细表(D4 数据修改、D5 差额对比、D6 单品级门店备注、D8 对账状态标记)
if (! Schema::hasTable('reconciliation_item')) {
Schema::create('reconciliation_item', function (Blueprint $table) {
$table->increments('id')->comment('明细ID');
$table->integer('recon_id')->comment('财务对账单ID');
$table->integer('store_id')->comment('门店ID');
$table->integer('purchase_item_id')->default(0)->comment('采购单明细ID');
$table->integer('order_item_id')->default(0)->comment('门店订货明细ID');
$table->integer('product_id')->comment('商品ID');
$table->string('product_name', 100)->comment('品名(快照)');
$table->decimal('quantity', 10, 2)->default(0)->comment('数量(D4可修改)');
$table->decimal('weight', 10, 3)->default(0)->comment('称重数据(D4可修改)');
$table->decimal('publish_amount', 10, 2)->default(0)->comment('公布金额(门店订货金额)');
$table->decimal('actual_amount', 10, 2)->default(0)->comment('实际采购金额(分摊)');
$table->decimal('diff_amount', 10, 2)->default(0)->comment('差额');
$table->integer('is_reconciled')->default(0)->comment('对账状态(1已对账 0未对账,D8)');
$table->string('store_remark', 255)->default('')->comment('单品级门店备注(D6');
$table->integer('sort')->default(0)->comment('排序');
$table->timestamps();
$table->index(['recon_id'], 'reconciliation_item_recon_index');
$table->index(['store_id', 'is_reconciled'], 'reconciliation_item_store_index');
$table->comment('财务对账明细表');
});
}
// 门店对账单表(门店在小程序端自助生成,回款周期快照决定应结算日期)
if (! Schema::hasTable('statement')) {
Schema::create('statement', function (Blueprint $table) {
$table->increments('id')->comment('对账单ID');
$table->string('statement_no', 32)->unique()->comment('对账单编号');
$table->integer('store_id')->comment('门店ID');
$table->date('period_start')->comment('对账周期开始');
$table->date('period_end')->comment('对账周期结束');
$table->decimal('total_amount', 10, 2)->default(0)->comment('对账总金额');
$table->integer('payment_cycle_days')->default(0)->comment('回款周期(天),生成时从门店快照');
$table->date('settlement_date')->nullable()->comment('应结算日期(按回款周期计算)');
$table->integer('status')->default(0)->comment('状态(0未对账 1已对账 2已结算)');
$table->timestamp('reconciled_at')->nullable()->comment('对账完成时间');
$table->timestamp('settled_at')->nullable()->comment('结算时间');
$table->string('remark', 255)->default('')->comment('备注');
$table->timestamps();
$table->index(['store_id', 'period_start'], 'statement_store_period_index');
$table->comment('门店对账单表');
});
}
// 门店对账单明细表(每个单品/订单的对账状态标识)
if (! Schema::hasTable('statement_item')) {
Schema::create('statement_item', function (Blueprint $table) {
$table->increments('id')->comment('明细ID');
$table->integer('statement_id')->comment('对账单ID');
$table->integer('order_id')->comment('订单ID');
$table->integer('order_item_id')->comment('订货明细ID');
$table->integer('product_id')->comment('商品ID');
$table->string('product_name', 100)->comment('品名(快照)');
$table->decimal('price', 10, 2)->default(0)->comment('单价');
$table->decimal('quantity', 10, 2)->default(0)->comment('订货量');
$table->decimal('weight', 10, 3)->default(0)->comment('重量');
$table->decimal('amount', 10, 2)->default(0)->comment('单品金额');
$table->integer('is_reconciled')->default(0)->comment('对账状态(1已对账 0未对账)');
$table->string('store_remark', 255)->default('')->comment('门店备注');
$table->timestamps();
$table->index(['statement_id'], 'statement_item_statement_index');
$table->comment('门店对账单明细表');
});
}
// 结算表(D9 对账结束后生成结算表/回框统计表,D10 下载存档)
if (! Schema::hasTable('settlement')) {
Schema::create('settlement', function (Blueprint $table) {
$table->increments('id')->comment('结算ID');
$table->string('settlement_no', 32)->unique()->comment('结算单编号');
$table->integer('recon_id')->default(0)->comment('关联财务对账单ID');
$table->integer('store_id')->default(0)->comment('门店ID0为汇总结算)');
$table->date('period_start')->comment('结算周期开始');
$table->date('period_end')->comment('结算周期结束');
$table->decimal('total_amount', 10, 2)->default(0)->comment('结算总金额(公布)');
$table->decimal('actual_amount', 10, 2)->default(0)->comment('实际采购总金额');
$table->decimal('diff_amount', 10, 2)->default(0)->comment('差额合计');
$table->integer('status')->default(0)->comment('状态(0待结算 1已结算)');
$table->string('file_path', 255)->default('')->comment('导出文件路径(Excel/PDFD10');
$table->integer('operator_id')->default(0)->comment('操作人(系统用户ID');
$table->timestamp('settled_at')->nullable()->comment('结算时间');
$table->string('remark', 255)->default('')->comment('备注');
$table->timestamps();
$table->index(['store_id', 'status'], 'settlement_store_status_index');
$table->comment('结算表');
});
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('reconciliation');
Schema::dropIfExists('reconciliation_item');
Schema::dropIfExists('statement');
Schema::dropIfExists('statement_item');
Schema::dropIfExists('settlement');
}
};