/*
* 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.Diagnostics;
using System.Linq;
namespace ChatworkBulkSender.UserControls
{
/// <summary>
/// 顧客マスタ画面DGVコントロール。
/// デザイナー表示のためデバッグ時は、中間クラスを経由する。
/// </summary>
[DesignerCategory("UserControl")] // デザイナーでユーザーコントロールとして表示することを明記する
public partial class CustomerDgvControl : BaseCustomerDgvControl
{
protected override int EditButtonColumnIndex => 6;
protected override int SortableColumnMaxIndex => 5;
protected override string InitialSortColumnName => "SortOrder";
EventHandler<CustomerMasterDto> _createdCustomer;
public CustomerDgvControl()
{
if (!IsInDesignMode())
{
InitializeComponent();
if (_dgv == null)
{
base._dgv = this.customerDgv;
}
InitializeDgv();
SetUpColumns();
customerDgv.Dock = DockStyle.Fill;
}
}
protected override void InitializeDgv()
{
base.InitializeDgv();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!IsInDesignMode())
{
_createdCustomer = (s, args) => CreatedCustomer();
_individualEditForm = new M_CustomerMasterIndividualEdit();
_individualEditForm.DataCreated += _createdCustomer;
RefreshData();
}
}
public void ClearSelectionCell()
{
ClearSelection();
}
public void ShowCreateForm()
{
customerDgv.Enabled = false;
try
{
var createForm = new M_CustomerMasterIndividualEdit(
M_CustomerMasterIndividualEdit.ButtonMode.Register);
createForm.DataCreated += _createdCustomer;
createForm.Owner = this.ParentForm;
createForm.FormClosed += (s, args) =>
{
customerDgv.Enabled = true;
if (this.ParentForm != null && !this.ParentForm.Visible)
{
this.ParentForm.Show();
this.ParentForm.BringToFront();
}
RefreshData();
};
this.ParentForm.Hide();
createForm.Show();
}
catch(Exception e)
{
customerDgv.Enabled = true;
if (this.ParentForm != null && !this.ParentForm.Visible)
{
this.ParentForm.Show();
}
MessageBoxUtil.ShowErr($"新規作成画面の表示中にエラーが発生しました。\n\n{e.Message}");
}
}
protected override void ShowEditForm(CustomerMasterDto selectedItem)
{
customerDgv.Enabled = false;
try
{
if(_individualEditForm != null && !_individualEditForm.IsDisposed)
{
var form = _individualEditForm;
if (form != null)
{
form.DataCreated += _createdCustomer;
}
_individualEditForm.Close();
_individualEditForm.Dispose();
// 内部メッセージ処理
Application.DoEvents();
}
// 編集前に最新のデータを取得して更新チェック
var dao = new CustomerMasterDao();
var latestData = dao.GetByManagementNumber(selectedItem.ManagementNumber);
if (latestData == null)
{
MessageBox.Show("対象のデータが削除されています。一覧を更新します。", "エラー",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
customerDgv.Enabled = true; // DataGridViewを再度有効化
RefreshData();
return;
}
// 元の更新日時を取得(データロード時に保存された値)
var originalUpdateTime = GetOriginalUpdateTime(selectedItem);
// 更新日時が異なる場合(元の値と最新値を比較)
// DateTime精度問題対策:1秒以内の差は同じとみなす
bool isUpdatedByOthers = false;
if (latestData.UpdatedAt.HasValue && originalUpdateTime.HasValue)
{
var timeDiff = Math.Abs((latestData.UpdatedAt.Value - originalUpdateTime.Value).TotalSeconds);
isUpdatedByOthers = timeDiff > 1.0; // 1秒以上の差がある場合のみ更新とみなす
}
else if (latestData.UpdatedAt != originalUpdateTime)
{
isUpdatedByOthers = true;
}
if (isUpdatedByOthers)
{
MessageBox.Show(MessageBoxUtil.DB_011, "エラー",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
customerDgv.Enabled = true; // DataGridViewを再度有効化
RefreshData();
return;
}
// フォームを作成(更新ボタン配置の設定にする)
_individualEditForm = new M_CustomerMasterIndividualEdit(
M_CustomerMasterIndividualEdit.ButtonMode.Update, latestData);
var editForm = _individualEditForm;
if (editForm != null)
{
editForm.DataCreated += _createdCustomer;
}
_individualEditForm.Owner = this.ParentForm;
_individualEditForm.FormClosed += (s, args) =>
{
customerDgv.Enabled = true;
if (this.ParentForm != null && !this.ParentForm.Visible)
{
this.ParentForm.Show();
this.ParentForm.BringToFront();
}
RefreshData();
};
this.ParentForm.Hide();
_individualEditForm.Show();
}
catch(Exception e)
{
customerDgv.Enabled = true;
if (this.ParentForm != null && !this.ParentForm.Visible)
{
this.ParentForm.Show();
}
MessageBoxUtil.ShowErr($"個別編集画面の表示中にエラーが発生しました。\n\n{e.Message}");
}
}
private void CreatedCustomer()
{
RefreshData();
}
private void SetUpColumns()
{
_dgv.Columns.Clear();
_dgv.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = nameof(CustomerMasterDto.ManagementNumber),
Name = nameof(CustomerMasterDto.ManagementNumber),
HeaderText = "管理番号",
ReadOnly = true,
SortMode = DataGridViewColumnSortMode.Programmatic
,
});
var mgmtNumberCol = customerDgv.Columns[nameof(CustomerMasterDto.ManagementNumber)];
mgmtNumberCol.FillWeight = 60;
_dgv.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = nameof(CustomerMasterDto.CustomerName),
Name = nameof(CustomerMasterDto.CustomerName),
HeaderText = "顧客名",
ReadOnly = true,
SortMode = DataGridViewColumnSortMode.Programmatic
,
});
var customerNameCol = customerDgv.Columns[nameof(CustomerMasterDto.CustomerName)];
customerNameCol.FillWeight = 400;
_dgv.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = nameof(CustomerMasterDto.RoomId),
Name = nameof(CustomerMasterDto.RoomId),
HeaderText = "ルームID(rid)",
ReadOnly = true,
SortMode = DataGridViewColumnSortMode.Programmatic
,
});
var roomIdCol = customerDgv.Columns[nameof(CustomerMasterDto.RoomId)];
roomIdCol.FillWeight = 60;
_dgv.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = nameof(CustomerMasterDto.DestinationAccountId),
Name = nameof(CustomerMasterDto.DestinationAccountId),
HeaderText = "宛先アカウントID",
ReadOnly = true,
SortMode = DataGridViewColumnSortMode.Programmatic
,
});
var destinationCol = customerDgv.Columns[nameof(CustomerMasterDto.DestinationAccountId)];
destinationCol.FillWeight = 90;
_dgv.Columns.Add(new DataGridViewTextBoxColumn
{
DataPropertyName = nameof(CustomerMasterDto.SortOrder),
Name = nameof(CustomerMasterDto.SortOrder),
HeaderText = "並び順",
ReadOnly = true,
SortMode = DataGridViewColumnSortMode.Programmatic
,
});
var sortOrderCol = customerDgv.Columns[nameof(CustomerMasterDto.SortOrder)];
sortOrderCol.FillWeight = 38;
sortOrderCol.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
sortOrderCol.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
sortOrderCol.HeaderCell.Style.Padding = new Padding(12, 0, 0, 0);
_dgv.Columns.Add(new DataGridViewCheckBoxColumn
{
DataPropertyName = nameof(CustomerMasterDto.IsUnused),
Name = nameof(CustomerMasterDto.IsUnused),
HeaderText = "未使用フラグ",
ReadOnly = true,
SortMode = DataGridViewColumnSortMode.Programmatic
,
});
var isUnusedCol = customerDgv.Columns[nameof(CustomerMasterDto.IsUnused)];
isUnusedCol.FillWeight = 55;
isUnusedCol.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
isUnusedCol.HeaderCell.Style.Padding = new Padding(12, 0, 0, 0);
_dgv.Columns.Add(new DataGridViewButtonColumn
{
// Data列ではないのでNameのみを設定
Name = "BtnEdit",
HeaderText = "編集",
Text = "\u270F\uFE0F",
UseColumnTextForButtonValue = true,
ReadOnly = true,
DefaultCellStyle = new DataGridViewCellStyle
{
Font = new Font("Segoe UI Emoji", 10),
Alignment = DataGridViewContentAlignment.MiddleCenter
,
}
});
var editCol = customerDgv.Columns["BtnEdit"];
editCol.FillWeight = 38;
editCol.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
}
protected override List<CustomerMasterDto> GetDataFromDao()
{
var dao = new CustomerMasterDao();
// 検索条件から未使用データ表示フラグを取得
bool includeUnused = false;
if (_searchCriteria != null && _searchCriteria.ContainsKey("IncludeUnused"))
{
includeUnused = (bool)_searchCriteria["IncludeUnused"];
}
// DAOから全データを取得(未使用フラグに応じて)
List<CustomerMasterDto> currentData = dao.GetAll(includeUnused);
if (_searchCriteria != null && _searchCriteria.Count > 0)
{
var query = currentData.AsQueryable();
if (_searchCriteria.ContainsKey("ManagementNumber"))
{
var mgmtNumber = _searchCriteria["ManagementNumber"].ToString();
query = query.Where(x => x.ManagementNumber.ToString().StartsWith(mgmtNumber));
}
if (_searchCriteria.ContainsKey("CustomerName"))
{
var customerName = _searchCriteria["CustomerName"].ToString();
query = query.Where(x => x.CustomerName.ToString().Contains(customerName));
}
return query.ToList();
}
return currentData;
}
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<CustomerMasterDto> list)
{
_originalUpdateTimes.Clear();
// メモリ効率化: 大量データの場合は警告
if (list.Count > 10000)
{
System.Diagnostics.Debug.WriteLine($"警告: 顧客マスタデータが{list.Count}件あります。メモリ使用量: 約{list.Count * 80 / 1024}KB");
}
// DataGridViewに実際に表示されているデータのみ保存する最適化も可能
// 現在は全データを保存(画面スクロール時の一貫性のため)
foreach (var dto in list)
{
_originalUpdateTimes[dto.ManagementNumber] = dto.UpdatedAt;
}
}
/// <summary>
/// 指定された顧客DTOの元の更新日時を取得する
/// </summary>
protected override DateTime? GetOriginalUpdateTime(CustomerMasterDto dto)
{
if (_originalUpdateTimes.ContainsKey(dto.ManagementNumber))
{
return _originalUpdateTimes[dto.ManagementNumber];
}
// 見つからない場合は現在の値を返す(後方互換性のため)
return dto.UpdatedAt;
}
/// <summary>
/// 新規アイテムの更新日時のみを追加(既存アイテムの更新日時は変更しない)
/// </summary>
protected override void UpdateOriginalUpdateTimesForNewItems(List<CustomerMasterDto> list)
{
foreach (var dto in list)
{
// 既存のエントリがない場合のみ追加
if (!_originalUpdateTimes.ContainsKey(dto.ManagementNumber))
{
_originalUpdateTimes[dto.ManagementNumber] = dto.UpdatedAt;
}
}
}
}
}