期末结账功能目前的设计是,在总账期末结账界面点击“结账”按钮,服务端依次检查各个模块,如果存在异常,则提示 用户,用户可以选择通过“继续结账”忽略掉这些异常;否则就依次结账各个模块。
由于涉及的模块较多,且分属不同代码模块。因此当点击结账时,通过发布事件的方式,其余模块捕获事件做结账前检测、结账时动作。
代码在com.usoftchina.saas.finance.controller.LedgerController.endGeneralLedger
BeforePeriodEndEvent beforePeriodEndEvent = new BeforePeriodEndEvent(currentPeriod, nextPeriod);
// 结账前事件,其他模块通过该事件做结账前检测
SpringContextHolder.getContext().publishEvent(beforePeriodEndEvent);
if (beforePeriodEndEvent.hasError() || beforePeriodEndEvent.hasWarn()) {
return Result.error(beforePeriodEndEvent);
}
PeriodEndEvent periodEndEvent = new PeriodEndEvent(currentPeriod, nextPeriod);
// 结账事件,其他模块通过该事件做结账动作
SpringContextHolder.getContext().publishEvent(periodEndEvent);
反结账也是通过事件,通知其他模块。
PeriodUnEndEvent periodUnEndEvent = new PeriodUnEndEvent(currentPeriod, prevPeriod);
// 反结账事件,其他模块通过该事件做反结账动作
SpringContextHolder.getContext().publishEvent(periodUnEndEvent);
结账前检测
扩展代码在com.usoftchina.saas.money.listener.ArPeriodEndListener.beforePeriodEndEvent
@EventListener(BeforePeriodEndEvent.class)
public void beforePeriodEndEvent(BeforePeriodEndEvent event) {
// 当期存在未审核的单据
checkUnAudit(event);
// 当期存在未生成凭证的单据
checkUnVoucher(event);
// 当期应收期末与总账应收账款科目余额不一致
checkRecBalance(event);
// 当期预收期末与总账预收账款科目余额不一致
checkPreRecBalance(event);
}
扩展代码在com.usoftchina.saas.money.listener.ApPeriodEndListener.beforePeriodEndEvent
@EventListener(BeforePeriodEndEvent.class)
public void beforePeriodEndEvent(BeforePeriodEndEvent event) {
// 当期存在未审核的单据
checkUnAudit(event);
// 当期存在未生成凭证的单据
checkUnVoucher(event);
// 当期应付期末与总账应收账款科目余额不一致
checkPayBalance(event);
// 当期预收期末与总账预收账款科目余额不一致
checkPreRecBalance(event);
}
扩展代码在com.usoftchina.saas.storage.listener.StPeriodEndListener.beforePeriodEndEvent
@EventListener(BeforePeriodEndEvent.class)
public void beforePeriodEndEvent(BeforePeriodEndEvent event) {
// 当期存在未审核的出入库单
checkUnAudit(event);
// 当期存在未生成凭证的单据
checkUnVoucher(event);
// 当期库存余额与总账存货科目余额不一致
checkBalance(event);
}
制造版补充扩展代码在com.usoftchina.saas.make.listener.MakePeriodEndListener.beforePeriodEndEvent
@EventListener(BeforePeriodEndEvent.class)
public void beforePeriodEndEvent(BeforePeriodEndEvent event) {
String appId = BaseContextHolder.getAppId();
if ("make-app".equals(appId)) {
// 当期存在未审核的报废单
checkUnAudit(event);
}
}
制造版补充扩展代码在com.usoftchina.saas.finance.listener.CoPeriodEndListener.beforePeriodEndEvent
@EventListener(BeforePeriodEndEvent.class)
public void beforePeriodEndEvent(BeforePeriodEndEvent event) {
String appId = BaseContextHolder.getAppId();
if ("make-app".equals(appId)) {
// 当期成本表制造工单(期末金额+期末报废结余)与总账生产成本:直接材料科目余额不一致
checkBalance(event);
// 当期成本表外协工单(期末金额+期末报废结余)与总账委托加工物资科目余额不一致
checkOsBalance(event);
}
}
扩展代码在com.usoftchina.saas.finance.listener.GlPeriodEndListener.beforePeriodEndEvent
@EventListener(BeforePeriodEndEvent.class)
@Order(100)
public void beforePeriodEndEvent(BeforePeriodEndEvent event) {
// 当期存在未审核的凭证
checkUnAudit(event);
// 当期存在断号的凭证
checkBrokenNumber(event);
// 当期银行余额与总账银行现金科目余额不一致
checkBankBalance(event);
// 存在未结转损益余额
checkLossBalance(event);
}
结账
扩展代码在com.usoftchina.saas.biz.listener.BizPeriodEndListener.onPeriodEndEvent
@EventListener(PeriodEndEvent.class)
@Order(1)
public void onPeriodEndEvent(PeriodEndEvent event) {
// 该方法调用的是sp_end存储过程,该过程囊括了库存/应收/应付/成本的期末数据结转
endProductService.endAccount(event.getCurrentPeriod());
}
扩展代码在com.usoftchina.saas.finance.listener.GlPeriodEndListener.onPeriodEndEvent
@EventListener(PeriodEndEvent.class)
@Order(100)
public void onPeriodEndEvent(PeriodEndEvent event) {
ledgerService.end(event.getCurrentPeriod());
}
反结账
扩展代码在com.usoftchina.saas.biz.listener.BizPeriodEndListener.onPeriodUnEndEvent
@EventListener(PeriodUnEndEvent.class)
@Order(1)
public void onPeriodUnEndEvent(PeriodUnEndEvent event) {
endProductService.unEndAccount(event.getCurrentPeriod());
}
扩展代码在com.usoftchina.saas.finance.listener.GlPeriodEndListener.onPeriodUnEndEvent
@EventListener(PeriodUnEndEvent.class)
@Order(100)
public void onPeriodUnEndEvent(PeriodUnEndEvent event) {
ledgerService.unEnd(event.getCurrentPeriod());
}