OA系统-报销收支模块

1.报销管理-添加报销单-业务层

(1)在报销主表和明细表中都有一个字段叫expid,这个字段在数据库中是利用序列获取的,但是在业务层中,我们要控制主表和明细表的expid一致,所以要先获取expid赋值给主表和明细表,那么这个expid的值怎么得到呢?
通过获取序列的下一个值

2.报销管理-添加报销单-DAO层代码

(1)在我们的逻辑中,要向主表添加数据,要向明细表添加数据,但是假如在向明细表添加数据的过程中,出现异常了,那么程序就中断了,但是主表的数据被添加进去了,这个问题要怎么解决呢?
将多个操作视为一个事务,主要方法是将dao层的操作上升到业务层

(2)在我们目前的代码中,当添加明细出现问题的时候,页面还是会跳转到添加成功页面,这个问题怎么解决呢?
向上抛出异常
(3)现在的代码中,会出现另一个问题:主表数据添加成功,明细表数据添加失败,但是这些操作肯定是要么都成功,要么都失败的,那么这个问题怎么解决呢?
将多个操作视为一个事务,主要方法是将dao层的操作上升到业务层

3.报销管理-使用ThreadLocal实现业务层事务1

(1)说明ThreadLocal的作用?
用来存放我们connection变量,可以保证同一个线程中,不同方法,不同的层次操作使用的都是同一个connection

4.报销管理-使用ThreadLocal实现业务层事务2

(1)如何保证DBUtils工具类中getConnection方法获取到的Connection对象是一个呢?
创建ThreadLocal,并将我们创建的connection存放于ThreadLocal中,
(2)在DBUtils中是否要将Connection关闭呢?那要在什么时候关闭?
不需要,要在业务层所有的事务结束之后关闭connection

5.报销管理-待审报销单

(1)简述待审报销的思路?
当浏览器发送待审报销单的请求时,servlet处理请求,调用业务层的查询待审报销单的方法,传入从session中获取的登录人的id,业务层调用dao层方法,访问数据库,将查询结果返回给servlet层,然后放在request中,请求转发到页面,页面进行显示
(2)如何查询的是不是下一级审批人是当前登录人的信息?
我们从session中获取登录人的id,然后在数据库根据下一个审批人作为查询的条件

标题6.我要查询的是不是下一级审批人是当前登录人的信息?

我们从session中获取登录人的id,然后在数据库根据下一个审批人作为查询的条件

(1)根据业务流程图,请用文字详细描述报销流程。
根据报销单状态,有通过,拒绝,打回,
判断当前需要报销的金额,如果金额小于2500,直接由上级审核即可
如果当前报销的金额大于2500,直接上级审核过后,还要传到当前审核人的上级,要经由总裁审核
最终审核过后的报销单都会到财务那里,财务通过,并作出支出
(2)审核报销单业务涉及到哪些表?
报销单表,审核表,支出表

8.报销管理-审核报销单-控制层代码和业务层思路

(1)如何在后台sql中进行条件的拼接?
对于字符串的拼接,我们可以使用stringbuilder类型

	//创建SQL命令
			StringBuilder sql=new StringBuilder("select item.itemid,item.type,item.amount,item.itemdesc,"
					+ " pm.paytime,exp.expid,emp.realname,emp2.realname"
					+ " from payment pm join expense exp on pm.expid=exp.expid"
					+ " join expenseitem item on exp.expid=item.expid join employee emp "
					+ " on pm.payempid=emp.empid join employee emp2 on exp.empid=emp2.empid "
					+ " where 1=1 ");
			if (startDate!=null) {
				sql.append("and paytime>=to_date('"+startDate+"','yyyy-MM-dd')");
			}
			if (endDate!=null) {
				sql.append("and paytime>=to_date('"+endDate+"','yyyy-MM-dd')");
			}
			if (payEmpid!=null) {
				sql.append("and pm.payEmpid='"+payEmpid+"'");
			}
			if (type!=0) {
				sql.append("and item.type="+type);
			}

9.报销管理-审核报销单-DAO层和业务层代码实现1

(1)在填充业务层代码过程中,需要注意哪些事项?
因为操作多个操作,涉及多个事务,所以我们需要将Dao层事务上升到业务层,要让都成功或者都失败

10.报销管理-审核报销单-DAO层和业务层代码实现2

(1)完成审核报销单业务层代码。

