<?php
/*
 * This file is part of INQMAN
 *
 * Copyright(c) 2008 BULLHEAD,INC. ALL RIGHTS RESERVED.
 *
 * http://www.bullhead.co.jp/
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation;
 * either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * 問い合わせ管理のロジッククラス
 * 
 * 
 *
 */
class Inqman_InquiryModel extends Inqman_AbstractDao
{
    /** Columns Define **/
    const ID                  = 'id';
    const NUMBER              = 'number';
    const SUBJECT             = 'subject';
    const RECEIVED_FROM       = 'received_from';
    const CONTENT             = 'content';
    const STATUS              = 'status';
    const PRIORITY            = 'priority';
    const SERVICE_ID          = 'service_id';
    const REGISTRANT_ID       = 'registrant_id';
    
    const CREATE_DATETIME     = 'create_datetime';
    const ACCEPT_DATETIME     = 'accept_datetime';
    const APPROVAL_DATETIME   = 'approval_datetime';
    const ASSIGN_DATETIME     = 'assign_datetime';
    const REPLYLIMIT_DATETIME = 'replylimit_datetime';
    const SUSPENSION_DATETIME = 'suspension_datetime';
    const SOLUTION_DATETIME   = 'solution_datetime';
    const ACCEPTER_ID         = 'accepter_id';
    const OPERATOR_ID         = 'operator_id';
    const PARENT_INQUIRY_ID   = 'parent_inquiry_id';
    const ATTACH_FILES        = 'attach_files';
    
    const STATUS_CODE_UNACCEPT   = '10';
    const STATUS_CODE_UNAPPROVAL = '20';
    const STATUS_CODE_REJECT     = '25';
    const STATUS_CODE_UNASSIGN   = '30';
    const STATUS_CODE_PROCESS    = '40';
    const STATUS_CODE_SUSPEND    = '50';
    const STATUS_CODE_SOLVED     = '80';
    
    const PRIORITY_CODE_HIGH     = '10';
    const PRIORITY_CODE_XHIGH    = '20';
    const PRIORITY_CODE_MIDDLE   = '30';
    const PRIORITY_CODE_XLOW     = '40';
    const PRIORITY_CODE_LOW      = '50';
    
    protected $_name = 't_inquiry';
    
    /**
     * 重要度のオプションリストを取得する
     * 
     * @access public
     * @return 重要度のオプションリストをKEY=コード、VALUE=名前の連想配列で返す
     */
    public function getPriorityOptions()
    {
        $codes = self::getPriorityCodes();
        $translator = Zend_Registry::get('Zend_Translate');
        
        $options = array();
        foreach ($codes as $code) {
            $options[$code] = $translator->translate("inquiry.priority.label.{$code}");
        }
        return $options;
    }
    
    /**
     * 重要度コードを取得する
     * 
     * @access public
     * @return 重要度コードを配列で返す
     */
    public static function getPriorityCodes()
    {
        $priorityCode = array(
            self::PRIORITY_CODE_HIGH,
            self::PRIORITY_CODE_XHIGH,
            self::PRIORITY_CODE_MIDDLE,
            self::PRIORITY_CODE_XLOW,
            self::PRIORITY_CODE_LOW,
        );
        return $priorityCode;
    }
    
    /**
     * 問い合わせステータス（状態）のオプションリストを取得する
     * 
     * @access public
     * @return array 問い合わせステータスをKEY=コード、VALUE=名前の連想配列で返す
     */
    public function getStatusOptions()
    {
        $codes = self::getStatusCodes();
        $translator = Zend_Registry::get('Zend_Translate');
        $options = array();
        foreach ($codes as $code) {
            $options[$code] = $translator->translate("inquiry.status.label.{$code}");
        }
        return $options;
    }
    
    /**
     * 問い合わせステータス（状態）コードを取得する
     * 
     * @access public
     * @return 問い合わせステータス（状態）コードを配列で返す
     */
    public static function getStatusCodes()
    {
        $status_code = array(
            self::STATUS_CODE_PROCESS,
            self::STATUS_CODE_REJECT,
            self::STATUS_CODE_SOLVED,
            self::STATUS_CODE_SUSPEND,
            self::STATUS_CODE_UNACCEPT,
            self::STATUS_CODE_UNAPPROVAL,
            self::STATUS_CODE_UNASSIGN,
        );
        return $status_code;
    }
    
