flexbiz-server 12.4.7 → 12.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "flexbiz-server",
3
3
  "main": "./server/app.js",
4
4
  "description": "Flexible Server",
5
- "version": "12.4.7",
5
+ "version": "12.4.9",
6
6
  "author": {
7
7
  "name": "Van Truong Pham",
8
8
  "email": "invncur@gmail.com"
@@ -102,7 +102,8 @@ const rptHandler = async (ctrl,req,callback,res=undefined)=> {
102
102
  console.log(`✅ [rptHanlder] sessionID=${getCurrentSession()?._debugId}`);
103
103
  getData(req, async (error, data, stream,from_cache) => {
104
104
  if (error) {
105
- if (!sendHeader_yn || !options.stream || !res) return callback({error:error.message||error});
105
+ console.error(`❌ [rptHanlder] ${rptId} lỗi:`,error);
106
+ if (!sendHeader_yn || !options.stream || !res) return callback(error);
106
107
  if (_interval) clearInterval(_interval);
107
108
  setTimeout(() => {
108
109
  res.end(JSON.stringify({error: error.toString()}));
@@ -269,7 +269,7 @@ post.prototype.run = async function(callback=()=>{}) {
269
269
  if(details.length==0) return callback(null,[]);
270
270
  model_book.create(details,async (e,rs)=>{
271
271
  if(e){
272
- console.error("[postBook] Đã có lỗi khi postdata",e.error||e.message||e);
272
+ console.error("[postBook] Đã có lỗi khi postdata",e.error||e.message||e,master.ma_ct,master.so_ct);
273
273
  let msg_error = e.message || e.error || e.toString();
274
274
  if(msg_error.indexOf("E11000 duplicate")>=0 && msg_error.indexOf("id_ct_1_line_1")>=0){
275
275
  rs = await model_book.find({id_ct: master._id.toString()});
@@ -88,7 +88,7 @@ exports.handlerWithSession = async function (handler, ctrl, req, callback, ...ex
88
88
 
89
89
  try {
90
90
  if (error) {
91
- console.error("❌ [handlerWithSession] error in handler, aborting...", ctrl.name, error.message);
91
+ console.error("❌ [handlerWithSession] error in handler, aborting...", ctrl.name, error.message,error?.errorLabels);
92
92
  await session.abortTransaction();
93
93
  reject(error);
94
94
  } else {
@@ -173,19 +173,21 @@ exports.handlerWithSession = async function (handler, ctrl, req, callback, ...ex
173
173
  * Thêm callback để chạy sau khi commit.
174
174
  * {string} description miêu tả cb để hiện log (tuỳ chọn)
175
175
  */
176
- exports.onAfterCommit = function (cb,description="") {
176
+ exports.onAfterCommit = function (cb,description="",session=null) {
177
+
177
178
  const store = storage.getStore();
178
- if (store && store.session && exports.isSessionActive(store.session)) {
179
+ session = session || store?.session
180
+ if (store && session && exports.isSessionActive(session)) {
179
181
  // ✅ Lưu vào store.afterCommit
180
182
  store.afterCommit = store.afterCommit || [];
181
183
  store.afterCommit.push(cb);
182
184
  console.log(`[onAfterCommit] added callback, storeId=${store.storeId}, count=${store.afterCommit.length},des=${description}`);
183
185
  } else {
184
186
  // Không có session → chạy ngay
185
- console.log("[onAfterCommit] no active session, running immediately",description);
187
+ console.log("[onAfterCommit] no active session, running immediately",description,", storeId=",store?.storeId);
186
188
  Promise.resolve()
187
189
  .then(cb)
188
- .catch((err) => console.error("[onAfterCommit immediate error]", err,description));
190
+ .catch((err) => console.error("[onAfterCommit immediate error]", err,description,", storeId=",store?.storeId));
189
191
  }
190
192
  };
191
193
 
@@ -1,4 +1,48 @@
1
- const redisCache=require("../libs/redis-cache"),{onAfterCommit}=require("../libs/sessionContext"),assuser_identitySchema=new Schema({id_app:{type:String,required:!0,maxlength:1024},ten_cmnd:{type:String},so_cmnd:{type:String,required:!0,maxlength:32},trang_thai:{type:String},status:{type:Boolean,default:!0},date_created:{type:Date,default:Date.now},date_updated:{type:Date,default:Date.now},user_created:{type:String,default:""},user_updated:{type:String,default:""}});
2
- (global.configs||{}).createIndexes&&(assuser_identitySchema.index({id_app:1,trang_thai:1,so_cmnd:1}),assuser_identitySchema.index({id_app:1,so_cmnd:1},{unique:!0}),assuser_identitySchema.index({so_cmnd:"text"}),assuser_identitySchema.index({status:1}),assuser_identitySchema.index({date_created:1}),assuser_identitySchema.index({date_updated:1}),assuser_identitySchema.index({user_created:1,visible_to:1,visible_to_users:1}));
3
- assuser_identitySchema.post("save",async function($doc$$,$next$$){onAfterCommit(()=>{$doc$$.trang_thai==="1"&&global.getModel("user").findOne({email:$doc$$.user_created},async($error$$,$u$$)=>{console.log("of user",$u$$);$u$$&&($u$$.name=$doc$$.ten_cmnd,$u$$.local=$u$$.local||{},$u$$.local.name=$doc$$.ten_cmnd,await $u$$.save(),await global.getModel("participant").updateOne({email:$doc$$.user_created,id_app:$doc$$.id_app},{name:$doc$$.ten_cmnd}),redisCache.set("user",$u$$.toObject(),function($e$$){$e$$?
4
- console.error($e$$):console.log("cache user infomation to redis")}));$next$$()});$next$$()})});module.exports=mongoose.models.assuser_identity||mongoose.model("assuser_identity",assuser_identitySchema);
1
+ const redisCache = require("../libs/redis-cache");
2
+ const assuser_identitySchema = new Schema({
3
+ id_app: {type: String, required: true, maxlength: 1024},
4
+ ten_cmnd:{type: String},
5
+ so_cmnd: {type: String, required: true, maxlength: 32},
6
+ trang_thai: {type: String},
7
+ status: {type: Boolean, default: true},
8
+ date_created: {type: Date, default: Date.now},
9
+ date_updated: {type: Date, default: Date.now},
10
+ user_created: {type: String, default: ''},
11
+ user_updated: {type: String, default: ''}
12
+ });
13
+ if((global.configs||{}).createIndexes){
14
+ assuser_identitySchema.index({id_app: 1, trang_thai: 1, so_cmnd: 1});
15
+ assuser_identitySchema.index({id_app: 1,so_cmnd: 1},{unique: true });
16
+ assuser_identitySchema.index({so_cmnd: "text"});
17
+ assuser_identitySchema.index({status: 1});
18
+ assuser_identitySchema.index({date_created: 1});
19
+ assuser_identitySchema.index({date_updated: 1});
20
+ assuser_identitySchema.index({user_created: 1,visible_to: 1,visible_to_users: 1});
21
+ }
22
+ assuser_identitySchema.post("save",async function(doc,next){
23
+ if(doc.trang_thai==="1"){
24
+ let User = global.getModel("user");
25
+ User.findOne({email:doc.user_created},async (error,u)=>{
26
+ console.log("of user",u);
27
+ if(u){
28
+ u.name = doc.ten_cmnd;
29
+ u.local = u.local ||{};
30
+ u.local.name = doc.ten_cmnd;
31
+ await u.save();
32
+ await global.getModel("participant").updateOne({email:doc.user_created,id_app:doc.id_app},{name:doc.ten_cmnd});
33
+ //cache
34
+ redisCache.set("user", u.toObject(), function(e) {
35
+ if(e)
36
+ console.error(e)
37
+ else
38
+ console.log("cache user infomation to redis")
39
+ }
40
+ );
41
+ }
42
+ next()
43
+ })
44
+ }
45
+ next();
46
+
47
+ });
48
+ module.exports = mongoose.models.assuser_identity || mongoose.model('assuser_identity', assuser_identitySchema);
@@ -1,295 +1,339 @@
1
1
  const moment = require("moment");
2
2
  const {createSocaiTC} = require("../libs/utils")
3
- const {onAfterCommit} = require("../libs/sessionContext")
3
+ const {onAfterCommit,getCurrentSession} = require("../libs/sessionContext")
4
4
  const socaiSchema = new Schema({
5
- id_app: {type: String, required: true, maxlength: 1024},
6
- ma_dvcs: {type: String, required: true, maxlength: 1024},
7
- id_ct: {type: String, required: true, maxlength: 1024,trim:true},
8
- ma_ct: {type: String, required: true, uppercase: true, maxlength: 32,trim:true},
9
- ma_gd: {type: String, default: '0', maxlength: 32,trim:true},
10
- ngay_ct: {type: Date, required: true},
11
- ngay_ct_full: {type: Date},
12
-
13
- so_ct: {type: String, required: true, uppercase: true, maxlength: 32,trim:true},
14
-
15
- ngay_hd: {type: Date},
16
- so_hd: {type: String, uppercase: true, maxlength: 32,trim:true},
17
-
18
- tk_no: {type: String, required: true, uppercase: true, maxlength: 32,trim:true},
19
- tk_co: {type: String, required: true, uppercase: true, maxlength: 32,trim:true},
20
-
21
- ma_kh_no: {type: String, uppercase: true, default: '', maxlength: 32,trim:true},
22
- ma_kh_co: {type: String, uppercase: true, default: '', maxlength: 32,trim:true},
23
-
24
- ma_nt: {type: String, default: 'VND', required: true, uppercase: true, maxlength: 32,trim:true},
25
- ty_gia: {type: Number, default: 1},
26
-
27
- tien_nt: {type: Number, default: 0},
28
- tien: {type: Number, default: 0},
29
-
30
- dien_giai: {type: String, default: '', maxlength: 1024},
31
- ong_ba: {type: String, default: '', maxlength: 1024},
32
-
33
- ma_kho: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
34
- ma_bp: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
35
- ma_phi: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
36
- ma_hd: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
37
- ma_dt: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
38
- ma_nv: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
39
-
40
- ma_lo: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
41
- han_sd: {type: Date},
42
- ma_tt1: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
43
- ma_tt2: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
44
- ma_tt3: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
45
-
46
- ma_ca: {type: String, uppercase: true, maxlength: 32,trim:true},
47
-
48
- ma_cp: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
49
-
50
- ma_sp: {type: String, default: '', uppercase: true, maxlength: 1024,trim:true},
51
- ma_vt: {type: String, default: '', uppercase: true, maxlength: 1024,trim:true},
52
- ma_dvt_sp: {type: String, maxlength: 32,trim:true},
53
- ma_tt1_sp: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
54
- ma_tt2_sp: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
55
- ma_tt3_sp: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
56
-
57
- ma_cum_chi_tiet: {type: String, uppercase: true, default: '', maxlength: 32,trim:true},
58
- ten_cum_chi_tiet: {type: String, default: '', maxlength: 1024,trim:true},
59
- ma_cong_doan: {type: String, uppercase: true, default: '', maxlength: 32,trim:true},
60
- id_lenhsx: {type: String, maxlength: 1024},
61
- id_cs: {type: String, maxlength: 1024},
62
- id_cs_ck: {type: String, maxlength: 1024},
63
-
64
- id_link:String,
65
- ma_ct_link:String,
66
- so_ct_link:String,
67
-
68
- id_ct_goc:String,
69
- ma_ct_goc:String,
70
- so_ct_goc:String,
71
- ngay_ct_goc:Date,
72
- pt_thanh_toan_goc:String,
73
-
74
- pt_thanh_toan:String,
75
- pt_thanh_toan2:String,
76
-
77
- trang_thai: {type: String, maxlength: 32},
78
-
79
- nh_dk: {type:Number,default:0},
80
- id_kbbtpb:{type:String,maxlength: 1024},
81
- exfields:Schema.Types.Mixed,
82
- exfields_detail:Schema.Types.Mixed,
83
- flag:{type:String,maxlength: 1024},
84
-
85
- gio:Number,
86
- ngay:Number,
87
- thang:Number,
88
- quy:Number,
89
- nam:Number,
90
-
91
- ma_kenh:String,
92
- ma_td1:Schema.Types.Mixed,
93
- ma_td2:Schema.Types.Mixed,
94
- ma_td3:Schema.Types.Mixed,
95
- ma_td4:Schema.Types.Mixed,
96
- ma_td5:Schema.Types.Mixed,
97
- ma_td6:Schema.Types.Mixed,
98
- ma_td7:Schema.Types.Mixed,
99
- ma_td8:Schema.Types.Mixed,
100
- ma_td9:Schema.Types.Mixed,
101
-
102
-
103
-
104
- status: {type: Boolean, default: true},
105
- date_created: {type: Date, default: Date.now},
106
- date_updated: {type: Date, default: Date.now},
107
- user_created: {type: String, default: ''},
108
- user_updated: {type: String, default: ''},
109
- id_client:String,//app dùng để nhập liệu
110
- listinfo_code:String,//form dùng để nhập liệu
5
+ id_app: {type: String, required: true, maxlength: 1024},
6
+ ma_dvcs: {type: String, required: true, maxlength: 1024},
7
+ id_ct: {type: String, required: true, maxlength: 1024,trim:true},
8
+ ma_ct: {type: String, required: true, uppercase: true, maxlength: 32,trim:true},
9
+ ma_gd: {type: String, default: '0', maxlength: 32,trim:true},
10
+ ngay_ct: {type: Date, required: true},
11
+ ngay_ct_full: {type: Date},
12
+
13
+ so_ct: {type: String, required: true, uppercase: true, maxlength: 32,trim:true},
14
+
15
+ ngay_hd: {type: Date},
16
+ so_hd: {type: String, uppercase: true, maxlength: 32,trim:true},
17
+
18
+ tk_no: {type: String, required: true, uppercase: true, maxlength: 32,trim:true},
19
+ tk_co: {type: String, required: true, uppercase: true, maxlength: 32,trim:true},
20
+
21
+ ma_kh_no: {type: String, uppercase: true, default: '', maxlength: 32,trim:true},
22
+ ma_kh_co: {type: String, uppercase: true, default: '', maxlength: 32,trim:true},
23
+
24
+ ma_nt: {type: String, default: 'VND', required: true, uppercase: true, maxlength: 32,trim:true},
25
+ ty_gia: {type: Number, default: 1},
26
+
27
+ tien_nt: {type: Number, default: 0},
28
+ tien: {type: Number, default: 0},
29
+
30
+ dien_giai: {type: String, default: '', maxlength: 1024},
31
+ ong_ba: {type: String, default: '', maxlength: 1024},
32
+
33
+ ma_kho: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
34
+ ma_bp: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
35
+ ma_phi: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
36
+ ma_hd: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
37
+ ma_dt: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
38
+ ma_nv: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
39
+
40
+ ma_lo: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
41
+ han_sd: {type: Date},
42
+ ma_tt1: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
43
+ ma_tt2: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
44
+ ma_tt3: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
45
+
46
+ ma_ca: {type: String, uppercase: true, maxlength: 32,trim:true},
47
+
48
+ ma_cp: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
49
+
50
+ ma_sp: {type: String, default: '', uppercase: true, maxlength: 1024,trim:true},
51
+ ma_vt: {type: String, default: '', uppercase: true, maxlength: 1024,trim:true},
52
+ ma_dvt_sp: {type: String, maxlength: 32,trim:true},
53
+ ma_tt1_sp: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
54
+ ma_tt2_sp: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
55
+ ma_tt3_sp: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
56
+
57
+ ma_cum_chi_tiet: {type: String, uppercase: true, default: '', maxlength: 32,trim:true},
58
+ ten_cum_chi_tiet: {type: String, default: '', maxlength: 1024,trim:true},
59
+ ma_cong_doan: {type: String, uppercase: true, default: '', maxlength: 32,trim:true},
60
+ id_lenhsx: {type: String, maxlength: 1024},
61
+ id_cs: {type: String, maxlength: 1024},
62
+ id_cs_ck: {type: String, maxlength: 1024},
63
+
64
+ id_link:String,
65
+ ma_ct_link:String,
66
+ so_ct_link:String,
67
+
68
+ id_ct_goc:String,
69
+ ma_ct_goc:String,
70
+ so_ct_goc:String,
71
+ ngay_ct_goc:Date,
72
+ pt_thanh_toan_goc:String,
73
+
74
+ pt_thanh_toan:String,
75
+ pt_thanh_toan2:String,
76
+
77
+ trang_thai: {type: String, maxlength: 32},
78
+
79
+ nh_dk: {type:Number,default:0},
80
+ id_kbbtpb:{type:String,maxlength: 1024},
81
+ exfields:Schema.Types.Mixed,
82
+ exfields_detail:Schema.Types.Mixed,
83
+ flag:{type:String,maxlength: 1024},
84
+
85
+ gio:Number,
86
+ ngay:Number,
87
+ thang:Number,
88
+ quy:Number,
89
+ nam:Number,
90
+
91
+ ma_kenh:String,
92
+ ma_td1:Schema.Types.Mixed,
93
+ ma_td2:Schema.Types.Mixed,
94
+ ma_td3:Schema.Types.Mixed,
95
+ ma_td4:Schema.Types.Mixed,
96
+ ma_td5:Schema.Types.Mixed,
97
+ ma_td6:Schema.Types.Mixed,
98
+ ma_td7:Schema.Types.Mixed,
99
+ ma_td8:Schema.Types.Mixed,
100
+ ma_td9:Schema.Types.Mixed,
101
+
102
+
103
+
104
+ status: {type: Boolean, default: true},
105
+ date_created: {type: Date, default: Date.now},
106
+ date_updated: {type: Date, default: Date.now},
107
+ user_created: {type: String, default: ''},
108
+ user_updated: {type: String, default: ''},
109
+ id_client:String,//app dùng để nhập liệu
110
+ listinfo_code:String,//form dùng để nhập liệu
111
111
  },{ toJSON: { virtuals: true } });
112
112
  if((global.configs||{}).createIndexes){
113
- socaiSchema.index({id_app: 1});
114
- socaiSchema.index({id_app: 1,ma_dvcs: 1});
115
- socaiSchema.index({id_app: 1,ma_ct: 1,so_ct: 1});
116
- socaiSchema.index({id_app: 1,ma_ct: 1});
113
+ socaiSchema.index({id_app: 1});
114
+ socaiSchema.index({id_app: 1,ma_dvcs: 1});
115
+ socaiSchema.index({id_app: 1,ma_ct: 1,so_ct: 1});
116
+ socaiSchema.index({id_app: 1,ma_ct: 1});
117
117
 
118
- socaiSchema.index({id_app: 1,ma_nt: 1,ngay_ct: -1});
119
- socaiSchema.index({id_app: 1,so_ct: 1,ngay_ct: -1});
118
+ socaiSchema.index({id_app: 1,ma_nt: 1,ngay_ct: -1});
119
+ socaiSchema.index({id_app: 1,so_ct: 1,ngay_ct: -1});
120
120
 
121
- socaiSchema.index({id_app: 1,gio: 1});
122
- socaiSchema.index({id_app: 1,ngay: 1});
123
- socaiSchema.index({id_app: 1,thang: 1});
124
- socaiSchema.index({id_app: 1,quy: 1});
125
- socaiSchema.index({id_app: 1,nam: -1});
121
+ socaiSchema.index({id_app: 1,gio: 1});
122
+ socaiSchema.index({id_app: 1,ngay: 1});
123
+ socaiSchema.index({id_app: 1,thang: 1});
124
+ socaiSchema.index({id_app: 1,quy: 1});
125
+ socaiSchema.index({id_app: 1,nam: -1});
126
126
 
127
127
 
128
- socaiSchema.index({id_ct: 1});
129
- socaiSchema.index({id_app: 1,id_ct: 1});
128
+ socaiSchema.index({id_ct: 1});
129
+ socaiSchema.index({id_app: 1,id_ct: 1});
130
130
 
131
- socaiSchema.index({id_app: 1,ma_ct_goc: 1,id_ct_goc: 1});
131
+ socaiSchema.index({id_app: 1,ma_ct_goc: 1,id_ct_goc: 1});
132
132
 
133
133
 
134
- socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_bp: 1,ngay_ct:-1});
135
- socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_phi: 1,ngay_ct:-1});
136
- socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_hd: 1,ngay_ct:-1});
137
- socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_dt: 1,ngay_ct:-1});
138
- socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_nv: 1,ngay_ct:-1});
139
- socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_sp: 1,ngay_ct:-1});
140
- socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_kho:1,ma_vt: 1,ngay_ct:-1});
134
+ socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_bp: 1,ngay_ct:-1});
135
+ socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_phi: 1,ngay_ct:-1});
136
+ socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_hd: 1,ngay_ct:-1});
137
+ socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_dt: 1,ngay_ct:-1});
138
+ socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_nv: 1,ngay_ct:-1});
139
+ socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_sp: 1,ngay_ct:-1});
140
+ socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_kho:1,ma_vt: 1,ngay_ct:-1});
141
141
 
