Pārlūkot izejas kodu

Merge branch 'master' of http://192.168.1.41:3000/SmartCost/ConstructionCost

zhangweicheng 5 gadi atpakaļ
vecāks
revīzija
9f34fcd857

+ 0 - 31
modules/all_models/product.js

@@ -1,31 +0,0 @@
-'use strict';
-
-/**
- *
- *
- * @author Zhong
- * @date 2019/3/21
- * @version
- */
-/*
- * 与产品绑定的信息都可以在此设置
- * */
-const mongoose = require('mongoose');
-const Schema = mongoose.Schema;
-const productSchema = new Schema({
-    name: {
-        type: String,
-        default: '纵横建筑计价'
-    },
-    company: {
-        type: String,
-        default: '珠海纵横创新软件有限公司'
-    },
-    icp: {
-        type: String,
-        default: '粤ICP备14032472号'
-    },
-    version: String
-}, {versionKey: false});
-
-mongoose.model('product', productSchema, 'product');

+ 3 - 0
modules/all_models/system_setting.js

@@ -21,5 +21,8 @@ let modelSchema = {
         project: Number,
         ration:Number
     },
+    company: String, // 软件供应商
+    product: String, // 产品名
+    version: String // 版本号
 };
 mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));

+ 3 - 2
modules/all_models/user.js

