YonBuilder应用构建实战案例-体检管理(下)

紧接着上篇文章,我们将继续讲解体检管理案例操作。

体检单

一、业务对象

创建体检单业务对象,以下是业务对象下的实体为主子孙结构

1.体检单

在这里插入图片描述

2. 体检项目_体检单子表

在这里插入图片描述

二、页面建模

1、根据业务对象创建一主多子结构单据命名为体检单

2、设置主表字段不允许修改

组织、客户、累计出库年月、单据状态

3、设置子表所有字段不允许修改
体检项目、物料、二维码编号、是否检测、检测结果、检测人

4、删除子表的新增、删行按钮

5、设置子表表格的编辑方式为侧滑弹框

6、 体检单列表页面删除新增按钮

7 、配置体检按审批流

8、配置业务流
在这里插入图片描述
9、体检预约下推体检单
防止重复下推: isNull(getValue(“AT1772AFF21C18000A.AT1772AFF21C18000A.examination_bill”,“id”,“source_id”,id))

错误提示语:下游数据已存在

触发设置:手工触发

生单方式:默认新增单据

转换规则配置如下图
在这里插入图片描述

在这里插入图片描述

10、体检单下推销售订单
目标交易类型:体检

过滤设置增加防止重复下推:isNull(getValue(“voucher.order.Order”,“id”,“srcBill”,id))&&verifystate==2

错误提示语:下游单据已存在或单据未审核

触发设置:手工触发

生单默认: 默认新增单据,勾选转单画面

转换规则配置如下图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用到的公式:

税目税率id : getValue(“bd.taxrate.TaxRateVO”,“id”,“code”,“VAT0”)

本币pk :getValue(“bd.currencytenant.CurrencyTenantVO”,“id”,“code”,“CNY”)

汇率类型id: getValue(“bd.exchangeRate.ExchangeRateTypeVO”,“id”,“code”,“01”)

单据日期: dateFormat(sysdate(),“yyyy-MM-dd”)

11、体检单列表页面增加月底汇总出库按钮,点击汇总消耗品生成其他出库单
(1).创建业务对象月底汇总
在这里插入图片描述

(2)、根据业务对象创建一个卡片页面,删除列表页面

(3)、将卡片页面设置为模态框,具体操作省略

(4)、保存按钮取消保存规则,然后增加保存函数

函数中调用了其他出库单接口,具体调用接口API脚本查看


 viewModel.get('btnSave') && viewModel.get('btnSave').on('click', function (data) {
  // 确定--单击
  let date = viewModel.get("date").getValue();
  let org = viewModel.get("org").getValue();
  let warehouse = viewModel.get("warehouse").getValue();
  let use_version = viewModel.get("use_version").getValue();
  cb.rest.invokeFunction("AT1772AFF21C18000A.api.monthUsePro", {"date":date,"org":org,"warehouse":warehouse,"use_version":use_version},
  function(err, res) {
    if(err!=null){
      cb.utils.alert(err);
      return ;
    }else{
      cb.utils.alert("发起请求成功,请到其他出库节点查看");
      viewModel.communication({type:'modal',payload:{data:false}});
    }
  })
});

(5)、调用出库单API脚本

获取日期函数


let AbstractTrigger = require('AbstractTrigger');
  class MyTrigger extends AbstractTrigger {
    execute(context,param){
      Date.prototype.format = function(fmt)
      { 
      var o = {
      "M+" : this.getMonth()+1, //月份
      "d+" : this.getDate(), //日
      "h+" : this.getHours()%12 == 0 ? 12 : this.getHours()%12, //小时
      "H+" : this.getHours(), //小时
      "m+" : this.getMinutes(), //分
      "s+" : this.getSeconds(), //秒
      "q+" : Math.floor((this.getMonth()+3)/3), //季度
      "S" : this.getMilliseconds() //毫秒
      };
    if(/(y+)/.test(fmt))
    fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));
    for(var k in o)
    if(new RegExp("("+ k +")").test(fmt))
      fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
    return fmt;
    } 
    let date = new Date().format(context);
    return {date};
    }
  }
  exports({"entryPoint":MyTrigger});

汇总统计耗材