142
- socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_kenh: 1,ngay_ct:-1});
143
- socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_td1: 1,ngay_ct:-1});
144
- socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_td2: 1,ngay_ct:-1});
145
- socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_td3: 1,ngay_ct:-1});
142
+ socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_kenh: 1,ngay_ct:-1});
143
+ socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_td1: 1,ngay_ct:-1});
144
+ socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_td2: 1,ngay_ct:-1});
145
+ socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_td3: 1,ngay_ct:-1});
146
146
 
147
147
 
148
- socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_vt:1,ma_tt1: 1,ma_tt2: 1,ma_tt3: 1,ma_lo: 1,han_sd:-1,ngay_ct:-1});
148
+ socaiSchema.index({id_app: 1,tk_no:1,tk_co:1,ma_vt:1,ma_tt1: 1,ma_tt2: 1,ma_tt3: 1,ma_lo: 1,han_sd:-1,ngay_ct:-1});
149
149
 
150
- socaiSchema.index({id_app: 1,id_lenhsx: 1});
151
- socaiSchema.index({id_app: 1,id_link: 1});
152
- socaiSchema.index({id_app: 1,id_cs: 1});//id chinh sach khuyen mai
153
- socaiSchema.index({id_app: 1,id_cs_ck: 1});//id chinh sach khuyen mai
150
+ socaiSchema.index({id_app: 1,id_lenhsx: 1});
151
+ socaiSchema.index({id_app: 1,id_link: 1});
152
+ socaiSchema.index({id_app: 1,id_cs: 1});//id chinh sach khuyen mai
153
+ socaiSchema.index({id_app: 1,id_cs_ck: 1});//id chinh sach khuyen mai
154
154
 