    /** get inquiry info **/
    
    /**
     * IDで指定した問い合わせ情報を取得する
     * 
     * @access public
     * @param integer $id 問い合わせID
     * @return array 問い合わせ情報を連想配列で返す
     */
    public function getOneInquiry($id)
    {
        $data = null;
        if(!empty($id) && !is_array($id)) {
            $db = $this->getAdapter();
            $select = $db->select()
                     ->from(array('i' => 't_inquiry'))
                     ->joinLeft(array('u' => 'm_user'), 'i.operator_id=u.id', array('operator_name' => 'u.name'))
                     ->joinLeft(array('u2' => 'm_user'), 'i.registrant_id=u2.id', array('registrant_name' => 'u2.name'))
                     ->joinLeft(array('u3' => 'm_user'), 'i.accepter_id=u3.id', array('accepter_name' => 'u3.name'))
                     ->joinLeft(array('u4' => 'm_user'), 'i.approver_id=u4.id', array('approver_name' => 'u4.name'))
                     ->where('i.id=?', $id)
            ;
            $this->_logger->info('Inqman_InquiryModel->getOneInquiry : ' . $select->__toString());
            $data = $db->fetchRow($select);
            
            $select = $db->select()
                         ->from(array('ia' => 't_inquiry_attach'))
                         ->where('ia.inquiry_id=?', $id)
            ;
            $this->_logger->info('Inqman_InquiryModel->getOneInquiry : ' . $select->__toString());
            $data['attach_files'] = $db->fetchAll($select);
            
        }
        return $data;
    }
    
    /**
     * サービスIDとサービス内通番で指定した問い合わせ情報を取得する
     * 
     * @access public
     * @param integer $service_id
     * @param integer $number
     * @return array 問い合わせ情報を連想配列で返す
     */
    public function getOneInquiryByNumber($service_id, $number)
    {
        $data = null;
        $db = $this->getAdapter();
        $select = $db->select()
                 ->from(array('i' => 't_inquiry'))
                 ->joinLeft(array('u' => 'm_user'), 'i.operator_id=u.id', array('operator_name' => 'u.name'))
                 ->joinLeft(array('u2' => 'm_user'), 'i.registrant_id=u2.id', array('registrant_name' => 'u2.name'))
                 ->joinLeft(array('u3' => 'm_user'), 'i.accepter_id=u3.id', array('accepter_name' => 'u3.name'))
                 ->joinLeft(array('u4' => 'm_user'), 'i.approver_id=u4.id', array('approver_name' => 'u4.name'))
                 ->where('i.service_id=?', $service_id)
                 ->where('i.number=?', $number)
        ;
        $this->_logger->info('Inqman_InquiryModel->getOneInquiry : ' . $select->__toString());
        $data = $db->fetchRow($select);
        
        $select = $db->select()
                     ->from(array('ia' => 't_inquiry_attach'))
                     ->where('ia.inquiry_id=?', $data['id'])
        ;
        $this->_logger->info('Inqman_InquiryModel->getOneInquiry : ' . $select->__toString());
        $data['attach_files'] = $db->fetchAll($select);

        return $data;
    }
    