@@ -26,10 +26,11 @@ const versionSchema = new Schema({
 });
 
 let upgrade = mongoose.Schema({
-    compilationID:String,//编办ID
+    compilationID:String,// 编办ID
     upgrade_time:Number,
     isUpgrade:Boolean,
-    remark:String//描述:广东办刘飞 2018-06-17 启用/关闭
+    remark:String,// 描述:广东办刘飞 2018-06-17 启用/关闭
+    deadline: String,
 }, { _id: false })
 
 const userdList = mongoose.Schema({

+ 4 - 1
modules/main/routes/main_route.js

@@ -6,6 +6,7 @@
 import BaseController from "../../common/base/base_controller";
 const projectModel = require("../../pm/models/project_model");
 const pmFacade = require('../../pm/facade/pm_facade');
+const systemSettingModel = require('../../system_setting/model/index');
 let config = require("../../../config/config.js");
 import OptionsDao from '../../options/models/optionsModel';
 import optionSetting from '../../options/models/optionTypes';
@@ -40,6 +41,7 @@ module.exports =function (app) {
                     options = await optionsDao.saveOptions(req.session.sessionUser.id, req.session.sessionCompilation._id, optionSetting);
                 }
                 const markReadProjectIDs = isOpenShareProject ? await pmFacade.markShareItemsRead(projectID, req.session.sessionUser.id) : [];
+                const version = await systemSettingModel.getVersion();
                 res.render('building_saas/main/html/main.html',
                     {
                         userAccount: req.session.userAccount,
@@ -54,7 +56,8 @@ module.exports =function (app) {
                         overWriteUrl:req.session.sessionCompilation.overWriteUrl,
                         fileKind: fileKind,
                         options:JSON.stringify(options),
-                        markReadProjectIDs: JSON.stringify(markReadProjectIDs)
+                        markReadProjectIDs: JSON.stringify(markReadProjectIDs),
+                        version
                     });
             } else {
                 res.redirect('/pm');

+ 3 - 4
modules/pm/facade/pm_facade.js

@@ -92,7 +92,6 @@ let compilationModel = mongoose.model('compilation');
 let engineeringModel = mongoose.model('engineering_lib');
 let basicInfoModel = mongoose.model('std_basic_info_lib');
 let projectFeatureModel = mongoose.model('std_project_feature_lib');
-let productModel = mongoose.model('product');
 let stdRationItemModel = mongoose.model('std_ration_lib_ration_items');
 let stdGljItemModel = mongoose.model('std_glj_lib_gljList');
 import BillsTemplateModel from "../models/templates/bills_template_model";
@@ -1910,9 +1909,9 @@ async function getProjectByGranularity(tenderID, granularity, summaryField, user
     //获取汇总信息
     constructionProject.summaryInfo = await getSummaryInfo([constructionProject.ID], summaryField);
     //获取编制软件信息: 软件公司;软件名;版本号;授权信息; base64
-    let product = await productModel.findOne({});
-    let company = product.company || '珠海纵横创新软件有限公司',
-        version = product.version || '';
+    const systemSetting = await systemSettingModel.findOne({});
+    let company = systemSetting.company || '珠海纵横创新软件有限公司',
+        version = systemSetting.version || '';
     constructionProject.softInfo = `${company};${versionName};${version};${userID}`;
     return constructionProject;
 }

+ 6 - 2
modules/reports/rpt_component/jpc_cross_tab.js

@@ -235,8 +235,12 @@ JpcCrossTabSrv.prototype.createNew = function(){
                     for (let di = 0; di < data_fields.length; di++) {
                         rowGrandTotal.push(0.0);
                         for (let k = 0; k < me.sortedRowSequence[i][j].length; k++) {
-                            //3. start to sum
-                            rowGrandTotal[di] = rowGrandTotal[di] + 1.0 * JpcFieldHelper.getValue(data_fields[di], me.sortedRowSequence[i][j][k]);
+                            // 3. start to sum
+                            let vTtl = parseFloat(JpcFieldHelper.getValue(data_fields[di], me.sortedRowSequence[i][j][k]));
+                            if (isNaN(vTtl)) {
+                                vTtl = 0;
+                            }
+                            rowGrandTotal[di] = rowGrandTotal[di] + vTtl;
                         }
                     }
                     me.col_sum_fields_value_total[i].push(rowGrandTotal);

+ 11 - 0
modules/system_setting/model/index.js

@@ -0,0 +1,11 @@
+module.exports = {
+    getVersion,
+};
+
+const mongoose = require('mongoose');
+const sysModel = mongoose.model('system_setting');
+
+async function getVersion() {
+    const data = await sysModel.findOne({}, '-_id version').lean();
+    return data && data.version || '';
+}

+ 66 - 4
modules/users/controllers/cld_controller.js

@@ -12,6 +12,8 @@ import CLDModel from "../models/cld_model";
 import UserModel from "../models/user_model"
 import CompilationModel from "../models/compilation_model";
 let online_facade = require('../facade/online_facade')
+const SMS = require('../models/sms');
+const moment = require('moment');
 
 class CLDController {
 
@@ -106,6 +108,9 @@ class CLDController {
     async setUsersUpgrade(request, response) {
         let ssoID = request.body.ssoId;
         let compilationID = request.body.cid;
+        let deadline = request.body.deadline || '';
+        let status = parseInt(request.body.status);
+        let smssend = parseInt(request.body.smssend);
         try {
 
             let userModel = new UserModel();
@@ -114,7 +119,7 @@ class CLDController {
 
             let compilationModel = new CompilationModel();
 
-            let compilationData = compilationModel.getCompilationById(compilationID);
+            let compilationData = await compilationModel.getCompilationById(compilationID);
 
             if (compilationData === null || compilationData === undefined) {
                 throw '不存在该编办或者编办未发布';
@@ -125,12 +130,12 @@ class CLDController {
             let upgradeIndex = upgrade_list.findIndex(function (item) {
                 return item.compilationID === compilationID
             });
-
             let upgradeInfo = {
                 compilationID:compilationID,//编办ID
                 upgrade_time:new Date().getTime(),
-                isUpgrade:true,
-                remark: ''
+                isUpgrade: status !== 2,
+                remark: '',
+                deadline: deadline,
             };
 
             if (upgradeIndex === -1) {
@@ -143,6 +148,12 @@ class CLDController {
             let result = await userModel.updateUser(condition, {upgrade_list: upgrade_list});
 
             if (result) {
+                // 短信发送
+                if (smssend) {
+                    // 发送短信
+                    const Sms = new SMS();
+                    await Sms.sendProductMsg(userData.mobile, status, userData.real_name, compilationData.name, deadline);
+                }
                 response.json({error: 0, msg: 'success'});
             } else {
                 throw '更新失败';
@@ -301,6 +312,57 @@ class CLDController {
         }
         response.json(responseData);
     }
+
+    async checkUserCompilationStatus(request, response) {
+        try {
+            let today = moment(new Date()-86400*1000).format('YYYY-MM-DD');
+            let userModel = new UserModel();
+            let userList = await userModel.getDeadlineList({upgrade_list: {$elemMatch:{ deadline: today }}});
+            if (userList.length > 0) {
+                for (let user of userList) {
+                    for (let cul of user.upgrade_list) {
+                        if (cul.deadline === today) {
+                            // cul.deadline = '';
+                            cul.isUpgrade = false;
+                        }
+                    }
+                    let condition = {ssoId: user.ssoId};
+                    await userModel.updateUser(condition, {upgrade_list: user.upgrade_list});
+                }
+            }
+            response.json({error: 0, msg: 'success', data: userList});
+        } catch (error) {
+            response.json({error: 1, msg: error});
+        }
+    }
+
+    async sendCompilationStatusSms(request, response) {
+        try {
+            let today = moment(new Date()-86400*1000).format('YYYY-MM-DD');
+            let userModel = new UserModel();
+            let userList = await userModel.getDeadlineList({upgrade_list: {$elemMatch:{ deadline: today }}});
+            if (userList.length > 0) {
+                let compilationModel = new CompilationModel();
+                const Sms = new SMS();
+                for (let user of userList) {
+                    for (let cul of user.upgrade_list) {
+                        if (cul.deadline === today) {
+                            cul.deadline = '';
+                            // cul.isUpgrade = false;
+                            // 发送短信
+                            let compilationData = await compilationModel.getCompilationById(cul.compilationID);
+                            await Sms.sendProductMsg(user.mobile, 2, user.real_name, compilationData.name, '');
+                        }
+                    }
+                    let condition = {ssoId: user.ssoId};
+                    await userModel.updateUser(condition, {upgrade_list: user.upgrade_list});
+                }
+            }
+            response.json({error: 0, msg: 'success', data: userList});
+        } catch (error) {
+            response.json({error: 1, msg: error});
+        }
+    }
 }
 
 export default CLDController;

+ 45 - 0
modules/users/models/sms.js

@@ -111,6 +111,51 @@ class SMS {
         }
     }
 
+    async sendProductMsg(mobile, status, name, product, deadline) {
+        try {
+            let templateId = 0;
+            switch (status) {
+                case 1: templateId = 746377;break;// 产品升级通知
+                case 2: templateId = 746376;break;// 产品降级通知
+                case 3: templateId = 746378;break;// 产品延期通知
+            }
+            const formData = {
+                smsUser: this.smsUser,
+                templateId: templateId,
+                msgType: 0,
+                phone: mobile,
+            };
+            formData.vars = '{"%name%": "' + name + '", "%product%": "' + product + '"' + (status !== 2 ? ', "%deadline%": "' + deadline + '"' : '') +'}';
+            const signature = await this.getSignature(this.sortDict(formData), this.smskey);
+            formData.signature = signature;
+
+            let postData = {
+                url: this.url,
+                form: formData,
+                encoding: 'utf8'
+            };
+
+            return new Promise(function (resolve, reject) {
+                try {
+                    // 请求接口
+                    Request.post(postData, function (err, postResponse, body) {
+                        if (err) {
+                            throw '请求错误';
+                        }
+                        if (postResponse.statusCode !== 200) {
+                            throw '短信发送失败!';
+                        }
+                        resolve(body);
+                    });
+                } catch (error) {
+                    reject([]);
+                }
+            });
+        } catch (error) {
+            console.log(error);
+        }
+    }
+
     md5(data) {
         var str = data;
         return crypto.createHash("md5").update(str).digest("hex");

+ 17 - 1
modules/users/models/user_model.js

@@ -386,7 +386,7 @@ class UserModel extends BaseModel {
     /**
      * 从session中判断用户是否是免费版
      * @param {String} sessionVersion
-     * @return {Boolean} 
+     * @return {Boolean}
      */
     isFreeFromSession(sessionVersion) {
         if (!sessionVersion) {
@@ -523,6 +523,22 @@ class UserModel extends BaseModel {
     getDayMsg(index){
         return this.dayMsg[index];
     }
+
+    /**
+     * 获取usercompilation到期列表
+     *
+     * @param {object} condition
+     * @param {number} page
+     * @param {Number} pageSize
+     * @return {promise}
+     */
+    async getDeadlineList(condition = null) {
+
+        let userList = await this.db.find(condition);
+        userList = userList.length > 0 ? userList : [];
+
+        return userList;
+    }
 }
 
 export default UserModel;

+ 4 - 0
modules/users/routes/cld_route.js

@@ -30,5 +30,9 @@ module.exports = function (app) {
 
     router.post('/getUserOnlineInfo', cldController.getUserOnlineInfo);
 
+    router.get('/checkUserCompilationStatus', cldController.checkUserCompilationStatus);
+
+    router.get('/sendCompilationStatusSms', cldController.sendCompilationStatusSms);
+
     app.use('/cld',router)
 };

+ 31 - 5
public/common_util.js

@@ -96,12 +96,38 @@ function deleteEmptyObject(arr) {
     // 通过F11打开全屏后,没有办法通过代码退出全屏,只能通过F11退出:
     // https://stackoverflow.com/questions/51114885/combining-requestfullscreen-and-f11; https://stackoverflow.com/questions/43392583/fullscreen-api-not-working-if-triggered-with-f11/44368592#44368592;
     function handleFullscreen() {
-        const isFullscreen = window.innerHeight === window.screen.height;
-        if (isFullscreen) {
-            const p = document.exitFullscreen();
-            p.catch(() => alert('按F11即可退出全屏模式'));
+        if (isFullscreen()) {
+            const p = exitFullscreen();
+            if (Object.prototype.toString.call(p) === '[object Promise]') {
+                p.catch(() => alert('按F11即可退出全屏模式'));
+            }
         } else {
-            document.documentElement.requestFullscreen();
+            fullscreen(document.documentElement);
+        }
+    }
+    function isFullscreen() {
+        return window.innerHeight === window.screen.height;
+    }
+    function fullscreen(ele) {
+        if (ele.requestFullscreen) {
+            ele.requestFullscreen();
+        } else if (ele.mozRequestFullscreen) {
+            ele.mozRequestFullScreen();
+        } else if (ele.webkitRequestFullscreen) {
+            ele.webkitRequestFullscreen();
+        } else if (ele.msRequestFullscreen) {
+            ele.msRequestFullscreen();
+        }
+    }
+    function exitFullscreen() {
+        if(document.exitFullscreen) {
+            return document.exitFullscreen();
+        } else if(document.mozCancelFullscreen) {
+            return document.mozCancelFullscreen();
+        } else if(document.webkitExitFullscreen) {
+            return document.webkitExitFullscreen();
+        } else if(document.msExitFullscreen) {
+            return document.msExitFullscreen();
         }
     }
 

+ 5 - 2
public/web/syntax-detection.js

@@ -151,8 +151,11 @@ function checkSyntax() {
         }
 
         // DOM
-        if (typeof document.documentElement.requestFullscreen !== 'function') {
-            throw new TypeError('document.documentElement.requestFullscreen is not a function');
+        if (typeof document.documentElement.requestFullscreen !== 'function' && 
+            typeof document.documentElement.mozRequestFullscreen !== 'function' &&
+            typeof document.documentElement.webkitRequestFullscreen !== 'function' &&
+            typeof document.documentElement.msRequestFullscreen !== 'function') {
+            throw new TypeError('fullscreen is not a function');
         }
 
     } catch (err) {

+ 2 - 2
test/unit/reports/test_rpt_test_template.js

@@ -56,7 +56,7 @@ let demoPrjId = - 1;
 // let demoRptId = 551; //表05
 // let demoRptId = 1104; //内蒙2017 表09
 
-let demoRptId = 1143;
+let demoRptId = 1162;
 
 let pagesize = "A4";
 
@@ -72,7 +72,7 @@ let userId_me = "5b6a60b1c4ba33000dd417c0"; //我的
 // demoPrjId = 2260; //QA:
 // demoPrjId = 5029; //
 // demoPrjId = 5029; //项目名称过长
-demoPrjId = 22936; //
+demoPrjId = 23964; //
 // demoPrjId = 4107; //UAT:
 //*/
 let userId_Dft = userId_Leng;

+ 1 - 0
web/building_saas/main/html/main.html

@@ -46,6 +46,7 @@
         console.log(projectCooperate);
         const G_SHOW_BLOCK_LIB = true;
         const markReadProjectIDs = JSON.parse('<%- markReadProjectIDs %>');
+        const VERSION = '<%- version %>';
 //        const G_SHOW_BLOCK_LIB = false;
     </script>
 </head>

+ 14 - 4
web/building_saas/main/js/models/calc_base.js

@@ -1540,9 +1540,17 @@ let cbCalctor = {
         }
         return 0;
     },
-    //计算
-    exec: function () {
-
+    tenderRef: function (fExp) {
+        let ID = cbParser.getUID([fExp]);
+        if(ID.length === 1){
+            let node = cbTools.getNodeByID(ID[0]);
+            return cbTools.isDef(node) &&
+                    cbTools.isDef(node.data.feesIndex) &&
+                    cbTools.isDef(node.data.feesIndex.common) &&
+                    cbTools.isDef(node.data.feesIndex.common.tenderTotalFee) ?
+                    node.data.feesIndex.common.tenderTotalFee : 0;
+        }
+        return 0;
     }
 };
 
@@ -1602,7 +1610,9 @@ let calcBase = {
                 throw '基数计算结果不为数值';
             }
             //调价
-            let tenderCalcExp = calcExp.replace(new RegExp('base', 'g'), 'tenderBase');
+            let tenderCalcExp = calcExp
+                .replace(new RegExp('base', 'g'), 'tenderBase')
+                .replace(new RegExp('ref', 'g'), 'tenderRef');
             let tenderCalcBaseValue = eval(tenderCalcExp);
             if(!cbTools.isNum(tenderCalcBaseValue)){
                 throw '调价基数计算结果不为数值';

+ 15 - 11
web/building_saas/main/js/models/calc_program.js

@@ -198,7 +198,7 @@ let calcTools = {
         if (!feeObj) return;
         if (feeObj.fieldName == '') return;
 
-        // 初始化前,先拦截属性定义、又要给该属性赋0的情况
+        // 初始化前,先拦截属性定义、又要给该属性赋0的情况
         if (!treeNode.data.feesIndex || !treeNode.data.feesIndex[feeObj.fieldName]){
             if (feeObj.unitFee == 0 && feeObj.totalFee == 0 && feeObj.tenderUnitFee == 0 && feeObj.tenderTotalFee == 0) return;
         }
@@ -1779,8 +1779,10 @@ class CalcProgram {
             calcTools.getGLJList(treeNode, true);
             nodes = me.project.Ration.getRationNodes(treeNode);
         }
-        else if (commonCalcType == 2)
-            nodes = treeNode.children
+        else if (commonCalcType == 2){  // 固定清单 "材料(工程设备)暂估价" 比较特殊,不进行父项汇总(需求是这么要求的)
+            // nodes = treeNode.children
+            nodes = me.project.Bills.getGatherNodes(treeNode);
+        }
         else if (commonCalcType == 3)
             nodes = treeNode.children;
 
@@ -1788,6 +1790,11 @@ class CalcProgram {
             return ['labour', 'material', 'machine', 'mainMaterial', 'equipment'].indexOf(type) > -1;
         };
 
+        let nQ = calcTools.uiNodeQty(treeNode);
+        let nTQ = calcTools.uiNodeTenderQty(treeNode);
+        let bq = nQ ? nQ : 1;
+        let btq = nTQ ? nTQ : 1;
+
         let rst = [];
         for (let ft of cpFeeTypes) {
             let ftObj = {};
@@ -1795,11 +1802,6 @@ class CalcProgram {
             ftObj.name = ft.name;
             let buf = 0, btf = 0, btuf = 0, bttf = 0;
 
-            let nQ = calcTools.uiNodeQty(treeNode);
-            let nTQ = calcTools.uiNodeTenderQty(treeNode);
-            let bq = nQ ? nQ : 1;
-            let btq = nTQ ? nTQ : 1;
-
             if (commonCalcType == 2){
                 for (let node of nodes) {
                     if (node.data.feesIndex && node.data.feesIndex[ft.type]) {
@@ -1928,11 +1930,13 @@ class CalcProgram {
         let fnArr = [];
         calcTools.getGLJList(treeNode, true);
 
+        let nQ = calcTools.uiNodeQty(treeNode);
+        let nTQ = calcTools.uiNodeTenderQty(treeNode);
+
         if (treeNode.calcType == treeNodeCalcType.ctRationCalcProgram) {
             // 量价、工料机类型的定额要求"市场合价"
             if (calcTools.isVP_or_GLJR(treeNode)){
                 let u = treeNode.data.marketUnitFee ? treeNode.data.marketUnitFee : 0;
-                let nQ = calcTools.uiNodeQty(treeNode);
                 let t = (u * nQ).toDecimal(decimalObj.ration.totalPrice);
                 if (treeNode.data.marketTotalFee != t){
                     treeNode.data.marketTotalFee = t;
@@ -1959,11 +1963,11 @@ class CalcProgram {
                     feeRate = parseFloat(calcItem.feeRate).toDecimal(decimalObj.feeRate);
 
                 calcItem.unitFee = (eval(calcItem.compiledExpr) * feeRate * 0.01).toDecimal(decimalObj.decimal('unitPrice', treeNode));
-                calcItem.totalFee = (calcItem.unitFee * calcTools.uiNodeQty(treeNode)).toDecimal(decimalObj.decimal('totalPrice', treeNode));
+                calcItem.totalFee = (calcItem.unitFee * nQ).toDecimal(decimalObj.decimal('totalPrice', treeNode));
 
                 let tExpr = analyzer.getCompiledTenderExpr(calcItem.compiledExpr);
                 calcItem.tenderUnitFee = (eval(tExpr) * feeRate * 0.01).toDecimal(decimalObj.decimal('unitPrice', treeNode));
-                calcItem.tenderTotalFee = (calcItem.tenderUnitFee * treeNode.data.tenderQuantity).toDecimal(decimalObj.decimal('totalPrice', treeNode));
+                calcItem.tenderTotalFee = (calcItem.tenderUnitFee * nTQ).toDecimal(decimalObj.decimal('totalPrice', treeNode));
 
                 if (calcItem.fieldName) {
                     fnArr.push(calcItem.fieldName);

+ 7 - 6
web/building_saas/main/js/views/project_view.js

@@ -1030,13 +1030,14 @@ var projectObj = {
                     disableSpread(that.mainSpread);
                 }
 
-                // 检查旧项目是否有调价数据,没有则自动生成
-                let node = projectObj.project.mainTree.firstNode();
-                if (node.data.feesIndex && node.data.feesIndex.common && node.data.feesIndex.common.totalFee
-                    && node.data.feesIndex.common.totalFee != 0){
-                    if (node.data.feesIndex.common.tenderTotalFee == undefined || node.data.feesIndex.common.tenderTotalFee == 0)
+                // 检查旧项目是否有调价数据,没有则自动生成 ----- 有种情况不行,如下:
+                // 未知情况:有调价数据,但调价算的不对,所以这里无论什么情况,打开时都要全局算一遍,牺牲速度体验,换来数据稳定。
+                // let node = projectObj.project.mainTree.firstNode();
+                // if (node.data.feesIndex && node.data.feesIndex.common && node.data.feesIndex.common.totalFee
+                //     && node.data.feesIndex.common.totalFee != 0){
+                //     if (node.data.feesIndex.common.tenderTotalFee == undefined || node.data.feesIndex.common.tenderTotalFee == 0)
                         projectObj.project.calcProgram.doTenderCalc();
-                };
+                // };
                 $.bootstrapLoading.end();
             }
             else {