UserControls/MessageInputControl.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Drawing;
using System.Windows.Forms;
using ChatworkBulkSender.Services.Chatwork;
using ChatworkBulkSender.Utils;
using ChatworkBulkSender.Daos;
using ChatworkBulkSender.Dtos;

namespace ChatworkBulkSender.UserControls
{
    public partial class MessageInputControl : AbstractUserControl
    {
        private Constants.SEND_TYPE _sendType;
        // 親への通知用
        public event EventHandler SwitchToMessageConfirm;
        public event EventHandler CloseForm;

        // 画面で設定された情報を保持するクラス
        private BulkSendJobDto _bulkSendJobDto = null;

        public MessageInputControl(Constants.SEND_TYPE sendType)
        {
            InitializeComponent();
            _sendType = sendType;
            Init();
        }

        public BulkSendJobDto GetBulkSendJobDto()
        {
            return _bulkSendJobDto;
        }

        /// <summary>
        /// 送信失敗したデータのみを読み込み、画面上にセットする。
        /// </summary>
        /// <param name="dto"></param>
        public void LoadFailedHistory(int reSendHistoryId)
        {
            // dto作成
            var header = new SendHistoryDao().GetSendHistory(reSendHistoryId);
            var details = new SendHistoryDetailDao().GetSendHistoryDetails(reSendHistoryId);

            // 画面情報セット
            patternDropDownControl1.SetPatternData(header.PatternId);
            sendContentControl1.SetSendContents(header.SendContents);
            sendContentControl1.SetSendTargetOnlyFailed(details);
            if(header.SendType == (int)Constants.SEND_TYPE.REGULAR_SENDING)
            {
                attachmentSelectionControl1.SetPath(header.RegularFolderPath);
            }
            else
            {
                attachmentSelectionControl1.SetPath(header.AdhocAttachmentFilePath);
            }
        }



        private void Init()
        {
            // パターン名称コンボ変更時イベントをセット
            patternDropDownControl1.PatternSelected += SetPatterneData;

            // 不定期送信の場合、レイアウトを調整
            // ※初期状態のレイアウトは定期送信用。
            if (_sendType == Constants.SEND_TYPE.ADHOC_SENDING)
            {
                // タイトル変更
                labelConfig.Text = "不定期送信";
                labelConfig.Size = new Size(180, 30);
                // パターン選択欄を非表示
                patternDropDownControl1.Visible = false;
                // パターン選択欄のあった場所まで、送信内容欄を拡大
                sendContentControl1.Location = new Point(sendContentControl1.Location.X, patternDropDownControl1.Location.Y);
                sendContentControl1.Size = new Size(sendContentControl1.Width, sendContentControl1.Height + patternDropDownControl1.Height);
                // 各ユーザーコントロールを「不定期送信」用に変更
                sendContentControl1.ChangeMode(_sendType);
                attachmentSelectionControl1.ChangeMode(_sendType);
            }
        }

        /// <summary>
        /// 戻るボタン 押下
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnBack_Click(object sender, EventArgs e)
        {
            CloseForm?.Invoke(this, EventArgs.Empty);
        }

        /// <summary>
        /// 送信前チェック処理ボタン 押下
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnConfirm_Click(object sender, EventArgs e)
        {
            // 送信処理に関する情報を作成
            MakeSendInfo();
            // validate
            if (!ValidateBeforeConfirm()) return;
            // 親フォームへ画面遷移リクエスト
            SwitchToMessageConfirm?.Invoke(this, EventArgs.Empty);
        }

        /// <summary>
        /// 送信処理に関する情報を作成
        /// </summary>
        private void MakeSendInfo()
        {
            // 各設定情報を元に作成
            _bulkSendJobDto = new BulkSendJobDto
            {
                SendType = _sendType,
                SendContents = sendContentControl1.GetContents(),
                RegularDestinationSelectType = sendContentControl1.GetTypeOfDestinationSelect(),
                DestinationList = sendContentControl1.GetDestinationList(),
                PatternMaster = patternDropDownControl1.GetSelectedPatternMaster(),
                RegularAttachmentFolderPath = _sendType == Constants.SEND_TYPE.REGULAR_SENDING ? attachmentSelectionControl1.GetPath() : "",
                AdhocAttachmentFilePath = _sendType == Constants.SEND_TYPE.ADHOC_SENDING ? attachmentSelectionControl1.GetPath() : "",
            };
            // 自動選択の場合のみ、送信先リストが添付ファイルが存在する顧客のみとなるように加工する
            if(_bulkSendJobDto.RegularDestinationSelectType == Constants.DESTINAION_SELECT_TYPE.AUTO)
            {
                _bulkSendJobDto.DestinationList = _bulkSendJobDto.DestinationList
                   .Where(c =>
                       !string.IsNullOrEmpty(c.FilePath) &&
                       File.Exists(c.FilePath)
                   )
                   .ToList();
            }
        }