let AbstractAPIHandler = require('AbstractAPIHandler');
  class MyAPIHandler extends AbstractAPIHandler {
   execute(request){
      let date = request.date; //获取日期
      let org = request.org;//组织
      let warehouse = request.warehouse; //仓库
      let use_version = request.use_version //版本
      // 因为两张表没有直接的关联关系,所以不能联查
      let sql = "select project as projectId,count(id) as num from AT1772AFF21C18000A.AT1772AFF21C18000A.examination_project "+
                " where yearmonth = '"+date+"' group by project";
      let projectNum = ObjectStore.queryByYonQL(sql);
      if(projectNum.length==0){
        throw new Error("为查找到数据");
      }
      //筛选出体检项
      var sqlConditionParamsStr = "";
      var projectMap = {}; //存储每个耗材使用了几份
      projectNum.forEach((project)=>{
        let kitId = "'"+project.projectId+"',";
        sqlConditionParamsStr+=kitId;
        projectMap[project.projectId]=project.num;
      })
      sqlConditionParamsStr = "("+substring(sqlConditionParamsStr, 0, sqlConditionParamsStr.length-1)+")";
      //根据查询条件查出耗材
      let consumptionSql = "select product,unit as stockUnitId,num,project_id from AT1772AFF21C18000A.AT1772AFF21C18000A.consumption "+
                " where project_id in "+sqlConditionParamsStr;
      let consumptionData = ObjectStore.queryByYonQL(consumptionSql);
      //循环重新赋值计算,将耗材数量统计
      consumptionData.forEach((data)=>{
        let totalConsumptionNum = projectMap[data.project_id]*data.num;
        data.qty = totalConsumptionNum;
        data.subQty = totalConsumptionNum;
        data._status = "Insert";
        data.othOutRecordsDefineCharacter = {"item02":data.project_id}
      })
      //拼装请求参数
      let othoutrecordParams = {};
      othoutrecordParams["org"] = org;
      othoutrecordParams["accountOrg"] = org;
      othoutrecordParams["bustype"] = "A10001";
      othoutrecordParams["_status"] = "Insert";
      othoutrecordParams["warehouse"] = warehouse;//仓库     
      othoutrecordParams["othOutRecords"] = consumptionData;
      othoutrecordParams["resubmitCheckKey"] = MD5Encode(JSON.stringify(othoutrecordParams)+use_version);
      let othoutrecordFun = extrequire("AT1772AFF21C18000A.backend.othoutrecord");
      othoutrecordFun.execute(othoutrecordParams);
   return {};
 }
}
exports({"entryPoint":MyAPIHandler});

其他出库单保存接口



let AbstractTrigger = require('AbstractTrigger');
  class MyTrigger extends AbstractTrigger {
    execute(context,param){
      //取得日期格式
      let date = extrequire("AT1772AFF21C18000A.backend.getDate");
      let dateFormat = date.execute("yyyy-MM-dd");
      context.vouchdate = dateFormat.date; //给单据日期赋值
      //调用接口
      let apiAction = "othoutrecord";
      let configFun = extrequire("AT1772AFF21C18000A.backend.config");
      let configRes = configFun.execute(null);
      let reqType = "POST";
      let body = {"data":context};
      let apiResponse;
      try{
        apiResponse = openLinker(reqType, configRes.apiurl[apiAction], configRes.appcode, JSON.stringify(body));
        let apiResponseData = JSON.parse(apiResponse);
        if(apiResponseData.code!=200){
          throw new Error("日志处理");
        }
      }catch(e){
        //处理日志,调用接口是避免回滚
        //取得日期格式
        let dateLog = extrequire("AT1772AFF21C18000A.backend.getDate");
        let dateFormatLog = dateLog.execute("yyyy-MM-dd HH:mm:ss");
        var error = {body:JSON.stringify(body),apiResponse:apiResponse,apiAction:apiAction,billnum:"examination_kit",createTime:dateFormatLog.date};
        openLinker(reqType, configRes.apiurl["apilog"], configRes.appcode, JSON.stringify(error));
        throw new Error("生成其他出库失败,请检查");
      }
     return {};
    }
  }
  exports({"entryPoint":MyTrigger});

体检单增加汇总耗材按钮,并增加点击事件打开创建的弹框


viewModel.get('button22rk') && viewModel.get('button22rk').on('click', function (params) {
  // 月终汇总出库--单击
  let data = {
    //TODO:填写单据类型及单据号
    billtype: 'Voucher',// 单据类型
    billno: 'monthtotal',// 单据号
    params: {
      mode: 'add',
    },
  };
  //打开一个单据,并在当前页面显示
  cb.loader.runCommandLine('bill', data, viewModel);
});

移动端

注:移动端和pc端公用元数据、工作流、业务流,后端函数可公用。移动端的页面和前端脚本以及发布应用是独立的。

一.体检预约单

(一).列表页

1.页面设计

调整列表页显示字段:姓名、手机号、身份证号、体检套餐、预约日期、价格。如下图
在这里插入图片描述

2. 功能(只看本人创建的预约单)

viewModel.on('beforeSearch',(args)=>{
  let userId = cb.context.getUserId();
  args.params.condition.simpleVOs=[
    {
      "field": "creator",
      "op": "eq",
      "value1": userId
    }
  ];
})

