/**
 * Copyright (c) 2006-2006 System Integrator Corporation.
 *                 All Rights Reserved.
 */
package jp.co.sint.basic;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.Collection;

import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Category;
import jp.co.sint.config.SIConfig;
import jp.co.sint.database.SIDBAccessException;
import jp.co.sint.database.SIDBUtil;
import jp.co.sint.tools.SICheckDataConf;
import jp.co.sint.tools.SICheckValid;
import jp.co.sint.tools.SICustomError;
import jp.co.sint.tools.SICustomErrors;
import jp.co.sint.tools.SIURLParameter;
import jp.co.sint.tools.SIUtil;

/**
 * @version $Id: SIPayment.java,v 1.0 2006/03/29 Exp $
 * @author  入金関連を処理します。
 * <br>Description:
 * <p>History</p>
 * <p>Author&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Reason</p>
 *  ============&nbsp;&nbsp;&nbsp;==========&nbsp;&nbsp;===========================<br>
 * Hong.M.J        2006/03/29 12:20:42  Original
 */
public class SIPayment extends SIBasic {
  
  //ログ用のインスタンスの生成
  private static Category log=Category.getInstance(SIConfig.SILOG4J_WEBSHOP_CATEGORY_NAME);
  
  /**基本データ関連変数**/
  //受注番号
  private String orderCode = "";
  //入金番号
  private String paymentNumber = "";
  //入金金額
  private String paymentPrice = "0";
  //入金手数料
  private String paymentFee = "0";
  //入金種別
  private String paymnetType = "";
  //入金予定日
  private String expectedPaymentDate = "";
  //入金日
  private String paymentDate = "";
  //請求書発行日
  private String billIssuedDate = "";
  //領収書発行日
  private String receiptIssuedDate = "";
  //入金総額
  private String totalPaymentPrice = "0";
  //商品合計金額
  private String totalPrice = "0";
  //未入金額残高
  private String totalBalance = "0";
  //支払状態(入金状態)
  private String receiptFlg = "0";
  //合計入金予定額(入金明細の金額合計)
  private String expectedTotalPaymentPrice = "0";
  //受注日
  private String orderinitDate = "";
  //ステータス
  private String status = "";
  //摘要
  private String remarks = "";
  
  /**更新用の配列**/
  //受注番号
  private String[] orderCodeUpdate = new String[0];
  //入金番号
  private String[] paymentNumberUpdate = new String[0];
  //入金金額
  private String[] paymentPriceUpdate = new String[0];
  //入金手数料
  private String[] paymentFeeUpdate = new String[0];
  //入金種別
  private String[] paymnetTypeUpdate = new String[0];
  //入金予定日
  private String[] expectedPaymentDateUpdate = new String[0];
  //入金日
  private String[] paymentDateUpdate = new String[0];
  //入金確認メールか入金督促メールか
  private String mailType = "";
  //メール送信フラグ
  private String mailSendFlg = "0";
  
  /**
   * @return billIssuedDate を戻します。
   */
  public String getBillIssuedDate() {
    return billIssuedDate;
  }
  
  /**
   * @param billIssuedDate billIssuedDate を設定。
   */
  public void setBillIssuedDate(String billIssuedDate) {
    this.billIssuedDate = billIssuedDate;
  }
  
  /**
   * @return expectedPaymentDate を戻します。
   */
  public String getExpectedPaymentDate() {
    return expectedPaymentDate;
  }
  
  /**
   * @param expectedPaymentDate expectedPaymentDate を設定。
   */
  public void setExpectedPaymentDate(String expectedPaymentDate) {
    this.expectedPaymentDate = expectedPaymentDate;
  }
  
  /**
   * @return orderCode を戻します。
   */
  public String getOrderCode() {
    return orderCode;
  }
  
  /**
   * @param orderCode orderCode を設定。
   */
  public void setOrderCode(String orderCode) {
    this.orderCode = orderCode;
  }
  