155
155
 
156
- socaiSchema.index({id_app:1,id_ct:1,so_ct: -1,ma_kh_no:1,ma_kh_co:1,tk_no:1,tk_co:1,ngay_ct:-1});
157
- socaiSchema.index({id_app:1,ma_kh_no:1,ma_kh_co:1,tk_no:1,tk_co:1,ngay_ct:-1});
158
- socaiSchema.index({id_app:1,tk_no:1,ngay_ct:-1});
159
- socaiSchema.index({id_app:1,tk_co:1,ngay_ct:-1});
156
+ socaiSchema.index({id_app:1,id_ct:1,so_ct: -1,ma_kh_no:1,ma_kh_co:1,tk_no:1,tk_co:1,ngay_ct:-1});
157
+ socaiSchema.index({id_app:1,ma_kh_no:1,ma_kh_co:1,tk_no:1,tk_co:1,ngay_ct:-1});
158
+ socaiSchema.index({id_app:1,tk_no:1,ngay_ct:-1});
159
+ socaiSchema.index({id_app:1,tk_co:1,ngay_ct:-1});
160
160
 
161
- socaiSchema.index({id_app:1,tk_no:1,ma_kho:1,ngay_ct_full:-1});
162
- socaiSchema.index({id_app:1,tk_co:1,ma_kho:1,ngay_ct_full:-1});
161
+ socaiSchema.index({id_app:1,tk_no:1,ma_kho:1,ngay_ct_full:-1});
162
+ socaiSchema.index({id_app:1,tk_co:1,ma_kho:1,ngay_ct_full:-1});
163
163
 
164
- socaiSchema.index({id_app: 1,date_created: -1});
165
-
164
+ socaiSchema.index({id_app: 1,date_created: -1});
165
+
166
166
  }
167
167
  socaiSchema.pre("save",function(next){
168
- const self = this;
169
- if(self.ma_nt=='VND'){
170
- self.tien_nt = Math.roundBy(self.tien_nt,0);
171
- self.tien = self.tien_nt;
172
- }else{
173
- self.tien = Math.roundBy(self.tien,0);
174
- }
175
- self.ngay_ct_full = new Date(self.ngay_ct);
176
- let ngay_ct = moment(self.ngay_ct);
177
- self.gio = ngay_ct.get("hours");
178
- self.ngay = ngay_ct.get("dates");
179
- self.quy = ngay_ct.get("quarters");
180
- self.thang = ngay_ct.get("months")+1;
181
- self.nam = ngay_ct.get("year");
182
- self.ngay_ct = ngay_ct.startOf("date").toDate();
168
+ const self = this;
169
+ if(self.ma_nt=='VND'){
170
+ self.tien_nt = Math.roundBy(self.tien_nt,0);
171
+ self.tien = self.tien_nt;
172
+ }else{
173
+ self.tien = Math.roundBy(self.tien,0);
174
+ }
175
+ self.ngay_ct_full = new Date(self.ngay_ct);
176
+ let ngay_ct = moment(self.ngay_ct);
177
+ self.gio = ngay_ct.get("hours");
178
+ self.ngay = ngay_ct.get("dates");
179
+ self.quy = ngay_ct.get("quarters");
180
+ self.thang = ngay_ct.get("months")+1;
181
+ self.nam = ngay_ct.get("year");
182
+ self.ngay_ct = ngay_ct.startOf("date").toDate();
183
183
 
184
- next();
184
+ next();
185
185
  });
186
186
 
187
187
  let socaiQueue = [];
188
188
  let socaiIsHandling = false;
189
189
  const handleCreateSocaiTc = async ()=>{
190
- if(socaiIsHandling) return;
191
- socaiQueue = [...new Set(socaiQueue)];
192
- let doc = socaiQueue.shift();
193
- if(doc){
194
- try{
195
- socaiIsHandling = true;
196
- doc = JSON.parse(doc);
197
- await createSocaiTC(doc.id_app,doc.ngay_ct,doc.ngay_ct);
198
- }catch(e){
199
- console.error("handleCreateSocaiTc",doc,e);
200
- }
201
- socaiIsHandling = false;
202
- setTimeout(()=>{
203
- handleCreateSocaiTc();
204
- },10)
205
- }
190
+ if(socaiIsHandling) return;
191
+ socaiQueue = [...new Set(socaiQueue)];
192
+ let doc = socaiQueue.shift();
193
+ if(doc){
194
+ try{
195
+ socaiIsHandling = true;
196
+ doc = JSON.parse(doc);
197
+ await createSocaiTC(doc.id_app,doc.ngay_ct,doc.ngay_ct);
198
+ }catch(e){
199
+ console.error("handleCreateSocaiTc",doc,e);
200
+ }
201
+ socaiIsHandling = false;
202
+ setTimeout(()=>{
203
+ handleCreateSocaiTc();
204
+ },10)
205
+ }
206
206
  }