        private bool ValidateBeforeConfirm()
        {
            // エラーメッセージを初期化
            errorMessageBeforeSendControl1.SetErrorMessage("");

            var errors = new List<string>();
            // 【sendContentControl1】
            // 送信内容
            if (string.IsNullOrWhiteSpace(_bulkSendJobDto.SendContents))
            {
                errors.Add("・送信内容が入力されていません。");
            }

            // 送信対象(添付ファイルに関するチェックは後で行う)
            if (_bulkSendJobDto.RegularDestinationSelectType == Constants.DESTINAION_SELECT_TYPE.AUTO)
            {
                // 送信先顧客が1件以上存在するか
                if (_bulkSendJobDto.DestinationList.Count == 0)
                {
                    errors.Add("・送信対象を1つも特定できませんでした。添付ファイル保存場所の設定や、用意したPDFファイルの名前などを確認してください。");
                }
            }
            else if (_bulkSendJobDto.RegularDestinationSelectType == Constants.DESTINAION_SELECT_TYPE.MANUAL)
            {
                // 送信先顧客が1件以上存在するか
                if (_bulkSendJobDto.DestinationList.Count == 0)
                {
                    errors.Add("・送信対象が1つも選択されていません。");
                }
            }
            else
            {
                errors.Add("・自動選択あるいは手動選択を選択してください。");
            }

            // 【attachmentSelectionControl1】
            // 添付フォルダ
            if(_sendType == Constants.SEND_TYPE.REGULAR_SENDING)
            {
                if (string.IsNullOrEmpty(_bulkSendJobDto.RegularAttachmentFolderPath))
                {
                    errors.Add($"・添付ファイル保存場所が未設定です。");
                }
                else if (!Directory.Exists(_bulkSendJobDto.RegularAttachmentFolderPath))
                {
                    errors.Add($"・添付ファイル保存場所に設定されたフォルダが見つかりません。");
                }
            }
            else
            {
                // 不定期送信の場合は添付ファイルを設定する(任意)
                if (string.IsNullOrEmpty(_bulkSendJobDto.AdhocAttachmentFilePath))
                {
                    // 未設定のためチェック不要。
                }
                else if (!File.Exists(_bulkSendJobDto.AdhocAttachmentFilePath))
                {
                    errors.Add($"・添付ファイルが見つかりません。");
                }
            }

            // 【sendContentControl1】
            // 送信対象(添付ファイル関連のチェック)
            if(_bulkSendJobDto.DestinationList != null)
            {
                // ファイルサイズチェック(5MB以上はエラー)
                var oversizeList = _bulkSendJobDto.DestinationList
                    .Where(c =>
                        !string.IsNullOrWhiteSpace(c.FilePath)
                        && File.Exists(c.FilePath)
                        && new FileInfo(c.FilePath).Length >= 5 * 1024 * 1024  // 5MB
                    )
                    .Select(c => c.ManagementNumber.ToString())
                    .ToList();
                if (oversizeList.Any())
                {
                    errors.Add($"・次の管理番号の添付ファイルが5MBを超えています。このツールからアップロードできるファイルサイズ上限は5MBです。:{string.Join(", ", oversizeList)}");
                }
            }
            if (_sendType == Constants.SEND_TYPE.REGULAR_SENDING)
            {
                if (_bulkSendJobDto.RegularDestinationSelectType == Constants.DESTINAION_SELECT_TYPE.AUTO)
                {
                    // 一つの送信先に対して添付ファイルが複数存在しないか
                    var multipleFileList = _bulkSendJobDto.DestinationList
                        .Where(c => c.ExistsMultiplePDF)
                        .Select(c => c.ManagementNumber.ToString())
                        .ToList();
                    if (multipleFileList.Any())
                        errors.Add($"・次の管理番号を含む添付ファイルが複数個見つかりました。:{string.Join(", ", multipleFileList)}");
                }
                else if (_bulkSendJobDto.RegularDestinationSelectType == Constants.DESTINAION_SELECT_TYPE.MANUAL)
                {
                    // 送信先顧客へ送付する添付ファイルが存在するか
                    var noFileList = _bulkSendJobDto.DestinationList
                        .Where(c => string.IsNullOrWhiteSpace(c.FilePath) || !File.Exists(c.FilePath))
                        .Select(c => c.ManagementNumber.ToString())
                        .ToList();
                    if (noFileList.Any())
                        errors.Add($"・次の管理番号を含む添付ファイルが見つかりません。:{string.Join(", ", noFileList)}");
                    // 一つの送信先に対して添付ファイルが複数存在しないか
                    var multipleFileList = _bulkSendJobDto.DestinationList
                        .Where(c => c.ExistsMultiplePDF)
                        .Select(c => c.ManagementNumber.ToString())
                        .ToList();
                    if (multipleFileList.Any())
                        errors.Add($"・次の管理番号を含む添付ファイルが複数個見つかりました。:{string.Join(", ", multipleFileList)}");
                }
            }

            // エラーがあれば表示して終了
            if (errors.Any())
            {
                errorMessageBeforeSendControl1.SetErrorMessage(string.Join("\r\n", errors));
                MessageBoxUtil.ShowErr("入力エラーが見つかりました。「エラーメッセージ」欄を確認してください。", "入力エラー");
                return false;
            }

            return true;
        }

