2way-batch — Repository Map
บทนี้เป็นแผนที่ไฟล์ของ 2way-batch (branch: master, 96 tracked files) — NestJS worker ที่เหลือ cron survey เป็นหลัก
แผนที่โฟลเดอร์ระดับ repo
2way-batch/ (branch: master)
├── package.json # name=2way-batch
├── config/configuration.ts # port, jwt, db, lineToken, contentStatus maps
├── docs/document.config.ts # Swagger; server default port 9340
├── libs/
│ ├── jwt/{jwt-auth.guard,jwt.strategy}.ts
│ ├── exception/http-exception.filter.ts
│ ├── log/logs.middleware.ts
│ └── common/{base64-to-file,ganarate-random-string,validator-date}.ts
├── nginx/
│ ├── conf/nginx.conf
│ └── conf.d/default.conf # /2way-batch/ → :9340, /2way/ → :8201
├── src/
│ ├── main.ts # bootstrap
│ ├── app.module.ts # live: Config + TypeORM + Schedule + SurveyTask
│ ├── app.controller.ts # empty @Controller()
│ ├── app.service.ts
│ ├── constants/surveys.constant.ts
│ ├── dto/ # announce, common, complaint, employee, line, survey, upload, user
│ ├── entities/ # 25 entity files
│ ├── modules/
│ │ ├── announces/ # มีครบ แต่ไม่ import ใน AppModule
│ │ ├── employees/ # มีครบ แต่ไม่ import
│ │ ├── surveys/ # ใช้ทางอ้อมผ่าน SurveyTaskModule providers
│ │ ├── line/ # LineService ใช้ใน cron; LineModule ไม่ import
│ │ └── uploadFiles/ # ไม่ import
│ ├── crontab/survey/
│ │ ├── survey.task.module.ts
│ │ └── survey.task.service.ts # @Cron EVERY_10_SECONDS
│ └── utils/surveys.util.ts
├── Dockerfile # node:16-alpine
├── bitbucket-pipelines.yml
├── endpoint.txt # scratch notes (announce/employee/complaint/survey paths)
├── lineText.text # scratch LINE helper (ไม่ถูก import)
└── test/Boot sequence
1. NestFactory.create(AppModule, I3GatewayLogger)
│ main.ts:15-17
▼
2. port = ConfigService.get('port') || 3000
│ main.ts:21
▼
3. setGlobalPrefix(`${BASE_PATH}api/v1`)
│ main.ts:23-25
▼
4. useStaticAssets(uploads) prefix '/2way-batch/'
│ main.ts:26-28
▼
5. bodyParser 50mb
│ main.ts:29-30
▼
6. Global filter / JwtAuthGuard / ValidationPipe
│ main.ts:31-33
▼
7. enableCors origin=*
│ main.ts:34-38
▼
8. Swagger `${BASE_PATH}docs`
│ main.ts:40-41
▼
9. listen(port, '0.0.0.0')
│ main.ts:42-45
▼
10. ScheduleModule triggers SurveyTaskService.handleCron
every 10 seconds (survey.task.service.ts:32-37)AppController ว่าง (app.controller.ts:3) — ไม่มี health endpoint ในไฟล์นี้
AppModule — สิ่งที่ถูกโหลดจริง
imports: [
ConfigModule.forRoot({ load: [configuration], isGlobal: true }),
TypeOrmModule.forRootAsync({ name: 'main', type: 'mssql', ... }),
// AnnouncesModule, SurveysModule, ComplaintsModule,
// EmployeesModule, LineModule, UploadModule, ← comment ปิด
ScheduleModule.forRoot(),
SurveyTaskModule,
],
controllers: [AppController],
providers: [AppService, JwtStrategy],แหล่ง: app.module.ts:11-48
TypeORM connection 'main'
| Option | ค่า | อ้างอิง |
|---|---|---|
| type | mssql | app.module.ts:21 |
| host/port/user/password/database | จาก ConfigService → configuration.ts db.* | app.module.ts:22-26 |
| synchronize | false | app.module.ts:27 |
| logging | error, query | app.module.ts:28 |
| entities | __dirname + '/**/*.entity{.ts,.js}' | app.module.ts:29 |
| encrypt | false | app.module.ts:32 |
| trustServerCertificate | true | app.module.ts:31 |
แม้ HTTP modules จะไม่ถูก import — TypeORM ยังโหลด ทุก *.entity ใต้ src/ รวม entity ของ announce/complaint ที่ cron ไม่ได้ใช้
SurveyTaskModule — wiring จริงของ cron
@Module({
imports: [HttpModule],
providers: [SurveyTaskService, LineService, SurveysService, SurveysRepository],
})
export class SurveyTaskModule {}แหล่ง: crontab/survey/survey.task.module.ts:8-12
ไม่ได้ import SurveysModule / LineModule เต็ม ๆ — inject service/repository ตรงเป็น providers ของ task module เอง
ผลข้างเคียง:
SurveysController/LineControllerไม่ได้ mount เพราะ module ของพวกมันถูก comment ในAppModuleLineServiceยังถูก instantiate สำหรับ cronSurveysServiceconstructor เรียกSurveysUtil.initializer(entityManager)(surveys.service.ts:21-27) — โหลด map ของMStatus/MErrorMessage/MContentFlowตอน boot ของ provider นี้
Dead code — modules ที่มีไฟล์ครบแต่ไม่ wire
| โฟลเดอร์ | มี controller | ถูก import ใน AppModule? |
|---|---|---|
src/modules/announces/ | ใช่ | ไม่ (app.module.ts:38) |
src/modules/surveys/ | ใช่ | ไม่เป็น module — ใช้แค่ service/repo ใน task |
src/modules/employees/ | ใช่ | ไม่ |
src/modules/line/ | มี LineController @Public() | ไม่เป็น module — ใช้แค่ LineService |
src/modules/uploadFiles/ | ใช่ | ไม่ |
ComplaintsModule ถูก mention ใน comment (app.module.ts:40) แต่โฟลเดอร์ modules/complaints/ ไม่มี ใน tree ของ branch master — มีแค่ complaint entities/DTOs ค้างจาก skeleton
LineController ใน batch มีแค่ POST /Line ที่ @Public() (line.controller.ts:9-17) — ไม่ได้ mount ในสถานะปัจจุบัน
Entities ที่ cron methods อ้างถึง (เมื่อเปิด logic)
จาก imports ใน survey.task.service.ts:6-17:
| Entity | ใช้ใน |
|---|---|
TContent | query หลักของ survey content |
MContentType | filter name_en = survey |
TContentAssign | ผู้ถูกมอบหมาย |
TContentStatus / MStatus | สถานะ |
TContentFlowHistory / MContentFlow | flow history + short_name |
UserLine | ผ่าน SurveysRepository.findLineIDAsEmpCode |
MConfig | ผ่าน findEmployeeCodeOfHrAdmin |
Constants: SurveysConstant (constants/surveys.constant.ts) — CONTENT_TYPE = 'survey', short names ACS/ACD/HAP, create code S00, config key list.empCode.hrAdmin
รายละเอียด schema และ query → 03-persistence-integrations
Config keys ที่ configuration.ts อ่าน
| Key | Env | อ้างอิง |
|---|---|---|
port | PORT | configuration.ts:2 |
jwtSecretKey | SECRET_KEY | configuration.ts:3 |
db.* | DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME | configuration.ts:4-10 |
lineToken | LINE_AUTH_TOKEN | configuration.ts:11 |
contentStatus.survey.* | (static maps ในโค้ด) | configuration.ts:19-40 |
ไม่มี .env.example ใน repo — ผู้ deploy ต้องรู้ชื่อตัวแปรจาก configuration.ts เอง (QUAL-2WAYBATCH-02)
หมายเหตุ: lineToken ถูกโหลดใน config แต่ LineService.pushMassage ของ batch ไม่ได้ใช้ token นี้ — ยิง HTTP ไป IP hardcode แทน (line.service.ts:25-26)
Nginx snippets ใน repo
nginx/conf.d/default.conf:
server_name api.vtrcapp.com;
location /2way-batch/ {
proxy_pass http://0.0.0.0:9340/;
}
location /2way/ {
proxy_pass http://0.0.0.0:8201/;
}แหล่ง: nginx/conf.d/default.conf:1-16
/2way/ → 8201 น่าจะชี้ไปยังบริการอื่นในกลุ่ม — ไม่ยืนยันจาก compose ใน repo นี้ ว่า process ไหนฟัง 8201 (ไม่มี docker-compose.yml ใน 2way-batch)
nginx/conf/nginx.conf เป็น nginx มาตรฐาน (daemon off, gzip, include conf.d) — nginx.conf:1-28
LineService — hardcode IP (สำคัญ)
แม้ LineModule จะไม่ถูก import แต่ LineService.pushMassage ที่ cron จะเรียก (ถ้าเปิด fetchApproval / fetchCreateOutScope) ยิงไป:
this.http.post('http://10.188.128.126:9340/2way-batch/api/v1/line', data)แหล่ง: src/modules/line/line.service.ts:25-26
จุดสังเกต:
- IP + port hardcode — ไม่ผ่าน env
- Path เป็น
/2way-batch/api/v1/lineซึ่งตาม nginx คือตัวเองบน 9340 - แต่
LineControllerไม่ได้ถูก mount ใน AppModule ปัจจุบัน → ถ้า cron เปิด logic จริงโดยไม่เปิดLineModuleการ push มีแนวโน้มได้ 404 / fail - Body map
replyToken: body.lineId(line.service.ts:20-22) — ชื่อฟิลด์สับสนกับ LINE reply token จริง - DTO ใน batch ใช้
lineId(dto/line.dto.ts:4-11) ไม่ใช่replyTokenแบบ2way-line-service
เปรียบเทียบ: 2way-api เรียก rich-menu ของ 2way-line-service ที่ IP อื่น (20.212.116.206:8200) — คนละเส้นทางกับ hardcode ของ batch
Auth libs ที่โหลดแต่ไม่ได้ปกป้อง business route
| ส่วน | พฤติกรรม | อ้างอิง |
|---|---|---|
Global JwtAuthGuard | ข้ามถ้า @Public() | main.ts:32, libs/jwt/jwt-auth.guard.ts:15-23 |
JwtStrategy | Bearer + jwtSecretKey จาก SECRET_KEY | jwt.strategy.ts:11-15 |
| Live controllers | ว่าง (AppController) | app.controller.ts:3 |
ในสถานะ wiring ปัจจุบันไม่มี business HTTP route ให้ guard ปกป้อง — ความเสี่ยงจะกลับมาถ้า uncomment modules ที่ติด @Public()
CI / scratch files
bitbucket-pipelines.ymlใช้ imagenode:16(bitbucket-pipelines.yml:6) — สอดคล้อง Dockerfileendpoint.txt/lineText.textเป็น scratch ที่ commit ไว้ — ไม่ถูก import จากsrc/
สิ่งที่อยู่นอกขอบเขตบทนี้
- Trace cron / dead methods → 02-core-pipeline
- Entity schema / LINE hop → 03-persistence-integrations
- Debt IDs → 04-scorecard