    /**
     * 問い合わせ情報を取得する
     * 
     * @param serviceId サービスID
     * @param statusCode ステータスコード
     * @param order ソート順
     * @param offset 取得するデータのオフセット値
     * @param count 取得するデータ数
     * @return array 問い合わせ情報を連想配列で返す
     * 
     */
    public function getInquiriesByServiceId($service_id, $status_code=null, $order=null, $page=null, $rp=null, $criteria=null)
    {
        //ソート順の設定
        $order = $this->_makeOrderString($order);
        
        //取得対象データのステータスを設定
        if ($status_code == null) {
            //指定がないときは、全ステータスを対象とする
            $status_code = self::getStatusCodes();
        }
        
        if (!empty($service_id)) {// && !is_array($service_id)) {

            $status_code = array_map('intval', (array) $status_code);
            $service_id  = array_map('intval', (array) $service_id);
            
            $status_code = implode(',', $status_code);
            $service_id = implode(',', $service_id);
            
            $db = $this->getAdapter();
            $select = $db->select()
                    ->from(array('i' => 't_inquiry'))
                    ->joinLeft(array('u' => 'm_user'), 'i.operator_id=u.id', array('operator_name' => 'u.name'))
                    ->joinLeft(array('u2' => 'm_user'), 'i.registrant_id=u2.id', array('registrant_name' => 'u2.name'))
                     ->joinLeft(array('u3' => 'm_user'), 'i.accepter_id=u3.id', array('accepter_name' => 'u3.name'))
                     ->joinLeft(array('u4' => 'm_user'), 'i.approver_id=u4.id', array('approver_name' => 'u4.name'))
                    ->joinLeft(array('s' => 'm_service'), 'i.service_id=s.id', array('service_name'=>'s.name'))
                    ->where("i.status in ({$status_code})")
                    ->where("service_id in ({$service_id})")
            ;
            
            if ($order !== null) {
                foreach ((array) $order as $str) {
                    $select->order($str);
                }
                $select->order($this->_primary[1] . " asc");
            }
            
            if ($page !== null && $rp !== null) {
                $select->limitPage($page, $rp);
            }
            
            $select = $this->_buildFindQuery($select, $criteria);
            
            $this->_logger->info($select->__toString());
            $data = $db->fetchAssoc($select);
            
            return $data;
        }
        return null;
    }
    
    /**
     * 問い合わせ件数を取得する
     * 
     * @param integer $service_d サービスID
     * @param array $status_code ステータスコード
     * @param array $criteria 抽出条件
     * @return array 問い合わせ情報を連想配列で返す
     * 
     */
    public function getInquiriesDataSizeByServiceId($service_id, $status_code=null, $criteria=null)
    {
        //
        if ($status_code == null) $status_code = self::getStatusCodes();
        
        if (!empty($service_id)){ //&& !is_array($service_id)) {
            
            $status_code = array_map('intval', (array) $status_code);
            $service_id  = array_map('intval', (array) $service_id);
            
            $status_code = implode(',', $status_code);
            $service_id = implode(',', $service_id);
            
            $db = $this->getAdapter();
            $select = $db->select()
                ->from(array('i' => 't_inquiry'), array('count(*)'))
                ->where("i.status in ({$status_code})")
                ->where("service_id in ({$service_id})")
            ;
            
            $select = $this->_buildFindQuery($select, $criteria);
            
            $this->_logger->info($select->__toString());
            
            $size = $db->fetchOne($select);
            
            return $size;
        }
        return 0;
    }
    
    /**
     * 指定したユーザが担当している問い合わせ情報を取得する
     * 
     * @access public
     */
    public function getTakesChargeInquiries($service_id, $operator_id, $order=null, $page=null, $rp=null, $criteria=null)
    {
        $status_codes = array(
                self::STATUS_CODE_PROCESS,
                self::STATUS_CODE_SUSPEND,
        );
        
        $criteria['op_id'] = $operator_id;
        
        return $this->getInquiriesByServiceId($service_id, $status_codes, $order, $page, $rp, $criteria);
    }
    
    /**
     * 指定したユーザが担当している問い合わせ件数を取得する
     * 
     * @access public
     */
    public function getTakesChargeInquiriesDataSize($service_id, $operator_id, $criteria=null)
    {
        $status_codes = array(
                self::STATUS_CODE_PROCESS,
                self::STATUS_CODE_SUSPEND,
        );
        
        $criteria['op_id'] = $operator_id;
        
        return $this->getInquiriesDataSizeByServiceId($service_id, $status_codes, $criteria);
    }
    
    /**
     * 指定したユーザが起票した問い合わせ情報を取得する
     */
    public function getAcceptedInquiries($service_id, $operator_id, $order=null, $page=null, $rp=null, $criteria=null)
    {
        $status_codes = $this->getStatusCodes();
        $criteria['ac_id'] = $operator_id;
        
        return $this->getInquiriesByServiceId($service_id, $status_codes, $order, $page, $rp, $criteria);
    }
    
    /**
     * 指定したユーザが起票した問い合わせ件数を取得する
     * 
     * 
     */
    public function getAcceptedInquiriesDataSize($service_id, $operator_id, $criteria=null)
    {
        $status_codes = $this->getStatusCodes();
        $criteria['ac_id'] = $operator_id;
        
        return $this->getInquiriesDataSizeByServiceId($service_id, $status_codes, $criteria);
    }
    
