flexbiz-server 12.5.26 → 12.5.28

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.5.26",
5
+ "version": "12.5.28",
6
6
  "author": {
7
7
  "name": "Van Truong Pham",
8
8
  "email": "invncur@gmail.com"
@@ -1,25 +1,351 @@
1
- const async=require("async"),utils=require("./utils"),tontucthoi=global.getModel("tontucthoi"),Dmvt=global.getModel("dmvt"),round=4,tinhgiatb=require("../libs/tinhgiatb1vt"),moment=require("moment"),dinhmucsx=async($id_app$$,$i_ma_sp_qd$$,$dm_ma_tt1$$,$sl_xuat_sl_xuat_qd$$,$dm_of_vt_ma_dvt_vt$$)=>{let $vts$$=[];$dm_ma_tt1$$=await global.getModel("dinhmucsx").findOne({id_app:$id_app$$,ma_sp:$i_ma_sp_qd$$,ma_tt1:$dm_ma_tt1$$||void 0},{details:1}).lean();if(!$dm_ma_tt1$$||!$dm_ma_tt1$$.details||$dm_ma_tt1$$.details.length===
2
- 0)return $vts$$;$dm_ma_tt1$$.details=$dm_ma_tt1$$.details.map($d$$=>{$d$$.toObject&&($d$$=$d$$.toObject());return $d$$});var $he_so_qd_sl$$=1;($i_ma_sp_qd$$=await global.getModel("dmqddvt").findOne({id_app:$id_app$$,ma_vt:$i_ma_sp_qd$$,ma_dvt:$dm_of_vt_ma_dvt_vt$$}).lean())&&($he_so_qd_sl$$=$i_ma_sp_qd$$.mau?$i_ma_sp_qd$$.tu/$i_ma_sp_qd$$.mau:$i_ma_sp_qd$$.ty_le_qd);$sl_xuat_sl_xuat_qd$$*=$he_so_qd_sl$$;await $dm_ma_tt1$$.details.asyncJoinModel2($id_app$$,Dmvt,{where:"ma_vt",setFields:($item$$,$ref$$)=>
3
- {$item$$.tk_vt||($item$$.tk_vt=$ref$$.tk_vt);$item$$.tk_gv||($item$$.tk_gv=$ref$$.tk_gv);$item$$.tg_tk=$ref$$.tg_tk;$item$$.xk_nvl=$ref$$.xk_nvl}});for($i_ma_sp_qd$$=0;$i_ma_sp_qd$$<$dm_ma_tt1$$.details.length;$i_ma_sp_qd$$++)$dm_of_vt_ma_dvt_vt$$=$dm_ma_tt1$$.details[$i_ma_sp_qd$$],$he_so_qd_sl$$=0,$he_so_qd_sl$$=$dm_of_vt_ma_dvt_vt$$.loai_dinh_muc==1?$dm_of_vt_ma_dvt_vt$$.sl_dinh_muc*$sl_xuat_sl_xuat_qd$$*(1+($dm_of_vt_ma_dvt_vt$$.ty_le_hao_hut||0)/100):$dm_of_vt_ma_dvt_vt$$.sl_dinh_muc*(1+$dm_of_vt_ma_dvt_vt$$.ty_le_hao_hut/
4
- 100),$dm_of_vt_ma_dvt_vt$$.xk_nvl?($dm_of_vt_ma_dvt_vt$$=await dinhmucsx($id_app$$,$dm_of_vt_ma_dvt_vt$$.ma_vt,$dm_of_vt_ma_dvt_vt$$.ma_tt1||void 0,$he_so_qd_sl$$,$dm_of_vt_ma_dvt_vt$$.ma_dvt),$vts$$=[...$vts$$,...$dm_of_vt_ma_dvt_vt$$]):($dm_of_vt_ma_dvt_vt$$.sl_xuat=$he_so_qd_sl$$,$vts$$.push($dm_of_vt_ma_dvt_vt$$));return $vts$$},post=function($master$$,$details$$,$prepare$$,$options$$={}){$details$$||=[];this.master={...$master$$};this.details=$details$$.map($detail$$=>({...$detail$$}));this.prepare=
5
- $prepare$$;this.options=$options$$};
6
- post.prototype.runPrepare=async($prepareFunction$$,$details$$)=>{$details$$=$details$$.map($d$$=>{$d$$.toObject&&($d$$=$d$$.toObject());return{...$d$$}});return new Promise($resolve$$=>{$prepareFunction$$?async.map($details$$,($detail$$,$callback$$)=>{setImmediate(()=>{$detail$$.toObject=function(){return Object.assign({},$detail$$)};$prepareFunction$$($detail$$,$detail$$=>{$detail$$.toObject=function(){return Object.assign({},$detail$$)};$callback$$(null,$detail$$)})})},($e$$,$details$$)=>{$resolve$$($details$$)}):
7
- $resolve$$($details$$)})};
8
- post.prototype.remove=function($callback$$=()=>{}){let $master$$=this.master;$master$$&&$master$$.toObject&&($master$$=$master$$.toObject());if(!$master$$._id)return $callback$$();let $query_delete$$={id_ct:$master$$._id.toString(),id_app:$master$$.id_app};this.options.queryDelete&&($query_delete$$={...$query_delete$$,...this.options.queryDelete,id_app:$master$$.id_app});async.series({sks:$callback$$=>{setImmediate(()=>{global.getModel("sokho").find({id_ct:$master$$._id.toString()}).lean().then(function($sks$$){$callback$$(null,$sks$$)}).catch($e$$=>
9
- {$callback$$($e$$)})})}},async($e$$,$rs$$)=>{if($e$$)return $callback$$($e$$);await global.getModel("sokho").deleteMany($query_delete$$);await global.getModel("sokhonpp").deleteMany($query_delete$$);await global.getModel("sokhokhongton").deleteMany($query_delete$$);$rs$$.sks.length>0&&tontucthoi.tinhTonTucThoi($rs$$.sks,$e$$=>{$e$$&&console.error("[post-sokho] T\u00ednh t\u1ed3n t\u1ee9c th\u1eddi sau khi xo\u00e1 sokho c\u1ee7a v\u1eadt t\u01b0",$e$$)});$callback$$()})};
10
- post.prototype.run=async function($callback$$=()=>{}){if(!this.details)return console.error("details not exists"),$callback$$(null);if(!this.master||!this.master._id)return console.error("masters not exists",this.master),$callback$$(null);let $master$$=this.master;$master$$.toObject&&($master$$=$master$$.toObject());let $details$$=await this.runPrepare(this.prepare,this.details);await $details$$.asyncJoinModel2($master$$.id_app,Dmvt,{where:"ma_vt",setFields:($item$$,$ref$$)=>{$item$$.tk_vt||($item$$.tk_vt=
11
- $ref$$.tk_vt);$item$$.tk_gv||($item$$.tk_gv=$ref$$.tk_gv);$item$$.tg_tk=$ref$$.tg_tk;$item$$.xk_nvl=$ref$$.xk_nvl}});if(($master$$.ma_ct||"").toUpperCase()!=="PKK"){var $ds_kho_kho_locked_ps_kg_dm_sp_co_dm_sp_xk_nvl$$=[...(new Set($details$$.map($d$$=>$d$$.ma_kho||$master$$.ma_kho)))];if($ds_kho_kho_locked_ps_kg_dm_sp_co_dm_sp_xk_nvl$$=await global.getModel("dmkho").findOne({id_app:$master$$.id_app,lock:!0,ma_kho:{$in:$ds_kho_kho_locked_ps_kg_dm_sp_co_dm_sp_xk_nvl$$}}).lean())return $callback$$(`Kho ${$ds_kho_kho_locked_ps_kg_dm_sp_co_dm_sp_xk_nvl$$.ten_kho} \u0111\u00e3 b\u1ecb kho\u00e1`)}$ds_kho_kho_locked_ps_kg_dm_sp_co_dm_sp_xk_nvl$$=
12
- $details$$.filter($p$$=>$p$$.xk_nvl&&$p$$.nxt==2);for(var $i$jscomp$1_i$$=0;$i$jscomp$1_i$$<$ds_kho_kho_locked_ps_kg_dm_sp_co_dm_sp_xk_nvl$$.length;$i$jscomp$1_i$$++)$ds_kho_kho_locked_ps_kg_dm_sp_co_dm_sp_xk_nvl$$[$i$jscomp$1_i$$].dinh_muc_nvl=await dinhmucsx($master$$.id_app,$ds_kho_kho_locked_ps_kg_dm_sp_co_dm_sp_xk_nvl$$[$i$jscomp$1_i$$].ma_vt,$ds_kho_kho_locked_ps_kg_dm_sp_co_dm_sp_xk_nvl$$[$i$jscomp$1_i$$].ma_tt1,$ds_kho_kho_locked_ps_kg_dm_sp_co_dm_sp_xk_nvl$$[$i$jscomp$1_i$$].sl_xuat,$ds_kho_kho_locked_ps_kg_dm_sp_co_dm_sp_xk_nvl$$[$i$jscomp$1_i$$].ma_dvt);
13
- $details$$=$details$$.filter($d$$=>$d$$.tg_tk||$d$$.dinh_muc_nvl&&$d$$.dinh_muc_nvl.length>0);$ds_kho_kho_locked_ps_kg_dm_sp_co_dm_sp_xk_nvl$$=$details$$.filter($p$$=>$p$$.xk_nvl&&$p$$.dinh_muc_nvl&&$p$$.dinh_muc_nvl.length>0);for($i$jscomp$1_i$$=0;$i$jscomp$1_i$$<$ds_kho_kho_locked_ps_kg_dm_sp_co_dm_sp_xk_nvl$$.length;$i$jscomp$1_i$$++){const $p$$=$ds_kho_kho_locked_ps_kg_dm_sp_co_dm_sp_xk_nvl$$[$i$jscomp$1_i$$];let $he_so_qd$$=1,$qd$$=await global.getModel("dmqddvt").findOne({id_app:$master$$.id_app,
14
- ma_vt:$p$$.ma_vt,ma_dvt:$p$$.ma_dvt}).lean();$qd$$&&($he_so_qd$$=$qd$$.mau?$qd$$.tu/$qd$$.mau:$qd$$.ty_le_qd);let $sl_sp$$=$p$$.sl_xuat*$he_so_qd$$;$p$$.dinh_muc_nvl=$p$$.dinh_muc_nvl.map($d$$=>{$d$$.nxt=$p$$.nxt;$d$$.ma_sp=$p$$.ma_vt;$d$$.sl_sp=$sl_sp$$;$d$$.ma_tt1_sp=$p$$.ma_tt1;$d$$.ma_tt2_sp=$p$$.ma_tt2;$d$$.ma_tt3_sp=$p$$.ma_tt3;$d$$.ma_kho=$p$$.ma_kho;return $d$$});$p$$.dinh_muc_nvl=$p$$.dinh_muc_nvl.filter($p$$=>$p$$.tg_tk)}$ds_kho_kho_locked_ps_kg_dm_sp_co_dm_sp_xk_nvl$$=$details$$.filter($p$$=>
15
- !$p$$.xk_nvl||!$p$$.dinh_muc_nvl||$p$$.dinh_muc_nvl.length===0);$i$jscomp$1_i$$=$details$$.filter($p$$=>$p$$.xk_nvl&&$p$$.dinh_muc_nvl&&$p$$.dinh_muc_nvl.length>0).map($p$$=>$p$$.dinh_muc_nvl).reduce(($a$$,$b$$)=>$a$$.concat($b$$),[]);$details$$=[...$ds_kho_kho_locked_ps_kg_dm_sp_co_dm_sp_xk_nvl$$,...$i$jscomp$1_i$$];await $details$$.asyncJoinModel2($master$$.id_app,global.getModel("dmqddvt"),{where:{ma_vt:"ma_vt",ma_dvt:"ma_dvt"},fields:["tu","mau",{he_so_qd:"ty_le_qd"}]});$details$$.forEach($detail$$=>
16
- {$detail$$.ma_kho=$detail$$.ma_kho||$master$$.ma_kho;$detail$$.he_so_qd=$detail$$.he_so_qd||1;$detail$$.mau&&$detail$$.tu?($detail$$.he_so_qd=$detail$$.tu/$detail$$.mau,$detail$$.sl_xuat_qd=utils.round(($detail$$.sl_xuat||0)*$detail$$.tu/$detail$$.mau,round),$detail$$.sl_nhap_qd=utils.round(($detail$$.sl_nhap||0)*$detail$$.tu/$detail$$.mau,round)):($detail$$.sl_xuat_qd=utils.round(($detail$$.sl_xuat||0)*$detail$$.he_so_qd,round),$detail$$.sl_nhap_qd=utils.round(($detail$$.sl_nhap||0)*$detail$$.he_so_qd,
17
- round))});let $nam$$=(new Date($master$$.ngay_ct)).getFullYear(),$thang$$=(new Date($master$$.ngay_ct)).getMonth()+1;await new Promise($rs$$=>{async.map($details$$.filter($p$$=>$p$$.tg_tk&&($p$$.sl_xuat&&!$p$$.px_gia_dd||$p$$.sl_nhap&&$p$$.pn_gia_tb)&&$p$$.sl_xuat),($p$$,$callback$$)=>{setImmediate(async()=>{let $he_so_qd$$=1;var $giatb_qd$$=await global.getModel("dmqddvt").findOne({id_app:$master$$.id_app,ma_vt:$p$$.ma_vt,ma_dvt:$p$$.ma_dvt}).lean();$giatb_qd$$&&($he_so_qd$$=$giatb_qd$$.mau?$giatb_qd$$.tu/
18
- $giatb_qd$$.mau:$giatb_qd$$.ty_le_qd);$giatb_qd$$={ma_vt:$p$$.ma_vt,nam:$nam$$,thang:$thang$$,ma_kho:{$in:[$p$$.ma_kho,"",null]}};if($giatb_qd$$=await global.getModel("giatb").findOne($giatb_qd$$).sort({ma_kho:-1}).lean())$p$$.gia_von_nt=$p$$.gia_von=($giatb_qd$$.gia||0)*$he_so_qd$$,$p$$.tien_xuat_nt=$p$$.tien_xuat=($p$$.sl_xuat||0)*$p$$.gia_von_nt,$p$$.tien_nhap_nt=$p$$.tien_nhap=($p$$.sl_nhap||0)*$p$$.gia_von_nt,$callback$$();else{let $condition$$={id_app:$master$$.id_app,ma_vt:$p$$.ma_vt,ma_kho:$p$$.ma_kho};
19
- $condition$$.tu_ngay=moment($master$$.ngay_ct).startOf("month").toDate();$condition$$.den_ngay=moment($master$$.ngay_ct).endOf("month").toDate();tinhgiatb($condition$$,($e$$,$giatb$$)=>{$e$$&&console.error("[postSokho] Kh\u00f4ng th\u1ec3 t\u00ednh gi\u00e1 trung b\u00ecnh",$e$$.message||$e$$.error||$e$$,$condition$$);$p$$.gia_von_nt=$rs$$?$p$$.gia_von=($giatb$$.gia||0)*$he_so_qd$$:$p$$.gia_von=0;$p$$.tien_xuat_nt=$p$$.tien_xuat=($p$$.sl_xuat||0)*$p$$.gia_von_nt;$p$$.tien_nhap_nt=$p$$.tien_nhap=($p$$.sl_nhap||
20
- 0)*$p$$.gia_von_nt;$callback$$()})}})},()=>{$rs$$()})});$details$$=$details$$.map(($detail$$,$line$$)=>{$detail$$.id_ct=$master$$._id.toString();$detail$$.ma_ct=$master$$.ma_ct;$detail$$.so_ct=$master$$.so_ct;$detail$$.ngay_ct=$master$$.ngay_ct;for(let $attr$$ in global.getModel("sokho").schema.paths)if($attr$$!="id_ct"&&$attr$$!="_id"&&$attr$$!="__v"&&$attr$$!="date_updated"&&$attr$$!="date_created"){let $v$$=$detail$$[$attr$$];$v$$!==void 0&&$v$$!==null&&$v$$!==""||$v$$===0||$master$$[$attr$$]===
21
- void 0||($detail$$[$attr$$]=$master$$[$attr$$])}$detail$$.line=$line$$;delete $detail$$.toObject;delete $detail$$._id;delete $detail$$.__v;return $detail$$});await $details$$.asyncJoinModel2($master$$.id_app,"dmkho",{where:"ma_kho",fields:"la_kho_npp"});const $self$$=this;$self$$.remove(async $error$$=>{if($error$$)return console.error("[postSokho] error delete data post",$error$$.message||$error$$.error||$error$$,$master$$.so_ct,$master$$.ma_ct),$callback$$($error$$);if($details$$.length==0)return $callback$$(null,
22
- []);try{let $data_sokho$$=$details$$.filter($d$$=>$d$$.tg_tk&&!$d$$.la_kho_npp),$rs_sokho$$=await global.getModel("sokho").create($data_sokho$$),$data_sokhonpp$$=$details$$.filter($d$$=>$d$$.tg_tk&&$d$$.la_kho_npp),$rs_sokhnpp$$=await global.getModel("sokhonpp").create($data_sokhonpp$$),$data_sokhokhongton$$=$details$$.filter($d$$=>$d$$.tg_tk==0),$rs_sokhokhongton$$=await global.getModel("sokhokhongton").create($data_sokhokhongton$$);if($master$$.ma_ct){let $contr$$=global.controllers[$master$$.ma_ct.toUpperCase()];
23
- $contr$$?await $contr$$.model.findById($master$$._id)?$callback$$(null,{rs_sokho:$rs_sokho$$,rs_sokhnpp:$rs_sokhnpp$$,rs_sokhokhongton:$rs_sokhokhongton$$}):(console.error("[postSokho] Ch\u1ee9ng t\u1eeb kh\u00f4ng t\u1ed3n t\u1ea1i. X\u00f3a s\u1ed5 s\u00e1ch",$master$$._id,$master$$.so_ct,$master$$.ma_ct),$self$$.remove(()=>{$callback$$("Ch\u1ee9ng t\u1eeb kh\u00f4ng t\u1ed3n t\u1ea1i")})):(console.log("[postSokho] not found controller",$master$$.ma_ct.toUpperCase()),$callback$$(null,{rs_sokho:$rs_sokho$$,
24
- rs_sokhnpp:$rs_sokhnpp$$,rs_sokhokhongton:$rs_sokhokhongton$$}))}else $callback$$(null,{rs_sokho:$rs_sokho$$,rs_sokhnpp:$rs_sokhnpp$$,rs_sokhokhongton:$rs_sokhokhongton$$});$rs_sokho$$&&setImmediate(()=>{tontucthoi.tinhTonTucThoi($rs_sokho$$,$e$$=>{$e$$&&console.error("L\u1ed7i t\u00ednh t\u1ed3n t\u1ee9c th\u1eddi v\u1eadt t\u01b0",$rs_sokho$$,$e$$.message||$e$$.error||$e$$,$master$$.so_ct,$master$$.ma_ct)})})}catch($e$$){console.error("[postSokho] \u0110\u00e3 c\u00f3 l\u1ed7i khi post sokho",$e$$),
25
- $callback$$($e$$)}})};module.exports=post;
1
+ const async = require("async");
2
+ const utils = require("./utils");
3
+ const tontucthoi = global.getModel("tontucthoi");
4
+ const Dmvt = global.getModel("dmvt");
5
+ const round = 4;
6
+ const tinhgiatb = require("../libs/tinhgiatb1vt");
7
+ const moment = require("moment");
8
+ const dinhmucsx = async (id_app,ma_sp,ma_tt1,sl_xuat,ma_dvt)=>{
9
+ let vts=[];
10
+ let dm = await global.getModel("dinhmucsx").findOne({id_app,ma_sp,ma_tt1:ma_tt1||undefined},{details:1}).lean();
11
+ if(!dm || !dm.details || dm.details.length===0) return vts;
12
+ dm.details = dm.details.map(d=>{
13
+ if(d.toObject) d = d.toObject();
14
+ return d;
15
+ })
16
+ //tinh so luong san pham quy doi
17
+ let he_so_qd=1;
18
+ let qd = await global.getModel("dmqddvt").findOne({id_app,ma_vt:ma_sp,ma_dvt}).lean();
19
+ if(qd) he_so_qd = (qd.mau?(qd.tu/qd.mau): qd.ty_le_qd);
20
+ let sl_xuat_qd = sl_xuat * he_so_qd;
21
+ //
22
+ await dm.details.asyncJoinModel2(id_app,Dmvt,{where:"ma_vt",setFields:(item,ref)=>{
23
+ if(!item.tk_vt) item.tk_vt = ref.tk_vt;
24
+ if(!item.tk_gv) item.tk_gv = ref.tk_gv;
25
+ item.tg_tk = ref.tg_tk;
26
+ item.xk_nvl = ref.xk_nvl;
27
+ }});
28
+ for(let i=0;i<dm.details.length;i++){
29
+ let vt = dm.details[i];
30
+ let sl = 0;
31
+ if(vt.loai_dinh_muc==1){
32
+ sl = vt.sl_dinh_muc * sl_xuat_qd * (1+(vt.ty_le_hao_hut||0)/100);
33
+ }else{
34
+ sl = vt.sl_dinh_muc * (1+vt.ty_le_hao_hut/100);
35
+ }
36
+ if(vt.xk_nvl){
37
+ let dm_of_vt = await dinhmucsx(id_app,vt.ma_vt,vt.ma_tt1||undefined,sl,vt.ma_dvt);
38
+ //console.log("dinh muc cua ban thanh pham",vt,dm_of_vt);
39
+ vts = [...vts,...dm_of_vt];
40
+ }else{
41
+ vt.sl_xuat = sl;
42
+ vts.push(vt);
43
+ }
44
+ }
45
+ return vts;
46
+
47
+ }
48
+ const post = function(master, details, prepare,options={}) {
49
+ //
50
+ if (!details) {
51
+ details =[]
52
+ }
53
+ //console.log("details",details)
54
+ //data
55
+ this.master = {...master}
56
+ this.details = details.map(detail=>{
57
+ return {...detail};
58
+ });
59
+ //prepare function
60
+ this.prepare = prepare;
61
+ this.options = options;
62
+ };
63
+ post.prototype.runPrepare = async (prepareFunction,details)=>{
64
+ details = details.map(d=>{
65
+ if(d.toObject) d = d.toObject();
66
+ return {...d}
67
+ })
68
+ return (new Promise(resolve=>{
69
+ if (prepareFunction) {
70
+ async.map(details,(detail,callback)=>{
71
+ setImmediate(()=>{
72
+ detail.toObject = function(){
73
+ return Object.assign({},detail)
74
+ }
75
+ prepareFunction(detail,(detail)=>{
76
+ detail.toObject = function(){
77
+ return Object.assign({},detail)
78
+ }
79
+ callback(null,detail);
80
+ })
81
+ })
82
+
83
+ },(e,details)=>{
84
+ resolve(details);
85
+ })
86
+ }else{
87
+ resolve(details);
88
+ }
89
+ }))
90
+ }
91
+ post.prototype.remove = function(callback = ()=>{}){
92
+ let master = this.master;
93
+ if(master && master.toObject) master = master.toObject();
94
+ if(!master._id) return callback();
95
+ let query_delete = {id_ct: master._id.toString(),id_app:master.id_app};
96
+ if(this.options.queryDelete){
97
+ query_delete = {...query_delete,...this.options.queryDelete,id_app:master.id_app}
98
+ }
99
+ async.series({
100
+ sks:(callback)=>{
101
+ setImmediate(()=>{
102
+ global.getModel("sokho").find({id_ct:master._id.toString()}).lean().then(function(sks){
103
+ callback(null,sks);
104
+ }).catch(e=>{
105
+ callback(e);
106
+ })
107
+ })
108
+
109
+ }
110
+ },async (e,rs)=>{
111
+ if(e) return callback(e);
112
+ //delete sokho congty
113
+ await global.getModel("sokho").deleteMany(query_delete);
114
+ //delete sokhonpp
115
+ await global.getModel("sokhonpp").deleteMany(query_delete);
116
+ //delete sokhokhongton
117
+ await global.getModel("sokhokhongton").deleteMany(query_delete);
118
+ //Tính tồn kho tức thời
119
+ if(rs.sks.length>0){
120
+ //tinh lai ton kho tuc thoi khi xoa sokho
121
+ tontucthoi.tinhTonTucThoi(rs.sks,(e)=>{
122
+ if(e) console.error("[post-sokho] Tính tồn tức thời sau khi xoá sokho của vật tư",e);
123
+ })
124
+ }
125
+ callback();
126
+ })
127
+ }
128
+ post.prototype.run = async function(callback=()=>{}) {
129
+ if (!this.details) {
130
+ console.error("details not exists")
131
+ return callback(null);
132
+ }
133
+ if (!this.master || !this.master._id) {
134
+ console.error("masters not exists",this.master)
135
+ return callback(null);
136
+ }
137
+
138
+ let master = this.master;
139
+ if(master.toObject) master = master.toObject();
140
+
141
+ let details = await this.runPrepare(this.prepare,this.details);
142
+ await details.asyncJoinModel2(master.id_app,Dmvt,{where:"ma_vt",setFields:(item,ref)=>{
143
+ if(!item.tk_vt) item.tk_vt = ref.tk_vt;
144
+ if(!item.tk_gv) item.tk_gv = ref.tk_gv;
145
+ item.tg_tk = ref.tg_tk;
146
+ item.xk_nvl = ref.xk_nvl;
147
+ }});
148
+ //kiểm tra kho bị khoá. loại trừ phiếu kiểm kê
149
+ if((master.ma_ct||"").toUpperCase()!=="PKK"){
150
+ let ds_kho = [...new Set(details.map(d=>d.ma_kho||master.ma_kho))]
151
+ const kho_locked = await global.getModel('dmkho').findOne({id_app:master.id_app,lock:true,ma_kho:{$in:ds_kho}}).lean();
152
+ if(kho_locked) return callback(`Kho ${kho_locked.ten_kho} đã bị khoá`);
153
+ }
154
+ //dinh muc san pham
155
+ let sp_xk_nvl = details.filter(p=>p.xk_nvl && p.nxt==2);
156
+ for(let i =0;i<sp_xk_nvl.length;i++){
157
+ sp_xk_nvl[i].dinh_muc_nvl = await dinhmucsx(master.id_app,sp_xk_nvl[i].ma_vt,sp_xk_nvl[i].ma_tt1,sp_xk_nvl[i].sl_xuat,sp_xk_nvl[i].ma_dvt);
158
+ }
159
+ //
160
+ details = details.filter(d=>d.tg_tk || (d.dinh_muc_nvl && d.dinh_muc_nvl.length>0));
161
+ const sp_co_dm = details.filter(p=>p.xk_nvl && p.dinh_muc_nvl && p.dinh_muc_nvl.length>0);
162
+ for(let i =0;i<sp_co_dm.length;i++){
163
+ //Xác định nguyên vật liệu cho sản phẩm
164
+ const p = sp_co_dm[i];
165
+ //Tính số lượng sản phẩm sản xuất (quy đổi sang đơn vị tính chuẩn)
166
+ let he_so_qd=1;
167
+ let qd = await global.getModel("dmqddvt").findOne({id_app:master.id_app,ma_vt:p.ma_vt,ma_dvt:p.ma_dvt}).lean();
168
+ if(qd) he_so_qd = (qd.mau?(qd.tu/qd.mau): qd.ty_le_qd);
169
+ let sl_sp = p.sl_xuat * he_so_qd;
170
+ //
171
+ p.dinh_muc_nvl = p.dinh_muc_nvl.map(d=>{
172
+ d.nxt = p.nxt;
173
+ d.ma_sp = p.ma_vt;
174
+ d.sl_sp = sl_sp;
175
+
176
+ d.ma_tt1_sp = p.ma_tt1;
177
+ d.ma_tt2_sp = p.ma_tt2;
178
+ d.ma_tt3_sp = p.ma_tt3;
179
+ d.ma_kho = p.ma_kho;
180
+ /*if(d.loai_dinh_muc==1){
181
+ d.sl_xuat = d.sl_dinh_muc * p.sl_xuat * (1+(d.ty_le_hao_hut||0)/100);
182
+ }else{
183
+ d.sl_xuat = d.sl_dinh_muc * (1+p.ty_le_hao_hut/100);
184
+ }*/
185
+ return d;
186
+ })
187
+ /*await p.dinh_muc_nvl.asyncJoinModel2(master.id_app,Dmvt,{where:"ma_vt",setFields:(item,ref)=>{
188
+ if(!item.tk_vt) item.tk_vt = ref.tk_vt;
189
+ if(!item.tk_gv) item.tk_gv = ref.tk_gv;
190
+ item.tg_tk = ref.tg_tk;
191
+ item.xk_nvl = ref.xk_nvl;
192
+ }});*/
193
+ p.dinh_muc_nvl = p.dinh_muc_nvl.filter(p=>p.tg_tk);
194
+ //dinh muc ban thanh pham
195
+ }
196
+ //
197
+ let ps_kg_dm = details.filter(p=>!p.xk_nvl || !p.dinh_muc_nvl || p.dinh_muc_nvl.length===0);
198
+ let ps_dm = details.filter(p=>p.xk_nvl && p.dinh_muc_nvl && p.dinh_muc_nvl.length>0).map(p=>p.dinh_muc_nvl).reduce((a,b)=>a.concat(b),[]);
199
+ //
200
+ details = [...ps_kg_dm,...ps_dm];
201
+ //
202
+ await details.asyncJoinModel2(master.id_app,global.getModel("dmqddvt"),{where:{ma_vt:"ma_vt",ma_dvt:"ma_dvt"},fields:["tu","mau",{he_so_qd:"ty_le_qd"}]});
203
+ details.forEach((detail)=>{
204
+ detail.ma_kho = detail.ma_kho || master.ma_kho;
205
+ detail.he_so_qd = detail.he_so_qd || 1;
206
+ if(detail.mau && detail.tu){
207
+ detail.he_so_qd = detail.tu/detail.mau;
208
+ detail.sl_xuat_qd = utils.round((detail.sl_xuat||0) * detail.tu/detail.mau,round);
209
+ detail.sl_nhap_qd = utils.round((detail.sl_nhap||0) * detail.tu/detail.mau,round);
210
+ }else{
211
+ detail.sl_xuat_qd =utils.round( (detail.sl_xuat||0) * detail.he_so_qd,round);
212
+ detail.sl_nhap_qd =utils.round( (detail.sl_nhap||0) * detail.he_so_qd,round);
213
+ }
214
+ })
215
+ //kiểm tra các kho bị khoá
216
+
217
+ //tu dong xac dinh gia von
218
+ let nam = new Date(master.ngay_ct).getFullYear();
219
+ let thang = new Date(master.ngay_ct).getMonth() + 1;
220
+ await new Promise((rs)=>{
221
+ async.map( details.filter(p=>p.tg_tk && ((p.sl_xuat && !p.px_gia_dd) || (p.sl_nhap && p.pn_gia_tb)) && p.sl_xuat),(p,callback)=>{
222
+ setImmediate(async ()=>{
223
+ //xac dinh he so quy doi
224
+ let he_so_qd=1;
225
+ let qd = await global.getModel("dmqddvt").findOne({id_app:master.id_app,ma_vt:p.ma_vt,ma_dvt:p.ma_dvt}).lean();
226
+ if(qd) he_so_qd = (qd.mau?(qd.tu/qd.mau): qd.ty_le_qd);
227
+ //tim gia tb
228
+ let query = {ma_vt:p.ma_vt,nam,thang,ma_kho:{$in:[p.ma_kho,"",null]}}
229
+ let giatb = await global.getModel("giatb").findOne(query).sort({ma_kho:-1}).lean();
230
+ if(giatb){
231
+ p.gia_von_nt = p.gia_von = (giatb.gia||0) * he_so_qd;
232
+ p.tien_xuat_nt = p.tien_xuat = (p.sl_xuat||0) * p.gia_von_nt;
233
+ p.tien_nhap_nt = p.tien_nhap = (p.sl_nhap||0) * p.gia_von_nt;
234
+ callback();
235
+ }else{
236
+ let condition = {id_app:master.id_app,ma_vt:p.ma_vt,ma_kho:p.ma_kho};
237
+ condition.tu_ngay = moment(master.ngay_ct).startOf("month").toDate();
238
+ condition.den_ngay = moment(master.ngay_ct).endOf("month").toDate();
239
+ tinhgiatb(condition,(e,giatb)=>{
240
+ if(e) console.error("[postSokho] Không thể tính giá trung bình",e.message||e.error||e,condition);
241
+ if(rs){
242
+ p.gia_von_nt = p.gia_von = (giatb.gia||0) * he_so_qd;
243
+ }else{
244
+ p.gia_von_nt = p.gia_von =0;
245
+ }
246
+ p.tien_xuat_nt = p.tien_xuat = (p.sl_xuat||0) * p.gia_von_nt;
247
+ p.tien_nhap_nt = p.tien_nhap = (p.sl_nhap||0) * p.gia_von_nt;
248
+ callback();
249
+ })
250
+ }
251
+ })
252
+ },()=>{
253
+ rs();
254
+ })
255
+ })
256
+ //sync master and detail
257
+ details = details.map((detail,line)=>{
258
+ detail.id_ct = master._id.toString();
259
+ detail.ma_ct = master.ma_ct;
260
+ detail.so_ct = master.so_ct;
261
+ detail.ngay_ct = master.ngay_ct;
262
+ for (let attr in global.getModel("sokho").schema.paths) {
263
+ if (attr != 'id_ct' && attr != '_id' && attr != '__v' && attr != 'date_updated' && attr != 'date_created') {
264
+ let v = detail[attr];
265
+ if((v===undefined || v===null || v==="") && v!==0 && (master[attr]!==undefined)){
266
+ detail[attr] = master[attr]
267
+ }
268
+ }
269
+ }
270
+ detail.line = line;
271
+ delete detail.toObject;
272
+ delete detail._id;
273
+ delete detail.__v;
274
+ return detail;
275
+ })
276
+ //Xác định loại kho
277
+ await details.asyncJoinModel2(master.id_app,"dmkho",{where:"ma_kho",fields:"la_kho_npp"});
278
+ //xoá dư liệu cũ
279
+ const self = this;
280
+ self.remove(async (error)=> {
281
+ if (error){
282
+ console.error("[postSokho] error delete data post",error.message||error.error||error,master.so_ct,master.ma_ct)
283
+ return callback(error)
284
+ }
285
+ if(details.length==0) return callback(null,[]);
286
+ try{
287
+ //post sokho
288
+ let data_sokho = details.filter(d=>d.tg_tk && !d.la_kho_npp);
289
+ let rs_sokho = await global.getModel("sokho").create(data_sokho);
290
+ //console.log("post sokho",rs_sokho);
291
+ //post sokhonpp
292
+ let data_sokhonpp = details.filter(d=>d.tg_tk && d.la_kho_npp);
293
+ let rs_sokhnpp = await global.getModel("sokhonpp").create(data_sokhonpp);
294
+ //post sokhokhongton
295
+ let data_sokhokhongton = details.filter(d=>d.tg_tk==false);
296
+ let rs_sokhokhongton = await global.getModel("sokhokhongton").create(data_sokhokhongton);
297
+ /*if(master.ma_ct){
298
+ let contr = global.controllers[master.ma_ct.toUpperCase()];
299
+ if(contr){
300
+ let ct = await contr.model.findById(master._id).inTxt();
301
+ if(!ct){
302
+ console.error("[postSokho] Chứng từ không tồn tại. Xóa sổ sách",master._id,master.so_ct,master.ma_ct);
303
+ self.remove(()=> {
304
+ callback(`Chứng từ không tồn tại`);
305
+ })
306
+ }else{
307
+ callback(null,{rs_sokho,rs_sokhnpp,rs_sokhokhongton});
308
+ }
309
+ }else{
310
+ console.log("[postSokho] not found controller",master.ma_ct.toUpperCase());
311
+ callback(null,{rs_sokho,rs_sokhnpp,rs_sokhokhongton});
312
+ }
313
+ }else{
314
+ callback(null,{rs_sokho,rs_sokhnpp,rs_sokhokhongton});
315
+ }*/
316
+ callback(null,{rs_sokho,rs_sokhnpp,rs_sokhokhongton});
317
+ //tinh ton kho tuc thoi
318
+ if(rs_sokho){
319
+ setImmediate(()=>{
320
+ tontucthoi.tinhTonTucThoi(rs_sokho,(e)=>{
321
+ if(e) console.error("Lỗi tính tồn tức thời vật tư",rs_sokho,e.message||e.error||e,master.so_ct,master.ma_ct)
322
+ })
323
+ })
324
+ }
325
+ }catch(e){
326
+ console.error("[postSokho] Đã có lỗi khi post sokho",e);
327
+ callback(e);
328
+ /*let msg_error = e.message || e.error || e.toString();
329
+ if(msg_error.indexOf("E11000 duplicate")>=0 && msg_error.indexOf("id_ct_1_line_1")>=0){
330
+ let rs_sokho = await global.getModel("sokho").find({id_ct: master._id.toString()});
331
+ let rs_sokhnpp = await global.getModel("sokhonpp").find({id_ct: master._id.toString()});
332
+ let rs_sokhokhongton = await global.getModel("sokhokhongton").find({id_ct: master._id.toString()});
333
+ if(rs_sokho.length>0 || rs_sokhnpp.length>0 || rs_sokhokhongton.length>0 ){
334
+ callback(null, {rs_sokho,rs_sokhnpp,rs_sokhokhongton});
335
+ }else{
336
+ console.error("[postSokho] Error save data post",e.message||e.error||e,master.so_ct,master.ma_ct)
337
+ self.remove(()=> {
338
+ callback(e);
339
+ })
340
+ }
341
+ }else{
342
+ console.error("[postSokho] Error save data post",e.message||e.error||e,master.so_ct,master.ma_ct)
343
+ self.remove(()=> {
344
+ callback(e);
345
+ })
346
+ }*/
347
+
348
+ }
349
+ });
350
+ };
351
+ module.exports = post;
@@ -1,24 +1,336 @@
1
- const model=global.getModel("checkin"),customer=global.getModel("customer"),moment=require("moment"),dmnv=global.getModel("dmnv"),chamcong=global.getModel("chamcong"),User=global.getModel("user"),controller=require("../../controllers/controller"),PostBook=require("../../libs/post-book");function deg2rad($deg$$){return Math.PI/180*$deg$$}
2
- function getDistanceFromLatLonInM($a$$,$dLon_lon1$$,$lat2$$,$lon2$$){const $dLat$$=deg2rad($lat2$$-$a$$);$dLon_lon1$$=deg2rad($lon2$$-$dLon_lon1$$);$a$$=Math.sin($dLat$$/2)*Math.sin($dLat$$/2)+Math.cos(deg2rad($a$$))*Math.cos(deg2rad($lat2$$))*Math.sin($dLon_lon1$$/2)*Math.sin($dLon_lon1$$/2);return 2*Math.atan2(Math.sqrt($a$$),Math.sqrt(1-$a$$))*6371E3}
3
- const postData=async($obj$$,$callback$$)=>{if($obj$$.trang_thai!="1")return $callback$$();if(global.configs?.required_device_id&&!$obj$$.device_id)return $callback$$("C\u1ea7n th\u00f4ng tin ID c\u1ee7a thi\u1ebft b\u1ecb (device_id)");const $nv$$=await global.getModel("dmnv").findOne({id_app:$obj$$.id_app,$or:[{device_user_id:$obj$$.device_user_id},{user:$obj$$.device_user_id}]}).lean();if(!$nv$$)return $callback$$(`Ch\u01b0a khai b\u00e1o th\u00f4ng tin nh\u00e2n vi\u00ean cho '${$obj$$.device_user_id}'.`);
4
- if($nv$$.trusted_device_id){if($nv$$.trusted_device_id!=$obj$$.device_id)return $callback$$("Thi\u1ebft b\u1ecb ch\u1ea5m c\u00f4ng kh\u00f4ng h\u1ee3p l\u1ec7. B\u1ea1n c\u1ea7n d\u00f9ng thi\u1ebft b\u1ecb \u0111\u00e3 ch\u1ea5m c\u00f4ng l\u1ea7n tr\u01b0\u1edbc ho\u1eb7c li\u00ean h\u1ec7 v\u1edbi admin \u0111\u1ec3 \u0111\u0103ng k\u00fd thi\u1ebft b\u1ecb m\u1edbi.");$nv$$.trusted_device_id=$obj$$.device_id}if($obj$$.device_id){var $cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$=
5
- await global.getModel("dmnv").findOne({id_app:$obj$$.id_app,trusted_device_id:$obj$$.device_id},{_id:1}).lean();if($cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$&&$cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$._id!==$nv$$._id)return $callback$$("Thi\u1ebft b\u1ecb n\u00e0y \u0111\u00e3 \u0111\u01b0\u1ee3c s\u1eed d\u1ee5ng \u0111\u1ec3 ch\u1ea5m cho nh\u00e2n vi\u00ean kh\u00e1c. N\u1ebfu b\u1ea1n c\u1ea7n thay \u0111\u1ed5i h\u00e3y li\u00ean h\u1ec7 v\u1edbi admin.")}if($obj$$.location&&
6
- $obj$$.location.latitude&&$obj$$.location.longitude){var $candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$=null;$nv$$.ma_cn&&($candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$=await global.getModel("dmchinhanh").findOne({id_app:$obj$$.id_app,ma_cn:$nv$$.ma_cn,status:!0}).lean());if(!$candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$)return $callback$$("Ch\u01b0a khai b\u00e1o chi nh\u00e1nh l\u00e0m vi\u1ec7c cho nh\u00e2n vi\u00ean n\u00e0y");
7
- if(!$candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$.location||!$candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$.location.latitude||!$candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$.location.longitude)return $callback$$(`Ch\u01b0a khai b\u00e1o v\u1ecb tr\u00ed c\u1ee7a chi nh\u00e1nh ${$candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$.ten_cn}`);$cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$=
8
- getDistanceFromLatLonInM($obj$$.location.latitude,$obj$$.location.longitude,$candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$.location.latitude,$candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$.location.longitude);$candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$=$candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$.location.allowed_radius||50;if($cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$>
9
- $candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$&&!$obj$$.ma_kh)return console.warn(`[CheckIn Fail] Distance: ${$cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$}m. User: ${$obj$$.device_user_id}`),$callback$$(`V\u1ecb tr\u00ed ch\u1ea5m c\u00f4ng kh\u00f4ng h\u1ee3p l\u1ec7. B\u1ea1n \u0111ang c\u00e1ch c\u00f4ng ty ${Math.round($cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$)}m (Cho ph\u00e9p: ${$candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$}m).`)}else if(global.configs?.required_device_id)return $callback$$("Kh\u00f4ng x\u00e1c \u0111\u1ecbnh \u0111\u01b0\u1ee3c v\u1ecb tr\u00ed c\u1ee7a b\u1ea1n.");
10
- $cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$=await model.find({id_app:$obj$$.id_app,device_user_id:$obj$$.device_user_id,record_time:{$gte:moment($obj$$.record_time).startOf("date").toDate(),$lte:moment($obj$$.record_time).endOf("date").toDate()}}).sort({record_time:1}).lean();let $gio_vao$$,$gio_ra$$,$ma_loai_cong$$;$cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$.length>0&&($gio_vao$$=$cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$[0].record_time);
11
- $cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$.length>1&&($gio_ra$$=$cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$[$cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$.length-1].record_time);$cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$=$gio_vao$$&&$gio_ra$$?moment($gio_ra$$).diff(moment($gio_vao$$),"hours"):0;if($gio_vao$$){$candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$=moment($obj$$.record_time).day().toString();
12
- $candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$={id_app:$obj$$.id_app,status:!0,$and:[{$or:[{nhung_ngay_trong_tuan:{$exists:!1}},{nhung_ngay_trong_tuan:$candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$}]},{$or:[{tong_gio_lam_den:{$gte:$cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$}},{tong_gio_lam_den:0}]},{$or:[{tong_gio_lam_tu:{$lte:$cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$}},{tong_gio_lam_tu:0}]}]};
13
- $candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$=await global.getModel("dmloaicong").find($candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$).sort({tong_gio_lam_tu:-1,ngay_cong:-1}).lean();const $getMinutesFromMidnight$$=$dateStr_m$$=>{if(!$dateStr_m$$)return null;$dateStr_m$$=moment($dateStr_m$$);return $dateStr_m$$.hours()*60+$dateStr_m$$.minutes()},$input_vao_mins$$=$getMinutesFromMidnight$$($gio_vao$$),$input_ra_mins$$=$getMinutesFromMidnight$$($gio_ra$$||
14
- $gio_vao$$);if($candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$=$candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$.find($lc$$=>$lc$$.gio_vao_toi_thieu&&$getMinutesFromMidnight$$($lc$$.gio_vao_toi_thieu)<$input_vao_mins$$||$lc$$.gio_ra_toi_thieu&&$getMinutesFromMidnight$$($lc$$.gio_ra_toi_thieu)>$input_ra_mins$$?!1:!0))$ma_loai_cong$$=$candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$.ma_loai_cong}$candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$=
15
- $nv$$.ma_bp;$nv$$.bo_phan&&$nv$$.bo_phan.length>0&&($candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$=$nv$$.bo_phan[0].ma_bp);let $data$$=$obj$$.toObject?$obj$$.toObject():{...$obj$$};$data$$.id_checkin=$obj$$.device_user_id;$data$$.ngay=$obj$$.record_time;$data$$.ma_loai_cong=$ma_loai_cong$$||"UNKNOW";$data$$.ma_nv=$nv$$.ma_nv;$data$$.ma_bp=$candidates_chiNhanh_loaicong_ma_bp_max_radius_ngay_trong_tuan_query_loai_cong$$;delete $data$$._id;delete $data$$.trang_thai;
16
- $data$$.gio_vao=$gio_vao$$;$data$$.gio_ra=$gio_ra$$;$data$$.tong_gio_lam=$cac_lan_cham_cong_trong_ngay_distance_nv_device_id_tong_gio_lam$$;await chamcong.deleteMany({id_app:$obj$$.id_app,id_checkin:$obj$$.device_user_id,ngay:{$gte:moment($obj$$.record_time).startOf("date").toDate(),$lte:moment($obj$$.record_time).endOf("date").toDate()}});(new PostBook($obj$$,[$data$$],chamcong)).run(async($e$$,$rs$$)=>{$e$$||await global.getModel("dmnv").updateOne({_id:$nv$$._id},{trusted_device_id:$obj$$.device_id});
17
- $callback$$($e$$,$rs$$)})};
18
- module.exports=function($router$$){(new controller($router$$,model,"checkin",{notNeedRight:!0,sort:{record_time:-1},onView:async($user$$,$items$$,$next$$)=>{await $items$$.filter($item$$=>$item$$.trang_thai==="1").asyncJoinModel2($user$$.current_id_app,dmnv,{where:$item$$=>({$or:[{device_user_id:$item$$.device_user_id},{user:$item$$.device_user_id}]}),fields:["ma_nv","ten_nv","picture"]});await $items$$.filter($item$$=>$item$$.trang_thai==="2"||$item$$.trang_thai==="3").asyncJoinModel2($user$$.current_id_app,customer,
19
- {where:$item$$=>({$or:[{device_user_id:$item$$.device_user_id},{of_user:$item$$.device_user_id}]}),fields:["ma_kh","ten_kh","picture"]});await $items$$.filter($item$$=>$item$$.trang_thai==="3"&&$item$$.device_user_id2).asyncJoinModel2($user$$.current_id_app,dmnv,{where:{device_user_id2:"device_user_id"},fields:["ma_nv","ten_nv",{picture_nv:"picture"}]});await $items$$.filter($item$$=>!$item$$.picture).asyncJoinModel2(null,User,{where:{of_user:"email"},fields:["picture"]});await $items$$.filter($item$$=>
20
- !$item$$.picture).asyncJoinModel2(null,User,{where:{user:"email"},fields:["picture"]});await $items$$.filter($item$$=>$item$$.ma_kh).asyncJoinModel2($user$$.current_id_app,"customer",{where:"ma_kh",fields:["ten_kh"]});$next$$(null,$items$$)},onCreating:async($user$$,$obj$$,$next$$)=>{global.configs?.required_device_id&&$obj$$.location&&($obj$$.record_time=new Date);await chamcong.deleteMany({id_app:$obj$$.id_app,id_checkin:$obj$$.device_user_id||$user$$.email,ngay:{$gte:moment($obj$$.record_time).startOf("date").toDate(),
21
- $lte:moment($obj$$.record_time).endOf("date").toDate()}});$next$$(null,$obj$$)},onUpdating:async($user$$,$data$$,$obj$$,$next$$)=>{$data$$.device_user_id=$obj$$.device_user_id;delete $data$$.record_time;await chamcong.deleteMany({id_app:$obj$$.id_app,id_checkin:$obj$$.device_user_id,ngay:{$gte:moment($obj$$.record_time).startOf("date").toDate(),$lte:moment($obj$$.record_time).endOf("date").toDate()}});$next$$(null,$data$$,$obj$$)},onDeleting:async($user$$,$obj$$,$next$$)=>{await chamcong.deleteMany({id_app:$obj$$.id_app,
22
- id_checkin:$obj$$.device_user_id,ngay:{$gte:moment($obj$$.record_time).startOf("date").toDate(),$lte:moment($obj$$.record_time).endOf("date").toDate()}});$next$$(null,$obj$$)},onUpdated:async($user$$,$obj$$,$next$$)=>{postData($obj$$,async $e$$=>{if($e$$)return console.log("l\u1ed7i l\u00fd checkin..."),await model.deleteOne({_id:$obj$$._id}),$next$$($e$$);$next$$(null,$obj$$)})},onDeleted:async($obj_post_query_checkin_user$$,$obj$$,$next$$)=>{$obj_post_query_checkin_user$$={id_app:$obj$$.id_app,
23
- device_user_id:$obj$$.device_user_id,record_time:{$gte:moment($obj$$.record_time).startOf("date").toDate(),$lte:moment($obj$$.record_time).endOf("date").toDate()}};($obj_post_query_checkin_user$$=await model.findOne($obj_post_query_checkin_user$$).lean())?postData($obj_post_query_checkin_user$$,$e$$=>{if($e$$)return $next$$($e$$);$next$$(null,$obj$$)}):$next$$(null,$obj$$)},onCreated:async($user$$,$obj$$,$next$$)=>{postData($obj$$,async $e$$=>{if($e$$)return await model.deleteOne({_id:$obj$$._id}),
24
- $next$$($e$$);$next$$(null,$obj$$)})}})).route()};
1
+ const model = global.getModel('checkin');
2
+ const customer = global.getModel('customer');
3
+ const moment = require("moment");
4
+ const dmnv = global.getModel('dmnv');
5
+ const chamcong = global.getModel('chamcong');
6
+ const User = global.getModel('user');
7
+ const controller = require('../../controllers/controller');
8
+ const PostBook = require('../../libs/post-book');
9
+
10
+ function deg2rad(deg) {
11
+ return deg * (Math.PI / 180);
12
+ }
13
+
14
+ function getDistanceFromLatLonInM(lat1, lon1, lat2, lon2) {
15
+ const R = 6371000; // Bán kính trái đất tính bằng mét
16
+ const dLat = deg2rad(lat2 - lat1);
17
+ const dLon = deg2rad(lon2 - lon1);
18
+ const a =
19
+ Math.sin(dLat / 2) * Math.sin(dLat / 2) +
20
+ Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
21
+ Math.sin(dLon / 2) * Math.sin(dLon / 2);
22
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
23
+ const d = R * c; // Khoảng cách theo mét
24
+ return d;
25
+ }
26
+ const postData = async (obj,callback)=>{
27
+ if(obj.trang_thai!="1") return callback();
28
+ if(global.configs?.required_device_id && !obj.device_id) return callback("Cần thông tin ID của thiết bị (device_id)");
29
+ //Tìm nhân viên theo device_user_id
30
+ const nv = await global.getModel("dmnv").findOne({
31
+ id_app:obj.id_app,
32
+ $or:[
33
+ {device_user_id:obj.device_user_id},
34
+ {user:obj.device_user_id}
35
+ ]
36
+ }).lean();
37
+ if(!nv){
38
+ //console.error("Nhân viên không tồn tại",{id_app:obj.id_app,device_user_id:obj.device_user_id})
39
+ return callback(`Chưa khai báo thông tin nhân viên cho '${obj.device_user_id}'.`);
40
+ }
41
+ //Kiểm tra id thiết bị
42
+ if(nv.trusted_device_id){
43
+ if(nv.trusted_device_id!=obj.device_id){
44
+ return callback(`Thiết bị chấm công không hợp lệ. Bạn cần dùng thiết bị đã chấm công lần trước hoặc liên hệ với admin để đăng ký thiết bị mới.`);
45
+ }else{
46
+ nv.trusted_device_id = obj.device_id;
47
+ }
48
+ }
49
+ //Kiểm tra xem device_id này đã được sử dụng cho nhân viên nào khác không? nếu có thì không cho phép
50
+ if(obj.device_id){
51
+ const nv_device_id = await global.getModel("dmnv").findOne({id_app:obj.id_app,trusted_device_id:obj.device_id},{_id:1}).lean();
52
+ if(nv_device_id && nv_device_id._id!==nv._id){
53
+ return callback(`Thiết bị này đã được sử dụng để chấm cho nhân viên khác. Nếu bạn cần thay đổi hãy liên hệ với admin.`);
54
+ }
55
+ }
56
+ // Kiểm tra xem dữ liệu gửi lên có toạ độ không
57
+ if (obj.location && obj.location.latitude && obj.location.longitude) {
58
+ //Lấy thông tin chi nhánh của nhân viên đó
59
+ let chiNhanh = null;
60
+ if (nv.ma_cn) {
61
+ chiNhanh = await global.getModel("dmchinhanh").findOne({
62
+ id_app: obj.id_app,
63
+ ma_cn: nv.ma_cn,
64
+ status: true
65
+ }).lean();
66
+ }
67
+ if(!chiNhanh){
68
+ return callback("Chưa khai báo chi nhánh làm việc cho nhân viên này");
69
+ }
70
+ if(!chiNhanh.location || !chiNhanh.location.latitude || !chiNhanh.location.longitude){
71
+ return callback(`Chưa khai báo vị trí của chi nhánh ${chiNhanh.ten_cn}`);
72
+ }
73
+ //Tính khoảng cách
74
+ const distance = getDistanceFromLatLonInM(
75
+ obj.location.latitude,
76
+ obj.location.longitude,
77
+ chiNhanh.location.latitude,
78
+ chiNhanh.location.longitude
79
+ );
80
+ const max_radius = chiNhanh.location.allowed_radius || 50;
81
+ if (distance > max_radius) {
82
+ // Kiểm tra nếu KHÔNG có mã khách hàng (tức là chấm công tại văn phòng nhưng bị xa)
83
+ if (!obj.ma_kh) {
84
+ console.warn(`[CheckIn Fail] Distance: ${distance}m. User: ${obj.device_user_id}`);
85
+ return callback(`Vị trí chấm công không hợp lệ. Bạn đang cách công ty ${Math.round(distance)}m (Cho phép: ${max_radius}m).`);
86
+ }
87
+ // Nếu có obj.ma_kh -> Hợp lệ (đi công tác/gặp khách hàng), code chạy tiếp xuống dưới...
88
+ }
89
+ } else {
90
+ if(global.configs?.required_device_id ) return callback("Không xác định được vị trí của bạn.");
91
+ }
92
+ //Xác định thời gian vào ra
93
+ let cac_lan_cham_cong_trong_ngay = await model.find({
94
+ id_app: obj.id_app,
95
+ device_user_id: obj.device_user_id,
96
+ record_time:{
97
+ $gte:moment(obj.record_time).startOf("date").toDate(),
98
+ $lte:moment(obj.record_time).endOf("date").toDate(),
99
+ }
100
+ }).inTxn().sort({record_time:1}).lean();
101
+ //
102
+ let gio_vao,gio_ra,tong_gio_lam,ma_loai_cong;
103
+ if(cac_lan_cham_cong_trong_ngay.length>0){
104
+ gio_vao = cac_lan_cham_cong_trong_ngay[0].record_time;
105
+ }
106
+ if(cac_lan_cham_cong_trong_ngay.length>1){
107
+ gio_ra = cac_lan_cham_cong_trong_ngay[cac_lan_cham_cong_trong_ngay.length-1].record_time;
108
+ }
109
+ if(gio_vao && gio_ra){
110
+ tong_gio_lam = moment(gio_ra).diff(moment(gio_vao),"hours");
111
+ }else{
112
+ tong_gio_lam =0;
113
+ }
114
+ //Xác định mã loại công dựa vào thời gian làm việc
115
+ if (gio_vao) {
116
+ let ngay_trong_tuan = moment(obj.record_time).day().toString();
117
+ // 1. Query các điều kiện cứng (không dính đến so sánh giờ cụ thể)
118
+ const query_loai_cong = {
119
+ id_app: obj.id_app,
120
+ status: true,
121
+ $and: [
122
+ // Kiểm tra ngày trong tuần
123
+ {
124
+ $or: [
125
+ { nhung_ngay_trong_tuan: { $exists: false } },
126
+ { nhung_ngay_trong_tuan: ngay_trong_tuan }
127
+ ]
128
+ },
129
+ // Kiểm tra tổng giờ làm tối đa
130
+ {
131
+ $or: [
132
+ { tong_gio_lam_den: { $gte: tong_gio_lam } },
133
+ { tong_gio_lam_den: 0 }
134
+ ],
135
+ },
136
+ // Kiểm tra tổng giờ làm tối thiểu
137
+ {
138
+ $or: [
139
+ { tong_gio_lam_tu: { $lte: tong_gio_lam } },
140
+ { tong_gio_lam_tu: 0 }
141
+ ]
142
+ }
143
+ ]
144
+ };
145
+
146
+ // 2. Lấy danh sách các ứng viên (Candidates)
147
+ let candidates = await global.getModel("dmloaicong")
148
+ .find(query_loai_cong)
149
+ .sort({ tong_gio_lam_tu: -1, ngay_cong: -1 })
150
+ .lean();
151
+
152
+ // 3. Hàm helper để lấy số phút từ đầu ngày (00:00 -> Time)
153
+ const getMinutesFromMidnight = (dateStr) => {
154
+ if (!dateStr) return null;
155
+ const m = moment(dateStr);
156
+ return m.hours() * 60 + m.minutes();
157
+ };
158
+
159
+ const input_vao_mins = getMinutesFromMidnight(gio_vao);
160
+ const input_ra_mins = getMinutesFromMidnight(gio_ra || gio_vao);
161
+
162
+ // 4. Lọc lại bằng JS để so sánh giờ vào/ra (bỏ qua ngày)
163
+ let loaicong = candidates.find(lc => {
164
+ // Check giờ vào tối thiểu (DB >= Input)
165
+ // Nếu DB null thì pass, nếu có dữ liệu thì phải thỏa mãn
166
+ if (lc.gio_vao_toi_thieu) {
167
+ const db_vao_mins = getMinutesFromMidnight(lc.gio_vao_toi_thieu);
168
+ if (db_vao_mins < input_vao_mins) return false; // Logic của bạn: DB >= Input
169
+ }
170
+
171
+ // Check giờ ra tối thiểu (DB <= Input)
172
+ if (lc.gio_ra_toi_thieu) {
173
+ const db_ra_mins = getMinutesFromMidnight(lc.gio_ra_toi_thieu);
174
+ if (db_ra_mins > input_ra_mins) return false; // Logic của bạn: DB <= Input
175
+ }
176
+
177
+ return true;
178
+ });
179
+
180
+ // console.log("[checkin] tim loai cong", query_loai_cong, loaicong);
181
+ if (loaicong) {
182
+ ma_loai_cong = loaicong.ma_loai_cong;
183
+ }
184
+ }
185
+ //Tìm bộ phận của nhân viên
186
+ let ma_bp = nv.ma_bp;
187
+ if(nv.bo_phan && nv.bo_phan.length>0){
188
+ ma_bp = nv.bo_phan[0].ma_bp;
189
+ }
190
+ //Tạo công
191
+ let data = obj.toObject?obj.toObject():{...obj};
192
+ data.id_checkin = obj.device_user_id;
193
+ data.ngay = obj.record_time;
194
+ data.ma_loai_cong = ma_loai_cong||"UNKNOW";
195
+ data.ma_nv =nv.ma_nv;
196
+ data.ma_bp =ma_bp;
197
+ delete data._id;
198
+ delete data.trang_thai;
199
+ data.gio_vao = gio_vao;
200
+ data.gio_ra = gio_ra;
201
+ data.tong_gio_lam = tong_gio_lam;
202
+ //xoá post cũ
203
+ await chamcong.deleteMany({
204
+ id_app:obj.id_app,
205
+ id_checkin:obj.device_user_id,
206
+ ngay:{
207
+ $gte:moment(obj.record_time).startOf("date").toDate(),
208
+ $lte:moment(obj.record_time).endOf("date").toDate()}}
209
+ )
210
+ //tạo post mới
211
+ const postbangchamcong = new PostBook(obj, [data], chamcong);
212
+ postbangchamcong.run(async (e, rs)=>{
213
+ if(!e){
214
+ //lưu trusted_device_id
215
+ await global.getModel("dmnv").updateOne({_id:nv._id},{trusted_device_id:obj.device_id})
216
+ }
217
+ callback(e, rs);
218
+ });
219
+
220
+
221
+ }
222
+ module.exports = function(router) {
223
+ const contr = new controller(router, model, 'checkin', {
224
+ notNeedRight:true,
225
+ sort: {
226
+ record_time: -1
227
+ },
228
+ onView:async(user,items,next)=>{
229
+ //Cham cong
230
+ await items.filter(item=>item.trang_thai==="1").asyncJoinModel2(user.current_id_app,dmnv,{
231
+ where: (item=>{
232
+ return {$or: [
233
+ {device_user_id:item.device_user_id},
234
+ {user:item.device_user_id}
235
+ ]}
236
+ }),
237
+ fields:["ma_nv","ten_nv","picture"]}
238
+ );
239
+ //Khach hang
240
+ await items.filter(item=>item.trang_thai==="2" || item.trang_thai==="3").asyncJoinModel2(user.current_id_app,customer,{
241
+ where: (item=>{
242
+ return {$or: [
243
+ {device_user_id:item.device_user_id},
244
+ {of_user:item.device_user_id}
245
+ ]}
246
+ }),
247
+ fields:["ma_kh","ten_kh","picture"]}
248
+ );
249
+ //Ca khach hang va nhan vien
250
+ await items.filter(item=>item.trang_thai==="3" && item.device_user_id2).asyncJoinModel2(user.current_id_app,dmnv,{where:{device_user_id2:"device_user_id"},fields:["ma_nv","ten_nv",{picture_nv:"picture"}]});
251
+ //Get picture
252
+ await items.filter(item=>!item.picture).asyncJoinModel2(null,User,{where:{of_user:"email"},fields:["picture"]});
253
+ await items.filter(item=>!item.picture).asyncJoinModel2(null,User,{where:{user:"email"},fields:["picture"]});
254
+ await items.filter(item=>item.ma_kh).asyncJoinModel2(user.current_id_app,"customer",{where:"ma_kh",fields:["ten_kh"]});
255
+ next(null,items);
256
+ },
257
+ onCreating: async (user,obj,next)=>{
258
+ if(global.configs?.required_device_id && obj.location) obj.record_time = new Date();
259
+ await chamcong.deleteMany({
260
+ id_app:obj.id_app,
261
+ id_checkin:obj.device_user_id||user.email,
262
+ ngay:{
263
+ $gte:moment(obj.record_time).startOf("date").toDate(),
264
+ $lte:moment(obj.record_time).endOf("date").toDate()
265
+ }})
266
+ next(null,obj)
267
+ },
268
+ onUpdating:async (user,data,obj,next)=>{
269
+ data.device_user_id = obj.device_user_id;
270
+ delete data.record_time;
271
+
272
+ await chamcong.deleteMany({
273
+ id_app:obj.id_app,
274
+ id_checkin:obj.device_user_id,
275
+ ngay:{
276
+ $gte:moment(obj.record_time).startOf("date").toDate(),
277
+ $lte:moment(obj.record_time).endOf("date").toDate()
278
+ }}
279
+ )
280
+ next(null,data,obj)
281
+ },
282
+ onDeleting: async (user,obj,next)=>{
283
+ await chamcong.deleteMany({
284
+ id_app:obj.id_app,
285
+ id_checkin:obj.device_user_id,
286
+ ngay:{
287
+ $gte:moment(obj.record_time).startOf("date").toDate(),
288
+ $lte:moment(obj.record_time).endOf("date").toDate()
289
+ }})
290
+ next(null,obj)
291
+ },
292
+ onUpdated:async (user,obj,next)=>{
293
+ postData(obj,async (e)=>{
294
+ if(e){
295
+ console.log("lỗi lý checkin...");
296
+ await model.deleteOne({_id:obj._id})
297
+ return next(e);
298
+ }
299
+ next(null,obj);
300
+ })
301
+ },
302
+ onDeleted:async (user,obj,next)=>{
303
+ let query_checkin = {
304
+ id_app:obj.id_app,
305
+ device_user_id:obj.device_user_id,
306
+ record_time:{
307
+ $gte:moment(obj.record_time).startOf("date").toDate(),
308
+ $lte:moment(obj.record_time).endOf("date").toDate()
309
+ }
310
+ }
311
+
312
+ let obj_post = await model.findOne(query_checkin).lean();
313
+ //console.log("[checkin] checkin đã bị xoá. Tìm checkin khác cùng ngày để tạo lại chấm công",query_checkin,obj_post);
314
+ if(obj_post){
315
+ //post lại sau khi xoá checkin
316
+ //console.log("[checkin] tạo lại chấm công",obj_post)
317
+ postData(obj_post,(e)=>{
318
+ if(e) return next(e);
319
+ next(null,obj);
320
+ })
321
+ }else{
322
+ next(null,obj);
323
+ }
324
+ },
325
+ onCreated:async (user,obj,next)=>{
326
+ postData(obj,async (e)=>{
327
+ if(e){
328
+ await model.deleteOne({_id:obj._id});
329
+ return next(e);
330
+ }
331
+ next(null,obj);
332
+ })
333
+ },
334
+ });
335
+ contr.route();
336
+ };