public void auditService(Auditing auditing) {
		//开启事务
		Connection conn = DBUtil2.getConnection();
		try {
			conn.setAutoCommit(false);//事务不再自动结束(提交,回滚),事务并没有在此开始
			Expense exp = new Expense();
			exp.setExpId(auditing.getExpId());
			exp.setLastResult(auditing.getResult());
			String result = auditing.getResult();
			//审核通过吗
			if("通过".equals(result)){//审核通过
				//是财务吗				
				if(auditing.getAuditor().getPosition().getPosId()==6){//是财务
					//添加支出记录
					String payEmpId=auditing.getAuditor().getEmpId();
					Date payTime=new Date();
					int expId=auditing.getExpId();
					Expense exp2=expDao.findByexpId(expId);
					Double amount=(double) exp2.getTotalAmount();
					String empId=exp2.getEmpId();
					Payment payment=new Payment(payEmpId, amount, payTime, expId, empId);
					pm.save(payment);
					//修改报销单状态	
					exp.setStatus(Constants.EXPENSE_STATUS_PAIED);
					exp.setNextAuditorId(null);
				}else{
					//金额大于2500吗  auditing.getExp().getTotalAmount()>2500  空指针异常
					//获取报销单的金额
					int expId = auditing.getExpId();
					Expense exp2 = expDao.findByexpId(expId);
					if(exp2.getTotalAmount()>2500){//大于2500
						//当前审核人是总裁吗
						if(Constants.CEOID.equals(auditing.getAuditor().getEmpId())){
							//添加审核记录							
							auditDao.save(auditing);
							//修改报销单状态				
							exp.setStatus(Constants.EXPENSE_STATUS_AUDITED);
							exp.setNextAuditorId(Constants.CTOID); //财务							
						}else{
							//添加审核记录
							auditDao.save(auditing);
							//修改报销单状态					
							exp.setStatus(Constants.EXPENSE_STATUS_AUDITING);
							exp.setNextAuditorId(Constants.CEOID); //总裁
							//exp.setNextAuditorId(auditing.getAuditor().getMgr().getEmpId());
						}
					}else{//小于等于2500
						//添加审核记录
						auditDao.save(auditing);
						//修改报销单状态  下个处理人:财务  状态:审核通过						
						exp.setStatus(Constants.EXPENSE_STATUS_AUDITED);
						exp.setNextAuditorId(Constants.CTOID); //财务
					}					
				}
				
			}else{//不通过,拒绝或者打回
				//添加审核记录
				auditDao.save(auditing);
				//修改报销单状态
				if("打回".equals(auditing.getResult())){
					exp.setStatus(Constants.EXPENSE_STATUS_REJECT);
				}else{
					exp.setStatus(Constants.EXPENSE_STATUS_BACK);
				}
				exp.setNextAuditorId(null); //拒绝 打回 没有下个审核人	
			}
			expDao.update(exp);		
			//结束事务(提交或回滚)
			conn.commit();
		} catch (Exception e) {//!!! 所有异常,保存运行时异常,SQLSyntaxErrorException
			e.printStackTrace();			
			try {
				conn.rollback(); //回滚数据
			} catch (SQLException e1) {
				e1.printStackTrace();
				throw new MyException(e1.toString());
			}
			throw new MyException(e.toString());//向上一层抛出异常信息
			
		}finally{
			DBUtil2.closeAll(null, null, conn);			
		}

11.报销管理-理解数据库表和创建实体类

(1)简述系统中表之间的关系:
表之间用外键关联,在java中我们用的类与类之间的关系

12.报销管理-审核报销单-代码完善和业务流程图绘制

(1)在完成审核报销单功能后,你的感悟是什么?
对于mvc模式来说,一开始觉得代码量最多的在Dao层,然而现在才知道对于一个项目而言,最重要的是业务层,业务层才是逻辑和代码量最多的,而且业务层比较复杂
(2)在程序出错后或跟你预先结果不一致的时候,你的应对策略是什么?
第一步:查看出错的原因,根据输出的错误信息找到主要出错位置,然后如果是曾经遇到的错误,当然是自己解决,如果第一次遇到,而且还无从下手的话,先去百度上查看一下,然后看看别人的建议,自己在慢慢找错

13.收支管理-Echarts入门

(1)Echarts插件的作用?
是一款可视化类型的插件,具有丰富的可视化类型,多种数据格式无需转换直接使用,千万数据的前端展示,移动端可视化,多渲染方案,跨平台使用,深度的交互式数据搜索的特征
(2)如何使用Echarts插件?
第一步:引入echarts的js文件
第二步:准备一个div,并初始化echarts实例
第三步:展示数据

14.收支管理-使用Echarts柱状图显示收入统计信息-视图层和控制层

(1)使用Echarts柱状图显示收入统计信息的逻辑概述?
主要是返回类型的要求,我们需要在业务层进行数据的拼接,返回我们需要的json字符串类型,难点就是字符串的拼接

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小希一夏

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值