JAVA调用Oracle存储过程传入结构化参数

 

一、JAVA部分

import java.math.BigDecimal;
import java.util.Hashtable;
import java.util.Vector;
import com.sinocc.exception.*;
import com.sinocc.systemdbmanager.CPCDao;
import com.sinocc.systemdbmanager.DataCentre;
import com.sinocc.util.*;
import com.ajerp.util.*;
import java.util.ArrayList;
import java.sql.Connection;
import java.sql.SQLException;
import oracle.sql.*;
import oracle.jdbc.driver.*;

1.调用存储过程
 /**
  * 同步至EAS系统应付单。 创建日期:(2011-03-10 13:15:05) 1.
  * 调用EAS的存储过程p_ct_ccs_arapperiod获取EAS的当前应付期间,如获取失败,则提示错误并终止同步; 2.
  * 调用EAS的合法性检查 3. 写应付单到EAS接口表 4.
  * 调用EAS的生成应付单的存储过程/p_ct_应付单,将数据从EAS接口表写入EAS业务表,并回写执行情况至EAS接口表和记录操作日志 5.
  * 读取EAS接口表中的执行情况,写入CCS的操作日志
  *
  */
 public void doSyncToEas() throws SinocpcException, SQLException {

  Vector EasRecord = new Vector();

  Vector ap_invoices = this.Ap_Invoice_Heads.getRelationData();
  if (ap_invoices != null && ap_invoices.size() > 0) {

   Ap_Invoice_Head ap_invoice_head = new Ap_Invoice_Head();
   ap_invoice_head.setParent(this);

   Hashtable eas_exec_ht = new Hashtable();
   String easexecstatus = "0";
   String easexecdescription = "";

   // 循环采购发票信息
   for (int i = 0, n = ap_invoices.size(); i < n; i++) {
    Hashtable htRecord = new Hashtable();

    Hashtable ht = (Hashtable) ap_invoices.elementAt(i);
    ap_invoice_head.toObject(ht);

    ap_invoice_head.Year_Month = ErpUtil.toDate("yyyy-MM",
      ap_invoice_head.Date_Bill);

    // 执行EAS的存储过程,检查数据合法性,写入接口表,生成业务记录,返回执行情况
    eas_exec_ht = apOtherBill_Verify(
      ap_invoice_head.Ap_Invoice_Head_Id,
      ap_invoice_head.Ordinal_No, ap_invoice_head.Bill_Type);
    easexecstatus = (String) eas_exec_ht.get("easexecstatus");
    easexecdescription = (String) eas_exec_ht
      .get("easexecdescription");

    // 写日志表
    if (easexecstatus.compareTo("2") == 0) {
     easexecdescription = "成功";
    }
    ErpUtil erputil = new ErpUtil();
    erputil.writeEasLog("CCS_EAS_ApOtherBill_Log", "采购发票",
      ap_invoice_head.Ap_Invoice_Head_Id, 3, (new Date())
        .toText(), easexecdescription);

    // 返回EAS日志
    htRecord.put("ap_invoice_head_id", String
      .valueOf(ap_invoice_head.Ap_Invoice_Head_Id));
    htRecord.put("synceasstatus", easexecstatus);
    htRecord.put("eas_record", easexecdescription);
    EasRecord.add(htRecord);
   }

   this.Ap_Invoice_Heads.setRelationData(EasRecord);

  }
 }

 // 校验发票合法性
 private Hashtable apOtherBill_Verify(int ap_head_id, String ordinal_no,
   int Bill_Type) throws SinocpcException, SQLException {

  DataCentre ccsDc = null;
  Connection easCon = null;
  OracleCallableStatement proc = null;

  ArrayList lineArray = new ArrayList();
  ArrayList headArray = new ArrayList();

  int easExecStatus = 0;
  String easExecDescription = "";
  String sql = "";

  String FBillType = "";// EAS单据类型:201其他应付;202采购发票

  if (Bill_Type == 1) {
   FBillType = "202";
  } else {
   FBillType = "201";
  }


  // 执行存储过程
  try {
   // 连接数据中心
   ccsDc = new CPCDao(this.getVaultBean().getVaultId());
   ccsDc.setTransation(true);

   // 先将导入状态更新为成功.如果不成功则系统回滚不执行更新,导入标志依然为0
   sql = "update ap_invoice_head set synceasstatus = 2 "
     + " where synceasstatus <> 2 and Ap_Invoice_Head_Id ="
     + ap_head_id;
   if (ccsDc.execute(sql) > 0) {
    // 更新同步状态成功,执行同步
    // 查询主表
    sql = "select to_char(date_bill, 'yyyy-mm-dd hh24:mi:ss') fbilldate,"
      + "       '供应商' fasstacttype,"
      + "       vendor.vendor_code fasstactnumber,"
      + "       vendor.vendor_name fasstactname,"
      + "       2 as fbillstatus,"
      + FBillType
      + " fbilltype,"
      + "       0 fistransbill,"
      + "       0 fsourcebilltype,"
      + "       '' fasstactid_sourcebill,"
      + "       '' fasstacttypeid_sourcebill,"
      + "       0 fisreversebill,"
      + "       'RMB' fcurrencyid,"
      + "       1 fexchangerate,"
      + "       ap_invoice_head.note fabstractname,"
      + "       ap_invoice_head.organization_id fcompanyid,"
      + "       1 fisintax,"
      + "       ordinal_no fnumber,"
      + "       to_char(date_bill, 'yyyy-mm-dd hh24:mi:ss') fbizdate,"
      + "       to_char(ap_invoice_head.creation_date, 'yyyy-mm-dd hh24:mi:ss') fcreatetime,"
      + "       to_char(ap_invoice_head.last_update_date, 'yyyy-mm-dd hh24:mi:ss') flastupdatetime,"
      + "       ap_invoice_head_id fccsid,"
      + "       0 fccsstatus,"
      + "       0 fccsread,"
      + "       0 fexecstatus,"
      + "       0 fexecdescription,"
      + "       invoice_no finvoicenum,"
      + "      vendor_org.gl_account_subject_id_inv,"
      + "      gl_account_subject.km_code,"
      + "      ap_invoice_head.year_month"
      + "  from ap_invoice_head, vendor, vendor_org, gl_account_subject"
      + " where ap_invoice_head.vendor_id = vendor.vendor_id(+) and"
      + " ap_invoice_head.vendor_id = vendor_org.vendor_id(+) and"
      + " vendor_org. gl_account_subject_id_inv = gl_account_subject.gl_account_subject_id(+)"
      + " and vendor_org.organization_id (+)= "+ this.getUserBean().Organization_Id
      + "  and ap_invoice_head_id = " + ap_head_id;
    Hashtable ht_head = ccsDc.oneRowSelect(sql);

    if (ht_head == null || ht_head.size() == 0) {
     // 更新失败,应付单据应该已经更新
     ccsDc.rollback();
     easExecStatus = 1;
     easExecDescription = "同步失败,应付单据[" + ordinal_no
       + "]单据头信息未找到!";     
    }
    else {
     Vector vc_head = new Vector();
     vc_head.add((Hashtable) ht_head.clone());

     // 应付会计科目
     String km_code = ht_head.get("km_code").toString();
     if (km_code == null) {
      km_code = "";
     }

     // 查询明细.如果单据类型为“采购发票 1”则取细表数据,如果单据类型为“其他应付
     // 2”,则将主表的价格、税率、金额作细表
     if (Bill_Type == 1) {

      sql = "select line.ap_invoice_line_id as FCCSEntryID,"
        + "       line.ap_invoice_head_id as FCCSID,"
        + "       item_code as FmaterialNum,"
        + "       '01' FExpenseItemID,"
        + "       u.uom_name as FMeasureUnitID,"
        + "       line.note as fremark,"
        + "       line.qty_match as FQty,"
        + "       line.price_fact as FTaxPrice,"
        + "       head.tax_rate as FTaxRate,"
        + "       Line.AMOUNT_FACT/(1+ head.tax_rate / 100)*(head.tax_rate / 100)  FTAXAMOUNT,"
        + "       line.AMOUNT_FACT as FAmount, '"
        + km_code
        + "'    as FAccountID,"
        + "       rownum as FSeq,"
        + "       line.is_discount as Fisdiscount,"
        + "       decode(line.price_fact, 0, 2, 1) as Fispresent"
        + "  from ap_invoice_line line, ap_invoice_head head,item i, uom u"
        + " where line.ap_invoice_head_id = head.ap_invoice_head_id"
        + "   and line.item_id = i.item_id(+)"
        + "   and i.uom_id = u.uom_id(+)"
        + "   and line.ap_invoice_head_id = "
        + ap_head_id;
     }

     else {

      sql = "select 1 as fccsentryid, "
        + "          ap_invoice_head.ap_invoice_head_id as fccsid,"
        + "       '' as fmaterialnum,"
        + "       '' fexpenseitemid,"
        + "       '' as fmeasureunitid,"
        + "       '' as fremark,"
        + "       1 as fqty,"
        + "       amount_goods_f as ftaxprice,"
        + "       ap_invoice_head.tax_rate as ftaxrate,"
        + "       amount_tax_f ftaxamount,"
        + "       amount_goods_f as famount, '"
        + km_code
        + "'   as faccountid,"
        + "       1 as fseq,"
        + "       0 as fisdiscount,"
        + "       0 as fispresent"
        + "       from ap_invoice_head"
        + " where ap_invoice_head.ap_invoice_head_id = "
        + ap_head_id;

     }

     Vector line_vc = ccsDc.multiRowSelect(sql);
     if (line_vc == null || line_vc.size() == 0) {
      // 更新失败,应付单据应该已经更新
      ccsDc.rollback();
      easExecStatus = 1;
      easExecDescription = "同步失败,应付单据[" + ordinal_no
        + "]单据体信息未找到!";     
     }     
     

     easCon = ErpUtil.getDBConn("eas");
     easCon.setAutoCommit(false); // 关闭自动事务,手工提交和回滚事务

     // 加载主表数据
     headArray.clear();
     headArray.addAll(vc_head);
     ARRAY Head_Array = getHead_Array("TYPE_AP", "ARRAY_AP",
       headArray, easCon);

     // 加载细表数据
     lineArray.clear();
     lineArray.addAll(line_vc);
     ARRAY Line_Array = getLine_Array("TYPE_APEN", "ARRAY_APEN",
       lineArray, easCon);

     proc = (OracleCallableStatement) easCon
       .prepareCall("begin p_ct_ccs_APOtherBill_verify(?,?,?,?); end;");

     proc.setArray(1, Head_Array); // 单据头
     proc.setArray(2, Line_Array); // 单据体

     proc.registerOutParameter(3, java.sql.Types.INTEGER); // 写入EAS业务表的执行状态:0-未执行,1-失败,2-成功
     proc.registerOutParameter(4, java.sql.Types.VARCHAR); // 异常原因

     // 执行存储过程
     proc.execute();

     easExecStatus = proc.getInt(3);
     easExecDescription = proc.getString(4);

     if (easExecDescription == null) {
      easExecDescription = "";
     }

     // 提交事务
     easCon.commit();
     ccsDc.commit();
    }
   } else {
    // 更新失败,应付单据应该已经更新
    ccsDc.rollback();
    easExecStatus = 1;
    easExecDescription = "更新同步状态失败,可能应付单据[" + ordinal_no
      + "]已经同步到EAS!";
    
    
   }

  } catch (DatabaseException de) {
   // 回滚事务
   if (ccsDc != null) {
    ccsDc.rollback();
   }
   if (easCon != null) {
    easCon.rollback();
   }
   easExecStatus = 1;
   easExecDescription = "调用应付单校验存储过程(p_ct_ccs_APOtherBill_verify)出错:"+ de.getMessage();
     
  } catch (Exception e) {
   // 回滚事务
   if (ccsDc != null) {
    ccsDc.rollback();
   }
   if (easCon != null) {
    easCon.rollback();
   }
   easExecStatus = 1;
   easExecDescription = "调用应付单校验存储过程(p_ct_ccs_APOtherBill_verify)出错:"+ e.getMessage();
     
  } finally {

   // 关闭连接
   ccsDc.freeConnection();
   ErpUtil.freeDBConn(easCon);
  }

  // 执行状态及异常情况
  Hashtable easExecHt = new Hashtable();
  easExecHt.put("easexecstatus", String.valueOf(easExecStatus));
  easExecHt.put("easexecdescription", easExecDescription);
  return (Hashtable) easExecHt.clone();
 }

 /**
  * 将单据头的数据利用java结果集合转化成oracle自定义类型集合
  *
  * @param ora_type
  *            Oracle自定义Object TYPE
  * @param ora_array
  *            Oracle自定义Table Type
  * @param alist
  *            传输数据结果集
  * @param conn
  *            数据连接
  * @return 根据Oracle自定义类型包装转化后的结果集
  * @throws Exception
  */
 private ARRAY getHead_Array(String ora_type, String ora_array,
   ArrayList alist, Connection conn) throws Exception {

  ARRAY list = null;

  if (alist != null && alist.size() > 0) {

   StructDescriptor structdesc = new StructDescriptor(ora_type, conn);
   STRUCT[] structs = new STRUCT[alist.size()];
   Object[] result = null;

   for (int i = 0; i < alist.size(); i++) {
    result = new Object[26];
    Hashtable ht = (Hashtable) alist.get(i);

    // 如果单据区间等于EAS期间则单据日期不变,否取EAS期间的第一天
    if (this.Year_Month.compareTo(ht.get("year_month").toString()) == 0) {
     result[0] = ht.get("fbilldate").toString(); // 单据日期
    } else {
     result[0] = this.Year_Month + "-01 00:00:00"; // 单据日期
    }
 
    result[1] = String.valueOf(ht.get("fasstacttype")); // VARCHAR2(150)往来户类型
    result[2] = ht.get("fasstactnumber").toString(); // VARCHAR2(150)往来户编码
    result[3] = ht.get("fasstactname").toString(); // VARCHAR2(750)往来户名称
    result[4] = new BigDecimal((String) ht.get("fbillstatus")); // number(4)单据状态(默认“2提交”状态)
    result[5] = new BigDecimal((String) ht.get("fbilltype")); // number(4)单据类型(201其他应付单;202采购发票;203采购费用发票;204应付借贷项调整单)
    result[6] = new BigDecimal((String) ht.get("fistransbill")); // number(4)是否转移生成单据;应收:债权转移应付:债务转移
    result[7] = new BigDecimal((String) ht.get("fsourcebilltype")); // number(4)来源单据类型来源单据类型(0采购发票;9其他应付单;10采购费用发票;14代理业务单(应付);213应付借贷项调整单)
    result[8] = String.valueOf(ht.get("fasstactid_sourcebill")); // VARCHAR2(150)来源单往来户
    result[9] = String.valueOf(ht.get("fasstacttypeid_sourcebill"));// VARCHAR2(150)来源单往来类型来源单往来类型(客户、供应商)
    result[10] = new BigDecimal((String) ht.get("fisreversebill")); // number(4)是否为冲销单据
    result[11] = String.valueOf(ht.get("fcurrencyid")); // VARCHAR2(150)币别
    result[12] = new BigDecimal((String) ht.get("fexchangerate")); // number(28,10)汇率(默认1)
    result[13] = ht.get("fabstractname").toString();// varchar2(2000)摘要
    result[14] = "61"; // ht.get("fcompanyid").toString();VARCHAR2(150)公司
    result[15] = new BigDecimal((String) ht.get("fisintax")); // number(4)是否含税
    result[16] = ht.get("fnumber").toString(); // VARCHAR2(150)单据编号
    result[17] = ht.get("fbizdate").toString(); // TimeStamp(6)业务日期
    result[18] = ht.get("fcreatetime").toString(); // TimeStamp(6)创建时间
    result[19] = ht.get("flastupdatetime").toString(); // TimeStamp(6)最后修改时间
    result[20] = new BigDecimal(ht.get("fccsid").toString()); // number(28)CCS单据头ID
    result[21] = new BigDecimal(ht.get("fccsstatus").toString()); // number(4)编辑状态
    result[22] = new BigDecimal(ht.get("fccsread").toString()); // number(4)CCS是否已读取
    result[23] = new BigDecimal(ht.get("fexecstatus").toString());// number(4)执行状态
    result[24] = String.valueOf(ht.get("fexecdescription")); // VARCHAR2(2000)异常原因
    result[25] = ht.get("finvoicenum").toString(); // VARCHAR2(150)CCS发票号

    structs[i] = new STRUCT(structdesc, conn, result);
   }

   ArrayDescriptor arraydesc = new ArrayDescriptor(ora_array, conn);
   list = new ARRAY(arraydesc, conn, structs);
  }

  return list;

 }

 /**
  * 将java结果集合转化成oracle自定义类型集合
  *
  * @param ora_type
  *            Oracle自定义Object TYPE
  * @param ora_array
  *            Oracle自定义Table Type
  * @param alist
  *            传输数据结果集
  * @param conn
  *            数据连接
  * @return 根据Oracle自定义类型包装转化后的结果集
  * @throws Exception
  */
 private ARRAY getLine_Array(String ora_type, String ora_array,
   ArrayList alist, Connection conn) throws Exception {

  ARRAY list = null;

  if (alist != null && alist.size() > 0) {

   StructDescriptor structdesc = new StructDescriptor(ora_type, conn);
   STRUCT[] structs = new STRUCT[alist.size()];
   Object[] result = null;

   for (int i = 0; i < alist.size(); i++) {
    result = new Object[15];
    Hashtable ht = (Hashtable) alist.get(i);

    result[0] = new BigDecimal(ht.get("fccsentryid").toString());
    result[1] = new BigDecimal(ht.get("fccsid").toString());
    result[2] = ht.get("fmaterialnum").toString();
    result[3] = ht.get("fexpenseitemid").toString();
    result[4] = ht.get("fmeasureunitid").toString();
    result[5] = ht.get("fremark").toString();
    result[6] = new BigDecimal(ht.get("fqty").toString());
    result[7] = new BigDecimal(ht.get("ftaxprice").toString());
    result[8] = new BigDecimal(ht.get("ftaxrate").toString());
    result[9] = new BigDecimal(ht.get("ftaxamount").toString());
    result[10] = new BigDecimal(ht.get("famount").toString());
    result[11] = ht.get("faccountid").toString();
    result[12] = new BigDecimal(ht.get("fseq").toString());
    result[13] = new BigDecimal(ht.get("fisdiscount").toString());
    result[14] = new BigDecimal(ht.get("fispresent").toString());

    structs[i] = new STRUCT(structdesc, conn, result);
   }

   ArrayDescriptor arraydesc = new ArrayDescriptor(ora_array, conn);
   list = new ARRAY(arraydesc, conn, structs);
  }

  return list;

 }