    /**
     * 派生した問い合わせ情報を取得する
     * 
     * @param inquiry_id 問い合わせID
     * @return 指定した問い合わせから派生した問い合わせ情報を取得する
     */
    public function getDerivatedInquiries($inquiry_id)
    {
        $db = $this->getAdapter();
        
        $select = $db->select()
                     ->from('t_inquiry')
                     ->where('parent_inquiry_id=?', $inquiry_id)
                     ->order('id asc')
        ;
        
        $this->_logger->info('Inqman_InquiryModel->getDerivatedInquiries : ', $select->__toString());
        
        return $db->fetchAll($select);
    }
    
    /**
     * 未起票の問い合わせ情報を取得する
     * 
     * @param serviceId サービスID
     * @param order ソート順
     * @param offset 取得するデータのオフセット値
     * @param count 取得するデータ数
     * @return array 問い合わせ情報を連想配列で返す
     * 
     */
    public function getUnacceptInquiries($service_id, $order=null, $page=null, $rp=null)
    {
        $status_codes = array(
                self::STATUS_CODE_UNACCEPT,
                self::STATUS_CODE_REJECT,
        );
        
        return $this->getInquiriesByServiceId($service_id, $status_codes, $order, $page, $rp);
    }

    /**
     * 未起票の問い合わせ情報総件数を取得する
     * 
     * @param serviceId サービスID
     * @return array 問い合わせ情報を連想配列で返す
     * 
     */
    public function getUnacceptInquiriesTotalCount($service_id)
    {
        $status_codes = array(
                self::STATUS_CODE_UNACCEPT,
                self::STATUS_CODE_REJECT,
        );
        
        return $this->getInquiriesDataSizeByServiceId($service_id, $status_codes);
    }
    
    /**
     * 未承認の問い合わせ情報を取得する
     * 
     * @param serviceId サービスID
     * @param order ソート順
     * @param offset 取得するデータのオフセット値
     * @param count 取得するデータ数
     * @return array 問い合わせ情報の件数を返す
     * 
     */
    public function getUnapprovalInquiries($service_id, $order=null, $page=null, $rp=null)
    {
        $status_codes = array(
                self::STATUS_CODE_UNAPPROVAL,
        );
        
        return $this->getInquiriesByServiceId($service_id, $status_codes, $order, $page, $rp);
    }
    
    /**
     * 未承認の問い合わせ情報総件数取得する
     * 
     * @param serviceId サービスID
     * @return array 問い合わせ情報の件数を返す
     * 
     */
    public function getUnapprovalInquiriesTotalCount($service_id)
    {
        $status_codes = array(
                self::STATUS_CODE_UNAPPROVAL,
        );
        
        return $this->getInquiriesDataSizeByServiceId($service_id, $status_codes);
    }
    
    /**
     * 未解決の問い合わせ情報を取得する
     * 
     * @param serviceId サービスID
     * @param order ソート順
     * @param offset 取得するデータのオフセット値
     * @param count 取得するデータ数
     * @return array 問い合わせ情報を連想配列で返す
     * 
     */
    public function getUnsolvedInquiries($service_id, $order=null, $page=null, $rp=null)
    {
        $status_codes = array(
                self::STATUS_CODE_UNASSIGN,
                self::STATUS_CODE_PROCESS,
                self::STATUS_CODE_SUSPEND,
        );
        
        return $this->getInquiriesByServiceId($service_id, $status_codes, $order, $page, $rp);
    }
    
    /**
     * 未解決の問い合わせ情報総件数を取得する
     * 
     * @param serviceId サービスID
     * @return array 問い合わせ情報の件数を返す
     * 
     */
    public function getUnsolvedInquiriesTotalCount($service_id)
    {
        $status_codes = array(
                self::STATUS_CODE_UNASSIGN,
                self::STATUS_CODE_PROCESS,
                self::STATUS_CODE_SUSPEND,
        );
        
        return $this->getInquiriesDataSizeByServiceId($service_id, $status_codes);
    }
    
