feat: 第四阶段财务与人事薪资模块
- 新增2个migration(11张表): finance(6表)/hr(5表) - 新增11个Model + 11个Controller - 新增50条API路由(总计262条) - 新增2个前端API模块 + 10个管理页面 - 迁移运行通过, vite build验证通过
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
// 收支分类(树形)
|
||||
Schema::create('finance_categories', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('store_id')->index();
|
||||
$table->unsignedBigInteger('parent_id')->default(0)->index();
|
||||
$table->string('name', 50);
|
||||
$table->tinyInteger('type')->default(1)->comment('1=收入 2=支出');
|
||||
$table->tinyInteger('level')->default(1);
|
||||
$table->integer('sort')->default(0);
|
||||
$table->tinyInteger('status')->default(1);
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
// 收支记录
|
||||
Schema::create('finance_records', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('store_id')->index();
|
||||
$table->string('record_no', 50)->unique();
|
||||
$table->unsignedBigInteger('category_id')->nullable();
|
||||
$table->tinyInteger('type')->comment('1=收入 2=支出');
|
||||
$table->decimal('amount', 12, 2);
|
||||
$table->tinyInteger('pay_method')->nullable()->comment('1=现金 2=微信 3=支付宝 4=银行');
|
||||
$table->string('related_type', 50)->nullable()->comment('关联类型');
|
||||
$table->unsignedBigInteger('related_id')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->tinyInteger('audit_status')->default(0)->comment('0=待审核 1=已通过 2=已驳回');
|
||||
$table->unsignedBigInteger('audit_user_id')->nullable();
|
||||
$table->timestamp('audit_at')->nullable();
|
||||
$table->unsignedBigInteger('operator_id')->nullable();
|
||||
$table->date('record_date');
|
||||
$table->timestamps();
|
||||
$table->index(['store_id', 'type']);
|
||||
$table->index('record_date');
|
||||
});
|
||||
|
||||
// 客户账户
|
||||
Schema::create('customer_accounts', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('store_id')->index();
|
||||
$table->unsignedBigInteger('customer_id')->index();
|
||||
$table->decimal('cash_balance', 12, 2)->default(0);
|
||||
$table->decimal('card_balance', 12, 2)->default(0);
|
||||
$table->integer('points')->default(0);
|
||||
$table->timestamps();
|
||||
$table->unique(['store_id', 'customer_id']);
|
||||
});
|
||||
|
||||
// 账户流水
|
||||
Schema::create('account_transactions', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('store_id')->index();
|
||||
$table->unsignedBigInteger('customer_account_id')->index();
|
||||
$table->unsignedBigInteger('customer_id')->index();
|
||||
$table->tinyInteger('type')->comment('1=充值 2=消费 3=退款 4=积分变动');
|
||||
$table->decimal('amount', 12, 2);
|
||||
$table->decimal('balance_after', 12, 2);
|
||||
$table->string('related_type', 50)->nullable();
|
||||
$table->unsignedBigInteger('related_id')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->unsignedBigInteger('operator_id')->nullable();
|
||||
$table->timestamp('created_at')->nullable();
|
||||
});
|
||||
|
||||
// 储值卡种
|
||||
Schema::create('prepaid_cards', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('store_id')->index();
|
||||
$table->string('name', 100);
|
||||
$table->decimal('face_value', 10, 2);
|
||||
$table->decimal('sell_price', 10, 2);
|
||||
$table->decimal('discount_rate', 5, 2)->default(1.00);
|
||||
$table->integer('validity_days')->default(365);
|
||||
$table->tinyInteger('status')->default(1);
|
||||
$table->integer('sort')->default(0);
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
// 发票
|
||||
Schema::create('invoices', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('store_id')->index();
|
||||
$table->string('invoice_no', 50)->unique();
|
||||
$table->unsignedBigInteger('customer_id')->nullable();
|
||||
$table->tinyInteger('type')->default(1)->comment('1=电子 2=纸质');
|
||||
$table->decimal('amount', 12, 2);
|
||||
$table->decimal('tax_amount', 10, 2)->default(0);
|
||||
$table->string('title')->nullable();
|
||||
$table->string('tax_no', 50)->nullable();
|
||||
$table->string('related_type', 50)->nullable();
|
||||
$table->unsignedBigInteger('related_id')->nullable();
|
||||
$table->tinyInteger('status')->default(0)->comment('0=待开 1=已开 2=已红冲');
|
||||
$table->unsignedBigInteger('operator_id')->nullable();
|
||||
$table->timestamp('issued_at')->nullable();
|
||||
$table->timestamps();
|
||||
$table->index(['store_id', 'status']);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('invoices');
|
||||
Schema::dropIfExists('prepaid_cards');
|
||||
Schema::dropIfExists('account_transactions');
|
||||
Schema::dropIfExists('customer_accounts');
|
||||
Schema::dropIfExists('finance_records');
|
||||
Schema::dropIfExists('finance_categories');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
// 员工档案
|
||||
Schema::create('employee_profiles', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('store_id')->index();
|
||||
$table->unsignedBigInteger('user_id')->index();
|
||||
$table->string('employee_no', 30)->nullable();
|
||||
$table->date('hire_date')->nullable();
|
||||
$table->date('birth_date')->nullable();
|
||||
$table->tinyInteger('gender')->default(0)->comment('0=未知 1=男 2=女');
|
||||
$table->string('id_card', 20)->nullable();
|
||||
$table->string('education', 30)->nullable();
|
||||
$table->string('emergency_contact', 50)->nullable();
|
||||
$table->string('emergency_phone', 20)->nullable();
|
||||
$table->decimal('base_salary', 10, 2)->default(0);
|
||||
$table->decimal('position_salary', 10, 2)->default(0);
|
||||
$table->tinyInteger('status')->default(1)->comment('1=在职 2=试用 3=离职');
|
||||
$table->date('left_date')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
// 排班
|
||||
Schema::create('schedules', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('store_id')->index();
|
||||
$table->unsignedBigInteger('user_id')->index();
|
||||
$table->date('schedule_date');
|
||||
$table->tinyInteger('shift_type')->default(1)->comment('1=早班 2=中班 3=晚班 4=夜班 5=休息');
|
||||
$table->time('start_time')->nullable();
|
||||
$table->time('end_time')->nullable();
|
||||
$table->timestamp('created_at')->nullable();
|
||||
$table->index(['store_id', 'user_id', 'schedule_date']);
|
||||
});
|
||||
|
||||
// 考勤记录
|
||||
Schema::create('attendance_records', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('store_id')->index();
|
||||
$table->unsignedBigInteger('user_id')->index();
|
||||
$table->date('attendance_date');
|
||||
$table->time('clock_in')->nullable();
|
||||
$table->time('clock_out')->nullable();
|
||||
$table->tinyInteger('status')->default(1)->comment('1=正常 2=迟到 3=早退 4=旷工 5=请假');
|
||||
$table->decimal('overtime_hours', 5, 1)->default(0);
|
||||
$table->string('remark')->nullable();
|
||||
$table->timestamps();
|
||||
$table->index(['store_id', 'user_id', 'attendance_date']);
|
||||
});
|
||||
|
||||
// 请假申请
|
||||
Schema::create('leave_requests', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('store_id')->index();
|
||||
$table->unsignedBigInteger('user_id')->index();
|
||||
$table->tinyInteger('type')->comment('1=年假 2=事假 3=病假 4=调休 5=产假 6=婚假');
|
||||
$table->date('start_date');
|
||||
$table->date('end_date');
|
||||
$table->decimal('days', 4, 1);
|
||||
$table->text('reason')->nullable();
|
||||
$table->tinyInteger('status')->default(0)->comment('0=待审批 1=已批准 2=已拒绝');
|
||||
$table->unsignedBigInteger('audit_user_id')->nullable();
|
||||
$table->timestamp('audit_at')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
// 工资记录
|
||||
Schema::create('salary_records', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('store_id')->index();
|
||||
$table->unsignedBigInteger('user_id')->index();
|
||||
$table->string('year_month', 7)->comment('YYYY-MM');
|
||||
$table->decimal('base_salary', 10, 2)->default(0);
|
||||
$table->decimal('position_salary', 10, 2)->default(0);
|
||||
$table->decimal('performance', 10, 2)->default(0);
|
||||
$table->decimal('overtime_pay', 10, 2)->default(0);
|
||||
$table->decimal('subsidy', 10, 2)->default(0);
|
||||
$table->decimal('social_insurance', 10, 2)->default(0);
|
||||
$table->decimal('housing_fund', 10, 2)->default(0);
|
||||
$table->decimal('tax', 10, 2)->default(0);
|
||||
$table->decimal('absence_deduction', 10, 2)->default(0);
|
||||
$table->decimal('other_deduction', 10, 2)->default(0);
|
||||
$table->decimal('actual_amount', 10, 2)->default(0);
|
||||
$table->tinyInteger('status')->default(0)->comment('0=待确认 1=已确认 2=已发放');
|
||||
$table->timestamp('confirmed_at')->nullable();
|
||||
$table->timestamp('paid_at')->nullable();
|
||||
$table->timestamps();
|
||||
$table->unique(['store_id', 'user_id', 'year_month']);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('salary_records');
|
||||
Schema::dropIfExists('leave_requests');
|
||||
Schema::dropIfExists('attendance_records');
|
||||
Schema::dropIfExists('schedules');
|
||||
Schema::dropIfExists('employee_profiles');
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user