  /**
   * @return paymentDate を戻します。
   */
  public String getPaymentDate() {
    return paymentDate;
  }
  
  /**
   * @param paymentDate paymentDate を設定。
   */
  public void setPaymentDate(String paymentDate) {
    this.paymentDate = paymentDate;
  }
  
  /**
   * @return paymentFee を戻します。
   */
  public String getPaymentFee() {
    return paymentFee;
  }
  
  /**
   * @param paymentFee paymentFee を設定。
   */
  public void setPaymentFee(String paymentFee) {
    if (SIUtil.isNull(paymentFee)) paymentFee="0";
    this.paymentFee=SIUtil.changeTo(paymentFee.trim(),this.encode);
  }
  
  /**
   * @return paymentNumber を戻します。
   */
  public String getPaymentNumber() {
    return paymentNumber;
  }
  
  /**
   * @param paymentNumber paymentNumber を設定。
   */
  public void setPaymentNumber(String paymentNumber) {
    this.paymentNumber = paymentNumber;
  }
  
  /**
   * @return paymentPrice を戻します。
   */
  public String getPaymentPrice() {
    return paymentPrice;
  }
  
  /**
   * @param paymentPrice paymentPrice を設定。
   */
  public void setPaymentPrice(String paymentPrice) {
    if (SIUtil.isNull(paymentPrice)) paymentPrice="0";
    this.paymentPrice=SIUtil.changeTo(paymentPrice.trim(),this.encode);
  }
  
  /**
   * @return paymnetType を戻します。
   */
  public String getPaymnetType() {
    return paymnetType;
  }
  
  /**
   * @param paymnetType paymnetType を設定。
   */
  public void setPaymnetType(String paymnetType) {
    this.paymnetType = paymnetType;
  }
  
  /**
   * @return receiptIssuedDate を戻します。
   */
  public String getReceiptIssuedDate() {
    return receiptIssuedDate;
  }
  
  /**
   * @param receiptIssuedDate receiptIssuedDate を設定。
   */
  public void setReceiptIssuedDate(String receiptIssuedDate) {
    this.receiptIssuedDate = receiptIssuedDate;
  }
  
  /**
   * @return status を戻します。
   */
  public String getStatus() {
    return status;
  }
  
  /**
   * @param status status を設定。
   */
  public void setStatus(String status) {
    this.status = status;
  }
  
  /**
   * @return orderCodeUpdate を戻します。
   */
  public String[] getOrderCodeUpdate() {
    return orderCodeUpdate;
  }
  
  /**
   * @param orderCodeUpdate orderCodeUpdate を設定。
   */
  public void setOrderCodeUpdate(String[] orderCodeUpdate) {
    this.orderCodeUpdate = orderCodeUpdate;
  }
  
  /**
   * @return expectedPaymentDateUpdate を戻します。
   */
  public String[] getExpectedPaymentDateUpdate() {
    return expectedPaymentDateUpdate;
  }
  
  /**
   * @param expectedPaymentDateUpdate expectedPaymentDateUpdate を設定。
   */
  public void setExpectedPaymentDateUpdate(String[] expectedPaymentDateUpdate) {
    this.expectedPaymentDateUpdate = expectedPaymentDateUpdate;
  }
  
  /**
   * @return paymentDateUpdate を戻します。
   */
  public String[] getPaymentDateUpdate() {
    return paymentDateUpdate;
  }
  
  /**
   * @param paymentDateUpdate paymentDateUpdate を設定。
   */
  public void setPaymentDateUpdate(String[] paymentDateUpdate) {
    this.paymentDateUpdate = paymentDateUpdate;
  }
  
  /**
   * @return paymentFeeUpdate を戻します。
   */
  public String[] getPaymentFeeUpdate() {
    return paymentFeeUpdate;
  }
  
  /**
   * @param paymentFeeUpdate paymentFeeUpdate を設定。
   */
  public void setPaymentFeeUpdate(String[] paymentFeeUpdate) {
    this.paymentFeeUpdate = paymentFeeUpdate;
  }
  