    /**
     * 解決済みの問い合わせ情報を取得する
     * 
     * @param serviceId サービスID
     * @param order ソート順
     * @param offset 取得するデータのオフセット値
     * @param count 取得するデータ数
     * @return array 問い合わせ情報を連想配列で返す
     * 
     */
    public function getSolvedInquiries($service_id, $order=null, $page=null, $rp=null)
    {
        $status_codes = array(
                self::STATUS_CODE_SOLVED,
        );
        
        return $this->getInquiriesByServiceId($service_id, $status_codes, $order, $page, $rp);
    }
    
    /**
     * 解決済みの問い合わせ情報件数を取得する
     * 
     * @param serviceId サービスID
     * @return array 問い合わせ情報の件数を返す
     * 
     */
    public function getSolvedInquiriesTotalCount($service_id)
    {
        $status_codes = array(
                self::STATUS_CODE_SOLVED,
        );
        
        return $this->getInquiriesDataSizeByServiceId($service_id, $status_codes);
    }
    
    /**
     * 参照している問い合わせ情報を取得する
     */
    public function getReferenceInquiries($inquiry_id)
    {
        $db = $this->getAdapter();
        $select = $db->select()
                     ->from(array('ir'=>'t_inquiry_reference'))
                     ->joinInner(array('i1'=>'t_inquiry'), 'ir.referenced_inquiry_id=i1.id')
                     ->where('ir.inquiry_id=?', $inquiry_id)
                     ->order('i1.id asc')
        ;
        return $db->fetchAll($select);
    }
    
    /** isXxxxx **/
    
    /**
     * 指定されたユーザが指定された問い合わせの登録者か確認する 
     *
     * 
     */
    public function isRegistrant($inquiry_id, $user_id)
    {
        $count = 0;
        $db = $this->getAdapter();
        $count = $db->fetchOne($db->select()->from('t_inquiry', 'count(*)')->where('registrant_id=?', $user_id)->where('id=?', $inquiry_id));
        
        if ($count > 0)  return true;
        return false;
    }
    
    /**
     * 指定されたユーザが指定された問い合わせの起票者（受付者）か確認する 
     *
     * 
     */
    public function isAccepter($inquiry_id, $user_id)
    {
        $count = 0;
        $db = $this->getAdapter();
        $count = $db->fetchOne($db->select()->from('t_inquiry', 'count(*)')->where('accepter_id=?', $user_id)->where('id=?', $inquiry_id));
        
        if ($count > 0)  return true;
        return false;
    }
    
    /**
     * 指定されたユーザが指定された問い合わせの承認者か確認する 
     *
     * 
     */
    public function isApprover($inquiry_id, $user_id)
    {
        $count = 0;
        $db = $this->getAdapter();
        $count = $db->fetchOne($db->select()->from('t_inquiry', 'count(*)')->where('approver_id=?', $user_id)->where('id=?', $inquiry_id));
        
        if ($count > 0)  return true;
        return false;
    }
    
    /**
     * 指定されたユーザが指定された問い合わせの登録者か確認する 
     *
     * 
     */
    public function isOperator($inquiry_id, $user_id)
    {
        $count = 0;
        $db = $this->getAdapter();
        $count = $db->fetchOne($db->select()->from('t_inquiry', 'count(*)')->where('operator_id=?', $user_id)->where('id=?', $inquiry_id));
        
        if ($count > 0)  return true;
        return false;
    }
    
    /** create **/
    
    /**
     * 問い合わせ情報を登録する
     * 
     * @param mixed $values
     */
    public function createInquiry($values, $attach_files=null)
    {
        $db = $this->getAdapter();
        
        //サービス内通版を取得
        $inquiry_number = $this->_getLastNumberInService($values['service_id']) + 1;
        $values['number'] = $inquiry_number;
        
        //サービスコードを取得
        //$service_code = $db->fetchOne($db->select()->from('m_service', 'service_code')->where('id=?', $values['service_id']));
        //サービス内IDを件名に付与
        //$subject = "[{$service_code}:{$inquiry_number}] " . $subject;
        
        if (empty($values['create_datetime'])) {
            $values['create_datetime'] = date("Y-m-d H:i:s", time());
        }
        
        $db->insert('t_inquiry', $values);
        
        $inquiry_id = $db->lastInsertId('t_inquiry');
        
        $this->registerAttachFiles($inquiry_id, $attach_files);
        
        return $inquiry_id;
    }
    