(二) .详情页

1.页面设计

表头: 手机号、姓名、客户分类:必填; 身份证号:必填 根据身份证号自动计算年龄和性别; 价格:不可修改,设置公式sum子表的使用金额,所有数值的精度为2 性别、年龄、客户:不可修改

效果如下图:
在这里插入图片描述

子表: 体检项目必填,其余字段不可编辑; 选择体检项目,其余字段自动带入;

效果如下图:
在这里插入图片描述

  1. 功能:根据身份证号自动计算年龄和性别
//身份证带出年龄和性别
viewModel.get('identity').on('afterValueChange',(data)=>{
  debugger;
  if(data && data.value != "") {
    let identity = JSON.parse(data.value).identity;
    let sex = parseInt(identity.substr(16, 1)) % 2 == 1 ? '1' : '2';
    let age = getAge(identity);
    viewModel.get('gender').setValue(sex);
    viewModel.get('age').setValue(age);
  }

})   

function getAge(userCard) {
  var myDate = new Date();
  var month = myDate.getMonth() + 1;
  var day = myDate.getDate();
  var age = myDate.getFullYear() - userCard.substring(6, 10) - 1;
  if (userCard.substring(10, 12) < month || userCard.substring(10, 12) == month && userCard.substring(12, 14) <= day) {
      age++;
  }
  return age;
}

3 功能:详情增加动作扩展(和pc动作通用)

在这里插入图片描述

4 子表功能:体检项目必填,其余字段不可编辑

//editRowModel的字段状态
viewModel.on('afterLoadData',(args)=>{
  viewModel.getGridModel().getEditRowModel().get("project_name").setState('bIsNull',false);
  viewModel.getGridModel().getEditRowModel().get("examination_kit_name").setState('bCanModify',false);
  viewModel.getGridModel().getEditRowModel().get("original_price").setState('bCanModify',false);
  viewModel.getGridModel().getEditRowModel().get("price").setState('bCanModify',false);
  viewModel.getGridModel().getEditRowModel().get("is_kit").setState('bCanModify',false);
  viewModel.getGridModel().getEditRowModel().get("useprice").setState('bCanModify',false);
  viewModel.getGridModel().getEditRowModel().get("product_standard_name").setState('bCanModify',false);
})

5、子加粗样式表功能:选择体检项目,其余字段自动带入

//选择项目带入其他字段
viewModel.getGridModel().getEditRowModel().get("project_name").on("afterValueChange",(args)=>{ 
  let index = viewModel.getGridModel().getFocusedRowIndex();
  viewModel.getGridModel().getEditRowModel().get('original_price').setValue(args.value.original_price);
  viewModel.getGridModel().setCellValue(index,"original_price",args.value.original_price);
  viewModel.getGridModel().setCellValue(index,'original_price',args.value.original_price);
  // 所属套餐 examination_kit_name
  viewModel.getGridModel().getEditRowModel().get('examination_kit').setValue(args.value.examination_kit_id);
  viewModel.getGridModel().setCellValue(index,'examination_kit',args.value.examination_kit_id);
  viewModel.getGridModel().getEditRowModel().get('examination_kit_name').setValue(args.value.examination_kit_id_name);
  viewModel.getGridModel().setCellValue(index,'examination_kit_name',args.value.examination_kit_id_name);
  //套餐价格
  viewModel.getGridModel().getEditRowModel().get('price').setValue(args.value.price);
  viewModel.getGridModel().setCellValue(index,'price',args.value.price);
  //是否套餐
  viewModel.getGridModel().getEditRowModel().get('is_kit').setValue("2");
  viewModel.getGridModel().setCellValue(index,'is_kit',"2");
  //使用金额
  viewModel.getGridModel().getEditRowModel().get('useprice').setValue(args.value.original_price,true);
  viewModel.getGridModel().setCellValue(index,'useprice',args.value.original_price);
  //物料
  viewModel.getGridModel().getEditRowModel().get('product_standard').setValue(args.value.product);
  viewModel.getGridModel().setCellValue(index,'product_standard',args.value.product);
  viewModel.getGridModel().getEditRowModel().get('product_standard_name').setValue(args.value.product_name);
  viewModel.getGridModel().setCellValue(index,'product_standard_name',args.value.product_name);
})

6、子表功能:编辑页,拦截保存动作

viewModel.get("btnSubSave_1").on('click',(data)=>{
  if(!viewModel.getGridModel().getEditRowModel().get("project_name").getValue()) {
    cb.utils.alert("项目不能为空");
    return false;
  }
  viewModel.biz.do('closePage',viewModel);
})