        private void SetPatterneData(object sender, PatternDropDownControl.PatternSelectedEventArgs e)
        {
            // テンプレートデータをロードする
            sendContentControl1.SetPatternData(e.SelectedPattern);
        }

        private void SetFilePath()
        {
            string folderPass = attachmentSelectionControl1.GetPath();
            List<CustomerMasterDto> destinationList = sendContentControl1.GetDestinationList();

            // フォルダが存在しない場合は全件ブランク
            if (!Directory.Exists(folderPass))
            {
                foreach (var dest in destinationList)
                    dest.FilePath = string.Empty;
                return;
            }

            // フォルダが存在する場合は個別にファイル名を特定してセット
            foreach (var dest in destinationList)
            {
                // 末尾が _<管理番号>.pdf に一致するファイルを検索
                string pattern = $"*_{dest.ManagementNumber}.pdf";
                var match = Directory
                    .EnumerateFiles(folderPass, pattern, SearchOption.TopDirectoryOnly)
                    .FirstOrDefault();

                // 見つかれば絶対パス、なければ空文字
                dest.FilePath = match != null
                    ? Path.GetFullPath(match)
                    : string.Empty;
            }
        }

        /// <summary>
        /// テスト送信ボタン 押下
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void btnTestSend_Click(object sender, EventArgs e)
        {
            try
            {
                // 重複実行防止
                btnTestSend.Enabled = false;

                // テスト送信確認
                var needsTestSend = MessageBoxUtil.ShowYesNo(MessageBoxUtil.ASK_002);
                if (needsTestSend != DialogResult.Yes) return;

                // PDFアップロード+メッセージ送信
                var roomId = GetTestRoomId();
                var comment = sendContentControl1.GetContents();
                var pdfPath = Path.Combine(Application.StartupPath, "Assets", "Chatwork_テスト送信サンプルファイル.pdf");
                var client = new ChatworkService();
                var result = await client.UploadFileAsync(roomId, pdfPath, comment);
                if (result.Success == Constants.SEND_RESULT.SUCCESS)
                {
                    MessageBoxUtil.Show($"テスト送信処理が成功しました。", "送信成功");
                }
                else
                {
                    MessageBoxUtil.ShowErr($"テスト送信処理が失敗しました。\r\nエラー内容:{result.DisplayErrorMessage}", "送信失敗");
                }

            }
            catch (Exception ex)
            {
                MessageBoxUtil.ShowErr($"テスト送信処理が失敗しました。\r\n{ex.Message}", "送信失敗");
            }
            finally
            {
                btnTestSend.Enabled = true;
            }
        }

        private string GetTestRoomId()
        {
            var senderMasterDto = new SenderMasterDao().GetAll().FirstOrDefault();
            return senderMasterDto.TestRoomId;
        }
    }
}