    /**
     * 添付ファイルを登録する
     * 
     * @access public
     * @param integer $inquiry_id 問い合わせID
     * @param array $attach_files
     */
    public function registerAttachFiles($inquiry_id, $attach_files)
    {
        $db = $this->getAdapter();
        if ($attach_files != null) {
            foreach ((array) $attach_files as $attach_file) {
                $attach_values = array(
                        'inquiry_id'        => $inquiry_id,
                        'name'              => $attach_file['name'],
                        'mime_type'         => $attach_file['type'],
                        'enced_content'     => $attach_file['enced_content'],
                        'register_datetime' => date('Y-m-d H:i:s'),
                );
                $db->insert('t_inquiry_attach', $attach_values);
            }
        }
    }
    
    /** update status **/
    
    /**
     * 問い合わせを承認待ちor割当待ち状態にする
     * 
     */
    public function acceptInquiry($inquiry_id, $values=null)
    {
        $values[self::ID]              = $inquiry_id;
        $values[self::STATUS]          = self::STATUS_CODE_UNAPPROVAL;
        $values[self::ACCEPT_DATETIME] = date("Y-m-d H:i:s", time());
        
        $db = $this->getAdapter();
        $where = array($db->quoteInto('id=?', $inquiry_id));
        $db->update('t_inquiry', $values, $where);
    }
    
    /**
     * 問い合わせを承認状態に更新する
     * 
     */
    public function approveInquiry($inquiry_id, $values=null)
    {
        $values[self::ID]                = $inquiry_id;
        $values[self::STATUS]            = self::STATUS_CODE_UNASSIGN;
        $values[self::APPROVAL_DATETIME] = date("Y-m-d H:i:s", time());
        
        $db = $this->getAdapter();
        $where = array($db->quoteInto('id=?', $inquiry_id));
        $db->update('t_inquiry', $values, $where);
    }
    
    /**
     * 問い合わせを却下状態に更新する
     * 
     */
    public function rejectInquiry($inquiry_id, $values=null)
    {
        $values[self::ID]                = $inquiry_id;
        $values[self::STATUS]            = self::STATUS_CODE_REJECT;
        $values[self::APPROVAL_DATETIME] = date("Y-m-d H:i:s", time());
        
        $db = $this->getAdapter();
        $where = array($db->quoteInto('id=?', $inquiry_id));
        $db->update('t_inquiry', $values, $where);
    }
    
    /**
     * 問い合わせを処理中状態に更新する
     * 
     */
    public function assignOperator($inquiry_id, $operator_id)
    {
        $values = array();
        $values[self::ID]              = $inquiry_id;
        $values[self::STATUS]          = self::STATUS_CODE_PROCESS;
        $values[self::ASSIGN_DATETIME] = date("Y-m-d H:i:s", time());
        $values[self::OPERATOR_ID]     = $operator_id;
        
        $db = $this->getAdapter();
        $where = array($db->quoteInto('id=?', $inquiry_id));
        $db->update('t_inquiry', $values, $where);
    }
    
    /**
     * 回答期限を設定する
     * 
     */
    public function setReplyLimitDatetime($inquiry_id, $datetime)
    {
        if (!empty($datetime)) {
            $datetime = date("Y-m-d H:i:s", $datetime); 
        }
        
        $values = array();
        $values[self::ID]                  = $inquiry_id;
        $values[self::REPLYLIMIT_DATETIME] = $datetime;
        
        $db = $this->getAdapter();
        $where = array($db->quoteInto('id=?', $inquiry_id));
        $db->update('t_inquiry', $values, $where);
    }
    
    /**
     * 担当者を変更する
     */
    public function changeOperator($inquiry_id, $operator_id)
    {
        $values = array();
        $values[self::ID]          = $inquiry_id;
        $values[self::OPERATOR_ID] = $operator_id;
        
        $db = $this->getAdapter();
        $where = array($db->quoteInto('id=?', $inquiry_id));
        $db->update('t_inquiry', $values, $where);
    }
    
