690329:1621 Fixing superadmin by GPT-5.3 #01
This commit is contained in:
BIN
Binary file not shown.
+881
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+361
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+361
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+881
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+65
@@ -0,0 +1,65 @@
|
|||||||
|
14540db954a05918780678361189125c
|
||||||
|
"use strict";
|
||||||
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||||
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||||
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||||
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||||
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||||
|
};
|
||||||
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||||
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||||
|
};
|
||||||
|
var _a, _b, _c, _d;
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.Tag = void 0;
|
||||||
|
const typeorm_1 = require("typeorm");
|
||||||
|
const project_entity_1 = require("../../project/entities/project.entity");
|
||||||
|
let Tag = class Tag {
|
||||||
|
};
|
||||||
|
exports.Tag = Tag;
|
||||||
|
__decorate([
|
||||||
|
(0, typeorm_1.PrimaryGeneratedColumn)(),
|
||||||
|
__metadata("design:type", Number)
|
||||||
|
], Tag.prototype, "id", void 0);
|
||||||
|
__decorate([
|
||||||
|
(0, typeorm_1.Column)({ name: 'project_id', type: 'int', nullable: true }),
|
||||||
|
__metadata("design:type", Object)
|
||||||
|
], Tag.prototype, "projectId", void 0);
|
||||||
|
__decorate([
|
||||||
|
(0, typeorm_1.Column)({ name: 'tag_name', length: 100 }),
|
||||||
|
__metadata("design:type", String)
|
||||||
|
], Tag.prototype, "tagName", void 0);
|
||||||
|
__decorate([
|
||||||
|
(0, typeorm_1.Column)({ name: 'color_code', length: 30, default: 'default' }),
|
||||||
|
__metadata("design:type", String)
|
||||||
|
], Tag.prototype, "colorCode", void 0);
|
||||||
|
__decorate([
|
||||||
|
(0, typeorm_1.Column)({ type: 'text', nullable: true }),
|
||||||
|
__metadata("design:type", Object)
|
||||||
|
], Tag.prototype, "description", void 0);
|
||||||
|
__decorate([
|
||||||
|
(0, typeorm_1.ManyToOne)(() => project_entity_1.Project),
|
||||||
|
(0, typeorm_1.JoinColumn)({ name: 'project_id' }),
|
||||||
|
__metadata("design:type", typeof (_a = typeof project_entity_1.Project !== "undefined" && project_entity_1.Project) === "function" ? _a : Object)
|
||||||
|
], Tag.prototype, "project", void 0);
|
||||||
|
__decorate([
|
||||||
|
(0, typeorm_1.CreateDateColumn)({ name: 'created_at' }),
|
||||||
|
__metadata("design:type", typeof (_b = typeof Date !== "undefined" && Date) === "function" ? _b : Object)
|
||||||
|
], Tag.prototype, "createdAt", void 0);
|
||||||
|
__decorate([
|
||||||
|
(0, typeorm_1.UpdateDateColumn)({ name: 'updated_at' }),
|
||||||
|
__metadata("design:type", typeof (_c = typeof Date !== "undefined" && Date) === "function" ? _c : Object)
|
||||||
|
], Tag.prototype, "updatedAt", void 0);
|
||||||
|
__decorate([
|
||||||
|
(0, typeorm_1.Column)({ name: 'created_by', type: 'int', nullable: true }),
|
||||||
|
__metadata("design:type", Object)
|
||||||
|
], Tag.prototype, "createdBy", void 0);
|
||||||
|
__decorate([
|
||||||
|
(0, typeorm_1.DeleteDateColumn)({ name: 'deleted_at' }),
|
||||||
|
__metadata("design:type", Object)
|
||||||
|
], Tag.prototype, "deletedAt", void 0);
|
||||||
|
exports.Tag = Tag = __decorate([
|
||||||
|
(0, typeorm_1.Entity)('tags'),
|
||||||
|
(0, typeorm_1.Unique)('ux_tag_project', ['projectId', 'tagName'])
|
||||||
|
], Tag);
|
||||||
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcbWFzdGVyXFxlbnRpdGllc1xcdGFnLmVudGl0eS50cyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7O0FBQUEscUNBVWlCO0FBQ2pCLDBFQUFnRTtBQUl6RCxJQUFNLEdBQUcsR0FBVCxNQUFNLEdBQUc7Q0FnQ2YsQ0FBQTtBQWhDWSxrQkFBRztBQUVkO0lBREMsSUFBQSxnQ0FBc0IsR0FBRTs7K0JBQ2I7QUFHWjtJQURDLElBQUEsZ0JBQU0sRUFBQyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUM7O3NDQUNsQztBQUcxQjtJQURDLElBQUEsZ0JBQU0sRUFBQyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDOztvQ0FDekI7QUFHakI7SUFEQyxJQUFBLGdCQUFNLEVBQUMsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxDQUFDOztzQ0FDNUM7QUFHbkI7SUFEQyxJQUFBLGdCQUFNLEVBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQzs7d0NBQ2I7QUFLNUI7SUFGQyxJQUFBLG1CQUFTLEVBQUMsR0FBRyxFQUFFLENBQUMsd0JBQU8sQ0FBQztJQUN4QixJQUFBLG9CQUFVLEVBQUMsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLENBQUM7a0RBQ3pCLHdCQUFPLG9CQUFQLHdCQUFPO29DQUFDO0FBR2xCO0lBREMsSUFBQSwwQkFBZ0IsRUFBQyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsQ0FBQztrREFDN0IsSUFBSSxvQkFBSixJQUFJO3NDQUFDO0FBR2pCO0lBREMsSUFBQSwwQkFBZ0IsRUFBQyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsQ0FBQztrREFDN0IsSUFBSSxvQkFBSixJQUFJO3NDQUFDO0FBR2pCO0lBREMsSUFBQSxnQkFBTSxFQUFDLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQzs7c0NBQ2xDO0FBRzFCO0lBREMsSUFBQSwwQkFBZ0IsRUFBQyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsQ0FBQzs7c0NBQ2pCO2NBL0JiLEdBQUc7SUFGZixJQUFBLGdCQUFNLEVBQUMsTUFBTSxDQUFDO0lBQ2QsSUFBQSxnQkFBTSxFQUFDLGdCQUFnQixFQUFFLENBQUMsV0FBVyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0dBQ3RDLEdBQUcsQ0FnQ2YiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiRTpcXG5wLWRtc1xcbGNicDNcXGJhY2tlbmRcXHNyY1xcbW9kdWxlc1xcbWFzdGVyXFxlbnRpdGllc1xcdGFnLmVudGl0eS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIEVudGl0eSxcclxuICBDb2x1bW4sXHJcbiAgUHJpbWFyeUdlbmVyYXRlZENvbHVtbixcclxuICBDcmVhdGVEYXRlQ29sdW1uLFxyXG4gIFVwZGF0ZURhdGVDb2x1bW4sXHJcbiAgRGVsZXRlRGF0ZUNvbHVtbixcclxuICBVbmlxdWUsXHJcbiAgTWFueVRvT25lLFxyXG4gIEpvaW5Db2x1bW4sXHJcbn0gZnJvbSAndHlwZW9ybSc7XHJcbmltcG9ydCB7IFByb2plY3QgfSBmcm9tICcuLi8uLi9wcm9qZWN0L2VudGl0aWVzL3Byb2plY3QuZW50aXR5JztcclxuXHJcbkBFbnRpdHkoJ3RhZ3MnKVxyXG5AVW5pcXVlKCd1eF90YWdfcHJvamVjdCcsIFsncHJvamVjdElkJywgJ3RhZ05hbWUnXSlcclxuZXhwb3J0IGNsYXNzIFRhZyB7XHJcbiAgQFByaW1hcnlHZW5lcmF0ZWRDb2x1bW4oKVxyXG4gIGlkITogbnVtYmVyOyAvLyDguYDguJ7guLTguYjguKEgIVxyXG5cclxuICBAQ29sdW1uKHsgbmFtZTogJ3Byb2plY3RfaWQnLCB0eXBlOiAnaW50JywgbnVsbGFibGU6IHRydWUgfSlcclxuICBwcm9qZWN0SWQhOiBudW1iZXIgfCBudWxsOyAvLyDguYDguJ7guLTguYjguKEgIVxyXG5cclxuICBAQ29sdW1uKHsgbmFtZTogJ3RhZ19uYW1lJywgbGVuZ3RoOiAxMDAgfSlcclxuICB0YWdOYW1lITogc3RyaW5nOyAvLyDguYDguJ7guLTguYjguKEgIVxyXG5cclxuICBAQ29sdW1uKHsgbmFtZTogJ2NvbG9yX2NvZGUnLCBsZW5ndGg6IDMwLCBkZWZhdWx0OiAnZGVmYXVsdCcgfSlcclxuICBjb2xvckNvZGUhOiBzdHJpbmc7IC8vIOC5gOC4nuC4tOC5iOC4oSAhXHJcblxyXG4gIEBDb2x1bW4oeyB0eXBlOiAndGV4dCcsIG51bGxhYmxlOiB0cnVlIH0pXHJcbiAgZGVzY3JpcHRpb24hOiBzdHJpbmcgfCBudWxsOyAvLyDguYDguJ7guLTguYjguKEgIVxyXG5cclxuICAvLyBSZWxhdGlvbnNcclxuICBATWFueVRvT25lKCgpID0+IFByb2plY3QpXHJcbiAgQEpvaW5Db2x1bW4oeyBuYW1lOiAncHJvamVjdF9pZCcgfSlcclxuICBwcm9qZWN0PzogUHJvamVjdDtcclxuXHJcbiAgQENyZWF0ZURhdGVDb2x1bW4oeyBuYW1lOiAnY3JlYXRlZF9hdCcgfSlcclxuICBjcmVhdGVkQXQhOiBEYXRlOyAvLyDguYDguJ7guLTguYjguKEgIVxyXG5cclxuICBAVXBkYXRlRGF0ZUNvbHVtbih7IG5hbWU6ICd1cGRhdGVkX2F0JyB9KVxyXG4gIHVwZGF0ZWRBdCE6IERhdGU7IC8vIOC5gOC4nuC4tOC5iOC4oSAhXHJcblxyXG4gIEBDb2x1bW4oeyBuYW1lOiAnY3JlYXRlZF9ieScsIHR5cGU6ICdpbnQnLCBudWxsYWJsZTogdHJ1ZSB9KVxyXG4gIGNyZWF0ZWRCeSE6IG51bWJlciB8IG51bGw7IC8vIOC5gOC4nuC4tOC5iOC4oSAhXHJcblxyXG4gIEBEZWxldGVEYXRlQ29sdW1uKHsgbmFtZTogJ2RlbGV0ZWRfYXQnIH0pXHJcbiAgZGVsZXRlZEF0ITogRGF0ZSB8IG51bGw7IC8vIOC5gOC4nuC4tOC5iOC4oSAhXHJcbn1cclxuIl0sInZlcnNpb24iOjN9
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
{"file":"E:\\np-dms\\lcbp3\\backend\\src\\modules\\master\\entities\\tag.entity.ts","mappings":";;;;;;;;;;;;;AAAA,qCAUiB;AACjB,0EAAgE;AAIzD,IAAM,GAAG,GAAT,MAAM,GAAG;CAgCf,CAAA;AAhCY,kBAAG;AAEd;IADC,IAAA,gCAAsB,GAAE;;+BACb;AAGZ;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;sCAClC;AAG1B;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;;oCACzB;AAGjB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;;sCAC5C;AAGnB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;wCACb;AAK5B;IAFC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,wBAAO,CAAC;IACxB,IAAA,oBAAU,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;kDACzB,wBAAO,oBAAP,wBAAO;oCAAC;AAGlB;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;kDAC7B,IAAI,oBAAJ,IAAI;sCAAC;AAGjB;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;kDAC7B,IAAI,oBAAJ,IAAI;sCAAC;AAGjB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;sCAClC;AAG1B;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;;sCACjB;cA/Bb,GAAG;IAFf,IAAA,gBAAM,EAAC,MAAM,CAAC;IACd,IAAA,gBAAM,EAAC,gBAAgB,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;GACtC,GAAG,CAgCf","names":[],"sources":["E:\\np-dms\\lcbp3\\backend\\src\\modules\\master\\entities\\tag.entity.ts"],"sourcesContent":["import {\r\n Entity,\r\n Column,\r\n PrimaryGeneratedColumn,\r\n CreateDateColumn,\r\n UpdateDateColumn,\r\n DeleteDateColumn,\r\n Unique,\r\n ManyToOne,\r\n JoinColumn,\r\n} from 'typeorm';\r\nimport { Project } from '../../project/entities/project.entity';\r\n\r\n@Entity('tags')\r\n@Unique('ux_tag_project', ['projectId', 'tagName'])\r\nexport class Tag {\r\n @PrimaryGeneratedColumn()\r\n id!: number; // เพิ่ม !\r\n\r\n @Column({ name: 'project_id', type: 'int', nullable: true })\r\n projectId!: number | null; // เพิ่ม !\r\n\r\n @Column({ name: 'tag_name', length: 100 })\r\n tagName!: string; // เพิ่ม !\r\n\r\n @Column({ name: 'color_code', length: 30, default: 'default' })\r\n colorCode!: string; // เพิ่ม !\r\n\r\n @Column({ type: 'text', nullable: true })\r\n description!: string | null; // เพิ่ม !\r\n\r\n // Relations\r\n @ManyToOne(() => Project)\r\n @JoinColumn({ name: 'project_id' })\r\n project?: Project;\r\n\r\n @CreateDateColumn({ name: 'created_at' })\r\n createdAt!: Date; // เพิ่ม !\r\n\r\n @UpdateDateColumn({ name: 'updated_at' })\r\n updatedAt!: Date; // เพิ่ม !\r\n\r\n @Column({ name: 'created_by', type: 'int', nullable: true })\r\n createdBy!: number | null; // เพิ่ม !\r\n\r\n @DeleteDateColumn({ name: 'deleted_at' })\r\n deletedAt!: Date | null; // เพิ่ม !\r\n}\r\n"],"version":3}
|
||||||
+361
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
|||||||
{"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\due-date-reminder.service.spec.ts":[1,1723],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts":[1,11114],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\auth.service.spec.ts":[1,1538],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\document-numbering\\document-numbering.service.spec.ts":[1,2037],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\casl\\ability.factory.spec.ts":[1,1294],"E:\\np-dms\\lcbp3\\backend\\src\\common\\services\\uuid-resolver.service.spec.ts":[1,5491],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\workflow-engine\\workflow-engine.service.spec.ts":[1,5639],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\workflow-engine\\dsl\\parser.service.spec.ts":[1,5818],"E:\\np-dms\\lcbp3\\backend\\src\\common\\pipes\\parse-uuid.pipe.spec.ts":[1,355],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\user\\user.service.spec.ts":[1,1270],"E:\\np-dms\\lcbp3\\backend\\src\\common\\file-storage\\file-storage.service.spec.ts":[1,1187],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.controller.spec.ts":[1,12100],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\migration\\migration.service.spec.ts":[1,1296],"E:\\np-dms\\lcbp3\\backend\\src\\common\\entities\\uuid-base.entity.spec.ts":[1,430],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\project\\project.service.spec.ts":[1,1109],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\auth.controller.spec.ts":[1,2191],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\document-numbering\\services\\manual-override.service.spec.ts":[1,5256],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\project\\project.controller.spec.ts":[1,1827],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\migration\\migration.controller.spec.ts":[1,6380],"E:\\np-dms\\lcbp3\\backend\\src\\common\\file-storage\\file-storage.controller.spec.ts":[1,1482],"E:\\np-dms\\lcbp3\\backend\\src\\app.controller.spec.ts":[1,587],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\json-schema\\json-schema.controller.spec.ts":[1,5062]}
|
{"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\due-date-reminder.service.spec.ts":[1,1723],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.service.spec.ts":[1,7901],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\auth.service.spec.ts":[1,1538],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\document-numbering\\document-numbering.service.spec.ts":[1,2037],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\casl\\ability.factory.spec.ts":[1,1294],"E:\\np-dms\\lcbp3\\backend\\src\\common\\services\\uuid-resolver.service.spec.ts":[1,5491],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\workflow-engine\\workflow-engine.service.spec.ts":[1,5639],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\workflow-engine\\dsl\\parser.service.spec.ts":[1,5818],"E:\\np-dms\\lcbp3\\backend\\src\\common\\pipes\\parse-uuid.pipe.spec.ts":[1,355],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\user\\user.service.spec.ts":[1,1270],"E:\\np-dms\\lcbp3\\backend\\src\\common\\file-storage\\file-storage.service.spec.ts":[1,1187],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\correspondence\\correspondence.controller.spec.ts":[1,8495],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\migration\\migration.service.spec.ts":[1,1296],"E:\\np-dms\\lcbp3\\backend\\src\\common\\entities\\uuid-base.entity.spec.ts":[1,430],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\project\\project.service.spec.ts":[1,1109],"E:\\np-dms\\lcbp3\\backend\\src\\common\\auth\\auth.controller.spec.ts":[1,2191],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\document-numbering\\services\\manual-override.service.spec.ts":[1,5256],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\project\\project.controller.spec.ts":[1,1827],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\migration\\migration.controller.spec.ts":[1,6380],"E:\\np-dms\\lcbp3\\backend\\src\\common\\file-storage\\file-storage.controller.spec.ts":[1,1482],"E:\\np-dms\\lcbp3\\backend\\src\\app.controller.spec.ts":[1,587],"E:\\np-dms\\lcbp3\\backend\\src\\modules\\json-schema\\json-schema.controller.spec.ts":[1,5062]}
|
||||||
@@ -15,9 +15,15 @@ import { UpdateCirculationRoutingDto } from './dto/update-circulation-routing.dt
|
|||||||
import { SearchCirculationDto } from './dto/search-circulation.dto';
|
import { SearchCirculationDto } from './dto/search-circulation.dto';
|
||||||
import { DocumentNumberingService } from '../document-numbering/services/document-numbering.service';
|
import { DocumentNumberingService } from '../document-numbering/services/document-numbering.service';
|
||||||
import { UuidResolverService } from '../../common/services/uuid-resolver.service';
|
import { UuidResolverService } from '../../common/services/uuid-resolver.service';
|
||||||
|
import { UserService } from '../user/user.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CirculationService {
|
export class CirculationService {
|
||||||
|
private async hasSystemManageAllPermission(userId: number): Promise<boolean> {
|
||||||
|
const permissions = await this.userService.getUserPermissions(userId);
|
||||||
|
return permissions.includes('system.manage_all');
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(Circulation)
|
@InjectRepository(Circulation)
|
||||||
private circulationRepo: Repository<Circulation>,
|
private circulationRepo: Repository<Circulation>,
|
||||||
@@ -25,11 +31,36 @@ export class CirculationService {
|
|||||||
private routingRepo: Repository<CirculationRouting>,
|
private routingRepo: Repository<CirculationRouting>,
|
||||||
private numberingService: DocumentNumberingService,
|
private numberingService: DocumentNumberingService,
|
||||||
private dataSource: DataSource,
|
private dataSource: DataSource,
|
||||||
private uuidResolver: UuidResolverService
|
private uuidResolver: UuidResolverService,
|
||||||
|
private userService: UserService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async create(createDto: CreateCirculationDto, user: User) {
|
async create(createDto: CreateCirculationDto, user: User) {
|
||||||
if (!user.primaryOrganizationId) {
|
let userOrgId = user.primaryOrganizationId;
|
||||||
|
if (!userOrgId) {
|
||||||
|
const fullUser = await this.userService.findOne(user.user_id);
|
||||||
|
if (fullUser) {
|
||||||
|
userOrgId = fullUser.primaryOrganizationId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolvedOriginatorId = createDto.originatorId
|
||||||
|
? await this.uuidResolver.resolveOrganizationId(createDto.originatorId)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) {
|
||||||
|
const canManageAll = await this.hasSystemManageAllPermission(
|
||||||
|
user.user_id
|
||||||
|
);
|
||||||
|
if (!canManageAll) {
|
||||||
|
throw new ForbiddenException(
|
||||||
|
'You do not have permission to create documents on behalf of other organizations.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
userOrgId = resolvedOriginatorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!userOrgId) {
|
||||||
throw new BadRequestException('User must belong to an organization');
|
throw new BadRequestException('User must belong to an organization');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +83,7 @@ export class CirculationService {
|
|||||||
// Generate No. using DocumentNumberingService (Type 900 - Circulation)
|
// Generate No. using DocumentNumberingService (Type 900 - Circulation)
|
||||||
const result = await this.numberingService.generateNextNumber({
|
const result = await this.numberingService.generateNextNumber({
|
||||||
projectId: resolvedProjectId,
|
projectId: resolvedProjectId,
|
||||||
originatorOrganizationId: user.primaryOrganizationId,
|
originatorOrganizationId: userOrgId,
|
||||||
typeId: 900, // Fixed Type ID for Circulation
|
typeId: 900, // Fixed Type ID for Circulation
|
||||||
year: new Date().getFullYear(),
|
year: new Date().getFullYear(),
|
||||||
customTokens: {
|
customTokens: {
|
||||||
@@ -62,7 +93,7 @@ export class CirculationService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const circulation = queryRunner.manager.create(Circulation, {
|
const circulation = queryRunner.manager.create(Circulation, {
|
||||||
organizationId: user.primaryOrganizationId,
|
organizationId: userOrgId,
|
||||||
correspondenceId: resolvedCorrId,
|
correspondenceId: resolvedCorrId,
|
||||||
circulationNo: result.number,
|
circulationNo: result.number,
|
||||||
subject: createDto.subject,
|
subject: createDto.subject,
|
||||||
@@ -76,7 +107,7 @@ export class CirculationService {
|
|||||||
queryRunner.manager.create(CirculationRouting, {
|
queryRunner.manager.create(CirculationRouting, {
|
||||||
circulationId: savedCirculation.id,
|
circulationId: savedCirculation.id,
|
||||||
stepNumber: index + 1,
|
stepNumber: index + 1,
|
||||||
organizationId: user.primaryOrganizationId,
|
organizationId: userOrgId,
|
||||||
assignedTo: assigneeId,
|
assignedTo: assigneeId,
|
||||||
status: 'PENDING',
|
status: 'PENDING',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ export class CreateCirculationDto {
|
|||||||
@IsOptional()
|
@IsOptional()
|
||||||
projectId?: number | string; // Project ID or UUID for Numbering
|
projectId?: number | string; // Project ID or UUID for Numbering
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
originatorId?: number | string; // ระบุองค์กรเจ้าของเอกสาร (ต้องใช้ร่วมกับสิทธิ system.manage_all)
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
subject!: string; // หัวข้อเรื่อง (Subject)
|
subject!: string; // หัวข้อเรื่อง (Subject)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { FileStorageService } from '../../common/file-storage/file-storage.servi
|
|||||||
import { UuidResolverService } from '../../common/services/uuid-resolver.service';
|
import { UuidResolverService } from '../../common/services/uuid-resolver.service';
|
||||||
import { NotificationService } from '../notification/notification.service';
|
import { NotificationService } from '../notification/notification.service';
|
||||||
import { UpdateCorrespondenceDto } from './dto/update-correspondence.dto';
|
import { UpdateCorrespondenceDto } from './dto/update-correspondence.dto';
|
||||||
|
import { CreateCorrespondenceDto } from './dto/create-correspondence.dto';
|
||||||
import { User } from '../user/entities/user.entity';
|
import { User } from '../user/entities/user.entity';
|
||||||
|
|
||||||
describe('CorrespondenceService', () => {
|
describe('CorrespondenceService', () => {
|
||||||
@@ -336,4 +337,95 @@ describe('CorrespondenceService', () => {
|
|||||||
).toHaveBeenCalled();
|
).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('create', () => {
|
||||||
|
it('should allow system.manage_all user without primaryOrganizationId when originatorId is provided', async () => {
|
||||||
|
const mockUser = {
|
||||||
|
user_id: 1,
|
||||||
|
primaryOrganizationId: null,
|
||||||
|
} as unknown as User;
|
||||||
|
|
||||||
|
const createDto: CreateCorrespondenceDto = {
|
||||||
|
projectId: 'project-uuid',
|
||||||
|
typeId: 1,
|
||||||
|
subject: 'Test Subject',
|
||||||
|
originatorId: 'originator-uuid',
|
||||||
|
recipients: [{ organizationId: 'recipient-uuid', type: 'TO' }],
|
||||||
|
};
|
||||||
|
|
||||||
|
const userService = testingModule.get<UserService>(UserService);
|
||||||
|
const typeRepo = testingModule.get<Repository<CorrespondenceType>>(
|
||||||
|
getRepositoryToken(CorrespondenceType)
|
||||||
|
);
|
||||||
|
const statusRepo = testingModule.get<Repository<CorrespondenceStatus>>(
|
||||||
|
getRepositoryToken(CorrespondenceStatus)
|
||||||
|
);
|
||||||
|
const uuidResolver =
|
||||||
|
testingModule.get<UuidResolverService>(UuidResolverService);
|
||||||
|
|
||||||
|
(userService.findOne as jest.Mock).mockResolvedValue({
|
||||||
|
user_id: 1,
|
||||||
|
primaryOrganizationId: null,
|
||||||
|
});
|
||||||
|
(userService.getUserPermissions as jest.Mock).mockResolvedValue([
|
||||||
|
'system.manage_all',
|
||||||
|
]);
|
||||||
|
|
||||||
|
(uuidResolver.resolveProjectId as jest.Mock).mockResolvedValue(100);
|
||||||
|
(uuidResolver.resolveOrganizationId as jest.Mock).mockImplementation(
|
||||||
|
(value: number | string) => {
|
||||||
|
if (value === 'originator-uuid') return 10;
|
||||||
|
if (value === 'recipient-uuid') return 20;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
(typeRepo.findOne as jest.Mock).mockResolvedValue({
|
||||||
|
id: 1,
|
||||||
|
typeCode: 'LTR',
|
||||||
|
});
|
||||||
|
(statusRepo.findOne as jest.Mock).mockResolvedValue({
|
||||||
|
id: 1,
|
||||||
|
statusCode: 'DRAFT',
|
||||||
|
});
|
||||||
|
|
||||||
|
(numberingService.generateNextNumber as jest.Mock).mockResolvedValue({
|
||||||
|
number: 'DOC-001',
|
||||||
|
});
|
||||||
|
|
||||||
|
mockDataSource.manager.findOne
|
||||||
|
.mockResolvedValueOnce({ id: 10, organizationCode: 'ORG' })
|
||||||
|
.mockResolvedValueOnce({ id: 20, organizationCode: 'REC' });
|
||||||
|
|
||||||
|
const queryRunner = {
|
||||||
|
connect: jest.fn(),
|
||||||
|
startTransaction: jest.fn(),
|
||||||
|
commitTransaction: jest.fn(),
|
||||||
|
rollbackTransaction: jest.fn(),
|
||||||
|
release: jest.fn(),
|
||||||
|
manager: {
|
||||||
|
create: jest.fn(
|
||||||
|
(_entity: unknown, payload: Record<string, unknown>) => payload
|
||||||
|
),
|
||||||
|
save: jest
|
||||||
|
.fn()
|
||||||
|
.mockResolvedValueOnce({ id: 999, publicId: 'corr-uuid' })
|
||||||
|
.mockResolvedValueOnce({ id: 1000 })
|
||||||
|
.mockResolvedValueOnce([]),
|
||||||
|
findOne: jest.fn(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
(mockDataSource.createQueryRunner as jest.Mock).mockReturnValue(
|
||||||
|
queryRunner
|
||||||
|
);
|
||||||
|
|
||||||
|
await service.create(createDto, mockUser);
|
||||||
|
|
||||||
|
expect(queryRunner.manager.create).toHaveBeenCalledWith(
|
||||||
|
Correspondence,
|
||||||
|
expect.objectContaining({ originatorId: 10 })
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -50,6 +50,11 @@ interface ResolvedRecipient {
|
|||||||
export class CorrespondenceService {
|
export class CorrespondenceService {
|
||||||
private readonly logger = new Logger(CorrespondenceService.name);
|
private readonly logger = new Logger(CorrespondenceService.name);
|
||||||
|
|
||||||
|
private async hasSystemManageAllPermission(userId: number): Promise<boolean> {
|
||||||
|
const permissions = await this.userService.getUserPermissions(userId);
|
||||||
|
return permissions.includes('system.manage_all');
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(Correspondence)
|
@InjectRepository(Correspondence)
|
||||||
private correspondenceRepo: Repository<Correspondence>,
|
private correspondenceRepo: Repository<Correspondence>,
|
||||||
@@ -92,9 +97,22 @@ export class CorrespondenceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!userOrgId) {
|
if (!userOrgId) {
|
||||||
throw new BadRequestException(
|
if (createDto.originatorId) {
|
||||||
'User must belong to an organization to create documents'
|
const canManageAll = await this.hasSystemManageAllPermission(
|
||||||
);
|
user.user_id
|
||||||
|
);
|
||||||
|
if (canManageAll) {
|
||||||
|
userOrgId = await this.uuidResolver.resolveOrganizationId(
|
||||||
|
createDto.originatorId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!userOrgId) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'User must belong to an organization to create documents'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For impersonation, use the specified originator
|
// For impersonation, use the specified originator
|
||||||
@@ -187,10 +205,10 @@ export class CorrespondenceService {
|
|||||||
|
|
||||||
// Impersonation Logic
|
// Impersonation Logic
|
||||||
if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) {
|
if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) {
|
||||||
const permissions = await this.userService.getUserPermissions(
|
const canManageAll = await this.hasSystemManageAllPermission(
|
||||||
user.user_id
|
user.user_id
|
||||||
);
|
);
|
||||||
if (!permissions.includes('system.manage_all')) {
|
if (!canManageAll) {
|
||||||
throw new ForbiddenException(
|
throw new ForbiddenException(
|
||||||
'You do not have permission to create documents on behalf of other organizations.'
|
'You do not have permission to create documents on behalf of other organizations.'
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -25,6 +25,14 @@ export class CreateRfaDto {
|
|||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
toOrganizationId!: number | string;
|
toOrganizationId!: number | string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
description:
|
||||||
|
'Originator Organization ID or UUID (for users with system.manage_all)',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
originatorId?: number | string;
|
||||||
|
|
||||||
@ApiProperty({ description: 'ID ของประเภท RFA', example: 1 })
|
@ApiProperty({ description: 'ID ของประเภท RFA', example: 1 })
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
|
|||||||
@@ -63,6 +63,11 @@ import { UuidResolverService } from '../../common/services/uuid-resolver.service
|
|||||||
export class RfaService {
|
export class RfaService {
|
||||||
private readonly logger = new Logger(RfaService.name);
|
private readonly logger = new Logger(RfaService.name);
|
||||||
|
|
||||||
|
private async hasSystemManageAllPermission(userId: number): Promise<boolean> {
|
||||||
|
const permissions = await this.userService.getUserPermissions(userId);
|
||||||
|
return permissions.includes('system.manage_all');
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(Rfa)
|
@InjectRepository(Rfa)
|
||||||
private rfaRepo: Repository<Rfa>,
|
private rfaRepo: Repository<Rfa>,
|
||||||
@@ -226,12 +231,29 @@ export class RfaService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const resolvedOriginatorId = createDto.originatorId
|
||||||
|
? await this.uuidResolver.resolveOrganizationId(createDto.originatorId)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
// Determine User Organization
|
// Determine User Organization
|
||||||
let userOrgId = user.primaryOrganizationId;
|
let userOrgId = user.primaryOrganizationId;
|
||||||
if (!userOrgId) {
|
if (!userOrgId) {
|
||||||
const fullUser = await this.userService.findOne(user.user_id);
|
const fullUser = await this.userService.findOne(user.user_id);
|
||||||
if (fullUser) userOrgId = fullUser.primaryOrganizationId;
|
if (fullUser) userOrgId = fullUser.primaryOrganizationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) {
|
||||||
|
const canManageAll = await this.hasSystemManageAllPermission(
|
||||||
|
user.user_id
|
||||||
|
);
|
||||||
|
if (!canManageAll) {
|
||||||
|
throw new ForbiddenException(
|
||||||
|
'You do not have permission to create documents on behalf of other organizations.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
userOrgId = resolvedOriginatorId;
|
||||||
|
}
|
||||||
|
|
||||||
if (!userOrgId) {
|
if (!userOrgId) {
|
||||||
throw new BadRequestException('User must belong to an organization');
|
throw new BadRequestException('User must belong to an organization');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,14 @@ export class CreateTransmittalDto {
|
|||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
recipientOrganizationId!: number | string;
|
recipientOrganizationId!: number | string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
description:
|
||||||
|
'ผู้ส่ง Organization ID หรือ UUID (สำหรับผู้ใช้ที่มีสิทธิ system.manage_all)',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
originatorId?: number | string;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Correspondence ID หรือ UUID (ADR-019)',
|
description: 'Correspondence ID หรือ UUID (ADR-019)',
|
||||||
required: false,
|
required: false,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
NotFoundException,
|
NotFoundException,
|
||||||
InternalServerErrorException,
|
InternalServerErrorException,
|
||||||
BadRequestException,
|
BadRequestException,
|
||||||
|
ForbiddenException,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Repository, DataSource } from 'typeorm';
|
import { Repository, DataSource } from 'typeorm';
|
||||||
@@ -22,11 +23,17 @@ import { CorrespondenceType } from '../correspondence/entities/correspondence-ty
|
|||||||
import { CorrespondenceStatus } from '../correspondence/entities/correspondence-status.entity';
|
import { CorrespondenceStatus } from '../correspondence/entities/correspondence-status.entity';
|
||||||
import { UuidResolverService } from '../../common/services/uuid-resolver.service';
|
import { UuidResolverService } from '../../common/services/uuid-resolver.service';
|
||||||
import { CorrespondenceRecipient } from '../correspondence/entities/correspondence-recipient.entity';
|
import { CorrespondenceRecipient } from '../correspondence/entities/correspondence-recipient.entity';
|
||||||
|
import { UserService } from '../user/user.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TransmittalService {
|
export class TransmittalService {
|
||||||
private readonly logger = new Logger(TransmittalService.name);
|
private readonly logger = new Logger(TransmittalService.name);
|
||||||
|
|
||||||
|
private async hasSystemManageAllPermission(userId: number): Promise<boolean> {
|
||||||
|
const permissions = await this.userService.getUserPermissions(userId);
|
||||||
|
return permissions.includes('system.manage_all');
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(Transmittal)
|
@InjectRepository(Transmittal)
|
||||||
private transmittalRepo: Repository<Transmittal>,
|
private transmittalRepo: Repository<Transmittal>,
|
||||||
@@ -38,7 +45,8 @@ export class TransmittalService {
|
|||||||
private statusRepo: Repository<CorrespondenceStatus>,
|
private statusRepo: Repository<CorrespondenceStatus>,
|
||||||
private numberingService: DocumentNumberingService,
|
private numberingService: DocumentNumberingService,
|
||||||
private dataSource: DataSource,
|
private dataSource: DataSource,
|
||||||
private uuidResolver: UuidResolverService
|
private uuidResolver: UuidResolverService,
|
||||||
|
private userService: UserService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async create(
|
async create(
|
||||||
@@ -61,7 +69,31 @@ export class TransmittalService {
|
|||||||
await queryRunner.connect();
|
await queryRunner.connect();
|
||||||
await queryRunner.startTransaction();
|
await queryRunner.startTransaction();
|
||||||
|
|
||||||
if (!user.primaryOrganizationId) {
|
let userOrgId = user.primaryOrganizationId;
|
||||||
|
if (!userOrgId) {
|
||||||
|
const fullUser = await this.userService.findOne(user.user_id);
|
||||||
|
if (fullUser) {
|
||||||
|
userOrgId = fullUser.primaryOrganizationId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolvedOriginatorId = createDto.originatorId
|
||||||
|
? await this.uuidResolver.resolveOrganizationId(createDto.originatorId)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
if (resolvedOriginatorId && resolvedOriginatorId !== userOrgId) {
|
||||||
|
const canManageAll = await this.hasSystemManageAllPermission(
|
||||||
|
user.user_id
|
||||||
|
);
|
||||||
|
if (!canManageAll) {
|
||||||
|
throw new ForbiddenException(
|
||||||
|
'You do not have permission to create documents on behalf of other organizations.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
userOrgId = resolvedOriginatorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!userOrgId) {
|
||||||
throw new BadRequestException(
|
throw new BadRequestException(
|
||||||
'User must belong to an organization to create a transmittal'
|
'User must belong to an organization to create a transmittal'
|
||||||
);
|
);
|
||||||
@@ -76,7 +108,7 @@ export class TransmittalService {
|
|||||||
// 2. Generate Number
|
// 2. Generate Number
|
||||||
const docNumber = await this.numberingService.generateNextNumber({
|
const docNumber = await this.numberingService.generateNextNumber({
|
||||||
projectId: internalProjectId,
|
projectId: internalProjectId,
|
||||||
originatorOrganizationId: user.primaryOrganizationId,
|
originatorOrganizationId: userOrgId,
|
||||||
typeId: type.id,
|
typeId: type.id,
|
||||||
year: new Date().getFullYear(),
|
year: new Date().getFullYear(),
|
||||||
customTokens: {
|
customTokens: {
|
||||||
@@ -90,7 +122,7 @@ export class TransmittalService {
|
|||||||
correspondenceNumber: docNumber.number,
|
correspondenceNumber: docNumber.number,
|
||||||
correspondenceTypeId: type.id,
|
correspondenceTypeId: type.id,
|
||||||
projectId: internalProjectId,
|
projectId: internalProjectId,
|
||||||
originatorId: user.primaryOrganizationId,
|
originatorId: userOrgId,
|
||||||
isInternal: false,
|
isInternal: false,
|
||||||
createdBy: user.user_id,
|
createdBy: user.user_id,
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user