207
207
  socaiSchema.post("save",async function(doc){
208
- onAfterCommit(()=>{
209
- //tạo socaitheongay
210
- setImmediate(async ()=>{
211
- //cập nhật ngày mua gần nhất của khác hàng
212
- if(["SO1","HD2","HD1","PBL"].indexOf(doc.ma_ct)>=0){
213
- if(doc.ma_kh_no){
214
- let dhgn = await global.getModel("socai").findOne({ma_kh_no:doc.ma_kh_no,id_app:doc.id_app},{ngay_ct:1}).sort({ngay_ct:-1});
215
- if(dhgn){
216
- const so_ngay_da_mua = moment().diff(moment(dhgn.ngay_ct),"days");
217
- global.getModel("customer").updateOne({ma_kh:doc.ma_kh_no,id_app:doc.id_app},{ngay_mua_gan_nhat:dhgn.ngay_ct,so_ngay_da_mua});
218
- }
219
- }
220
- if(doc.ma_kh_co && doc.ma_kh_co!=doc.ma_kh_no){
221
- let dhgn = await global.getModel("socai").findOne({ma_kh_co:doc.ma_kh_co,id_app:doc.id_app},{ngay_ct:1}).sort({ngay_ct:-1});
222
- if(dhgn){
223
- const so_ngay_da_mua = moment().diff(moment(dhgn.ngay_ct),"days");
224
- global.getModel("customer").updateOne({ma_kh:doc.ma_kh_co,id_app:doc.id_app},{ngay_mua_gan_nhat:dhgn.ngay_ct,so_ngay_da_mua});
225
- }
226
- }
227
- }
228
- let key = JSON.stringify({id_app:doc.id_app,ngay_ct:doc.ngay_ct});
229
- if(!socaiQueue.find(d=>d==key)){
230
- socaiQueue.push(key);
231
- if(!socaiIsHandling){
232
- handleCreateSocaiTc();
233
- }
234
- }
235
- })
236
- },"Xử lý sự kiện sau khi lưu socai")
208
+ // Lấy session từ document
209
+ const session = doc.$session() || getCurrentSession();
210
+ // Định nghĩa hàm xử lý
211
+ const handleSaveAfterCommit = async () => {
212
+ //cập nhật ngày mua gần nhất của khác hàng
213
+ if(["SO1","HD2","HD1","PBL"].indexOf(doc.ma_ct)>=0){
214
+ if(doc.ma_kh_no){
215
+ let dhgn = await global.getModel("socai").findOne({ma_kh_no:doc.ma_kh_no,id_app:doc.id_app},{ngay_ct:1}).sort({ngay_ct:-1});
216
+ if(dhgn){
217
+ const so_ngay_da_mua = moment().diff(moment(dhgn.ngay_ct),"days");
218
+ global.getModel("customer").updateOne({ma_kh:doc.ma_kh_no,id_app:doc.id_app},{ngay_mua_gan_nhat:dhgn.ngay_ct,so_ngay_da_mua});
219
+ }
220
+ }
221
+ if(doc.ma_kh_co && doc.ma_kh_co!=doc.ma_kh_no){
222
+ let dhgn = await global.getModel("socai").findOne({ma_kh_co:doc.ma_kh_co,id_app:doc.id_app},{ngay_ct:1}).sort({ngay_ct:-1});
223
+ if(dhgn){
224
+ const so_ngay_da_mua = moment().diff(moment(dhgn.ngay_ct),"days");
225
+ global.getModel("customer").updateOne({ma_kh:doc.ma_kh_co,id_app:doc.id_app},{ngay_mua_gan_nhat:dhgn.ngay_ct,so_ngay_da_mua});
226
+ }
227
+ }
228
+ }
229
+ let key = JSON.stringify({id_app:doc.id_app,ngay_ct:doc.ngay_ct});
230
+ if(!socaiQueue.find(d=>d==key)){
231
+ socaiQueue.push(key);
232
+ if(!socaiIsHandling){
233
+ handleCreateSocaiTc();
234
+ }
235
+ }
236
+ };
237
+
238
+ if (session) {
239
+ // Nếu có session, thêm vào danh sách
240
+ onAfterCommit(handleSaveAfterCommit, "Xử lý sự kiện sau khi lưu socai",session);
241
+ } else {
242
+ // Không có session (chạy ngoài transaction), chạy ngay
243
+ try {
244
+ await handleSaveAfterCommit();
245
+ } catch (e) {
246
+ console.error("❌ post save immediate error:", e);
247
+ }
248
+ }
237
249
  });
238
250
 
239
251
  socaiSchema.pre('deleteMany', async function (next) {
240
- onAfterCommit(async ()=>{
241
- let query = this.getQuery();
242
- let deletedDocs =(await global.getModel("socai").find(query,{id_app:1,ngay_ct:1}).lean()).map(r=>{
243
- return JSON.stringify({id_app:r.id_app,ngay_ct:r.ngay_ct});
244
- })
245
- setImmediate(()=>{
246
- deletedDocs = [...new Set(deletedDocs)];
247
- deletedDocs.forEach(doc=>{
248
- if(!socaiQueue.find(d=>d==doc)){
249
- socaiQueue.push(doc);
250
- }
251
- })
252
- if(!socaiIsHandling){
253
- handleCreateSocaiTc();
254
- }
255
-
256
- })
257
- next();
258
- },"Xử lý sự kiện trước khi xoá socai")
259
-
252
+
253
+ // 1. Lấy session từ Query object
254
+ const session = this.options.session || getCurrentSession();
255
+
256
+ // 2. Định nghĩa hàm xử lý
257
+ const handleDeletionAfterCommit = async () => {
258
+ let query = this.getQuery();
259
+ let deletedDocs =(await global.getModel("socai").find(query,{id_app:1,ngay_ct:1}).lean()).map(r=>{
260
+ return JSON.stringify({id_app:r.id_app,ngay_ct:r.ngay_ct});
261
+ })
262
+ setImmediate(()=>{
263
+ deletedDocs = [...new Set(deletedDocs)];
264
+ deletedDocs.forEach(doc=>{
265
+ if(!socaiQueue.find(d=>d==doc)){
266
+ socaiQueue.push(doc);
267
+ }
268
+ })
269
+ if(!socaiIsHandling){
270
+ handleCreateSocaiTc();
271
+ }
272
+
273
+ })
274
+ };
275
+
276
+ if (session) {
277
+ // 3. Nếu có session, thêm vào danh sách afterCommit
278
+ onAfterCommit(handleDeletionAfterCommit, "Xử lý sự kiện sau khi xoá socai",session);
279
+ next(); // KẾT THÚC hook ngay lập tức, cho phép deleteMany chạy
280
+ } else {
281
+ // 4. Nếu không có session, chạy ngay lập tức (dùng next(err) nếu lỗi)
282
+ try {
283
+ await handleDeletionAfterCommit();
284
+ next();
285
+ } catch (e) {
286
+ next(e);
287
+ }
288
+ }
260
289
  });
261
290
  socaiSchema.pre('deleteOne', async function (next) {
262
- onAfterCommit(async ()=>{
263
- let query = this.getQuery();
264
- let deletedDocs =(await global.getModel("socai").find(query,{id_app:1,ngay_ct:1}).lean()).map(r=>{
265
- return JSON.stringify({id_app:r.id_app,ngay_ct:r.ngay_ct});
266
- })
267
- setImmediate(()=>{
268
- deletedDocs = [...new Set(deletedDocs)];
269
- deletedDocs.forEach(doc=>{
270
- if(!socaiQueue.find(d=>d==doc)){
271
- socaiQueue.push(doc);
272
- }
273
- })
274
- if(!socaiIsHandling){
275
- setTimeout(()=>{
276
- handleCreateSocaiTc();
277
- },1*60*1000)
278
- }
279
-
280
- })
281
- next();
282
- },"Xử lý sự kiện trước khi xoá socai")
291
+ // 1. Lấy session từ Query object
292
+ const session = this.options.session || getCurrentSession();
293
+ // 2. Định nghĩa hàm xử lý
294
+ const handleDeletionAfterCommit = async () => {
295
+ let query = this.getQuery();
296
+ let deletedDocs =(await global.getModel("socai").find(query,{id_app:1,ngay_ct:1}).lean()).map(r=>{
297
+ return JSON.stringify({id_app:r.id_app,ngay_ct:r.ngay_ct});
298
+ })
299
+ setImmediate(()=>{
300
+ deletedDocs = [...new Set(deletedDocs)];
301
+ deletedDocs.forEach(doc=>{
302
+ if(!socaiQueue.find(d=>d==doc)){
303
+ socaiQueue.push(doc);
304
+ }
305
+ })
306
+ if(!socaiIsHandling){
307
+ setTimeout(()=>{
308
+ handleCreateSocaiTc();
309
+ },1*60*1000)
310
+ }
311
+
312
+ })
313
+ };
314
+ if (session) {
315
+ // 3. Nếu có session, thêm vào danh sách afterCommit
316
+ onAfterCommit(handleDeletionAfterCommit, "Xử lý sự kiện trước khi xoá socai",session);
317
+ next(); // KẾT THÚC hook ngay lập tức, cho phép deleteMany chạy
318
+ } else {
319
+ // 4. Nếu không có session, chạy ngay lập tức (dùng next(err) nếu lỗi)
320
+ try {
321
+ await handleDeletionAfterCommit();
322
+ next();
323
+ } catch (e) {
324
+ next(e);
325
+ }
326
+ }
283
327
  });
284
328
  const model = mongoose.models.socai || mongoose.model('socai', socaiSchema);
285
329
  if((global.configs||{}).createIndexes){
286
- model.on('index', async function(err) {
287
- if (err) {
288
- console.error('socai index error',err);
289
- } else {
290
- console.info('socai indexing complete');
291
- }
292
- });
330
+ model.on('index', async function(err) {
331
+ if (err) {
332
+ console.error('socai index error',err);
333
+ } else {
334
+ console.info('socai indexing complete');
335
+ }
336
+ });
293
337
 
294
338
  }
295
339
 