    /**
     * ステータスを「保留」にし、保留日時を設定する
     * 
     */
    public function suspendInquiry($inquiry_id, $datetime=null)
    {
        if (empty($datetime)) $datetime = time();
        
        $values = array();
        $values[self::ID]                  = $inquiry_id;
        $values[self::STATUS]              = self::STATUS_CODE_SUSPEND;
        $values[self::SUSPENSION_DATETIME] = date("Y-m-d H:i:s", $datetime);
        
        $db = $this->getAdapter();
        $where = array($db->quoteInto('id=?', $inquiry_id));
        $db->update('t_inquiry', $values, $where);
    }
    
    /**
     * ステータスを「処理中」にし、保留日時を削除する
     * 
     */
    public function resumeInquiry($inquiry_id)
    {
        $values = array();
        $values[self::ID]                  = $inquiry_id;
        $values[self::STATUS]              = self::STATUS_CODE_PROCESS;
        $values[self::SUSPENSION_DATETIME] = null;
        
        $db = $this->getAdapter();
        $where = array($db->quoteInto('id=?', $inquiry_id));
        $db->update('t_inquiry', $values, $where);
    }
    
    /**
     * ステータスを「解決済み」にし、解決日時を設定する
     * 
     */
    public function solutionInqiury($inquiry_id, $datetime=null)
    {
        if (empty($datetime)) $datetime = time();
        
        $values = array();
        $values[self::ID]                = $inquiry_id;
        $values[self::STATUS]            = self::STATUS_CODE_SOLVED;
        $values[self::SOLUTION_DATETIME] = date("Y-m-d H:i:s", $datetime);
        
        $db = $this->getAdapter();
        $where = array($db->quoteInto('id=?', $inquiry_id));
        $db->update('t_inquiry', $values, $where);
    }
    
    /**
     * 指定された問い合わせの派生関係を削除する（親問い合わせIDを削除する）
     * 
     * @param integer $inquiry_id 
     */
    public function removeDerivation($inquiry_id)
    {
        $values = array();
        $values[self::PARENT_INQUIRY_ID] = null;
        
        $db = $this->getAdapter();
        $where = array($db->quoteInto('id=?', $inquiry_id));
        $db->update('t_inquiry', $values, $where);
    }
    
    /**
     * 
     * 
     */
    public function addReference($inquiry_id, $referenced_inquiry_id)
    {
        $db = $this->getAdapter();
        
        $values = array('inquiry_id'=>$inquiry_id, 'referenced_inquiry_id'=>$referenced_inquiry_id);
        $db->insert('t_inquiry_reference', $values);
        
    }
    
    public function removeReference($inquiry_id, $referenced_inquiry_id)
    {
        $db = $this->getAdapter();
        
        $where = array($db->quoteInto('inquiry_id=?',$inquiry_id),
                       $db->quoteInto('referenced_inquiry_id=?', $referenced_inquiry_id));
        $db->delete('t_inquiry_reference', $where);
        
    }
    
    /** Mail Sender **/
    
    /**
     * メール送信処理
     */
    public function sendMail($event_action_id, $criteria)
    {
        //メール送信
        $acl_model          = new Inqman_AclModel();
        $event_model        = new Inqman_EventModel();
        $mailtemplate_model = new Inqman_MailtemplateModel();
        $mail_sender        = new Inqman_MailSender();
        $service_model      = new Inqman_ServiceModel();
        
        //イベント設定取得
        $rows = $event_model->getEvanetActionTarget($criteria['service_id'], $event_action_id);
        
        //サービス情報取得
        $service = $service_model->getOneService($criteria['service_id']);
        $service_code = $service['code'];
        
        //問い合わせ情報取得
        $inquiry = $this->getOneInquiry($criteria['inquiry_id']);
        $inquiry_number = $inquiry['number'];
        
        foreach ($rows as $row) {
            //対象者取得
            $send_to = array();
            $users = (array) $acl_model->getUsersByAuthority($row['authority_id']);
            foreach ($users as $user) {
                if (!empty($user['mailaddress'])) {
                    $send_to[] = $user['mailaddress'];
                }
            }
            
            //システム変数置換
            $subject = $mailtemplate_model->replaceSysvar($row['subject'], $criteria);
            $from    = $mailtemplate_model->replaceSysvar($row['mail_from'], $criteria);
            $content = $mailtemplate_model->replaceSysvar($row['content'], $criteria);
            
            //サービス内IDを件名に付与
            $subject = "[{$service_code}:{$inquiry_number}] " . $subject;
            
            $headers = array(
                    'from'      => $from,
                    'from_name' => $service['name'],
                    'subject'   => $subject,
            );
            $body = $content;
            //$to_list = implode(', ', $send_to);
            
            $mail_sender->sendBroadcastMail($send_to, $headers, $body);
        }
    }
    