二、ORACL部分
2.1 定义Type
CREATE OR REPLACE TYPE type_ap AS OBJECT
--定义应付单对象类型。by kingdee 殷明柳 2011-03-11
(
  FBillDate                 VARCHAR2(150), --  单据日期
  FAsstActType              VARCHAR2(150), --  往来户类型
  FAsstActNumber            VARCHAR2(150), --  往来户编码
  FAsstActName              VARCHAR2(750), --  往来户名称
  FBillStatus               number(4), --  单据状态
  FBillType                 number(4), --  单据类型
  FIsTransBill              number(4), --  是否转移生成单据
  FSourceBillType           number(4), --  来源单据类型
  FAsstActID_SourceBill     VARCHAR2(150), --  来源单往来户
  FAsstActTypeID_SourceBill VARCHAR2(150), --  来源单往来类型
  FIsReverseBill            number(4), --  是否为冲销单据
  FCurrencyID               VARCHAR2(150), --  币别
  FExchangeRate             number(28, 10), --  汇率(默认1)
  FAbstractName             varchar2(2000), --  摘要
  FCompanyID                VARCHAR2(150), --  公司
  FIsInTax                  number(4), --  是否含税
  Fnumber                   VARCHAR2(150), --  单据编号
  FBizDate                  VARCHAR2(150), --  业务日期
  FCreateTime               VARCHAR2(150), --  创建时间
  FLastUpdateTime           VARCHAR2(150), --  最后修改时间
  FCCSID                    number(28), --  CCS单据头ID
  FCCSStatus                number(4), --  编辑状态
  FCCSREAD                  number(4), --  CCS是否已读取
  FExecStatus               number(4), --  执行状态
  FExecDescription          VARCHAR2(2000), --  异常原因
  FInvoiceNum               VARCHAR2(150) --  CCS发票号
)