  /**
   * @return paymentNumberUpdate を戻します。
   */
  public String[] getPaymentNumberUpdate() {
    return paymentNumberUpdate;
  }
  
  /**
   * @param paymentNumberUpdate paymentNumberUpdate を設定。
   */
  public void setPaymentNumberUpdate(String[] paymentNumberUpdate) {
    this.paymentNumberUpdate = paymentNumberUpdate;
  }
  
  /**
   * @return paymentPriceUpdate を戻します。
   */
  public String[] getPaymentPriceUpdate() {
    return paymentPriceUpdate;
  }
  
  /**
   * @param paymentPriceUpdate paymentPriceUpdate を設定。
   */
  public void setPaymentPriceUpdate(String[] paymentPriceUpdate) {
    this.paymentPriceUpdate = paymentPriceUpdate;
  }
  
  /**
   * @return paymnetTypeUpdate を戻します。
   */
  public String[] getPaymnetTypeUpdate() {
    return paymnetTypeUpdate;
  }
  
  /**
   * @param paymnetTypeUpdate paymnetTypeUpdate を設定。
   */
  public void setPaymnetTypeUpdate(String[] paymnetTypeUpdate) {
    this.paymnetTypeUpdate = paymnetTypeUpdate;
  }
  
  /**
   * @return totalPaymentPrice を戻します。
   */
  public String getTotalPaymentPrice() {
    return totalPaymentPrice;
  }
  
  /**
   * @param totalPaymentPrice totalPaymentPrice を設定。
   */
  public void setTotalPaymentPrice(String totalPaymentPrice) {
    if (SIUtil.isNull(totalPaymentPrice)) totalPaymentPrice="0";
    this.totalPaymentPrice=SIUtil.changeTo(totalPaymentPrice.trim(),this.encode);
  }
  
  /**
   * @return totalBalance を戻します。
   */
  public String getTotalBalance() {
    this.totalBalance = SIUtil.sub(this.getTotalPrice(),this.getTotalPaymentPrice());
    return totalBalance;
  }
  
  /**
   * @param totalBalance totalBalance を設定。
   */
  public void setTotalBalance(String totalBalance) {
    if (SIUtil.isNull(totalBalance)) totalBalance="0";
    this.totalBalance=SIUtil.changeTo(totalBalance.trim(),this.encode);
  }
  
  /**
   * @return totalPrice を戻します。
   */
  public String getTotalPrice() {
    return totalPrice;
  }
  
  /**
   * @param totalPrice totalPrice を設定。
   */
  public void setTotalPrice(String totalPrice) {
    if (SIUtil.isNull(totalPrice)) totalPrice="0";
    this.totalPrice=SIUtil.changeTo(totalPrice.trim(),this.encode);
  }
  
  /**
   * @return receiptFlg を戻します。
   */
  public String getReceiptFlg() {
    long payTotal = 0;
    long priceTotal = 0;
    if(SIUtil.isNotNull(this.getTotalPaymentPrice())){
      payTotal = Long.parseLong(this.getTotalPaymentPrice());
    }
    if(SIUtil.isNotNull(this.getTotalPrice())){
      priceTotal = Long.parseLong(this.getTotalPrice());
    }
    if(payTotal==0&&Long.parseLong(this.getTotalPrice())>0){
      this.receiptFlg = "0";
    }else if(payTotal!=0&&payTotal<priceTotal){
      this.receiptFlg = "1";
    }else if(payTotal>=priceTotal){
      this.receiptFlg = "2";
    }
    return receiptFlg;
  }
  
  /**
   * @param receiptFlg receiptFlg を設定。
   */
  public void setReceiptFlg(String receiptFlg) {
    if (SIUtil.isNull(receiptFlg)) receiptFlg="0";
    this.receiptFlg=SIUtil.changeTo(receiptFlg.trim(),this.encode);
  }
  