    /** local methods **/
    
    /**
     * 検索条件からSQLを構築する
     * 
     * @param mixed $criteria 検索条件
     * @return Zend_DB_Select
     */
    protected function _buildFindQuery($select, $criteria)
    {
        //検索条件の設定
        foreach ((array) $criteria as $field => $cond) {
            
            switch ($field) {
                case 'sbj':
                    if ($cond['mtd']=='equal' && !empty($cond['val'])) {
                        $select->where("i.subject=?", $cond['val']);
                    } elseif($cond['mtd']=='like' && !empty($cond['val'])) {
                        $value = $cond['val'];
                        $select->where("i.subject like ?", "%{$value}%");
                    }
                    break;
                    
                case 'cdt':
                    $sdate = $cond['sd'];
                    $stime = $cond['st'];
                    $edate = $cond['ed'];
                    $etime = $cond['et'];
                    
                    if (!empty($sdate)) {
                        if (empty($stime)) $stime = "00:00";
                        $sdt = "{$sdate} {$stime}";
                        $select->where('create_datetime > ?', $sdt);
                    }
                    
                    if (!empty($edate)) {
                        if (empty($etime)) $etime = "23:59";
                        $edt = "{$edate} {$etime}";
                        $select->where('create_datetime < ?', $edt);
                    }
                    
                    break;
                    
                case 'sts':
                    array_map('intval', (array) $cond);
                    $cond = implode(',', $cond);
                    $select->where("status in ({$cond})");
                    break;
                    
                case 'op_id':
                    if (is_array($cond)) {
                        array_map('intval', (array) $cond);
                        $cond = implode(',', $cond);
                        $select->where("operator_id in ({$cond})");
                    } else {
                        $select->where("operator_id=?", intval($cond));
                    }
                    break;
                case 'ac_id':
                    if (is_array($cond)) {
                        array_map('intval', (array) $cond);
                        $cond = implode(',', $cond);
                        $select->where("accepter_id in ({$cond})");
                    } else {
                        $select->where("accepter_id=?", intval($cond));
                    }
                    break;
                default:
                    break;
            }
        }
        return $select;
    }
    
    /**
     * サービス内通番の最終番号を取得する
     * 
     * @param integer $service_id
     */
    protected function _getLastNumberInService($service_id)
    {
        $db = $this->getAdapter();
        
        $select = $db->select()
                ->from('t_inquiry', array('MAX(number)'))
                ->where('service_id=?', $service_id)
        ;
        $result = $db->fetchOne($select);
        
        if (null === $result) $result = 0;
        
        return $result;
    }
    
    /**
     * ORDER句を生成する
     * 
     * @access protected
     */
    protected function _makeOrderString($order)
    {
        
        if ($order == null) return $order;
        
        list($col, $row) = split("_", $order);
        
        switch (strtolower($col)) {
            case "ctime":
                $col = self::CREATE_DATETIME;
                break;
            case "subject":
                $col = self::SUBJECT;
                break;
            case "from":
                $col = self::RECEIVED_FROM;
                break;
            case "status":
                $col = self::STATUS;
                break;
            case "priority":
                $col = self::PRIORITY;
                break;
            case "createdatetime":
                $col = self::CREATE_DATETIME;
                break;
            case "acceptdatetime":
                $col = self::ACCEPT_DATETIME;
                break;
            case "registrant":
                $col = self::REGISTRANT_ID;
                break;
            case "accepter":
                $col = self::ACCEPTER_ID;
                break;
            case "operator":
                $col = self::OPERATOR_ID;
                break;
            default:
                $col = self::ID;
                break;
        }
        
        if ($row = strtolower($row) == "asc") {
            $row = "asc";
        } else {
            $row = "desc";
        }
            
        return "{$col} {$row}";
    }
        
}