@@ -1,17 +1,268 @@
1
- const moment=require("moment"),{onAfterCommit}=require("../libs/sessionContext"),socainppSchema=new Schema({id_app:{type:String,required:!0,maxlength:1024},ma_dvcs:{type:String,required:!0,maxlength:1024},id_ct:{type:String,required:!0,maxlength:1024,trim:!0},ma_ct:{type:String,required:!0,uppercase:!0,maxlength:32,trim:!0},ma_gd:{type:String,default:"0",maxlength:32,trim:!0},ngay_ct:{type:Date,required:!0},so_ct:{type:String,required:!0,uppercase:!0,maxlength:32,trim:!0},ngay_hd:{type:Date},so_hd:{type:String,
2
- uppercase:!0,maxlength:32,trim:!0},tk_no:{type:String,required:!0,uppercase:!0,maxlength:32,trim:!0},tk_co:{type:String,required:!0,uppercase:!0,maxlength:32,trim:!0},ma_kh_no:{type:String,uppercase:!0,default:"",maxlength:32,trim:!0},ma_kh_co:{type:String,uppercase:!0,default:"",maxlength:32,trim:!0},ma_nt:{type:String,default:"VND",required:!0,uppercase:!0,maxlength:32,trim:!0},ty_gia:{type:Number,default:1},tien_nt:{type:Number,default:0},tien:{type:Number,default:0},dien_giai:{type:String,default:"",
3
- maxlength:1024},ong_ba:{type:String,default:"",maxlength:1024},ma_kho:{type:String,default:"",uppercase:!0,maxlength:32,trim:!0},ma_bp:{type:String,default:"",uppercase:!0,maxlength:32,trim:!0},ma_phi:{type:String,default:"",uppercase:!0,maxlength:32,trim:!0},ma_hd:{type:String,default:"",uppercase:!0,maxlength:32,trim:!0},ma_dt:{type:String,default:"",uppercase:!0,maxlength:32,trim:!0},ma_nv:{type:String,default:"",uppercase:!0,maxlength:32,trim:!0},ma_lo:{type:String,default:"",uppercase:!0,maxlength:32,
4
- trim:!0},han_sd:{type:Date},ma_tt1:{type:String,default:"",uppercase:!0,maxlength:32,trim:!0},ma_tt2:{type:String,default:"",uppercase:!0,maxlength:32,trim:!0},ma_tt3:{type:String,default:"",uppercase:!0,maxlength:32,trim:!0},ma_ca:{type:String,uppercase:!0,maxlength:32,trim:!0},ma_cp:{type:String,default:"",uppercase:!0,maxlength:32,trim:!0},ma_sp:{type:String,default:"",uppercase:!0,maxlength:1024,trim:!0},ma_vt:{type:String,default:"",uppercase:!0,maxlength:1024,trim:!0},ma_dvt_sp:{type:String,
5
- maxlength:32,trim:!0},ma_tt1_sp:{type:String,default:"",uppercase:!0,maxlength:32,trim:!0},ma_tt2_sp:{type:String,default:"",uppercase:!0,maxlength:32,trim:!0},ma_tt3_sp:{type:String,default:"",uppercase:!0,maxlength:32,trim:!0},ma_cum_chi_tiet:{type:String,uppercase:!0,default:"",maxlength:32,trim:!0},ten_cum_chi_tiet:{type:String,default:"",maxlength:1024,trim:!0},ma_cong_doan:{type:String,uppercase:!0,default:"",maxlength:32,trim:!0},id_lenhsx:{type:String,maxlength:1024},id_cs:{type:String,maxlength:1024},
6
- id_link:String,ma_ct_link:String,so_ct_link:String,id_ct_goc:String,ma_ct_goc:String,so_ct_goc:String,ngay_ct_goc:Date,pt_thanh_toan_goc:String,pt_thanh_toan:String,pt_thanh_toan2:String,trang_thai:{type:String,maxlength:32},nh_dk:{type:Number,default:0},id_kbbtpb:{type:String,maxlength:1024},exfields:Schema.Types.Mixed,exfields_detail:Schema.Types.Mixed,flag:{type:String,maxlength:1024},gio:Number,ngay:Number,thang:Number,quy:Number,nam:Number,ma_kenh:String,ma_td1:Schema.Types.Mixed,ma_td2:Schema.Types.Mixed,
7
- ma_td3:Schema.Types.Mixed,ma_td4:Schema.Types.Mixed,ma_td5:Schema.Types.Mixed,ma_td6:Schema.Types.Mixed,ma_td7:Schema.Types.Mixed,ma_td8:Schema.Types.Mixed,ma_td9:Schema.Types.Mixed,status:{type:Boolean,default:!0},date_created:{type:Date,default:Date.now},date_updated:{type:Date,default:Date.now},user_created:{type:String,default:""},user_updated:{type:String,default:""},id_client:String,listinfo_code:String},{toJSON:{virtuals:!0}});
8
- socainppSchema.pre("save",function($next$$){this.tien=this.ma_nt=="VND"?this.tien_nt=Math.roundBy(this.tien_nt,0):Math.roundBy(this.tien,0);let $ngay_ct$$=moment(this.ngay_ct);this.gio=$ngay_ct$$.get("hours");this.ngay=$ngay_ct$$.get("dates");this.quy=$ngay_ct$$.get("quarters");this.thang=$ngay_ct$$.get("months")+1;this.nam=$ngay_ct$$.get("year");this.ngay_ct=$ngay_ct$$.startOf("date").toDate();$next$$()});
9
- (global.configs||{}).createIndexes&&(socainppSchema.index({id_app:1}),socainppSchema.index({id_app:1,ma_dvcs:1}),socainppSchema.index({id_app:1,ma_ct:1,so_ct:1}),socainppSchema.index({id_app:1,ma_ct:1}),socainppSchema.index({id_app:1,ngay_ct:-1,ma_nt:1}),socainppSchema.index({id_app:1,so_ct:1,ngay_ct:-1}),socainppSchema.index({id_app:1,gio:1}),socainppSchema.index({id_app:1,ngay:1}),socainppSchema.index({id_app:1,thang:1}),socainppSchema.index({id_app:1,quy:1}),socainppSchema.index({id_app:1,nam:-1}),
10
- socainppSchema.index({id_ct:1}),socainppSchema.index({id_app:1,id_ct:1}),socainppSchema.index({id_app:1,ma_ct_goc:1,id_ct_goc:1}),socainppSchema.index({id_app:1,ngay_ct:-1,tk_no:1,tk_co:1,ma_bp:1}),socainppSchema.index({id_app:1,ngay_ct:-1,tk_no:1,tk_co:1,ma_phi:1}),socainppSchema.index({id_app:1,ngay_ct:-1,tk_no:1,tk_co:1,ma_hd:1}),socainppSchema.index({id_app:1,ngay_ct:-1,tk_no:1,tk_co:1,ma_dt:1}),socainppSchema.index({id_app:1,ngay_ct:-1,tk_no:1,tk_co:1,ma_nv:1}),socainppSchema.index({id_app:1,
11
- ngay_ct:-1,tk_no:1,tk_co:1,ma_sp:1}),socainppSchema.index({id_app:1,ngay_ct:-1,tk_no:1,tk_co:1,ma_kho:1,ma_vt:1}),socainppSchema.index({id_app:1,ngay_ct:-1,tk_no:1,tk_co:1,ma_kenh:1}),socainppSchema.index({id_app:1,ngay_ct:-1,tk_no:1,tk_co:1,ma_td1:1}),socainppSchema.index({id_app:1,ngay_ct:-1,tk_no:1,tk_co:1,ma_td2:1}),socainppSchema.index({id_app:1,ngay_ct:-1,tk_no:1,tk_co:1,ma_td3:1}),socainppSchema.index({id_app:1,ngay_ct:-1,tk_no:1,tk_co:1,ma_vt:1,ma_tt1:1,ma_tt2:1,ma_tt3:1,ma_lo:1,han_sd:-1}),
12
- socainppSchema.index({id_app:1,id_lenhsx:1}),socainppSchema.index({id_app:1,id_link:1}),socainppSchema.index({id_app:1,id_cs:1}),socainppSchema.index({id_app:1,id_cs_ck:1}),socainppSchema.index({id_app:1,id_ct:1,so_ct:-1,ngay_ct:-1,ma_kh_no:1,ma_kh_co:1,tk_no:1,tk_co:1}),socainppSchema.index({id_app:1,ngay_ct:-1,ma_kh_no:1,ma_kh_co:1,tk_no:1,tk_co:1}),socainppSchema.index({id_app:1,ngay_ct:-1,tk_no:1}),socainppSchema.index({id_app:1,ngay_ct:-1,tk_co:1}),socainppSchema.index({id_app:1,date_created:-1}));
13
- socainppSchema.post("save",async function($doc$$){onAfterCommit(async()=>{if(["SO1","HD2","HD1","PBL"].indexOf($doc$$.ma_ct)>=0){if($doc$$.ma_kh_no){var $dhgn_dhgn$$=await global.getModel("socainpp").findOne({ma_kh:$doc$$.ma_kh_no,id_app:$doc$$.id_app},{ngay_ct:1}).sort({ngay_ct:-1});if($dhgn_dhgn$$){var $so_ngay_da_mua_so_ngay_da_mua$$=moment().diff(moment($dhgn_dhgn$$.ngay_ct),"days");model.updateOne({ma_kh:$doc$$.ma_kh_no,id_app:$doc$$.id_app},{ngay_mua_gan_nhat:$dhgn_dhgn$$.ngay_ct,so_ngay_da_mua:$so_ngay_da_mua_so_ngay_da_mua$$})}}$doc$$.ma_kh_co&&
14
- $doc$$.ma_kh_co!=$doc$$.ma_kh_no&&($dhgn_dhgn$$=await global.getModel("socainpp").findOne({ma_kh:$doc$$.ma_kh_co,id_app:$doc$$.id_app},{ngay_ct:1}).sort({ngay_ct:-1}))&&($so_ngay_da_mua_so_ngay_da_mua$$=moment().diff(moment($dhgn_dhgn$$.ngay_ct),"days"),model.updateOne({ma_kh:$doc$$.ma_kh_co,id_app:$doc$$.id_app},{ngay_mua_gan_nhat:$dhgn_dhgn$$.ngay_ct,so_ngay_da_mua:$so_ngay_da_mua_so_ngay_da_mua$$}))}})});const model=mongoose.models.socainpp||mongoose.model("socainpp",socainppSchema);
15
- model.getArise=async($query$$,$options$$={fields:void 0})=>{let $condition$$={ngay_ct:{$gte:$query$$.tu_ngay,$lte:$query$$.den_ngay},id_app:$query$$.id_app};$query$$.ma_dvcs&&($condition$$.ma_dvcs=$query$$.ma_dvcs);$query$$.ma_bp&&($condition$$.ma_bp=$query$$.ma_bp);$query$$.ma_hd&&($condition$$.ma_hd=$query$$.ma_hd);$query$$.ma_dt&&($condition$$.ma_dt=$query$$.ma_dt);$query$$.ma_sp&&($condition$$.ma_sp=$query$$.ma_sp);$query$$.ma_nv&&($condition$$.ma_nv=$query$$.ma_nv);$query$$.ma_phi&&($condition$$.ma_phi=
16
- $query$$.ma_phi);$query$$.ma_kho&&($condition$$.ma_kho=$query$$.ma_kho);if($query$$.tk_no&&Array.isArray($query$$.tk_no)){var $tk_co_tk_no$$=$query$$.tk_no.reg();$condition$$.tk_no=$query$$.giam_tru_no?{$not:new RegExp($tk_co_tk_no$$)}:{$regex:$tk_co_tk_no$$,$options:"i"}}$query$$.tk_co&&Array.isArray($query$$.tk_co)&&($tk_co_tk_no$$=$query$$.tk_co.reg(),$condition$$.tk_co=$query$$.giam_tru_co&&$tk_co_tk_no$$?{$not:new RegExp($tk_co_tk_no$$)}:{$regex:$tk_co_tk_no$$,$options:"i"});return await model.find($condition$$,
17
- $options$$.fields).lean()};module.exports=model;
1
+ const moment = require("moment");
2
+ const {onAfterCommit,getCurrentSession} = require("../libs/sessionContext");
3
+ const socainppSchema = new Schema({
4
+ id_app: {type: String, required: true, maxlength: 1024},
5
+ ma_dvcs: {type: String, required: true, maxlength: 1024},
6
+ id_ct: {type: String, required: true, maxlength: 1024,trim:true},
7
+ ma_ct: {type: String, required: true, uppercase: true, maxlength: 32,trim:true},
8
+ ma_gd: {type: String, default: '0', maxlength: 32,trim:true},
9
+ ngay_ct: {type: Date, required: true},
10
+ so_ct: {type: String, required: true, uppercase: true, maxlength: 32,trim:true},
11
+
12
+ ngay_hd: {type: Date},
13
+ so_hd: {type: String, uppercase: true, maxlength: 32,trim:true},
14
+
15
+ tk_no: {type: String, required: true, uppercase: true, maxlength: 32,trim:true},
16
+ tk_co: {type: String, required: true, uppercase: true, maxlength: 32,trim:true},
17
+
18
+ ma_kh_no: {type: String, uppercase: true, default: '', maxlength: 32,trim:true},
19
+ ma_kh_co: {type: String, uppercase: true, default: '', maxlength: 32,trim:true},
20
+
21
+ ma_nt: {type: String, default: 'VND', required: true, uppercase: true, maxlength: 32,trim:true},
22
+ ty_gia: {type: Number, default: 1},
23
+
24
+ tien_nt: {type: Number, default: 0},
25
+ tien: {type: Number, default: 0},
26
+
27
+ dien_giai: {type: String, default: '', maxlength: 1024},
28
+ ong_ba: {type: String, default: '', maxlength: 1024},
29
+
30
+ ma_kho: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
31
+ ma_bp: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
32
+ ma_phi: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
33
+ ma_hd: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
34
+ ma_dt: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
35
+ ma_nv: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
36
+
37
+ ma_lo: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
38
+ han_sd: {type: Date},
39
+ ma_tt1: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
40
+ ma_tt2: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
41
+ ma_tt3: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
42
+
43
+ ma_ca: {type: String, uppercase: true, maxlength: 32,trim:true},
44
+
45
+ ma_cp: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
46
+
47
+ ma_sp: {type: String, default: '', uppercase: true, maxlength: 1024,trim:true},
48
+ ma_vt: {type: String, default: '', uppercase: true, maxlength: 1024,trim:true},
49
+ ma_dvt_sp: {type: String, maxlength: 32,trim:true},
50
+ ma_tt1_sp: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
51
+ ma_tt2_sp: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
52
+ ma_tt3_sp: {type: String, default: '', uppercase: true, maxlength: 32,trim:true},
53
+
54
+ ma_cum_chi_tiet: {type: String, uppercase: true, default: '', maxlength: 32,trim:true},
55
+ ten_cum_chi_tiet: {type: String, default: '', maxlength: 1024,trim:true},
56
+ ma_cong_doan: {type: String, uppercase: true, default: '', maxlength: 32,trim:true},
57
+ id_lenhsx: {type: String, maxlength: 1024},
58
+ id_cs: {type: String, maxlength: 1024},
59
+
60
+ id_link:String,
61
+ ma_ct_link:String,
62
+ so_ct_link:String,
63
+
64
+ id_ct_goc:String,
65
+ ma_ct_goc:String,
66
+ so_ct_goc:String,
67
+ ngay_ct_goc:Date,
68
+ pt_thanh_toan_goc:String,
69
+
70
+ pt_thanh_toan:String,
71
+ pt_thanh_toan2:String,
72
+
73
+ trang_thai: {type: String, maxlength: 32},
74
+
75
+ nh_dk: {type:Number,default:0},
76
+ id_kbbtpb:{type:String,maxlength: 1024},
77
+ exfields:Schema.Types.Mixed,
78
+ exfields_detail:Schema.Types.Mixed,
79
+ flag:{type:String,maxlength: 1024},
80
+
81
+ gio:Number,
82
+ ngay:Number,
83
+ thang:Number,
84
+ quy:Number,
85
+ nam:Number,
86
+
87
+ ma_kenh:String,
88
+ ma_td1:Schema.Types.Mixed,
89
+ ma_td2:Schema.Types.Mixed,
90
+ ma_td3:Schema.Types.Mixed,
91
+ ma_td4:Schema.Types.Mixed,
92
+ ma_td5:Schema.Types.Mixed,
93
+ ma_td6:Schema.Types.Mixed,
94
+ ma_td7:Schema.Types.Mixed,
95
+ ma_td8:Schema.Types.Mixed,
96
+ ma_td9:Schema.Types.Mixed,
97
+
98
+ status: {type: Boolean, default: true},
99
+ date_created: {type: Date, default: Date.now},
100
+ date_updated: {type: Date, default: Date.now},
101
+ user_created: {type: String, default: ''},
102
+ user_updated: {type: String, default: ''},
103
+ id_client:String,//app dùng để nhập liệu
104
+ listinfo_code:String,//form dùng để nhập liệu
105
+ },{ toJSON: { virtuals: true } });
106
+ socainppSchema.pre("save",function(next){
107
+ const self = this;
108
+ if(self.ma_nt=='VND'){
109
+ self.tien_nt = Math.roundBy(self.tien_nt,0);
110
+ self.tien = self.tien_nt;
111
+ }else{
112
+ self.tien = Math.roundBy(self.tien,0);
113
+ }
114
+
115
+ let ngay_ct = moment(self.ngay_ct);
116
+ self.gio = ngay_ct.get("hours");
117
+ self.ngay = ngay_ct.get("dates");
118
+ self.quy = ngay_ct.get("quarters");
119
+ self.thang = ngay_ct.get("months")+1;
120
+ self.nam = ngay_ct.get("year");
121
+ self.ngay_ct = ngay_ct.startOf("date").toDate();
122
+
123
+ next();
124
+ });
125
+ if((global.configs||{}).createIndexes){
126
+
127
+ socainppSchema.index({id_app: 1});
128
+ socainppSchema.index({id_app: 1,ma_dvcs: 1});
129
+ socainppSchema.index({id_app: 1,ma_ct: 1,so_ct: 1});
130
+ socainppSchema.index({id_app: 1,ma_ct: 1});
131
+
132
+ socainppSchema.index({id_app: 1,ngay_ct: -1,ma_nt: 1});
133
+ socainppSchema.index({id_app: 1,so_ct: 1,ngay_ct: -1});
134
+
135
+ socainppSchema.index({id_app: 1,gio: 1});
136
+ socainppSchema.index({id_app: 1,ngay: 1});
137
+ socainppSchema.index({id_app: 1,thang: 1});
138
+ socainppSchema.index({id_app: 1,quy: 1});
139
+ socainppSchema.index({id_app: 1,nam: -1});
140
+
141
+
142
+ socainppSchema.index({id_ct: 1});
143
+ socainppSchema.index({id_app: 1,id_ct: 1});
144
+
145
+ socainppSchema.index({id_app: 1,ma_ct_goc: 1,id_ct_goc: 1});
146
+
147
+
148
+ socainppSchema.index({id_app: 1,ngay_ct:-1,tk_no:1,tk_co:1,ma_bp: 1});
149
+ socainppSchema.index({id_app: 1,ngay_ct:-1,tk_no:1,tk_co:1,ma_phi: 1});
150
+ socainppSchema.index({id_app: 1,ngay_ct:-1,tk_no:1,tk_co:1,ma_hd: 1});
151
+ socainppSchema.index({id_app: 1,ngay_ct:-1,tk_no:1,tk_co:1,ma_dt: 1});
152
+ socainppSchema.index({id_app: 1,ngay_ct:-1,tk_no:1,tk_co:1,ma_nv: 1});
153
+ socainppSchema.index({id_app: 1,ngay_ct:-1,tk_no:1,tk_co:1,ma_sp: 1});
154
+ socainppSchema.index({id_app: 1,ngay_ct:-1,tk_no:1,tk_co:1,ma_kho:1,ma_vt: 1});
155
+
156
+ socainppSchema.index({id_app: 1,ngay_ct:-1,tk_no:1,tk_co:1,ma_kenh: 1});
157
+ socainppSchema.index({id_app: 1,ngay_ct:-1,tk_no:1,tk_co:1,ma_td1: 1});
158
+ socainppSchema.index({id_app: 1,ngay_ct:-1,tk_no:1,tk_co:1,ma_td2: 1});
159
+ socainppSchema.index({id_app: 1,ngay_ct:-1,tk_no:1,tk_co:1,ma_td3: 1});
160
+
161
+ socainppSchema.index({id_app: 1,ngay_ct:-1,tk_no:1,tk_co:1,ma_vt:1,ma_tt1: 1,ma_tt2: 1,ma_tt3: 1,ma_lo: 1,han_sd:-1});
162
+
163
+ socainppSchema.index({id_app: 1,id_lenhsx: 1});
164
+ socainppSchema.index({id_app: 1,id_link: 1});
165
+ socainppSchema.index({id_app: 1,id_cs: 1});//id chinh sach khuyen mai
166
+ socainppSchema.index({id_app: 1,id_cs_ck: 1});//id chinh sach khuyen mai
167
+
168
+
169
+ socainppSchema.index({id_app:1,id_ct:1,so_ct: -1,ngay_ct:-1,ma_kh_no:1,ma_kh_co:1,tk_no:1,tk_co:1});
170
+ socainppSchema.index({id_app:1,ngay_ct:-1,ma_kh_no:1,ma_kh_co:1,tk_no:1,tk_co:1});
171
+ socainppSchema.index({id_app:1,ngay_ct:-1,tk_no:1});
172
+ socainppSchema.index({id_app:1,ngay_ct:-1,tk_co:1});
173
+
174
+ socainppSchema.index({id_app: 1,date_created: -1});
175
+
176
+ }
177
+
178
+
179
+ socainppSchema.post("save",async function(doc){
180
+ // Lấy session từ document
181
+ const session = doc.$session() || getCurrentSession();
182
+
183
+ // Định nghĩa hàm xử lý
184
+ const handleSaveAfterCommit = async () => {
185
+ if(["SO1","HD2","HD1","PBL"].indexOf(doc.ma_ct)>=0){
186
+ if(doc.ma_kh_no){
187
+ let dhgn = await global.getModel("socainpp").findOne({ma_kh:doc.ma_kh_no,id_app:doc.id_app},{ngay_ct:1}).sort({ngay_ct:-1});
188
+ if(dhgn){
189
+ const so_ngay_da_mua = moment().diff(moment(dhgn.ngay_ct),"days");
190
+ model.updateOne({ma_kh:doc.ma_kh_no,id_app:doc.id_app},{ngay_mua_gan_nhat:dhgn.ngay_ct,so_ngay_da_mua});
191
+ }
192
+ }
193
+ if(doc.ma_kh_co && doc.ma_kh_co!=doc.ma_kh_no){
194
+ let dhgn = await global.getModel("socainpp").findOne({ma_kh:doc.ma_kh_co,id_app:doc.id_app},{ngay_ct:1}).sort({ngay_ct:-1});
195
+ if(dhgn){
196
+ const so_ngay_da_mua = moment().diff(moment(dhgn.ngay_ct),"days");
197
+ model.updateOne({ma_kh:doc.ma_kh_co,id_app:doc.id_app},{ngay_mua_gan_nhat:dhgn.ngay_ct,so_ngay_da_mua});
198
+ }
199
+ }
200
+ }
201
+ };
202
+ if (session) {
203
+ // Nếu có session, thêm vào danh sách
204
+ onAfterCommit(handleSaveAfterCommit, "Xử lý sự kiện sau khi lưu socainpp",session);
205
+ } else {
206
+ // Không có session (chạy ngoài transaction), chạy ngay
207
+ try {
208
+ await handleSaveAfterCommit();
209
+ } catch (e) {
210
+ console.error("❌ post save immediate error:", e);
211
+ }
212
+ }
213
+
214
+
215
+ });
216
+
217
+ const model = mongoose.models.socainpp || mongoose.model('socainpp', socainppSchema);
218
+ model.getArise = async (query,options={fields:undefined})=>{
219
+ let condition = {
220
+ ngay_ct: {$gte: query.tu_ngay, $lte: query.den_ngay},
221
+ id_app: query.id_app
222
+ };
223
+ if (query.ma_dvcs) {
224
+ condition.ma_dvcs = query.ma_dvcs;
225
+ }
226
+ if (query.ma_bp) {
227
+ condition.ma_bp = query.ma_bp;
228
+ }
229
+ if (query.ma_hd) {
230
+ condition.ma_hd = query.ma_hd;
231
+ }
232
+ if (query.ma_dt) {
233
+ condition.ma_dt = query.ma_dt;
234
+ }
235
+ if (query.ma_sp) {
236
+ condition.ma_sp = query.ma_sp;
237
+ }
238
+ if (query.ma_nv) {
239
+ condition.ma_nv = query.ma_nv;
240
+ }
241
+ if (query.ma_phi) {
242
+ condition.ma_phi = query.ma_phi;
243
+ }
244
+ if (query.ma_kho) {
245
+ condition.ma_kho = query.ma_kho;
246
+ }
247
+
248
+ if (query.tk_no && Array.isArray(query.tk_no)) {
249
+ let tk_no = query.tk_no.reg();
250
+ if (query.giam_tru_no) {
251
+ condition.tk_no = {$not: new RegExp(tk_no)};
252
+ }else {
253
+ condition.tk_no = {$regex: tk_no, $options: 'i'};
254
+ }
255
+ }
256
+
257
+ if (query.tk_co && Array.isArray(query.tk_co)) {
258
+ let tk_co = query.tk_co.reg();
259
+ if (query.giam_tru_co && tk_co) {
260
+ condition.tk_co = {$not: new RegExp(tk_co)};
261
+ }else {
262
+ condition.tk_co = {$regex: tk_co, $options: 'i'};
263
+ }
264
+ }
265
+ return await model.find(condition,options.fields).lean();
266
+ }
267
+ module.exports =model
268
+
@@ -1,6 +1,6 @@
1
1
  const moment = require("moment");