7、主子联动:选择主表所属套餐,子表自动增加下属项目

let gridModel = viewModel.getGridModel();
viewModel.get("pay_examination_kitList").on("afterValueChange",function(data){
  //旧的数据  套餐id放数组
  let oldData = gridModel.getDataSourceRows();
  let oldRows = gridModel.getRows();
  let rowsDataState = gridModel.__data.rowsDataState
  let delIndex = [];
  if(data && data.value.length > 0) {
    let result = cb.rest.invokeFunction("AT17925AEA1C18000A.api.getProjectById", {data:data.value},function(err, res) {},viewModel, {async:false});
    debugger;
    //新的数据  套餐id放数组
    let newData = result.result.res;
    let newKit = [];
    newData.forEach((item,index)=>{
      newKit.push(item.examination_kit);
    })

    let oldKit = [];
    oldRows.forEach((item,index)=>{
      if(item.is_kit == '1') {
        oldKit.push(item.examination_kit);
      }
    })
    //多的数据就新增
    let addRows = [];
    newData.forEach((item,index)=>{
      if(!oldKit.includes(item.examination_kit)) {
        item.is_kit = '1';
        addRows.push(item);
        rowsDataState.push("Insert");
      }
    })
    //少的套餐就删除
    oldRows.forEach((item,index)=>{
      if(item.is_kit == '1' && !newKit.includes(item.examination_kit)) {
        delIndex.push(index);
      }
    })

    gridModel.setDataSource(oldData.concat(addRows));
    gridModel.__data.rowsDataState = rowsDataState;
    rowsDataState.forEach((item,index)=>{
      if(item == "Delete") {
        delIndex.push(index);
      }
    })
  } else {
    if(data) {
      oldRows.forEach((item,index)=>{
        if(item.is_kit == '1') {
          delIndex.push(index);
        }
      })
    }
  }
  viewModel.setCache('remark',1);
  gridModel.deleteRows(delIndex);
})

8、主子联动:子表删行,如果是删除的套餐项目,那么套餐中的其他项目更新使用金额=原价,是否套餐更新为否

gridModel.on('beforeDeleteRows',(args)=>{
  let mark = viewModel.getCache('remark');
  if(!mark) {
    if(args[0].is_kit == '1') {
      cb.utils.confirm("删除后不满足套餐的情况体检项将按照原价计算",function(){

      let rows = gridModel.getRows();
      let delIndex;
      rows.forEach((item,index)=>{
        //删除数据
        if(item._id == args[0]._id) {
          delIndex = index;
        } else {
          //更新同套餐数据
          if((item.examination_kit == args[0].examination_kit) && (item.is_kit == '1')) {
            item.is_kit = '2';
            item.useprice = item.original_price;
            gridModel.updateRow(index,item);
          }
        }
      })
      //删除数据
      viewModel.setCache('remark',1);
      gridModel.deleteRows([delIndex]);
      //更新表头套餐
      let kitList = viewModel.get("pay_examination_kitList").getData();
      let newKitList = [];
      let count = 0;
      kitList.forEach((item,index)=>{
        if(item.examination_kit == args[0].examination_kit) {
          if(item.id) {
            item._status = "Delete";
            newKitList.push(item);
          }
        } else {
          newKitList.push(item);
        }
      })
      debugger;
      viewModel.get("pay_examination_kitList").doPropertyChange('clearTag');
      viewModel.get("pay_examination_kitList").setData(newKitList);

      },function(){
        return false;
      })

      return false;
    }

  } else {
    viewModel.clearCache("remark");
  }
})

二、体检单

(一). 列表页

1、页面设计:字段调整如下图
在这里插入图片描述

2、功能:只看本人创建的客户的体检单

//前端脚本
viewModel.on('beforeSearch',(args)=>{
  let result = cb.rest.invokeFunction("AT17925AEA1C18000A.api.getCustomer", {},
  function(err, res) {},viewModel,{async:false})
  let arr = [];
  result.result.res.forEach((item,index)=>{
    arr.push(item.customer)
  })
  args.params.condition.simpleVOs=[
    {
      "field": "merchant",
      "op": "in",
      "value1": arr
    }
  ];
})
//后端脚本
let AbstractAPIHandler = require('AbstractAPIHandler');
  class MyAPIHandler extends AbstractAPIHandler {
   execute(request){
    let userId = ObjectStore.user().id;
    let sql = "select customer from AT17925AEA1C18000A.AT17925AEA1C18000A.pay where  creator= '"+ userId+"'";
    var res = ObjectStore.queryByYonQL(sql);
   return {res};

 }
}
exports({"entryPoint":MyAPIHandler});

(二).详情页

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值