  /**
   * @return expectedTotalPaymentPrice を戻します。
   */
  public String getExpectedTotalPaymentPrice() {
    return expectedTotalPaymentPrice;
  }
  
  /**
   * @param expectedTotalPaymentPrice expectedTotalPaymentPrice を設定。
   */
  public void setExpectedTotalPaymentPrice(String expectedTotalPaymentPrice) {
    if (SIUtil.isNull(expectedTotalPaymentPrice)) expectedTotalPaymentPrice="0";
    this.expectedTotalPaymentPrice=SIUtil.changeTo(expectedTotalPaymentPrice.trim(),this.encode);
  }
  
  /**
   * @return mailType を戻します。
   */
  public String getMailType() {
    return mailType;
  }
  
  /**
   * @param mailType mailType を設定。
   */
  public void setMailType(String mailType) {
    this.mailType = mailType;
  }
  
  /**
   * @return mailSendFlg を戻します。
   */
  public String getMailSendFlg() {
    return mailSendFlg;
  }
  
  /**
   * @param mailSendFlg mailSendFlg を設定。
   */
  public void setMailSendFlg(String mailSendFlg) {
    this.mailSendFlg = mailSendFlg;
  }
  
  /**
   * @return orderinitDate を戻します。
   */
  public String getOrderinitDate() {
    return orderinitDate;
  }
  
  /**
   * @param orderinitDate orderinitDate を設定。
   */
  public void setOrderinitDate(String orderinitDate) {
    this.orderinitDate = orderinitDate;
  }
  
  /**
   * @return remarks を戻します。
   */
  public String getRemarks() {
    return remarks;
  }
  
  /**
   * @param remarks remarks を設定。
   */
  public void setRemarks(String remarks) {
    this.remarks = remarks;
  }
  
  public SIPayment(){}
  
  /**
   * <b>init(登録データ)</b>
   * 入力したデータをチェックして、同時にSQLの条件文を作成します。
   * @param lRequest クライアントからのリクエスト
   * @param lUrlParam クライアントからのリクエスト
   * @return なし
   * @throws なし
   */
  public void init(HttpServletRequest lRequest,SIURLParameter lUrlParam){
    this.setEncode(SIConfig.SIENCODE_SHIFT_JIS);
    super.init(lRequest,lUrlParam);
    this.setOrderCode((String)lUrlParam.getParam("orderCode"));//受注番号
    this.setPaymentNumber((String)lUrlParam.getParam("paymentNumber"));//入金番号
    this.setPaymentPrice((String)lUrlParam.getParam("paymentPrice"));//入金金額
    this.setPaymentFee((String)lUrlParam.getParam("paymentFee"));//入金手数料
    this.setPaymnetType((String)lUrlParam.getParam("paymnetType"));//入金種別
    this.setExpectedPaymentDate((String)lUrlParam.getParam("expectedPaymentDate"));//入金予定日
    this.setPaymentDate((String)lUrlParam.getParam("paymentDate"));//入金日
    this.setMailSendFlg((String)lUrlParam.getParam("mailSendFlg"));
    this.setMailType((String)lUrlParam.getParam("mailType"));
    this.setRemarks((String)lUrlParam.getParam("remarks"));//摘要
    this.setTotalPrice((String)lUrlParam.getParam("totalPrice"));
  }
  