2
2
  const {createSokhoTC} = require("../libs/utils")
3
- const {onAfterCommit} = require("../libs/sessionContext")
3
+ const {onAfterCommit,getCurrentSession} = require("../libs/sessionContext")
4
4
  const sokhoSchema = new Schema({
5
5
  id_app: {type: String, required: true, maxlength: 1024},
6
6
  ma_dvcs: {type: String, required: true, maxlength: 1024},
@@ -309,29 +309,47 @@ const handleCreateSokhoTc = async ()=>{
309
309
  console.error("handleCreateSokhoTc",doc,e);
310
310
  }
311
311
  sokhoIsHandling = false;
312
- setTimeout(()=>{
313
- handleCreateSokhoTc();
314
- },100)
312
+ handleCreateSokhoTc();
315
313
  }
316
314
  }
317
315
  sokhoSchema.post("save",async function(doc){
318
- onAfterCommit(async ()=>{
319
- //tạo socaitheongay
320
- setImmediate(async ()=>{
321
- let key = JSON.stringify({id_app:doc.id_app,ngay_ct:doc.ngay_ct});
322
- if(!sokhoQueue.find(d=>d==key)){
323
- sokhoQueue.push(key);
324
- if(!sokhoIsHandling){
325
- handleCreateSokhoTc();
326
- }
316
+ // Lấy session từ document
317
+ const session = doc.$session() || getCurrentSession();
318
+
319
+ // Định nghĩa hàm xử lý
320
+ const handleSaveAfterCommit = async () => {
321
+ let key = JSON.stringify({id_app:doc.id_app,ngay_ct:doc.ngay_ct});
322
+ if(!sokhoQueue.find(d=>d==key)){
323
+ sokhoQueue.push(key);
324
+ if(!sokhoIsHandling){
325
+ handleCreateSokhoTc();
327
326
  }
328
- })
329
- })
327
+ }
328
+ };
329
+
330
+ if (session) {
331
+ // Nếu có session, thêm vào danh sách
332
+ onAfterCommit(handleSaveAfterCommit, "Xử lý sự kiện sau khi lưu sokho",session);
333
+ } else {
334
+ // Không có session (chạy ngoài transaction), chạy ngay
335
+ try {
336
+ await handleSaveAfterCommit();
337
+ } catch (e) {
338
+ console.error("❌ post save immediate error:", e);
339
+ }
340
+ }
341
+
342
+
330
343
  },"Xử lý sự kiện sau khi lưu sokho");
331
344
 
332
345
  sokhoSchema.pre('deleteMany', async function (next) {
333
- onAfterCommit(async ()=>{
334
- let query = this.getQuery();
346
+
347
+ // 1. Lấy session từ Query object
348
+ const session = this.options.session || getCurrentSession();
349
+
350
+ // 2. Định nghĩa hàm xử lý
351
+ const handleDeletionAfterCommit = async () => {
352
+ let query = this.getQuery();
335
353
  let deletedDocs =(await global.getModel("sokho").find(query,{id_app:1,ngay_ct:1}).lean()).map(r=>{
336
354
  return JSON.stringify({id_app:r.id_app,ngay_ct:r.ngay_ct});
337
355
  })
@@ -347,13 +365,32 @@ sokhoSchema.pre('deleteMany', async function (next) {
347
365
  }
348
366
 
349
367
  })
350
- next();
351
- })
368
+ };
369
+
370
+ if (session) {
371
+ // 3. Nếu có session, thêm vào danh sách afterCommit
372
+ onAfterCommit(handleDeletionAfterCommit, "Xử lý sự kiện sau khi xoá sokho",session);
373
+ next(); // KẾT THÚC hook ngay lập tức, cho phép deleteMany chạy
374
+ } else {
375
+ // 4. Nếu không có session, chạy ngay lập tức (dùng next(err) nếu lỗi)
376
+ try {
377
+ await handleDeletionAfterCommit();
378
+ next();
379
+ } catch (e) {
380
+ next(e);
381
+ }
382
+ }
383
+
352
384
 
353
- },"Xử lý sự kiện trước khi xoá sokho");
385
+
386
+ });
354
387
  sokhoSchema.pre('deleteOne', async function (next) {
355
- onAfterCommit(async ()=>{
356
- let query = this.getQuery();
388
+ // 1. Lấy session từ Query object
389
+ const session = this.options.session || getCurrentSession();
390
+
391
+ // 2. Định nghĩa hàm xử lý
392
+ const handleDeletionAfterCommit = async () => {
393
+ let query = this.getQuery();
357
394
  let deletedDocs =(await global.getModel("sokho").find(query,{id_app:1,ngay_ct:1}).lean()).map(r=>{
358
395
  return JSON.stringify({id_app:r.id_app,ngay_ct:r.ngay_ct});
359
396
  })
@@ -371,10 +408,23 @@ sokhoSchema.pre('deleteOne', async function (next) {
371
408
  }
372
409
 
373
410
  })
374
- next();
375
- })
411
+ };
412
+
413
+ if (session) {
414
+ // 3. Nếu có session, thêm vào danh sách afterCommit
415
+ onAfterCommit(handleDeletionAfterCommit, "Xử lý sự kiện sau khi xoá sokho",session);
416
+ next(); // KẾT THÚC hook ngay lập tức, cho phép deleteMany chạy
417
+ } else {
418
+ // 4. Nếu không có session, chạy ngay lập tức (dùng next(err) nếu lỗi)
419
+ try {
420
+ await handleDeletionAfterCommit();
421
+ next();
422
+ } catch (e) {
423
+ next(e);
424
+ }
425
+ }
376
426
 
377
- },"Xử lý sự kiện trước khi xoá sokho");
427
+ });
378
428
 