CREATE OR REPLACE TYPE type_apen AS OBJECT
--定义应付单分录对象类型。by kingdee 殷明柳 2011-03-11
(
  FCCSEntryID    number(28), --  CCS单据体ID
  FCCSID         number(28), --  CCS单据头ID
  FmaterialNum   VARCHAR2(150), --  物料编码
  FExpenseItemID VARCHAR2(150), --  费用项目
  FMeasureUnitID VARCHAR2(150), --  计量单位编码
  Fremark        VARCHAR2(350), --  备注
  FQty           number(28, 10), --  数量
  FTaxPrice      number(28, 10), --  含税单价
  FTaxRate       number(28, 10), --  税率
  FTaxAmount     number(28, 10), --  税额
  FAmount        number(28, 10), --  金额
  FAccountID     VARCHAR2(150), --  应付科目
  FSeq           number(28), --  单据分录序列号
  Fisdiscount    number(4), --  是否票折
  Fispresent     number(4) --  是否赠品
)

2.2定义Type 数组
CREATE OR REPLACE TYPE array_ap AS TABLE OF type_ap

CREATE OR REPLACE TYPE array_apen AS TABLE OF type_apen

2.3存储过程
CREATE OR REPLACE PROCEDURE p_ct_ccs_APOtherBill_verify(v_ap            array_ap, --表头
                                                        v_apen          array_apen, --分录
                                                        v_execstatus    out number, --执行状态(1失败,2成功)
                                                        v_return_reason out varchar2) IS
  --应付校验 --by kingdee YML 20110308
  --表头字段
  v_FBillDate                 ct_ccs_APOtherBill.Fbilldate%TYPE; --单据日期
  v_FAsstActType              ct_ccs_APOtherBill.FAsstActType%TYPE; --往来户类型(供应商)
  v_FAsstActNumber            ct_ccs_APOtherBill.FAsstActNumber%TYPE; --往来户编码
  v_FAsstActName              ct_ccs_APOtherBill.FAsstActName%TYPE; --往来户名称
  v_FBillStatus               ct_ccs_APOtherBill.FBillStatus%TYPE; --单据状态(默认“2 提交”状态)
  v_FBillType                 ct_ccs_APOtherBill.FBillType%TYPE; --单据类型(201其他应付单;202采购发票;203采购费用发票;204应付借贷项调整单)
  v_FIsTransBill              ct_ccs_APOtherBill.FIsTransBill%TYPE; --应收:债权转移 应付:债务转移
  v_FSourceBillType           ct_ccs_APOtherBill.FSourceBillType%TYPE; --来源单据类型(0采购发票;9其他应付单;10采购费用发票;14代理业务单(应付);213应付借贷项调整单)
  v_FAsstActID_SourceBill     ct_ccs_APOtherBill.FAsstActID_SourceBill%TYPE; --来源单往来户
  v_FAsstActTypeID_SourceBill ct_ccs_APOtherBill.FAsstActTypeID_SourceBill%TYPE; --来源单往来类型(客户、供应商)
  v_FIsReverseBill            ct_ccs_APOtherBill.FIsReverseBill%TYPE; --是否为冲销单据
  v_FCurrencyID               ct_ccs_APOtherBill.FCurrencyID%TYPE; --币别(默认RMB)
  v_FExchangeRate             ct_ccs_APOtherBill.FExchangeRate%TYPE; --汇率(默认1)
  v_FAbstractName             ct_ccs_APOtherBill.FAbstractName%TYPE; --摘要
  v_FCompanyID                ct_ccs_APOtherBill.FCompanyID%TYPE; --公司(对应CCS的Organization_Id)
  v_FIsInTax                  ct_ccs_APOtherBill.FIsInTax%TYPE; --是否含税
  v_Fnumber                   ct_ccs_APOtherBill.Fnumber%TYPE; --单据编号
  v_FBizDate                  ct_ccs_APOtherBill.Fbizdate%TYPE; --业务日期
  v_FCreateTime               ct_ccs_APOtherBill.Fcreatetime%TYPE; --创建时间
  v_FLastUpdateTime           ct_ccs_APOtherBill.Flastupdatetime%TYPE; --最后修改时间
  v_FCCSID                    ct_ccs_APOtherBill.FCCSID%TYPE; --CCS单据头ID
  v_FCCSStatus                ct_ccs_APOtherBill.FCCSStatus%TYPE; --编辑状态(0表示I,1表示U,2表示D)
  v_FCCSREAD                  ct_ccs_APOtherBill.FCCSREAD%TYPE; --CCS是否已读取(0未读取,1已读取)
  v_FExecStatus               ct_ccs_APOtherBill.FExecStatus%TYPE; --执行状态:0未执行,1失败, 2成功,3作废
  v_FExecDescription          ct_ccs_APOtherBill.FExecDescription%TYPE; --异常原因
  v_FInvoiceNum               ct_ccs_APOtherBill.FInvoiceNum%TYPE; --CCS发票号
  --分录字段
  v_FCCSEntryID    ct_ccs_APOtherBillentry.FCCSEntryID%TYPE; --CCS单据体ID
  v_FCCSPARENTID   ct_ccs_APOtherBillentry.FCCSID%TYPE; --CCS单据头ID
  v_FmaterialNum   ct_ccs_APOtherBillentry.FmaterialNum%TYPE; --物料编码
  v_FExpenseItemID ct_ccs_APOtherBillentry.FExpenseItemID%TYPE; --费用项目
  v_FMeasureUnitID ct_ccs_APOtherBillentry.FMeasureUnitID%TYPE; --计量单位编码
  v_Fremark        ct_ccs_APOtherBillentry.Fremark%TYPE; --备注
  v_FQty           ct_ccs_APOtherBillentry.FQty%TYPE; --开票数量
  v_FTaxPrice      ct_ccs_APOtherBillentry.FTaxPrice%TYPE; --含税单价=(税率+1)*单价
  v_FTaxRate       ct_ccs_APOtherBillentry.FTaxRate%TYPE; --默认为17,可以手工录入,不能为负值
  v_FTaxAmount     ct_ccs_APOtherBillentry.FTaxAmount%TYPE; --税额=金额*税率
  v_FAmount        ct_ccs_APOtherBillentry.FAmount%TYPE; --金额=实际含税单价*数量
  v_FAccountID     ct_ccs_APOtherBillentry.FAccountID%TYPE; --应付科目
  v_FSeq           ct_ccs_APOtherBillentry.FSeq%TYPE; --单据分录序列号(定义为序列属性即使用{seq})
  v_Fisdiscount    ct_ccs_APOtherBillentry.Fisdiscount%TYPE; --是否票折(0否,1是)
  v_Fispresent     ct_ccs_APOtherBillentry.Fispresent%TYPE; --是否赠品(0否,1是)

  --记录EAS业务表已存在对应记录的数量
  v_count1 number(10);
  --记录EAS业务表已存在对应记录的数量
  v_count2 number(10);
  --记录EAS业务表已存在对应记录的数量
  v_count3 number(10);

  --提示行数
  v_msg varchar2(100);

  -- 获取异常原因
  v_ErrText VARCHAR2(500);
  --记录异常字段
  v_execreason VARCHAR2(2000);

