251205:0000 Just start debug backend/frontend

This commit is contained in:
2025-12-05 00:32:02 +07:00
parent dc8b80c5f9
commit 2865bebdb1
88 changed files with 6751 additions and 1016 deletions
@@ -0,0 +1,72 @@
import { DataSource } from 'typeorm';
import { Organization } from '../../modules/organizations/entities/organization.entity';
export async function seedOrganizations(dataSource: DataSource) {
const repo = dataSource.getRepository(Organization);
const orgs = [
{ organizationCode: 'กทท.', organizationName: 'การท่าเรือแห่งประเทศไทย' },
{
organizationCode: 'สคฉ.3',
organizationName: 'โครงการพัฒนาท่าเรือแหลมฉบัง ระยะที่ 3',
},
{
organizationCode: 'สคฉ.3-01',
organizationName: 'ตรวจรับพัสดุ ที่ปรึกษาควบคุมงาน',
},
{
organizationCode: 'สคฉ.3-02',
organizationName: 'ตรวจรับพัสดุ งานทางทะเล',
},
{
organizationCode: 'สคฉ.3-03',
organizationName: 'ตรวจรับพัสดุ อาคารและระบบสาธารณูปโภค',
},
{
organizationCode: 'สคฉ.3-04',
organizationName: 'ตรวจรับพัสดุ ตรวจสอบผลกระทบสิ่งแวดล้อม',
},
{
organizationCode: 'สคฉ.3-05',
organizationName: 'ตรวจรับพัสดุ เยียวยาการประมง',
},
{
organizationCode: 'สคฉ.3-06',
organizationName: 'ตรวจรับพัสดุ งานก่อสร้าง ส่วนที่ 3',
},
{
organizationCode: 'สคฉ.3-07',
organizationName: 'ตรวจรับพัสดุ งานก่อสร้าง ส่วนที่ 4',
},
{
organizationCode: 'สคฉ.3-xx',
organizationName: 'ตรวจรับพัสดุ ที่ปรึกษาออกแบบ ส่วนที่ 4',
},
{ organizationCode: 'TEAM', organizationName: 'Designer Consulting Ltd.' },
{
organizationCode: 'คคง.',
organizationName: 'Construction Supervision Ltd.',
},
{ organizationCode: 'ผรม.1', organizationName: 'Contractor งานทางทะเล' },
{ organizationCode: 'ผรม.2', organizationName: 'Contractor งานก่อสร้าง' },
{
organizationCode: 'ผรม.3',
organizationName: 'Contractor งานก่อสร้าง ส่วนที่ 3',
},
{
organizationCode: 'ผรม.4',
organizationName: 'Contractor งานก่อสร้าง ส่วนที่ 4',
},
{ organizationCode: 'EN', organizationName: 'Third Party Environment' },
{ organizationCode: 'CAR', organizationName: 'Third Party Fishery Care' },
];
for (const org of orgs) {
const exists = await repo.findOneBy({
organizationCode: org.organizationCode,
});
if (!exists) {
await repo.save(repo.create(org));
}
}
}
+14 -57
View File
@@ -1,67 +1,24 @@
import { config } from 'dotenv';
import { DataSource } from 'typeorm';
import { seedWorkflowDefinitions } from '../seeds/workflow-definitions.seed'; // Import ฟังก์ชัน Seed ที่คุณมี
// Import Entities ที่เกี่ยวข้อง
import { WorkflowDefinition } from '../../modules/workflow-engine/entities/workflow-definition.entity';
import { WorkflowHistory } from '../../modules/workflow-engine/entities/workflow-history.entity';
import { WorkflowInstance } from '../../modules/workflow-engine/entities/workflow-instance.entity';
import { databaseConfig } from '../../config/database.config';
import { seedOrganizations } from './organization.seed';
import { seedUsers } from './user.seed';
// โหลด Environment Variables (.env)
config();
const runSeed = async () => {
// ตั้งค่าการเชื่อมต่อฐานข้อมูล (ควรตรงกับ docker-compose หรือ .env ของคุณ)
const dataSource = new DataSource({
type: 'mariadb',
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT || '3306'),
username: process.env.DB_USERNAME || 'root',
password: process.env.DB_PASSWORD || 'Center#2025',
database: process.env.DB_DATABASE || 'lcbp3_dev',
// สำคัญ: ต้องใส่ Entities ที่เกี่ยวข้องทั้งหมดเพื่อให้ TypeORM รู้จัก
entities: [
WorkflowDefinition,
WorkflowInstance,
WorkflowHistory,
// ใส่ Entity อื่นๆ ถ้าจำเป็น หรือใช้ path pattern: __dirname + '/../../modules/**/*.entity{.ts,.js}'
],
synchronize: false, // ห้ามใช้ true บน Production
});
async function runSeeds() {
const dataSource = new DataSource(databaseConfig as any);
await dataSource.initialize();
try {
console.log('🔌 Connecting to database...');
await dataSource.initialize();
console.log('✅ Database connected.');
console.log('🌱 Seeding database...');
console.log('🌱 Running Seeds...');
await seedWorkflowDefinitions(dataSource);
console.log('✅ Seeding completed successfully.');
await seedOrganizations(dataSource);
await seedUsers(dataSource);
console.log('✅ Seeding completed!');
} catch (error) {
console.error('❌ Error during seeding:', error);
console.error('❌ Seeding failed:', error);
} finally {
if (dataSource.isInitialized) {
await dataSource.destroy();
console.log('🔌 Database connection closed.');
}
await dataSource.destroy();
}
};
runSeed();
/*
npx ts-node -r tsconfig-paths/register src/database/run-seed.ts
**หรือเพิ่มใน `package.json` (แนะนำ):**
คุณสามารถเพิ่ม script ใน `package.json` เพื่อให้เรียกใช้ได้ง่ายขึ้นในอนาคต:
"scripts": {
"seed": "ts-node -r tsconfig-paths/register src/database/seeds/run-seed.ts"
}
http://googleusercontent.com/immersive_entry_chip/1
### 💡 ข้อควรระวัง
1. **Environment Variables:** ตรวจสอบให้แน่ใจว่าค่า Config (Host, User, Password) ในไฟล์ `run-seed.ts` หรือ `.env` นั้นถูกต้องและตรงกับ Docker Container ที่กำลังรันอยู่
2. **Entities:** หากฟังก์ชัน Seed มีการเรียกใช้ Entity อื่นนอกเหนือจาก `WorkflowDefinition` ต้องนำมาใส่ใน `entities: [...]` ของ `DataSource` ให้ครบ ไม่อย่างนั้นจะเจอ Error `RepositoryNotFoundError`
*/
runSeeds();
+106
View File
@@ -0,0 +1,106 @@
import { DataSource } from 'typeorm';
import { User } from '../../modules/users/entities/user.entity';
import { Role } from '../../modules/auth/entities/role.entity';
import * as bcrypt from 'bcrypt';
export async function seedUsers(dataSource: DataSource) {
const userRepo = dataSource.getRepository(User);
const roleRepo = dataSource.getRepository(Role);
// Create Roles
const rolesData = [
{
roleName: 'Superadmin',
description:
'ผู้ดูแลระบบสูงสุด: สามารถทำทุกอย่างในระบบ, จัดการองค์กร, และจัดการข้อมูลหลักระดับ Global',
},
{
roleName: 'Org Admin',
description:
'ผู้ดูแลองค์กร: จัดการผู้ใช้ในองค์กร, จัดการบทบาท / สิทธิ์ภายในองค์กร, และดูรายงานขององค์กร',
},
{
roleName: 'Document Control',
description:
'ควบคุมเอกสารขององค์กร: เพิ่ม / แก้ไข / ลบเอกสาร, และกำหนดสิทธิ์เอกสารภายในองค์กร',
},
{
roleName: 'Editor',
description:
'ผู้แก้ไขเอกสารขององค์กร: เพิ่ม / แก้ไขเอกสารที่ได้รับมอบหมาย',
},
{
roleName: 'Viewer',
description: 'ผู้ดูเอกสารขององค์กร: ดูเอกสารที่มีสิทธิ์เข้าถึงเท่านั้น',
},
{
roleName: 'Project Manager',
description:
'ผู้จัดการโครงการ: จัดการสมาชิกในโครงการ, สร้าง / จัดการสัญญาในโครงการ, และดูรายงานโครงการ',
},
{
roleName: 'Contract Admin',
description:
'ผู้ดูแลสัญญา: จัดการสมาชิกในสัญญา, สร้าง / จัดการข้อมูลหลักเฉพาะสัญญา, และอนุมัติเอกสารในสัญญา',
},
];
const roleMap = new Map();
for (const r of rolesData) {
let role = await roleRepo.findOneBy({ roleName: r.roleName });
if (!role) {
role = await roleRepo.save(roleRepo.create(r));
}
roleMap.set(r.roleName, role);
}
// Create Users
const usersData = [
{
username: 'superadmin',
email: 'superadmin@example.com',
firstName: 'Super',
lastName: 'Admin',
roleName: 'Superadmin',
},
{
username: 'admin',
email: 'admin@example.com',
firstName: 'Admin',
lastName: 'คคง.',
roleName: 'Org Admin',
},
{
username: 'editor01',
email: 'editor01@example.com',
firstName: 'DC',
lastName: 'C1',
roleName: 'Editor',
},
{
username: 'viewer01',
email: 'viewer01@example.com',
firstName: 'Viewer',
lastName: 'สคฉ.03',
roleName: 'Viewer',
},
];
const salt = await bcrypt.genSalt();
const passwordHash = await bcrypt.hash('password123', salt); // Default password
for (const u of usersData) {
const exists = await userRepo.findOneBy({ username: u.username });
if (!exists) {
const user = userRepo.create({
username: u.username,
email: u.email,
firstName: u.firstName,
lastName: u.lastName,
passwordHash,
roles: [roleMap.get(u.roleName)],
});
await userRepo.save(user);
}
}
}