/*
* Copyright XXXX Co.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using ChatworkBulkSender.Daos;
using ChatworkBulkSender.Dtos;
using ChatworkBulkSender.Utils;
using ChatworkBulkSender.Forms;
using System.Linq;
namespace ChatworkBulkSender.UserControls
{
[DesignerCategory("UserControl")] // デザイナーでユーザーコントロールとして表示することを明記する
public partial class PattrernDgvControl : BasePatternMasterDgvControl
{
protected override int EditButtonColumnIndex => 4; // 編集ボタンは5列目(インデックス4)
protected override int SortableColumnMaxIndex => 3; // ソート可能な最大列(未使用まで)
protected override string InitialSortColumnName => "SortOrder";
EventHandler<PatternMasterDto> _createdSendPattern;
public PattrernDgvControl()
{
if (!IsInDesignMode())
{
InitializeComponent();
if (_dgv == null)
{
base._dgv = this.patternDgv;
}
InitializeDgv();
SetUpColumns();
patternDgv.Dock = DockStyle.Fill;
}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!IsInDesignMode())
{
_createdSendPattern = (s, args) => CreatedSendPattern();
_individualEditForm = new M_SendPatternIndividualEdit();
_individualEditForm.DataCreated += _createdSendPattern;
RefreshData();
}
}
protected override void InitializeDgv()
{
base.InitializeDgv();
}
private void CreatedSendPattern()
{
RefreshData();
}
/// <summary>
/// 有効なパターンをDGVに読み込む
/// </summary>
private void SetUpColumns()
{
if (_dgv == null) { return; }
_dgv.Columns.Clear();
// パターン名称
var patternName = new DataGridViewTextBoxColumn
{
DataPropertyName = nameof(PatternMasterDto.PatternName),
Name = nameof(PatternMasterDto.PatternName),
HeaderText = "パターン名称",
ReadOnly = true,
SortMode = DataGridViewColumnSortMode.Programmatic,
};
patternName.FillWeight = 300;
_dgv.Columns.Add(patternName);
// 定型文
var templateText = new DataGridViewTextBoxColumn
{
DataPropertyName = nameof(PatternMasterDto.TemplateText),
Name = nameof(PatternMasterDto.TemplateText),
HeaderText = "定型文",
ReadOnly = true,
SortMode = DataGridViewColumnSortMode.Programmatic,
};
templateText.FillWeight = 500;
_dgv.Columns.Add(templateText);
// 並び順
var sortOrderCol = new DataGridViewTextBoxColumn
{
DataPropertyName = nameof(PatternMasterDto.SortOrder),
Name = nameof(PatternMasterDto.SortOrder),
HeaderText = "並び順",
ReadOnly = true,
SortMode = DataGridViewColumnSortMode.Programmatic,
};
sortOrderCol.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
sortOrderCol.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
sortOrderCol.HeaderCell.Style.Padding = new Padding(12, 0, 0, 0);
sortOrderCol.FillWeight = 50;
_dgv.Columns.Add(sortOrderCol);
// 未使用フラグ
var isUnusedCol = new DataGridViewCheckBoxColumn
{
DataPropertyName = nameof(PatternMasterDto.IsUnused),
Name = nameof(PatternMasterDto.IsUnused),
HeaderText = "未使用フラグ",
ReadOnly = true,
SortMode = DataGridViewColumnSortMode.Programmatic,
};
isUnusedCol.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
isUnusedCol.HeaderCell.Style.Padding = new Padding(12, 0, 0, 0);
isUnusedCol.FillWeight = 70;
_dgv.Columns.Add(isUnusedCol);
// 編集ボタン
var editCol = new DataGridViewButtonColumn
{
Name = "BtnEdit",
HeaderText = "編集",
Text = "✏",
UseColumnTextForButtonValue = true,
ReadOnly = true,
};
editCol.DefaultCellStyle.Font = new Font("Segoe UI Emoji", 10);
editCol.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
editCol.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
editCol.FillWeight = 50;
_dgv.Columns.Add(editCol);
}
protected override void ShowEditForm(PatternMasterDto selectedItem)
{
_dgv.Enabled = false;
try
{
if (_individualEditForm != null && !_individualEditForm.IsDisposed)
{
var form = _individualEditForm;
if (form != null)
{
form.DataCreated += _createdSendPattern;
}
_individualEditForm.Close();
_individualEditForm.Dispose();
// 内部メッセージ処理
Application.DoEvents();
}
// 編集前に最新のデータを取得して更新チェック
var dao = new PatternMasterDao();
var latestData = dao.GetById(selectedItem.PatternId);
if (latestData == null)
{
MessageBox.Show("対象のデータが削除されています。一覧を更新します。", "エラー",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
_dgv.Enabled = true; // DataGridViewを再度有効化
RefreshData();
return;
}
// 元の更新日時を取得(データロード時に保存された値)
var originalUpdateTime = GetOriginalUpdateTime(selectedItem);
// 更新日時が異なる場合(元の値と最新値を比較)
// DateTime精度問題対策:1秒以内の差は同じとみなす
bool isUpdatedByOthers = false;
if (latestData.UpdatedDate.HasValue && originalUpdateTime.HasValue)
{
var timeDiff = Math.Abs((latestData.UpdatedDate.Value - originalUpdateTime.Value).TotalSeconds);
isUpdatedByOthers = timeDiff > 1.0; // 1秒以上の差がある場合のみ更新とみなす
}
else if (latestData.UpdatedDate != originalUpdateTime)
{
isUpdatedByOthers = true;
}
if (isUpdatedByOthers)
{
MessageBox.Show(MessageBoxUtil.DB_011, "エラー",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
_dgv.Enabled = true; // DataGridViewを再度有効化
RefreshData();
return;
}
// フォームを作成(更新ボタン配置の設定にする)
_individualEditForm = new M_SendPatternIndividualEdit(
M_SendPatternIndividualEdit.ButtonMode.Update, latestData);
var editForm = _individualEditForm;
if (editForm != null)
{
editForm.DataCreated += _createdSendPattern;
}
_individualEditForm.Owner = this.ParentForm;
_individualEditForm.FormClosed += (s, args) =>
{
_dgv.Enabled = true;
if (this.ParentForm != null && !this.ParentForm.Visible)
{
this.ParentForm.Show();
this.ParentForm.BringToFront();
}
RefreshData();
};
this.ParentForm.Hide();
_individualEditForm.Show();
}
catch (Exception e)
{
_dgv.Enabled = true;
if (this.ParentForm != null && !this.ParentForm.Visible)
{
this.ParentForm.Show();
}
MessageBoxUtil.ShowErr($"個別編集画面の表示中にエラーが発生しました。\n\n{e.Message}");
}
}
protected override List<PatternMasterDto> GetDataFromDao()
{
var dao = new PatternMasterDao();
var currentData = dao.GetAll();
if (_searchCriteria != null && _searchCriteria.Count > 0)
{
var query = currentData.AsQueryable();
if (_searchCriteria.ContainsKey("PatternName"))
{
var patternName = _searchCriteria["PatternName"].ToString();
query = query.Where(x => x.PatternName != null && x.PatternName.Contains(patternName));
}
if ((_searchCriteria.ContainsKey("ManagementNumber") && !string.IsNullOrEmpty(_searchCriteria["ManagementNumber"].ToString())) ||
(_searchCriteria.ContainsKey("CustomerName") && !string.IsNullOrEmpty(_searchCriteria["CustomerName"].ToString())))
{
var customerDao = new CustomerMasterDao();
var allCostomers = customerDao.GetAll(true);
var patternCustomerDao = new PatternCustomerMasterDao();
var matchingPatternIds = new HashSet<int>();
foreach (var pattern in currentData)
{
var patternCustomers = patternCustomerDao.GetCustomersByPatternId(pattern.PatternId);
foreach (var patternCust in patternCustomers)
{
var customer = allCostomers.FirstOrDefault(c => c.ManagementNumber == patternCust.PatternId);
if (customer != null)
{
bool isMatch = false;
// 管理番号(前方一致)
if (_searchCriteria.ContainsKey("ManagementNumber") && !string.IsNullOrEmpty(_searchCriteria["ManagementNumber"].ToString()))
{
var searchMgmtNumber = _searchCriteria["ManagementNumber"].ToString();
if (customer.ManagementNumber.ToString().StartsWith(searchMgmtNumber))
{
isMatch = true;
}
}
// 顧客名(部分一致)
if (!isMatch && _searchCriteria.ContainsKey("CustomerName") && !string.IsNullOrEmpty(_searchCriteria["CustomerName"].ToString()))
{
var searchCustomerName = _searchCriteria["CustomerName"].ToString();
if (customer.CustomerName != null && customer.CustomerName.Contains(searchCustomerName))
{
isMatch = true;
}
}
if (isMatch)
{
matchingPatternIds.Add(pattern.PatternId);
break; // このパターンは既に一致したので次のパターンへ
}
}
}
}
query = query.Where(x => matchingPatternIds.Contains(x.PatternId));
}
// 未使用データ表示
if (_searchCriteria.ContainsKey("IncludeUnused") && !(bool)_searchCriteria["IncludeUnused"])
{
query = query.Where(x => !x.IsUnused);
}
return query.ToList();
}
// デフォルトは未使用を除外
return currentData.Where(x => !x.IsUnused).ToList();
}
protected override bool HasUpdateAfter(DateTime? lastLoadTime)
{
if (lastLoadTime == null) { return false; }
return new CustomerMasterDao().HasUpdatesAfter(lastLoadTime);
}
public override void Search(Dictionary<string, object> criteria)
{
base.Search(criteria);
this.GetDataFromDao();
}
protected override void Dgv_ColumnHeaderMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
{
base.Dgv_ColumnHeaderMouseDoubleClick(sender, e);
}
protected override void Dgv_CellClick(object sender, DataGridViewCellEventArgs e)
{
base.Dgv_CellClick(sender, e);
}
private void customerDgv_BringContextChanged(object sender, EventArgs e)
{
ClearSelection();
}
private void customerDgv_Leave(object sender, EventArgs e)
{
ClearSelection();
}
/// <summary>
/// 各パターンDTOの更新日時を保存する
/// </summary>
protected override void StoreOriginalUpdateTimes(List<PatternMasterDto> list)
{
_originalUpdateTimes.Clear();
foreach (var dto in list)
{
_originalUpdateTimes[dto.PatternId] = dto.UpdatedDate;
}
}
/// <summary>
/// 指定されたパターンDTOの元の更新日時を取得する
/// </summary>
protected override DateTime? GetOriginalUpdateTime(PatternMasterDto dto)
{
if (_originalUpdateTimes.ContainsKey(dto.PatternId))
{
return _originalUpdateTimes[dto.PatternId];
}
// 見つからない場合は現在の値を返す(後方互換性のため)
return dto.UpdatedDate;
}
/// <summary>
/// 新規アイテムの更新日時のみを追加(既存アイテムの更新日時は変更しない)
/// </summary>
protected override void UpdateOriginalUpdateTimesForNewItems(List<PatternMasterDto> list)
{
foreach (var dto in list)
{
// 既存のエントリがない場合のみ追加
if (!_originalUpdateTimes.ContainsKey(dto.PatternId))
{
_originalUpdateTimes[dto.PatternId] = dto.UpdatedDate;
}
}
}
}
}