|  | @@ -0,0 +1,225 @@
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Created by Mai on 2017/7/5.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const rationContent = 0, rationPrice = 1, rationPriceConverse = 2, billsPrice = 3;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const sumTotalFeeFlag = 0, totalFeeFlag = 1;
 | 
	
		
			
				|  |  | +const rationContentUnitFeeFlag = 0, averageQtyUnitFeeFlag = 1, billsPriceUnitFeeFlag = 2;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +let rationContentCalcFields = [
 | 
	
		
			
				|  |  | +    {'type': 'common', 'unitFeeFlag': rationContentUnitFeeFlag, 'totalFeeFlag': totalFeeFlag},
 | 
	
		
			
				|  |  | +    {'type': 'labour', 'unitFeeFlag': rationContentUnitFeeFlag, 'totalFeeFlag': sumTotalFeeFlag},
 | 
	
		
			
				|  |  | +    {'type': 'material', 'unitFeeFlag': rationContentUnitFeeFlag, 'totalFeeFlag': sumTotalFeeFlag},
 | 
	
		
			
				|  |  | +    {'type': 'machine', 'unitFeeFlag': rationContentUnitFeeFlag, 'totalFeeFlag': sumTotalFeeFlag},
 | 
	
		
			
				|  |  | +];
 | 
	
		
			
				|  |  | +let rationPriceCalcFields = [
 | 
	
		
			
				|  |  | +    {'type': 'common', 'unitFeeFlag': averageQtyUnitFeeFlag, 'totalFeeFlag': totalFeeFlag},
 | 
	
		
			
				|  |  | +    {'type': 'labour', 'unitFeeFlag': averageQtyUnitFeeFlag, 'totalFeeFlag': sumTotalFeeFlag},
 | 
	
		
			
				|  |  | +    {'type': 'material', 'unitFeeFlag': averageQtyUnitFeeFlag, 'totalFeeFlag': sumTotalFeeFlag},
 | 
	
		
			
				|  |  | +    {'type': 'machine', 'unitFeeFlag': averageQtyUnitFeeFlag, 'totalFeeFlag': sumTotalFeeFlag},
 | 
	
		
			
				|  |  | +];
 | 
	
		
			
				|  |  | +let rationPriceConverseCalcFields = [
 | 
	
		
			
				|  |  | +    {'type': 'common', 'unitFeeFlag': averageQtyUnitFeeFlag, 'totalFeeFlag': sumTotalFeeFlag},
 | 
	
		
			
				|  |  | +    {'type': 'labour', 'unitFeeFlag': averageQtyUnitFeeFlag, 'totalFeeFlag': sumTotalFeeFlag},
 | 
	
		
			
				|  |  | +    {'type': 'material', 'unitFeeFlag': averageQtyUnitFeeFlag, 'totalFeeFlag': sumTotalFeeFlag},
 | 
	
		
			
				|  |  | +    {'type': 'machine', 'unitFeeFlag': averageQtyUnitFeeFlag, 'totalFeeFlag': sumTotalFeeFlag},
 | 
	
		
			
				|  |  | +];
 | 
	
		
			
				|  |  | +let billsPriceCalcFields = [
 | 
	
		
			
				|  |  | +    {'type': 'common', 'unitFeeFlag': billsPriceUnitFeeFlag, 'totalFeeFlag': totalFeeFlag},
 | 
	
		
			
				|  |  | +    {'type': 'labour', 'unitFeeFlag': billsPriceUnitFeeFlag, 'totalFeeFlag': sumTotalFeeFlag},
 | 
	
		
			
				|  |  | +    {'type': 'material', 'unitFeeFlag': billsPriceUnitFeeFlag, 'totalFeeFlag': sumTotalFeeFlag},
 | 
	
		
			
				|  |  | +    {'type': 'machine', 'unitFeeFlag': billsPriceUnitFeeFlag, 'totalFeeFlag': sumTotalFeeFlag},
 | 
	
		
			
				|  |  | +];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Number.prototype.toDecimal = function (ADigit) {
 | 
	
		
			
				|  |  | +    return parseFloat(this.toFixed(ADigit));
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +let nodeCalcObj = {
 | 
	
		
			
				|  |  | +    node: null,
 | 
	
		
			
				|  |  | +    digit: 2,
 | 
	
		
			
				|  |  | +    field: null,
 | 
	
		
			
				|  |  | +    findFee: function (fieldName) {
 | 
	
		
			
				|  |  | +        if (!this.node.data.fees) {
 | 
	
		
			
				|  |  | +            this.node.data.fees = [];
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        for (let fee of this.node.data.fees) {
 | 
	
		
			
				|  |  | +            if (fee.fieldName === fieldName) {
 | 
	
		
			
				|  |  | +                return fee;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return null;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    AddFee: function (fieldName) {
 | 
	
		
			
				|  |  | +        let fee = {
 | 
	
		
			
				|  |  | +            'fieldName': fieldName,
 | 
	
		
			
				|  |  | +            'unitFee': 0,
 | 
	
		
			
				|  |  | +            'totalFee': 0,
 | 
	
		
			
				|  |  | +            'tenderUnitFee': 0,
 | 
	
		
			
				|  |  | +            'tenderTotalFee': 0
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        this.node.data.fees.push(fee);
 | 
	
		
			
				|  |  | +        this.node.data.feesIndex[fieldName] = fee;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    checkFields: function (fields) {
 | 
	
		
			
				|  |  | +        for (let field of fields) {
 | 
	
		
			
				|  |  | +            if (!this.findFee(field.type)) {
 | 
	
		
			
				|  |  | +                this.AddFee(field.type);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    getFee: function (data, fullField) {
 | 
	
		
			
				|  |  | +        let fields = fullField.split('.'), value = data;
 | 
	
		
			
				|  |  | +        for (let field of fields) {
 | 
	
		
			
				|  |  | +            if (value[field]) {
 | 
	
		
			
				|  |  | +                value = value[field];
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                return 0;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return value;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    getFeeSplit: function (data, fullFields) {
 | 
	
		
			
				|  |  | +        let value = data;
 | 
	
		
			
				|  |  | +        for (let field of fullFields) {
 | 
	
		
			
				|  |  | +            if (value[field]) {
 | 
	
		
			
				|  |  | +                value = value[field];
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                return 0;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return value;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    sumTotalFee: function() {
 | 
	
		
			
				|  |  | +        let result = 0, child;
 | 
	
		
			
				|  |  | +        for (child of this.node.children) {
 | 
	
		
			
				|  |  | +            result += this.getFee(child.data, this.field.totalFee);
 | 
	
		
			
				|  |  | +            //result += child.data.feesIndex[this.field.type].totalFee;
 | 
	
		
			
				|  |  | +            //result += this.getFeeSplit(child.data, this.field.totalFeeSplit);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    averageQty: function() {
 | 
	
		
			
				|  |  | +        let result = 0, child, qty;
 | 
	
		
			
				|  |  | +        result = this.sumTotalFee(this.field);
 | 
	
		
			
				|  |  | +        qty = this.getFee(this.node.data, 'quantity');
 | 
	
		
			
				|  |  | +        if (qty !== 0) {
 | 
	
		
			
				|  |  | +            result = result / qty;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    totalFee: function () {
 | 
	
		
			
				|  |  | +        return this.getFee(this.node.data, this.field.unitFee) * this.getFee(this.node.data, 'quantity');
 | 
	
		
			
				|  |  | +        //return this.node.data.feesIndex[this.field.type].unitFee * this.node.data.quantity;
 | 
	
		
			
				|  |  | +        //return this.getFeeSplit(this.node.data, this.field.unitFeeSplit) * this.getFee(this.node.data, 'quantity');
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    rationContentUnitFee: function () {
 | 
	
		
			
				|  |  | +        let result = 0, child, qty = this.getFee(this.node.data, 'quantity');
 | 
	
		
			
				|  |  | +        if (qty === 0) {
 | 
	
		
			
				|  |  | +            qty = 1;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        for (child of this.node.children) {
 | 
	
		
			
				|  |  | +            result += (this.getFee(child.data, this.field.unitFee) * this.getFee(child.data, 'quantity') / qty).toDecimal(this.digit);
 | 
	
		
			
				|  |  | +            //result += (child.data.feesIndex[this.field.type].unitFee * child.data.quantity / qty).toDecimal(this.digit);
 | 
	
		
			
				|  |  | +            //result += (this.getFeeSplit(child.data, this.field.unitFeeSplit) * this.getFee(child.data, 'quantity') / qty).toDecimal(this.digit);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class BillsCalc {
 | 
	
		
			
				|  |  | +    constructor (project, CalcFlag) {
 | 
	
		
			
				|  |  | +        this.project = project;
 | 
	
		
			
				|  |  | +        this.CalcFlag = CalcFlag;
 | 
	
		
			
				|  |  | +        this.digit = 2;
 | 
	
		
			
				|  |  | +        switch (this.CalcFlag) {
 | 
	
		
			
				|  |  | +            case rationContent:
 | 
	
		
			
				|  |  | +                this.calcFieldName = rationContentCalcFields;
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +            case rationPrice:
 | 
	
		
			
				|  |  | +                this.calcFieldName = rationPriceCalcFields;
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +            case rationPriceConverse:
 | 
	
		
			
				|  |  | +                this.calcFieldName = rationPriceConverseCalcFields;
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +            case billsPrice:
 | 
	
		
			
				|  |  | +                this.calcFieldName = billsPriceCalcFields;
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +            default:
 | 
	
		
			
				|  |  | +                this.calcFieldName = [];
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        this.InitFields(this.calcFieldName);
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    calcLeaf (node, fields) {
 | 
	
		
			
				|  |  | +        nodeCalcObj.node = node;
 | 
	
		
			
				|  |  | +        nodeCalcObj.digit = this.digit;
 | 
	
		
			
				|  |  | +        nodeCalcObj.checkFields(fields);
 | 
	
		
			
				|  |  | +        let nodeCalc = nodeCalcObj;
 | 
	
		
			
				|  |  | +        for (let field of fields) {
 | 
	
		
			
				|  |  | +            nodeCalcObj.field = field;
 | 
	
		
			
				|  |  | +            switch (field.unitFeeFlag) {
 | 
	
		
			
				|  |  | +                case rationContentUnitFeeFlag:
 | 
	
		
			
				|  |  | +                    node.data.feesIndex[field.type].unitFee = nodeCalcObj.rationContentUnitFee().toDecimal(this.digit);
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +                case averageQtyUnitFeeFlag:
 | 
	
		
			
				|  |  | +                    node.data.feesIndex[field.type].unitFee = nodeCalcObj.averageQty().toDecimal(this.digit);
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +                // to do billsPriceUnitFeeFlag(套用定额计算程序)
 | 
	
		
			
				|  |  | +                // case billsPriceUnitFeeFlag:
 | 
	
		
			
				|  |  | +                //     break;
 | 
	
		
			
				|  |  | +                default:
 | 
	
		
			
				|  |  | +                    node.data.feesIndex[field.type].unitFee = 0;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            switch (field.totalFeeFlag) {
 | 
	
		
			
				|  |  | +                case sumTotalFeeFlag:
 | 
	
		
			
				|  |  | +                    node.data.feesIndex[field.type].totalFee = nodeCalcObj.sumTotalFee().toDecimal(this.digit);
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +                case totalFeeFlag:
 | 
	
		
			
				|  |  | +                    node.data.feesIndex[field.type].totalFee = nodeCalcObj.totalFee().toDecimal(this.digit);
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +                default:
 | 
	
		
			
				|  |  | +                    node.data.feesIndex[field.type].totalFee = 0;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    calcParent (node, fields) {
 | 
	
		
			
				|  |  | +        nodeCalcObj.node = node;
 | 
	
		
			
				|  |  | +        nodeCalcObj.checkFields(fields);
 | 
	
		
			
				|  |  | +        for (let field of fields) {
 | 
	
		
			
				|  |  | +            nodeCalcObj.field = field;
 | 
	
		
			
				|  |  | +            node.data.feesIndex[field.type].totalFee = nodeCalcObj.sumTotalFee().toDecimal(this.digit);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    calcNodes (nodes) {
 | 
	
		
			
				|  |  | +        for (let node of nodes) {
 | 
	
		
			
				|  |  | +            if (node.sourceType !== this.project.Bills.getSourceType()) {
 | 
	
		
			
				|  |  | +                return;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (node.source.children.length > 0) {
 | 
	
		
			
				|  |  | +                this.calcNodes(node.children);
 | 
	
		
			
				|  |  | +                this.calcParent(node, this.calcFieldName);
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                this.calcLeaf(node, this.calcFieldName);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    calcAll () {
 | 
	
		
			
				|  |  | +        this.calcNodes(this.project.mainTree.roots);
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    InitFields (fields) {
 | 
	
		
			
				|  |  | +        for (let field of fields) {
 | 
	
		
			
				|  |  | +            if (field.unitFee) return;
 | 
	
		
			
				|  |  | +            field.unitFee = 'feesIndex.' + field.type + '.unitFee';
 | 
	
		
			
				|  |  | +            field.unitFeeSplit = field.unitFee.split('.');
 | 
	
		
			
				|  |  | +            field.totalFee = 'feesIndex.' + field.type + '.totalFee';
 | 
	
		
			
				|  |  | +            field.totalFeeSplit = field.totalFee.split('.');
 | 
	
		
			
				|  |  | +            field.tenderUnitFee = 'feesIndex.'+ field.type + '.tenderUnitFee';
 | 
	
		
			
				|  |  | +            field.tenderUnitFeeSplit = field.tenderUnitFee.split('.');
 | 
	
		
			
				|  |  | +            field.tenderTotalFee = 'feesIndex.' + field.type + '.tenderTotalFee';
 | 
	
		
			
				|  |  | +            field.tenderTotalFeeSplit = field.tenderTotalFee.split('.');
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 |