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 +1 -1
- package/server/controllers/rptHandler.js +2 -1
- package/server/libs/post-book.js +1 -1
- package/server/libs/sessionContext.js +7 -5
- package/server/models/assuser_identity.js +48 -4
- package/server/models/socai.js +298 -254
- package/server/models/socainpp.js +268 -17
- package/server/models/sokho.js +75 -25
- package/server/modules/reports/calc-tinhgiatb.js +50 -6
- package/server/workers/reportWorker.js +1 -0
package/package.json
CHANGED
|
@@ -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
|
-
|
|
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()}));
|
package/server/libs/post-book.js
CHANGED
|
@@ -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
|
-
|
|
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")
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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);
|
package/server/models/socai.js
CHANGED
|
@@ -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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
119
|
-
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
129
|
-
|
|
128
|
+
socaiSchema.index({id_ct: 1});
|
|
129
|
+
socaiSchema.index({id_app: 1,id_ct: 1});
|
|
130
130
|
|
|
131
|
-
|
|
131
|
+
socaiSchema.index({id_app: 1,ma_ct_goc: 1,id_ct_goc: 1});
|
|
132
132
|
|
|
133
133
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
|
|
162
|
-
|
|
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
|
-
|
|
165
|
-
|
|
164
|
+
socaiSchema.index({id_app: 1,date_created: -1});
|
|
165
|
+
|
|
166
166
|
}
|
|
167
167
|
socaiSchema.pre("save",function(next){
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
-
|
|
184
|
+
next();
|
|
185
185
|
});
|
|
186
186
|
|
|
187
187
|
let socaiQueue = [];
|
|
188
188
|
let socaiIsHandling = false;
|
|
189
189
|
const handleCreateSocaiTc = async ()=>{
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
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
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
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
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
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")
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
+
|
package/server/models/sokho.js
CHANGED
|
@@ -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
|
-
|
|
313
|
-
handleCreateSokhoTc();
|
|
314
|
-
},100)
|
|
312
|
+
handleCreateSokhoTc();
|
|
315
313
|
}
|
|
316
314
|
}
|
|
317
315
|
sokhoSchema.post("save",async function(doc){
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
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
|
-
|
|
334
|
-
|
|
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
|
-
|
|
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
|
-
|
|
385
|
+
|
|
386
|
+
});
|
|
354
387
|
sokhoSchema.pre('deleteOne', async function (next) {
|
|
355
|
-
|
|
356
|
-
|
|
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
|
-
|
|
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
|
-
}
|
|
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(
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
+
};
|