  /**
   * <b>initUpdate（更新データ）</b>
   * 入力したデータをチェックして、同時にSQLの条件文を作成します。
   * @param lRequest クライアントからのリクエスト
   * @param lUrlParam クライアントからのリクエスト
   * @return なし
   * @throws なし
   */
  public void initUpdate(HttpServletRequest lRequest,SIURLParameter lUrlParam){
    super.init(lRequest,lUrlParam);
    this.setOrderCode((String)lUrlParam.getParam("orderCode"));//受注番号-->更新対象データ
    this.setPaymentNumber((String)lUrlParam.getParam("paymentNumber"));//入金番号-->更新対象データ
    this.setPaymentNumberUpdate(lRequest.getParameterValues("paymentNumberUpdate"));//入金番号
    this.setPaymentPriceUpdate(lRequest.getParameterValues("paymentPriceUpdate"));//入金金額
    this.setPaymentFeeUpdate(lRequest.getParameterValues("paymentFeeUpdate"));//入金手数料
    this.setPaymnetTypeUpdate(lRequest.getParameterValues("paymnetTypeUpdate"));//入金種別
    this.setExpectedPaymentDateUpdate(lRequest.getParameterValues("expectedPaymentDateUpdate"));//入金予定日
    this.setPaymentDateUpdate(lRequest.getParameterValues("paymentDateUpdate"));//入金日
    this.setMailSendFlg((String)lUrlParam.getParam("mailSendFlg"));
    this.setMailType((String)lUrlParam.getParam("mailType"));
    this.setOrderinitDate((String)lUrlParam.getParam("orderinitDate"));//受注日
    this.setRemarks((String)lUrlParam.getParam("remarks"));//摘要
    this.setTotalPrice((String)lUrlParam.getParam("totalPrice"));
  }
  
  /**
   * <b>validate</b>
   * 入力したデータをチェックする
   * @param lRequest クライアントからのリクエスト
   * @return なし
   * @throws なし
   */
  public boolean validate(HttpServletRequest lRequest){
    SICustomErrors errors=new SICustomErrors();
    
    //入金金額
    SICheckValid.checkValid(errors,"金額",this.getPaymentPrice(),SICheckDataConf.SICHECK_DATA_EMPTY_TYPE);
    SICheckValid.checkValid(errors,"金額",this.getPaymentPrice(),SICheckDataConf.SICHECK_DATA_DIGIT_NEGATIVE_TYPE);
    SICheckValid.checkValid(errors,"金額",this.getPaymentPrice(),SICheckDataConf.SICHECK_DATA_BYTE_LEN_WITHIN_TYPE, 8);
    if(this.getPaymentPrice().trim().equals("0")){
      errors.addError(new SICustomError("input.data.require","金額"));
    }
    //入金種別
    SICheckValid.checkValid(errors,"入金種別",this.getPaymnetType(),SICheckDataConf.SICHECK_DATA_EMPTY_TYPE);
    if(this.getPaymnetType().trim().equals("選択してください")){
      errors.addError(new SICustomError("input.data.require","入金種別"));
    }
    
    //入金予定日・入金日
    if(SIUtil.isNull(this.getExpectedPaymentDate())&&SIUtil.isNull(this.getPaymentDate())){
      errors.addError(new SICustomError("manager.app.paymentDate.check2"));
    }
    
    //入金予定日
    if(SIUtil.isNotNull(this.getPaymentDate())&&SIUtil.isNull(this.getExpectedPaymentDate())) this.setExpectedPaymentDate(this.getPaymentDate());
    SICheckValid.checkValid(errors,"入金予定日",this.getExpectedPaymentDate(),SICheckDataConf.SICHECK_DATA_DATE_TYPE);
    
    //入金日
    SICheckValid.checkValid(errors,"入金日",this.getPaymentDate(),SICheckDataConf.SICHECK_DATA_DATE_TYPE);
    
    //入金手数料
    SICheckValid.checkValid(errors,"入金手数料",this.getPaymentFee(),SICheckDataConf.SICHECK_DATA_DIGIT_NEGATIVE_TYPE);
    
    if (!errors.isEmpty()){
      lRequest.setAttribute(SIConfig.SIERROR_ATTRIBUTE_MESSAGE_KEY,errors);
      return false;
    }else{
      lRequest.removeAttribute(SIConfig.SIERROR_ATTRIBUTE_MESSAGE_KEY);
      return true;
    }
  }
  