379
429
  const model = mongoose.models.sokho || mongoose.model('sokho', sokhoSchema);
380
430
  if((global.configs||{}).createIndexes){
@@ -1,6 +1,50 @@
1
- const tinhgiatb=require("../../libs/tinhgiatb"),controller=require("../../controllers/controllerRPT"),_Notification=global.getModel("notification"),async=require("async"),utils=require("../../libs/utils"),{getCurrentSession}=require("../../libs/sessionContext");
2
- module.exports=function($router$$){new controller($router$$,"tinhgiatb",async function($req$$,$callback$$){const $query$$=$req$$.query;if(!$query$$.nam||!$query$$.tu_thang||!$query$$.den_thang)return $callback$$("Ch\u1ee9c n\u0103ng n\u00e0y y\u00eau c\u1ea7u c\u00e1c tham s\u1ed1: nam,tu_thang,den_thang");var $ds_kho_moment_query_kho$$=require("moment"),$ngay_ks_tu_ngay$$=$ds_kho_moment_query_kho$$([Number($query$$.nam),Number($query$$.tu_thang)-1,1]).startOf("month").toDate();if($ngay_ks_tu_ngay$$=
3
- await utils.isBookLocked({id_app:$req$$.user.current_id_app,ngay_ct:$ngay_ks_tu_ngay$$}))return $callback$$(`\u0110\u00e3 kh\u00f3a s\u1ed5 \u0111\u1ebfn ng\u00e0y ${$ds_kho_moment_query_kho$$($ngay_ks_tu_ngay$$).format("DD/MM/YYYY")}`);const $id_app$$=$query$$.id_app;$ds_kho_moment_query_kho$$=[];$query$$.tinh_theo_kho&&!$query$$.ma_kho?($ds_kho_moment_query_kho$$={id_app:$id_app$$,status:!0},$ds_kho_moment_query_kho$$=(await global.getModel("dmkho").find($ds_kho_moment_query_kho$$,{ma_kho:1}).sort({stt:1}).lean()).map($r$$=>
4
- $r$$.ma_kho)):$ds_kho_moment_query_kho$$=[$query$$.ma_kho];console.log(`\u2705 [tinhgiatb] T\u00ednh gi\u00e1 trung b\u00ecnh, sessionID=${getCurrentSession()?._debugId}`);async.map($ds_kho_moment_query_kho$$,($ma_kho$$,$callback$$)=>{const $zquery$$=Object.assign({},$query$$);$zquery$$.ma_kho=$ma_kho$$;tinhgiatb($zquery$$,function($error$$){$error$$&&console.error("l\u1ed7i t\u00ednh gia trung b\u00ecnh:",$error$$,$zquery$$);$callback$$($error$$)})},$error$$=>{const $email$$=$req$$.user.email;$error$$?
5
- (console.error("L\u1ed7i khi t\u00ednh gi\u00e1 trung b\u00ecnh",$error$$),_Notification.createNotification($email$$,$email$$,$error$$.message||$error$$,$error$$.message||$error$$,null,{id_app:$id_app$$},!0,$req$$.access_token,!0),$callback$$($error$$)):(console.info("\u0110\u00e3 t\u00ednh xong gi\u00e1 trung b\u00ecnh. Th\u00f4ng b\u00e1o t\u1edbi",$email$$),_Notification.createNotification($email$$,$email$$,"Ch\u01b0\u01a1ng tr\u00ecnh \u0111\u00e3 t\u00ednh gi\u00e1 trung b\u00ecnh xong","Ch\u01b0\u01a1ng tr\u00ecnh \u0111\u00e3 t\u00ednh gi\u00e1 trung b\u00ecnh xong",
6
- null,{id_app:$id_app$$},!0,$req$$.access_token,!0),$callback$$(null))})},{stream:!1,useSession:!0,cache:!1,queue:!0,timeout:18E6,waiting_message:"Ch\u01b0\u01a1ng tr\u00ecnh \u0111ang th\u1ef1c hi\u1ec7n. B\u1ea1n c\u00f3 th\u1ec3 chuy\u1ec3n sang trang kh\u00e1c \u0111\u1ec3 l\u00e0m vi\u1ec7c. Khi ch\u01b0\u01a1ng tr\u00ecnh th\u1ef1c hi\u1ec7n xong s\u1ebd g\u1eedi th\u00f4ng b\u00e1o cho b\u1ea1n."})};
1
+ const tinhgiatb = require('../../libs/tinhgiatb');
2
+ const controller =require('../../controllers/controllerRPT');
3
+ const _Notification = global.getModel('notification');
4
+ const async = require("async");
5
+ const utils = require("../../libs/utils");
6
+ const {getCurrentSession} = require("../../libs/sessionContext")
7
+ module.exports = function(router) {
8
+ new controller(router, 'tinhgiatb', async function(req, callback) {
9
+ const query = req.query;
10
+ if (!query.nam || !query.tu_thang || !query.den_thang) {
11
+ return callback('Chức năng này yêu cầu các tham số: nam,tu_thang,den_thang');
12
+ }
13
+ //check ngay khoa so
14
+ const moment = require("moment");
15
+ let tu_ngay = moment([Number(query.nam),Number(query.tu_thang)-1,1]).startOf("month").toDate();
16
+ let ngay_ks = await utils.isBookLocked({id_app:req.user.current_id_app,ngay_ct:tu_ngay});
17
+ if(ngay_ks){
18
+ return callback(`Đã khóa sổ đến ngày ${moment(ngay_ks).format("DD/MM/YYYY")}`);
19
+ }
20
+ const id_app = query.id_app;
21
+ let ds_kho =[];
22
+ if(query.tinh_theo_kho && !query.ma_kho){
23
+ const query_kho = {id_app,status:true};
24
+ ds_kho = (await global.getModel("dmkho").find(query_kho,{ma_kho:1}).sort({stt:1}).lean()).map(r=>r.ma_kho);
25
+ }else{
26
+ ds_kho=[query.ma_kho]
27
+ }
28
+ console.log(`✅ [Calc-tinhgiatb] Tính giá trung bình, sessionID=${getCurrentSession()?._debugId}`);
29
+ async.map(ds_kho,(ma_kho,callback)=>{
30
+ const zquery = Object.assign({},query,);
31
+ zquery.ma_kho = ma_kho;
32
+ tinhgiatb(zquery, function(error) {
33
+ if(error) console.error("[Calc-tinhgiatb] Lỗi tính gia trung bình:",error.message||error.error||error,zquery);
34
+ callback(error);
35
+ });
36
+ },(error)=>{
37
+ const email = req.user.email;
38
+ if (error) {
39
+ console.error("[Calc-tinhgiatb] Lỗi khi tính giá trung bình",error.message||error.error||error)
40
+ _Notification.createNotification(email, email, error.message || error, error.message || error, null,{id_app},true,req.access_token,true);
41
+ callback(error)
42
+ }else{
43
+ console.info("[Calc-tinhgiatb] Đã tính xong giá trung bình. Thông báo tới",email)
44
+ _Notification.createNotification(email, email, "Chương trình đã tính giá trung bình xong", "Chương trình đã tính giá trung bình xong", null,{id_app},true,req.access_token,true);
45
+ callback(null)
46
+ }
47
+ })
48
+ //callback(null,[{message:"Chương trình đang thực hiện. Bạn có thể chuyển sang trang khác để làm việc. Khi chương trình thực hiện xong sẽ gửi thông báo cho bạn."}]);
49
+ }, {stream: false,useSession:true,cache:false,queue:true,timeout:5*60*60*1000,waiting_message:"Chương trình đang thực hiện. Bạn có thể chuyển sang trang khác để làm việc. Khi chương trình thực hiện xong sẽ gửi thông báo cho bạn."});
50
+ };
@@ -130,4 +130,5 @@ process.on('uncaughtException', (err) => {
130
130
 
131
131
  process.on('unhandledRejection', (reason) => {
132
132
  console.error('❌ [reportworker] Unhandled promise rejection:', reason.message);
133
+ process.exit(1)
133
134
  });