前回までの話。
申請処理作成(画面側)
今回は申請処理及び、メイン画面に表示される申請履歴表示について。
まずは申請処理。
…とその前に、準備を一つ。
MySQLManager.hを開きます。
ここにenumを 定義。
ついでに、今回使用する関数も定義しておきます。
typedef enum
{
enPending, // 申請中
enApprovaled, // 承認
enRejected // 拒否
}ApprovalMode;
class CMySQLManager
{
public:
// 申請履歴テーブル登録処理
BOOL bRecordTableCreate(CString strUserID, CString strGroupID, CString strKoumokuID, ApprovalMode enApproval);
};recordテーブルにはApproval列があり、そこには0か1か2が入ります。
0なら申請中、1なら承認、2なら申請拒否です。
正直、定義したところであまり使う場面はないですが、
わかりやすさのためenum化しました。
関数は、レコード登録に必要なユーザID、項目ID、申請状態を引数にします。
呼び出し元では、申請状態は常にenPendingを持ってくるように。
グループIDを引数に入れているのは、
念のためグループテーブルにそのIDが存在するかチェックするためです。
ヘッダー処理はここまで。
今度は申請画面内の処理、Request.cppを開きます。
まず、SQL処理を行うクラスへ繋ぎたいため、ヘッダーをインクルード。
#include "MySQLManager.h"続いて、申請ボタンが押された時に呼ばれる関数を修正。
void CRequest::OnBnClickedOk()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
UpdateData(TRUE);
int iComboIndex = m_ComboGroup.GetCurSel(); // インデックス取得
CString strComboText;
m_ComboGroup.GetLBText(iComboIndex, strComboText); // コンボボックス内の文字列取得
int id = GetCheckedRadioButton(IDC_RADIO1, IDC_RADIO5); // ラジオボタンの選択
CString strRadioText;
if (id == IDC_RADIO1 || id == IDC_RADIO2 || id == IDC_RADIO3 || id == IDC_RADIO4 || id == IDC_RADIO5)
{
// ラジオボタンからキャプション取得
GetDlgItemText(id, strRadioText);
}
else
{
// ラジオボタンが選択されていない場合
AfxMessageBox(_T("項目を選択してください。"), MB_OK | MB_ICONEXCLAMATION);
return;
}
int iKoumokuID = m_MapKoumokuReverse[strRadioText]; // 項目ID
KoumokuValue strcutKoumoku = m_MapKoumoku[iKoumokuID]; // 項目IDに対する構造体
CString strPrice = strcutKoumoku.strKoumokuPrice; // 選択された項目の値段
CString strMes = _T("以下を購入申請します。よろしいですか?");
strMes += _T("\r\nグループ名:");
strMes += strComboText;
strMes += _T("\r\n項目名:");
strMes += strRadioText;
strMes += _T("\r\n値段:");
strMes += strPrice;
if (AfxMessageBox(strMes, MB_OKCANCEL | MB_ICONQUESTION) == IDOK)
{
// 申請開始
// 逆引きからグループIDを取得
int iGroupID = m_MapGroupReverse[strComboText]; // グループID
CSupplyRequestManagerApp* pApp = static_cast<CSupplyRequestManagerApp*>(AfxGetApp());
CString strGroupId, strKoumokuId;
strGroupId.Format(_T("%d"), iGroupID);
strKoumokuId.Format(_T("%d"), iKoumokuID);
CMySQLManager Request;
Request.GetConnection(); // 接続確立
if (Request.bRecordTableCreate(pApp->strGetUserId(), strGroupId, strKoumokuId, enPending) == TRUE)
{
AfxMessageBox(_T("申請が完了しました。"));
CDialogEx::OnOK();
}
}
}ちょっと長いですが、
半分以上は選択されたコンボボックスやラジオボタンのID及び名称を取得しているだけです。
ID取得に逆引きマップを使用しています。
後はいつも通り、CmySQLManager側の関数を呼応し、成功したら画面を閉じます。
今更ですが、値段って36行目のメッセージで初めて表示させるんですよね。
申請画面に表示させた方がいいけど、
どうもレイアウトがうまく定まらなかったので、
今回はメッセージボックスで初めて値段を知る仕様にします。
申請処理作成(SQL)
そしてMySQLManager.cppを開き、テーブル操作処理を書きます。
/**
* @fn
* @brief 申請テーブル新規作成処理
* @param CString strUserID ユーザID
* CString strGroupID グループID
* CString strKoumokuID 項目ID
* ApprovalMode enApproval 申請状態(=enPending)
* @return TRUE 操作成功
* FALSE 操作失敗
*/
BOOL CMySQLManager::bRecordTableCreate(CString strUserID, CString strGroupID, CString strKoumokuID, ApprovalMode enApproval)
{
switch (enApproval)
{
case enPending:
// 申請中を登録
break;
default:
AfxMessageBox(_T("処理に問題があります。管理者へ連絡を!"));
return FALSE;
}
try
{
m_con->setSchema(SCHEMA); //スキーマ選択
sql::SQLString strSqlQuery = "";
// 各種型変換
sql::SQLString strsqlUserID = strConverter(strUserID); // ユーザID
sql::SQLString strsqlGroupID = strConverter(strGroupID); // グループID
sql::SQLString strsqlKoumokuID = strConverter(strKoumokuID); // 項目ID
sql::SQLString strsqlApproval = strConverter(_T("0")); // 申請状態(申請中)
// 本当にグループIDは存在する?
strSqlQuery = "SELECT * FROM " + TABLE_GROUP + " WHERE Id = " + strsqlGroupID;
// クエリを実行
std::unique_ptr<sql::PreparedStatement> pstmt1(m_con->prepareStatement(strSqlQuery));
std::unique_ptr<sql::ResultSet> res1(pstmt1->executeQuery());
if (!res1->next())
{
AfxMessageBox(_T("グループテーブルに問題があります。管理者へ連絡を!"));
return FALSE;
}
// 本当に項目IDは存在する?
strSqlQuery = "SELECT * FROM " + TABLE_KOUMOKU + " WHERE Id = " + strsqlKoumokuID;
// クエリを実行
std::unique_ptr<sql::PreparedStatement> pstmt2(m_con->prepareStatement(strSqlQuery));
std::unique_ptr<sql::ResultSet> res2(pstmt2->executeQuery());
if (!res2->next())
{
AfxMessageBox(_T("項目テーブルに問題があります。管理者へ連絡を!"));
return FALSE;
}
//登録処理開始
strSqlQuery = "INSERT INTO " + TABLE_RECORD + " (UserId, KoumokuId, Approval) VALUES ('" + strsqlUserID + "', " + strsqlKoumokuID + ", " + strsqlApproval + ")";
// クエリを実行
std::unique_ptr<sql::PreparedStatement> pstmt3(m_con->prepareStatement(strSqlQuery));
std::unique_ptr<sql::ResultSet> res3(pstmt3->executeQuery());
}
catch (sql::SQLException& e)
{
// 実行できなかった
ErrSQLException(e);
return FALSE;
}
return TRUE;
}この関数bRecordTableCreate、4番目の引数は常にenPendingが入ってくるようにしています。
だから、役割としてはここの引数いらねぇな、とも思いましたが。
作ってしまったのでこれはこれで…。
54行目まではチェックが入ってます。
基本的に自分が作った範囲ではここのチェックに引っかかることはありませんが…。
それが終われば、後はINSERT実行です。
ここで一度ビルド
動作確認
ユーザIDが00001さんでログインし、申請を実行してみます。

OKを押して、問題なく登録できたようです。
さて、recordテーブルを見ると。

ユーザIDが0Fillされてなーい(;´∀`)
まーた忘れてるよこの野郎。
後はOKかな?
テーブル設定修正
WorkBenchを開いて、Zero Fillにチェックを入れます。
A5M2でもできるのかな?
流石にできるとは思うけど、設定場所がわからなかった。

型もちゃんとINT(5)にしておきます。
ついでにですが、外部キー設定もしていなかったのでここで実施します。
UserId列はuserテーブルのId、
KoumokuId列はKoumokuテーブルのIdと紐づけへ。


これでApplyを押すと

ER図ではちゃんと設定できているように見えます。
手作業で一度レコードを削除し、再度申請ダイアログから申請を行います。
削除はDELETE FROMよりかはTRUNCATE TABLEの方がいいですかね。
申請実行すると。

できました。
ホント、IDはvarcharにした方がよかったな…。
終わりに
今回は購入申請ダイアログの処理を作成しました。
前回結構長めに書いて疲れたので、
今回は短め。
次回はいよいよメイン画面のリストコントロールに、
自分の申請状況を表示させます。
今回はここまで。

コメント