  /**
   * <b>validateUpdate</b>
   * 入力したデータをチェックする
   * @param lRequest クライアントからのリクエスト
   * @return なし
   * @throws なし
   */
  public boolean validateUpdate(HttpServletRequest lRequest,Connection lConnection){
    SICustomErrors errors=new SICustomErrors();
    for(int i=0;i<this.getPaymentNumberUpdate().length;i++){
      if(this.getPaymentNumber().equals(this.getPaymentNumberUpdate()[i])){
        //入金金額
        SICheckValid.checkValid(errors,"金額",this.getPaymentPriceUpdate()[i],SICheckDataConf.SICHECK_DATA_EMPTY_TYPE);
        SICheckValid.checkValid(errors,"金額",this.getPaymentPriceUpdate()[i],SICheckDataConf.SICHECK_DATA_DIGIT_NEGATIVE_TYPE);
        SICheckValid.checkValid(errors,"金額",this.getPaymentPriceUpdate()[i],SICheckDataConf.SICHECK_DATA_BYTE_LEN_WITHIN_TYPE, 8);
        if(this.getPaymentPriceUpdate()[i].trim().equals("0")){
          errors.addError(new SICustomError("input.data.require","金額"));
        }
        //入金種別
        SICheckValid.checkValid(errors,"入金種別",this.getPaymnetTypeUpdate()[i],SICheckDataConf.SICHECK_DATA_EMPTY_TYPE);
        if(this.getPaymnetTypeUpdate()[i].trim().equals("選択してください")){
          errors.addError(new SICustomError("input.data.require","入金種別"));
        }
        //入金予定日
        SICheckValid.checkValid(errors,"入金予定日",this.getExpectedPaymentDateUpdate()[i],SICheckDataConf.SICHECK_DATA_EMPTY_TYPE);
        SICheckValid.checkValid(errors,"入金予定日",this.getExpectedPaymentDateUpdate()[i],SICheckDataConf.SICHECK_DATA_DATE_TYPE);
        
        //入金日
        SICheckValid.checkValid(errors,"入金日",this.getPaymentDateUpdate()[i],SICheckDataConf.SICHECK_DATA_DATE_TYPE);
        
        //入金手数料
        SICheckValid.checkValid(errors,"入金手数料",this.getPaymentFeeUpdate()[i],SICheckDataConf.SICHECK_DATA_DIGIT_NEGATIVE_TYPE);
        
        //領収書が発行されたか
        StringBuffer lSqlBuf=new StringBuffer("SELECT receiptissueddate FROM paymenttbl ");
        lSqlBuf.append("  WHERE paymentnumber = ").append(this.getPaymentNumber());
        lSqlBuf.append("  AND ordercode = ").append(this.getOrderCode());
        try {
          if(SIUtil.isNotNull(SIDBUtil.getFirstData(lConnection,lSqlBuf.toString()))){
            errors.addError(new SICustomError("manager.message.bill.receiptCheck"));
          }
        } catch (SIDBAccessException e) {
          e.printStackTrace();
        }
        break;
      }
    }
    if (!errors.isEmpty()){
      lRequest.setAttribute(SIConfig.SIERROR_ATTRIBUTE_MESSAGE_KEY,errors);
      return false;
    }else{
      lRequest.removeAttribute(SIConfig.SIERROR_ATTRIBUTE_MESSAGE_KEY);
      return true;
    }
  }
  
  /**
   * <b>getPaymentNumber</b>
   * 入金番号を取得する
   * @param lConnection
   * @return なし
   * @throws SIDBAccessException
   */
  public String getPaymentNumber(Connection lConnection) throws SIDBAccessException{
    String result = new String("0");
    StringBuffer lSqlBuf=new StringBuffer();
    lSqlBuf.append("SELECT COALESCE(maxpaymentnumber,0)+1 ");
    lSqlBuf.append("FROM paymentheadertbl ");
    lSqlBuf.append("WHERE ordercode=").append(this.getOrderCode());
    result = SIDBUtil.getFirstData(lConnection,lSqlBuf.toString());
    return result;
  }
}