BEGIN
  BEGIN
    v_msg := '第 ';
    FOR h IN v_ap.FIRST .. v_ap.LAST LOOP
      v_FBillDate                 := case when v_ap(h).FBillDate is not null then to_date(v_ap(h).FBillDate, 'yyyy-mm-dd hh24:mi:ss') else null end; --单据日期
      v_FAsstActType              := v_ap(h).FAsstActType; --往来户类型
      v_FAsstActNumber            := v_ap(h).FAsstActNumber; --往来户编码
      v_FAsstActName              := v_ap(h).FAsstActName; --往来户名称
      v_FBillStatus               := v_ap(h).FBillStatus; --单据状态
      v_FBillType                 := v_ap(h).FBillType; --单据类型
      v_FIsTransBill              := v_ap(h).FIsTransBill; --是否转移生成单据
      v_FSourceBillType           := v_ap(h).FSourceBillType; --来源单据类型
      v_FAsstActID_SourceBill     := v_ap(h).FAsstActID_SourceBill; --来源单往来户
      v_FAsstActTypeID_SourceBill := v_ap(h).FAsstActTypeID_SourceBill; --来源单往来类型
      v_FIsReverseBill            := v_ap(h).FIsReverseBill; --是否为冲销单据
      v_FCurrencyID               := v_ap(h).FCurrencyID; --币别
      v_FExchangeRate             := v_ap(h).FExchangeRate; --汇率(默认1)
      v_FAbstractName             := v_ap(h).FAbstractName; --摘要
      v_FCompanyID                := v_ap(h).FCompanyID; --公司
      v_FIsInTax                  := v_ap(h).FIsInTax; --是否含税
      v_Fnumber                   := v_ap(h).Fnumber; --单据编号
      v_FBizDate                  := case when v_ap(h).FBizDate is not null then to_date(v_ap(h).FBizDate, 'yyyy-mm-dd hh24:mi:ss') else null end; --业务日期
      v_FCreateTime               := case when v_ap(h).FCreateTime is not null then to_date(v_ap(h).FCreateTime, 'yyyy-mm-dd hh24:mi:ss') else null end; --创建时间
      v_FLastUpdateTime           := case when v_ap(h).FLastUpdateTime is not null then to_date(v_ap(h).FLastUpdateTime, 'yyyy-mm-dd hh24:mi:ss') else null end; --最后修改时间
      v_FCCSID                    := v_ap(h).FCCSID; --CCS单据头ID
      v_FCCSStatus                := v_ap(h).FCCSStatus; --编辑状态
      v_FCCSREAD                  := v_ap(h).FCCSREAD; --CCS是否已读取
      v_FExecStatus               := v_ap(h).FExecStatus; --执行状态
      v_FExecDescription          := v_ap(h).FExecDescription; --异常原因
      v_FInvoiceNum               := v_ap(h).FInvoiceNum; --CCS发票号
   
      --校验公共参数
      v_execreason := f_ct_ccs_verify(v_FCompanyID,
                                      v_FBizDate,
                                      v_FCCSID,
                                      v_Fnumber,
                                      v_FCurrencyID);
   
      --校验往来户类型不为空
      if v_FAsstActType is null then
        v_execreason := v_execreason || '往来户类型为空;';
      else
        select count(1)
          into v_count1
          from t_Bd_Asstacttype
         where fname_l2 = v_FAsstActType;
        if v_count1 = 0 then
          v_execreason := v_execreason || v_FAsstActType ||
                          '往来户类型在EAS业务表不存在;';
        end if;
      end if;
      --校验往来户编码不为空
      if v_FAsstActNumber is null then
        v_execreason := v_execreason || '供应商编码为空;';
      elsif v_FAsstActNumber is not null then
        select count(1)
          into v_count1
          from t_bd_supplier
         where fnumber = v_FAsstActNumber;
        if v_count1 = 0 then
          v_execreason := v_execreason || v_FAsstActNumber ||
                          '供应商编码在EAS业务表不存在;';
        end if;
      end if;
   
      --校验往来户名称不为空
      if v_FAsstActName is null then
        v_execreason := v_execreason || '供应商名称为空;';
      end if;
      --校验分录
      FOR i IN v_apen.FIRST .. v_apen.LAST LOOP
        v_FCCSEntryID    := v_apen(i).FCCSEntryID; --CCS单据体ID
        v_FCCSParentID   := v_apen(i).FCCSID; --CCS单据头ID
        v_FmaterialNum   := v_apen(i).FmaterialNum; --物料编码
        v_FExpenseItemID := v_apen(i).FExpenseItemID; --费用项目
        v_FMeasureUnitID := v_apen(i).FMeasureUnitID; --计量单位编码
        v_Fremark        := v_apen(i).Fremark; --备注
        v_FQty           := v_apen(i).FQty; --数量
        v_FTaxPrice      := v_apen(i).FTaxPrice; --含税单价
        v_FTaxRate       := v_apen(i).FTaxRate; --税率
        v_FTaxAmount     := v_apen(i).FTaxAmount; --税额
        v_FAmount        := v_apen(i).FAmount; --金额
        v_FAccountID     := v_apen(i).FAccountID; --应付科目
        v_FSeq           := v_apen(i).FSeq; --单据分录序列号
        v_Fisdiscount    := v_apen(i).Fisdiscount; --是否票折
        v_Fispresent     := v_apen(i).Fispresent; --是否赠品
     
        /*---------判断字段是否为空 是否在EAS中存在---------*/
     
        if v_FCCSEntryID is null then
          v_execreason := v_execreason || v_msg || v_FSeq ||
                          ' 行CCS单据体ID为空;';
        end if;
        if v_FCCSParentID is null then
          v_execreason := v_execreason || v_msg || v_FSeq ||
                          ' 行CCS单据头ID为空;';
        end if;
        if v_Fqty is null then
          v_execreason := v_execreason || v_msg || v_FSeq || ' 行数量为空;';
        end if;
        if v_FTaxPrice is null then
          v_execreason := v_execreason || v_msg || v_FSeq || ' 行含税单价为空;';
        end if;
        if v_FAmount is null then
          v_execreason := v_execreason || v_msg || v_FSeq || ' 行金额为空;';
        end if;
        if v_FSeq is null then
          v_execreason := v_execreason || '分录序列号为空;';
        end if;
        if v_FBillType = '202' then
          select count(1)
            into v_count3
            from t_bd_material
           where fnumber = v_FMaterialNum;
          if v_count3 < 1 then
            v_execreason := v_execreason || v_msg || v_FSeq || ' 行' ||
                            v_FMaterialNum || '物料编码在EAS业务表中不存在;';
          end if;
        end if;
        if v_FBillType = '201' then
          select count(1)
            into v_count3
            from t_bd_accountview
           where fnumber = v_FAccountID;
          if v_count3 < 1 then
            v_execreason := v_execreason || v_msg || v_FSeq || ' 行' ||
                            v_FAccountID || '科目在EAS业务表中不存在;';
          end if;
        end if;
        if v_execreason is null then
          --分录
          insert into ct_ccs_apotherbillentry
            (FCCSEntryID, --CCS单据体ID
             FCCSID, --CCS单据头ID
             FmaterialNum, --物料编码
             FExpenseItemID, --费用项目
             FMeasureUnitID, --计量单位编码
             Fremark, --备注
             FQty, --数量
             FTaxPrice, --含税单价
             FTaxRate, --税率
             FTaxAmount, --税额
             FAmount, --金额
             FAccountID, --应付科目
             FSeq, --单据分录序列号
             Fisdiscount, --是否票折
             Fispresent --是否赠品
             )
          values
            (v_FCCSEntryID, --CCS单据体ID
             v_FCCSID, --CCS单据头ID
             v_FmaterialNum, --物料编码
             v_FExpenseItemID, --费用项目
             v_FMeasureUnitID, --计量单位编码
             v_Fremark, --备注
             v_FQty, --数量
             v_FTaxPrice, --含税单价
             v_FTaxRate, --税率
             v_FTaxAmount, --税额
             v_FAmount, --金额
             v_FAccountID, --应付科目
             v_FSeq, --单据分录序列号
             v_Fisdiscount, --是否票折
             v_Fispresent --是否赠品
             );
        /*else
          /*delete from ct_ccs_apotherbillentry apen
           where apen.fccsid = v_FCCSID;*/*/
        end if;
      end loop;
   
      --如果不能存在异常,在向中间表插入数据
      --表头
      if v_execreason is null then
        insert into ct_ccs_apotherbill
          (FBillDate, --单据日期
           FAsstActType, --往来户类型
           FAsstActNumber, --往来户编码
           FAsstActName, --往来户名称
           FBillStatus, --单据状态
           FBillType, --单据类型
           FIsTransBill, --是否转移生成单据
           FSourceBillType, --来源单据类型
           FAsstActID_SourceBill, --来源单往来户
           FAsstActTypeID_SourceBill, --来源单往来类型
           FIsReverseBill, --是否为冲销单据
           FCurrencyID, --币别
           FExchangeRate, --汇率(默认1)
           FAbstractName, --摘要
           FCompanyID, --公司
           FIsInTax, --是否含税
           Fnumber, --单据编号
           FBizDate, --业务日期
           FCreateTime, --创建时间
           FLastUpdateTime, --最后修改时间
           FCCSID, --CCS单据头ID
           FCCSStatus, --编辑状态
           FCCSREAD, --CCS是否已读取
           FExecStatus, --执行状态
           FExecDescription, --异常原因
           FInvoiceNum --CCS发票号
           )
        values
          (v_FBillDate,
           v_FAsstActType, --往来户类型
           v_FAsstActNumber, --往来户编码
           v_FAsstActName, --往来户名称
           v_FBillStatus, --单据状态
           v_FBillType, --单据类型
           v_FIsTransBill, --是否转移生成单据 
           v_FSourceBillType, --来源单据类型
           v_FAsstActID_SourceBill, --来源单往来户
           v_FAsstActTypeID_SourceBill, --来源单往来类型 
           v_FIsReverseBill, --是否为冲销单据
           v_FCurrencyID, --币别
           v_FExchangeRate, --汇率(默认1) 
           v_FAbstractName, --摘要
           v_FCompanyID, --公司 
           v_FIsInTax, --是否含税 
           v_Fnumber, --单据编号
           v_FBizDate,
           v_FCreateTime,
           v_FLastUpdateTime,
           v_FCCSID, --CCS单据头ID 
           v_FCCSStatus, --编辑状态 
           v_FCCSREAD, --CCS是否已读取 
           v_FExecStatus, --执行状态
           v_FExecDescription, --异常原因 
           v_FInvoiceNum --CCS发票号 
           );
        --从中间表取数据,生成业务表数据
        p_ct_ccs_apotherbill(v_FCCSID);
      end if;
    end loop;
    select count(1)
      into v_execStatus
      from ct_ccs_apotherbill ap
     where ap.fccsid = v_FCCSID;
    if v_execStatus > 0 then
      --返回执行状态到CCS
      select distinct ap.fexecstatus
        into v_execStatus
        from ct_ccs_apotherbill ap
       where ap.fccsid = v_FCCSID;
      if v_execstatus = 1 then
        select fexecdescription
          into v_ErrText
          from ct_ccs_apotherbill
         where fccsid = v_FCCSID;
        --异常原因
        v_execreason := v_execreason || v_ErrText;
      end if;
    else
      v_execStatus := 1;
    end if;
  EXCEPTION
    --捕捉其他异常,并获得 捕获异常的内容
    WHEN OTHERS THEN
      v_ErrText := SUBSTR(SQLERRM, 1, 500);
      --异常原因
      v_execreason := v_execreason || v_ErrText;
  END;
  --返回异常原因到CCS
  v_return_reason := v_execreason;

END p_ct_ccs_APOtherBill_verify;

你可能感兴趣的:(oracle)