Explorar o código

增加人员页

Joey hai 3 días
pai
achega
c3b6f8df49
Modificáronse 14 ficheiros con 1576 adicións e 171 borrados
  1. 110 5
      DDQ.Designer.cs
  2. 101 2
      DDQ.cs
  3. 68 45
      DataAccess.cs
  4. 113 32
      FundQ.Designer.cs
  5. 157 87
      FundQ.cs
  6. 3 0
      FundQ.resx
  7. 184 0
      PersonSelection.Designer.cs
  8. 125 0
      PersonSelection.cs
  9. 120 0
      PersonSelection.resx
  10. 255 0
      PersonnelQ.Designer.cs
  11. 95 0
      PersonnelQ.cs
  12. 120 0
      PersonnelQ.resx
  13. 106 0
      Utility.cs
  14. 19 0
      ddq.csproj

+ 110 - 5
DDQ.Designer.cs

@@ -49,8 +49,15 @@
             this.btnSearchFund = new System.Windows.Forms.Button();
             this.textBox1 = new System.Windows.Forms.TextBox();
             this.tabPeople = new System.Windows.Forms.TabPage();
+            this.grdPeopleList = new System.Windows.Forms.DataGridView();
+            this.panPeopleTool = new System.Windows.Forms.Panel();
+            this.cmbRole = new System.Windows.Forms.ComboBox();
+            this.label3 = new System.Windows.Forms.Label();
+            this.button1 = new System.Windows.Forms.Button();
+            this.textBox2 = new System.Windows.Forms.TextBox();
             this.tabCompany = new System.Windows.Forms.TabPage();
             this.tabSettings = new System.Windows.Forms.TabPage();
+            this.btnAddPersonn = new System.Windows.Forms.Button();
             this.tbcMain.SuspendLayout();
             this.tabRequests.SuspendLayout();
             this.panRequests.SuspendLayout();
@@ -63,6 +70,9 @@
             this.panFundList.SuspendLayout();
             ((System.ComponentModel.ISupportInitialize)(this.grdFundList)).BeginInit();
             this.panFundsTool.SuspendLayout();
+            this.tabPeople.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.grdPeopleList)).BeginInit();
+            this.panPeopleTool.SuspendLayout();
             this.SuspendLayout();
             // 
             // tbcMain
@@ -141,8 +151,7 @@
             // 
             // cmbRequestAction
             // 
-            this.cmbRequestAction.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
+            this.cmbRequestAction.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
             this.cmbRequestAction.FormattingEnabled = true;
             this.cmbRequestAction.Location = new System.Drawing.Point(594, 13);
             this.cmbRequestAction.Name = "cmbRequestAction";
@@ -151,6 +160,7 @@
             // 
             // label1
             // 
+            this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
             this.label1.AutoSize = true;
             this.label1.Location = new System.Drawing.Point(541, 17);
             this.label1.Name = "label1";
@@ -204,6 +214,7 @@
             this.tbcData.Size = new System.Drawing.Size(786, 481);
             this.tbcData.SizeMode = System.Windows.Forms.TabSizeMode.Fixed;
             this.tbcData.TabIndex = 0;
+            this.tbcData.SelectedIndexChanged += new System.EventHandler(this.tbcData_SelectedIndexChanged);
             // 
             // tabFunds
             // 
@@ -231,7 +242,7 @@
             this.grdFundList.AllowUserToAddRows = false;
             this.grdFundList.AllowUserToDeleteRows = false;
             this.grdFundList.AllowUserToOrderColumns = true;
-            this.grdFundList.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.DisplayedCells;
+            this.grdFundList.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.DisplayedCells;
             this.grdFundList.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
             this.grdFundList.Dock = System.Windows.Forms.DockStyle.Fill;
             this.grdFundList.Location = new System.Drawing.Point(0, 0);
@@ -256,8 +267,7 @@
             // 
             // cmbFundCategory
             // 
-            this.cmbFundCategory.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
+            this.cmbFundCategory.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
             this.cmbFundCategory.FormattingEnabled = true;
             this.cmbFundCategory.Location = new System.Drawing.Point(562, 18);
             this.cmbFundCategory.Name = "cmbFundCategory";
@@ -266,6 +276,7 @@
             // 
             // label2
             // 
+            this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
             this.label2.AutoSize = true;
             this.label2.Location = new System.Drawing.Point(493, 22);
             this.label2.Name = "label2";
@@ -294,6 +305,9 @@
             // 
             // tabPeople
             // 
+            this.tabPeople.Controls.Add(this.btnAddPersonn);
+            this.tabPeople.Controls.Add(this.grdPeopleList);
+            this.tabPeople.Controls.Add(this.panPeopleTool);
             this.tabPeople.Location = new System.Drawing.Point(4, 4);
             this.tabPeople.Name = "tabPeople";
             this.tabPeople.Padding = new System.Windows.Forms.Padding(3);
@@ -302,6 +316,74 @@
             this.tabPeople.Text = "People";
             this.tabPeople.UseVisualStyleBackColor = true;
             // 
+            // grdPeopleList
+            // 
+            this.grdPeopleList.AllowUserToAddRows = false;
+            this.grdPeopleList.AllowUserToDeleteRows = false;
+            this.grdPeopleList.AllowUserToOrderColumns = true;
+            this.grdPeopleList.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.grdPeopleList.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.DisplayedCells;
+            this.grdPeopleList.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+            this.grdPeopleList.Location = new System.Drawing.Point(3, 116);
+            this.grdPeopleList.MultiSelect = false;
+            this.grdPeopleList.Name = "grdPeopleList";
+            this.grdPeopleList.ReadOnly = true;
+            this.grdPeopleList.RowTemplate.Height = 23;
+            this.grdPeopleList.Size = new System.Drawing.Size(772, 331);
+            this.grdPeopleList.TabIndex = 1;
+            this.grdPeopleList.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.grdPeopleList_CellClick);
+            // 
+            // panPeopleTool
+            // 
+            this.panPeopleTool.Controls.Add(this.cmbRole);
+            this.panPeopleTool.Controls.Add(this.label3);
+            this.panPeopleTool.Controls.Add(this.button1);
+            this.panPeopleTool.Controls.Add(this.textBox2);
+            this.panPeopleTool.Dock = System.Windows.Forms.DockStyle.Top;
+            this.panPeopleTool.Location = new System.Drawing.Point(3, 3);
+            this.panPeopleTool.Name = "panPeopleTool";
+            this.panPeopleTool.Size = new System.Drawing.Size(772, 61);
+            this.panPeopleTool.TabIndex = 0;
+            // 
+            // cmbRole
+            // 
+            this.cmbRole.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.cmbRole.FormattingEnabled = true;
+            this.cmbRole.Location = new System.Drawing.Point(559, 18);
+            this.cmbRole.Name = "cmbRole";
+            this.cmbRole.Size = new System.Drawing.Size(196, 26);
+            this.cmbRole.TabIndex = 5;
+            // 
+            // label3
+            // 
+            this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.label3.AutoSize = true;
+            this.label3.Location = new System.Drawing.Point(517, 22);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(36, 18);
+            this.label3.TabIndex = 4;
+            this.label3.Text = "Role";
+            // 
+            // button1
+            // 
+            this.button1.Location = new System.Drawing.Point(280, 18);
+            this.button1.Name = "button1";
+            this.button1.Size = new System.Drawing.Size(75, 26);
+            this.button1.TabIndex = 3;
+            this.button1.Text = "Search";
+            this.button1.UseVisualStyleBackColor = true;
+            // 
+            // textBox2
+            // 
+            this.textBox2.Font = new System.Drawing.Font("Calibri", 11.25F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.textBox2.ForeColor = System.Drawing.SystemColors.GrayText;
+            this.textBox2.Location = new System.Drawing.Point(19, 18);
+            this.textBox2.Name = "textBox2";
+            this.textBox2.Size = new System.Drawing.Size(255, 26);
+            this.textBox2.TabIndex = 2;
+            this.textBox2.Text = "Type in fund name";
+            // 
             // tabCompany
             // 
             this.tabCompany.Location = new System.Drawing.Point(4, 4);
@@ -321,6 +403,18 @@
             this.tabSettings.Text = "Settings";
             this.tabSettings.UseVisualStyleBackColor = true;
             // 
+            // btnAddPersonn
+            // 
+            this.btnAddPersonn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnAddPersonn.Font = new System.Drawing.Font("Calibri", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.btnAddPersonn.Location = new System.Drawing.Point(644, 78);
+            this.btnAddPersonn.Name = "btnAddPersonn";
+            this.btnAddPersonn.Size = new System.Drawing.Size(128, 23);
+            this.btnAddPersonn.TabIndex = 2;
+            this.btnAddPersonn.Text = "Add a staff";
+            this.btnAddPersonn.UseVisualStyleBackColor = true;
+            this.btnAddPersonn.Click += new System.EventHandler(this.btnAddPersonn_Click);
+            // 
             // frmMain
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 14F);
@@ -345,6 +439,10 @@
             ((System.ComponentModel.ISupportInitialize)(this.grdFundList)).EndInit();
             this.panFundsTool.ResumeLayout(false);
             this.panFundsTool.PerformLayout();
+            this.tabPeople.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)(this.grdPeopleList)).EndInit();
+            this.panPeopleTool.ResumeLayout(false);
+            this.panPeopleTool.PerformLayout();
             this.ResumeLayout(false);
 
         }
@@ -374,6 +472,13 @@
         private System.Windows.Forms.ComboBox cmbFundCategory;
         private System.Windows.Forms.Label label2;
         private System.Windows.Forms.Button btnSearchFund;
+        private System.Windows.Forms.DataGridView grdPeopleList;
+        private System.Windows.Forms.Panel panPeopleTool;
+        private System.Windows.Forms.Button button1;
+        private System.Windows.Forms.TextBox textBox2;
+        private System.Windows.Forms.ComboBox cmbRole;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.Button btnAddPersonn;
     }
 }
 

+ 101 - 2
DDQ.cs

@@ -16,8 +16,10 @@ namespace ddq
 
         // 先hard-code公司ID,以后要按照登录用户来判断它的公司归属
         private string companyId = "CO000201PR";
+        private int userId = 123;
 
         private DataTable fundDataTable;
+        private DataTable peopleDataTable;
 
         public frmMain()
         {
@@ -33,11 +35,14 @@ namespace ddq
 
         private void tbcMain_SelectedIndexChanged(object sender, EventArgs e)
         {
+            // Request
             if (tbcMain.SelectedIndex == 0) { }
+            // Data
             else if (tbcMain.SelectedIndex == 1) {
 
                 LoadFundList(companyId);
             }
+            // Setting
             else { };
         }
 
@@ -48,10 +53,28 @@ namespace ddq
             {
                 fundDataTable = DataAccess.Get_fund_list_by_company(companyId, 1, 1000);
 
-                this.grdFundList.DataSource = fundDataTable;
+                InitFundListGrid(fundDataTable);
             }
         }
 
+        private void InitFundListGrid(DataTable dt)
+        {
+            this.grdFundList.DataSource = dt;
+
+            this.grdFundList.Columns["fund_id"].Visible = true;
+            this.grdFundList.Columns["company_id"].Visible = false;
+
+            this.grdFundList.Columns["fund_short_name"].HeaderText = "Fund Name";
+            this.grdFundList.Columns["fund_status"].HeaderText = "Operating Status";
+            this.grdFundList.Columns["management_start_date"].HeaderText = "Inception Date";
+            this.grdFundList.Columns["management_start_date"].DefaultCellStyle.Format = "yyyy-MM-dd";
+            this.grdFundList.Columns["management_end_date"].HeaderText = "Liquidate Date";
+            this.grdFundList.Columns["management_end_date"].DefaultCellStyle.Format = "yyyy-MM-dd";
+            this.grdFundList.Columns["ret_tenure"].HeaderText = "Return Since Inception";
+            this.grdFundList.Columns["ret_tenure"].DefaultCellStyle.Format = "P1";
+
+        }
+
         private void grdFundList_CellContentClick(object sender, DataGridViewCellEventArgs e)
         {
             int rowIndex = e.RowIndex;
@@ -66,10 +89,86 @@ namespace ddq
 
             if (entityId.Length == 10 && Regex.Match(entityId, "^[HM]F").Success)
             {
-                FundQ fundQ = new FundQ(entityId);
+                FundQ fundQ = new FundQ(entityId, companyId, userId);
                 fundQ.Show();
             }
 
         }
+
+        private void LoadPeopleList(string companyId)
+        {
+            if (peopleDataTable == null)
+            {
+                peopleDataTable = DataAccess.Get_dd_personnel_info(null, companyId);
+
+                InitPeopleListGrid(peopleDataTable);
+            }
+        }
+
+        private void InitPeopleListGrid(DataTable dt)
+        {
+            this.grdPeopleList.DataSource = dt;
+
+            this.grdPeopleList.Columns["personnel_id"].Visible = false;
+            this.grdPeopleList.Columns["company_id"].Visible = false;
+            this.grdPeopleList.Columns["role"].Visible = false;
+
+            this.grdPeopleList.Columns["name"].HeaderText = "Name";
+            this.grdPeopleList.Columns["role_desc"].HeaderText = "Role";
+            this.grdPeopleList.Columns["title"].HeaderText = "Title";
+            this.grdPeopleList.Columns["industry_start_year"].HeaderText = "Industry Start Year";
+            this.grdPeopleList.Columns["company_start_year"].HeaderText = "Company Start Year";
+            this.grdPeopleList.Columns["bio"].HeaderText = "Bio";
+
+        }
+
+
+        private void tbcData_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            if (tbcData.SelectedIndex == 0)
+            {
+                LoadFundList(companyId);
+            }
+            else if (tbcData.SelectedIndex == 1)
+            {
+                LoadPeopleList(companyId);
+            }
+            else { }
+        }
+        //
+        //  People
+        //
+        private void btnAddPersonn_Click(object sender, EventArgs e)
+        {
+            LoadPersonnelQ(null);
+        }
+
+        private void grdPeopleList_CellClick(object sender, DataGridViewCellEventArgs e)
+        {
+            int rowIndex = e.RowIndex;
+
+            if (rowIndex < 0) return;
+
+            string personnelId = peopleDataTable.Rows[rowIndex]["personnel_id"].ToString();
+
+            LoadPersonnelQ(personnelId);
+        }
+
+        private void LoadPersonnelQ(string personnelId)
+        {
+            using (PersonnelQ dialog = new PersonnelQ(personnelId, this.companyId, this.userId))
+            {
+                dialog.StartPosition = FormStartPosition.CenterParent;
+                DialogResult result = dialog.ShowDialog(this);
+
+                if (result == DialogResult.OK)
+                {
+                    peopleDataTable = DataAccess.Get_dd_personnel_info(null, this.companyId);
+                    
+                    this.grdPeopleList.DataSource = peopleDataTable;
+                }
+
+            }
+        }
     }
 }

+ 68 - 45
DataAccess.cs

@@ -73,26 +73,19 @@ namespace ddq
 
         }
 
-        /// <summary>
-        /// 从 mfdb 里取NAV
-        /// </summary>
-        /// <param name="fundId"></param>
-        /// <param name="startDate"></param>
-        /// <param name="endDate"></param>
-        /// <returns></returns>
-        public static DataTable Get_Nav(string fundId, DateTime? startDate, DateTime? endDate)
+
+        public static DataTable Get_dd_fund_info(string fundId, DateTime? effectiveDate, int isLatest)
         {
             MySqlConnection connection = new MySqlConnection(connectionString);
-            MySqlDataAdapter ad = new MySqlDataAdapter("sp_get_nav", connection);
+            MySqlDataAdapter ad = new MySqlDataAdapter("sp_dd_get_fund_info", connection);
 
             MySqlParameter i_fund_id = new MySqlParameter("i_fund_id", fundId);
-            MySqlParameter i_start_date = new MySqlParameter("i_start_date", startDate);
-            MySqlParameter i_end_date = new MySqlParameter("i_end_date", endDate);
+            MySqlParameter i_effective_date = new MySqlParameter("i_effective_date", effectiveDate);
+            MySqlParameter i_is_latest = new MySqlParameter("i_is_latest", isLatest);
 
             ad.SelectCommand.Parameters.Add(i_fund_id);
-            ad.SelectCommand.Parameters.Add(i_start_date);
-            ad.SelectCommand.Parameters.Add(i_end_date);
-
+            ad.SelectCommand.Parameters.Add(i_effective_date);
+            ad.SelectCommand.Parameters.Add(i_is_latest);
             ad.SelectCommand.CommandType = CommandType.StoredProcedure;
 
             DataTable dt = new DataTable();
@@ -101,46 +94,57 @@ namespace ddq
             connection.Close();
 
             return dt;
+
         }
 
-        /// <summary>
-        /// 取基金指数,benchmark_type: 0-主基准、1-分类平均
-        /// </summary>
-        /// <param name="fundId"></param>
-        /// <returns></returns>
-        public static DataTable Get_dm_fund_benchmark(string fundId)
+
+        public static int Set_dd_fund_info(string fundId, DateTime effectiveDate, string info, int status, int isValid, int userId)
         {
+            int ret = -1;
 
-            MySqlConnection connection = new MySqlConnection(connectionString);
-            MySqlDataAdapter ad = new MySqlDataAdapter("sp_get_dm_fund_benchmark", connection);
+            using (MySqlConnection connection = new MySqlConnection(connectionString))
+            {
 
-            MySqlParameter i_fund_id = new MySqlParameter("i_fund_id", fundId);
+                connection.Open();
 
-            ad.SelectCommand.Parameters.Add(i_fund_id);
+                MySqlCommand cmd = new MySqlCommand("sp_dd_set_fund_info", connection);
 
-            ad.SelectCommand.CommandType = CommandType.StoredProcedure;
+                MySqlParameter i_fund_id = new MySqlParameter("i_fund_id", fundId);
+                MySqlParameter i_effective_date = new MySqlParameter("i_effective_date", effectiveDate);
+                MySqlParameter i_info = new MySqlParameter("i_info", info);
+                MySqlParameter i_status = new MySqlParameter("i_status", status);
+                MySqlParameter i_isvalid = new MySqlParameter("i_isvalid", isValid);
+                MySqlParameter i_userid = new MySqlParameter("i_userid", userId);
 
-            DataTable dt = new DataTable();
-            ad.Fill(dt);
+                cmd.Parameters.Add(i_fund_id);
+                cmd.Parameters.Add(i_effective_date);
+                cmd.Parameters.Add(i_info);
+                cmd.Parameters.Add(i_status);
+                cmd.Parameters.Add(i_isvalid);
+                cmd.Parameters.Add(i_userid);
 
-            connection.Close();
+                cmd.CommandType = CommandType.StoredProcedure;
 
-            return dt;
+                cmd.Connection = connection;
+                cmd.ExecuteNonQuery();
+
+                ret = 1;
+            }
+
+            return ret;
         }
 
 
-        public static DataTable Get_dd_fund_info(string fundId, DateTime? effectiveDate, int isLatest)
+        public static DataTable Get_dd_personnel_info(string personnelId, string companyId)
         {
             MySqlConnection connection = new MySqlConnection(connectionString);
-            MySqlDataAdapter ad = new MySqlDataAdapter("sp_dd_get_fund_info", connection);
+            MySqlDataAdapter ad = new MySqlDataAdapter("sp_dd_get_personnel_info", connection);
 
-            MySqlParameter i_fund_id = new MySqlParameter("i_fund_id", fundId);
-            MySqlParameter i_effective_date = new MySqlParameter("i_effective_date", effectiveDate);
-            MySqlParameter i_is_latest = new MySqlParameter("i_is_latest", isLatest);
+            MySqlParameter i_personnel_id = new MySqlParameter("i_personnel_id", personnelId);
+            MySqlParameter i_company_id = new MySqlParameter("i_company_id", companyId);
 
-            ad.SelectCommand.Parameters.Add(i_fund_id);
-            ad.SelectCommand.Parameters.Add(i_effective_date);
-            ad.SelectCommand.Parameters.Add(i_is_latest);
+            ad.SelectCommand.Parameters.Add(i_personnel_id);
+            ad.SelectCommand.Parameters.Add(i_company_id);
             ad.SelectCommand.CommandType = CommandType.StoredProcedure;
 
             DataTable dt = new DataTable();
@@ -152,8 +156,9 @@ namespace ddq
 
         }
 
-
-        public static int Set_dd_fund_info(string fundId, DateTime effectiveDate, string info, int status, int isValid, int userId)
+        public static int Set_dd_personnel_info(string personnelId, DateTime effectiveDate, string companyId, 
+            string name, int? role, string title, int? companyStartYear, int? industryStartYear, string bio,
+            int status, int isValid, int userId, out string personnel_id)
         {
             int ret = -1;
 
@@ -162,32 +167,50 @@ namespace ddq
 
                 connection.Open();
 
-                MySqlCommand cmd = new MySqlCommand("sp_dd_set_fund_info", connection);
+                MySqlCommand cmd = new MySqlCommand("sp_dd_set_personnel_info", connection);
 
-                MySqlParameter i_fund_id = new MySqlParameter("i_fund_id", fundId);
+                MySqlParameter i_personnel_id = new MySqlParameter("i_personnel_id", personnelId);
                 MySqlParameter i_effective_date = new MySqlParameter("i_effective_date", effectiveDate);
-                MySqlParameter i_info = new MySqlParameter("i_info", info);
+                MySqlParameter i_company_id = new MySqlParameter("i_company_id", companyId);
+                MySqlParameter i_name = new MySqlParameter("i_name", name);
+                MySqlParameter i_role = new MySqlParameter("i_role", role);
+                MySqlParameter i_title = new MySqlParameter("i_title", title);
+                MySqlParameter i_company_start_year = new MySqlParameter("i_company_start_year", companyStartYear);
+                MySqlParameter i_industry_start_year = new MySqlParameter("i_industry_start_year", industryStartYear);
+                MySqlParameter i_bio = new MySqlParameter("i_bio", bio);
                 MySqlParameter i_status = new MySqlParameter("i_status", status);
                 MySqlParameter i_isvalid = new MySqlParameter("i_isvalid", isValid);
                 MySqlParameter i_userid = new MySqlParameter("i_userid", userId);
+                
+                MySqlParameter o_personnel_id = new MySqlParameter("o_personnel_id", MySqlDbType.String);
+                o_personnel_id.Direction = ParameterDirection.Output;
 
-                cmd.Parameters.Add(i_fund_id);
+
+                cmd.Parameters.Add(i_personnel_id);
                 cmd.Parameters.Add(i_effective_date);
-                cmd.Parameters.Add(i_info);
+                cmd.Parameters.Add(i_company_id);
+                cmd.Parameters.Add(i_name);
+                cmd.Parameters.Add(i_role);
+                cmd.Parameters.Add(i_title);
+                cmd.Parameters.Add(i_industry_start_year);
+                cmd.Parameters.Add(i_company_start_year);
+                cmd.Parameters.Add(i_bio);
                 cmd.Parameters.Add(i_status);
                 cmd.Parameters.Add(i_isvalid);
                 cmd.Parameters.Add(i_userid);
+                cmd.Parameters.Add(o_personnel_id);
 
                 cmd.CommandType = CommandType.StoredProcedure;
 
                 cmd.Connection = connection;
                 cmd.ExecuteNonQuery();
 
+                personnel_id = cmd.Parameters["o_personnel_id"].Value.ToString();
+
                 ret = 1;
             }
 
             return ret;
         }
-
     }
 }

+ 113 - 32
FundQ.Designer.cs

@@ -29,6 +29,7 @@
         private void InitializeComponent()
         {
             this.panStaticData = new System.Windows.Forms.Panel();
+            this.btnSaveGeneralInfo = new System.Windows.Forms.Button();
             this.lblDomicile = new System.Windows.Forms.Label();
             this.lblInceptionDate = new System.Windows.Forms.Label();
             this.lblCategory = new System.Windows.Forms.Label();
@@ -37,6 +38,8 @@
             this.tbcFund = new System.Windows.Forms.TabControl();
             this.tabGeneralInfo = new System.Windows.Forms.TabPage();
             this.panGeneralInfoMain = new System.Windows.Forms.Panel();
+            this.btnAddManager = new System.Windows.Forms.Button();
+            this.label16 = new System.Windows.Forms.Label();
             this.txtPolicyOfClosingFund = new System.Windows.Forms.TextBox();
             this.label14 = new System.Windows.Forms.Label();
             this.grdTER = new System.Windows.Forms.DataGridView();
@@ -64,9 +67,12 @@
             this.label2 = new System.Windows.Forms.Label();
             this.txtInvestmentObjective = new System.Windows.Forms.TextBox();
             this.label1 = new System.Windows.Forms.Label();
-            this.btnSaveGeneralInfo = new System.Windows.Forms.Button();
             this.tabProcess = new System.Windows.Forms.TabPage();
             this.panel2 = new System.Windows.Forms.Panel();
+            this.label18 = new System.Windows.Forms.Label();
+            this.txtOverrunPriceTarget = new System.Windows.Forms.TextBox();
+            this.label17 = new System.Windows.Forms.Label();
+            this.chkPriceTarget = new System.Windows.Forms.CheckBox();
             this.chkDerivatesForLeverage = new System.Windows.Forms.CheckBox();
             this.chkDerivativesForMarket = new System.Windows.Forms.CheckBox();
             this.chkDerivatesForHedging = new System.Windows.Forms.CheckBox();
@@ -81,7 +87,7 @@
             this.tabRisk = new System.Windows.Forms.TabPage();
             this.tabOwnership = new System.Windows.Forms.TabPage();
             this.tabPerformance = new System.Windows.Forms.TabPage();
-            this.label16 = new System.Windows.Forms.Label();
+            this.ofdProcessDiagram = new System.Windows.Forms.OpenFileDialog();
             this.panStaticData.SuspendLayout();
             this.tbcFund.SuspendLayout();
             this.tabGeneralInfo.SuspendLayout();
@@ -108,6 +114,18 @@
             this.panStaticData.Size = new System.Drawing.Size(1067, 76);
             this.panStaticData.TabIndex = 0;
             // 
+            // btnSaveGeneralInfo
+            // 
+            this.btnSaveGeneralInfo.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnSaveGeneralInfo.Location = new System.Drawing.Point(980, 39);
+            this.btnSaveGeneralInfo.Name = "btnSaveGeneralInfo";
+            this.btnSaveGeneralInfo.Size = new System.Drawing.Size(75, 28);
+            this.btnSaveGeneralInfo.TabIndex = 0;
+            this.btnSaveGeneralInfo.Text = "Save";
+            this.btnSaveGeneralInfo.UseVisualStyleBackColor = true;
+            this.btnSaveGeneralInfo.Click += new System.EventHandler(this.btnSaveGeneralInfo_Click);
+            // 
             // lblDomicile
             // 
             this.lblDomicile.AutoSize = true;
@@ -187,6 +205,7 @@
             // 
             this.panGeneralInfoMain.AutoScroll = true;
             this.panGeneralInfoMain.BackColor = System.Drawing.Color.Transparent;
+            this.panGeneralInfoMain.Controls.Add(this.btnAddManager);
             this.panGeneralInfoMain.Controls.Add(this.label16);
             this.panGeneralInfoMain.Controls.Add(this.txtPolicyOfClosingFund);
             this.panGeneralInfoMain.Controls.Add(this.label14);
@@ -207,6 +226,27 @@
             this.panGeneralInfoMain.Size = new System.Drawing.Size(1053, 562);
             this.panGeneralInfoMain.TabIndex = 14;
             // 
+            // btnAddManager
+            // 
+            this.btnAddManager.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnAddManager.Font = new System.Drawing.Font("Calibri", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.btnAddManager.Location = new System.Drawing.Point(839, 369);
+            this.btnAddManager.Name = "btnAddManager";
+            this.btnAddManager.Size = new System.Drawing.Size(141, 23);
+            this.btnAddManager.TabIndex = 15;
+            this.btnAddManager.Text = "Add a manager";
+            this.btnAddManager.UseVisualStyleBackColor = true;
+            this.btnAddManager.Click += new System.EventHandler(this.btnAddManager_Click);
+            // 
+            // label16
+            // 
+            this.label16.AutoSize = true;
+            this.label16.Location = new System.Drawing.Point(24, 936);
+            this.label16.Name = "label16";
+            this.label16.Size = new System.Drawing.Size(0, 18);
+            this.label16.TabIndex = 14;
+            // 
             // txtPolicyOfClosingFund
             // 
             this.txtPolicyOfClosingFund.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
@@ -214,7 +254,7 @@
             this.txtPolicyOfClosingFund.Location = new System.Drawing.Point(24, 779);
             this.txtPolicyOfClosingFund.Multiline = true;
             this.txtPolicyOfClosingFund.Name = "txtPolicyOfClosingFund";
-            this.txtPolicyOfClosingFund.Size = new System.Drawing.Size(673, 124);
+            this.txtPolicyOfClosingFund.Size = new System.Drawing.Size(956, 79);
             this.txtPolicyOfClosingFund.TabIndex = 12;
             // 
             // label14
@@ -259,10 +299,10 @@
             this.grbFees.Controls.Add(this.label6);
             this.grbFees.Location = new System.Drawing.Point(370, 524);
             this.grbFees.Name = "grbFees";
-            this.grbFees.Size = new System.Drawing.Size(644, 218);
+            this.grbFees.Size = new System.Drawing.Size(610, 218);
             this.grbFees.TabIndex = 9;
             this.grbFees.TabStop = false;
-            this.grbFees.Text = "Current Fees";
+            this.grbFees.Text = "Current Fees %";
             // 
             // txtTrusteeFee
             // 
@@ -388,15 +428,19 @@
             // 
             // grdPortfolioManager
             // 
+            this.grdPortfolioManager.AllowUserToAddRows = false;
             this.grdPortfolioManager.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
             this.grdPortfolioManager.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.DisplayedCells;
             this.grdPortfolioManager.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
             this.grdPortfolioManager.Location = new System.Drawing.Point(24, 398);
+            this.grdPortfolioManager.MultiSelect = false;
             this.grdPortfolioManager.Name = "grdPortfolioManager";
             this.grdPortfolioManager.RowTemplate.Height = 23;
-            this.grdPortfolioManager.Size = new System.Drawing.Size(990, 85);
+            this.grdPortfolioManager.Size = new System.Drawing.Size(956, 85);
             this.grdPortfolioManager.TabIndex = 7;
+            this.grdPortfolioManager.CellValidating += new System.Windows.Forms.DataGridViewCellValidatingEventHandler(this.grdPortfolioManager_CellValidating);
+            this.grdPortfolioManager.Validating += new System.ComponentModel.CancelEventHandler(this.grdPortfolioManager_Validating);
             // 
             // label4
             // 
@@ -414,7 +458,7 @@
             this.txtInvestmentPhilosophy.Location = new System.Drawing.Point(24, 255);
             this.txtInvestmentPhilosophy.Multiline = true;
             this.txtInvestmentPhilosophy.Name = "txtInvestmentPhilosophy";
-            this.txtInvestmentPhilosophy.Size = new System.Drawing.Size(990, 95);
+            this.txtInvestmentPhilosophy.Size = new System.Drawing.Size(956, 95);
             this.txtInvestmentPhilosophy.TabIndex = 5;
             // 
             // txtBenchmark
@@ -422,8 +466,9 @@
             this.txtBenchmark.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
             this.txtBenchmark.Location = new System.Drawing.Point(24, 179);
+            this.txtBenchmark.MaxLength = 260;
             this.txtBenchmark.Name = "txtBenchmark";
-            this.txtBenchmark.Size = new System.Drawing.Size(990, 26);
+            this.txtBenchmark.Size = new System.Drawing.Size(956, 26);
             this.txtBenchmark.TabIndex = 4;
             // 
             // label3
@@ -451,7 +496,7 @@
             this.txtInvestmentObjective.Location = new System.Drawing.Point(24, 39);
             this.txtInvestmentObjective.Multiline = true;
             this.txtInvestmentObjective.Name = "txtInvestmentObjective";
-            this.txtInvestmentObjective.Size = new System.Drawing.Size(990, 95);
+            this.txtInvestmentObjective.Size = new System.Drawing.Size(956, 95);
             this.txtInvestmentObjective.TabIndex = 1;
             // 
             // label1
@@ -463,18 +508,6 @@
             this.label1.TabIndex = 0;
             this.label1.Text = "Investment Objective";
             // 
-            // btnSaveGeneralInfo
-            // 
-            this.btnSaveGeneralInfo.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.btnSaveGeneralInfo.Location = new System.Drawing.Point(980, 39);
-            this.btnSaveGeneralInfo.Name = "btnSaveGeneralInfo";
-            this.btnSaveGeneralInfo.Size = new System.Drawing.Size(75, 28);
-            this.btnSaveGeneralInfo.TabIndex = 0;
-            this.btnSaveGeneralInfo.Text = "Save";
-            this.btnSaveGeneralInfo.UseVisualStyleBackColor = true;
-            this.btnSaveGeneralInfo.Click += new System.EventHandler(this.btnSaveGeneralInfo_Click);
-            // 
             // tabProcess
             // 
             this.tabProcess.AutoScroll = true;
@@ -490,6 +523,10 @@
             // panel2
             // 
             this.panel2.AutoScroll = true;
+            this.panel2.Controls.Add(this.label18);
+            this.panel2.Controls.Add(this.txtOverrunPriceTarget);
+            this.panel2.Controls.Add(this.label17);
+            this.panel2.Controls.Add(this.chkPriceTarget);
             this.panel2.Controls.Add(this.chkDerivatesForLeverage);
             this.panel2.Controls.Add(this.chkDerivativesForMarket);
             this.panel2.Controls.Add(this.chkDerivatesForHedging);
@@ -507,6 +544,46 @@
             this.panel2.Size = new System.Drawing.Size(1053, 562);
             this.panel2.TabIndex = 0;
             // 
+            // label18
+            // 
+            this.label18.AutoSize = true;
+            this.label18.Location = new System.Drawing.Point(15, 704);
+            this.label18.Name = "label18";
+            this.label18.Size = new System.Drawing.Size(363, 18);
+            this.label18.TabIndex = 15;
+            this.label18.Text = "-----------------------------------------------------------------------";
+            // 
+            // txtOverrunPriceTarget
+            // 
+            this.txtOverrunPriceTarget.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.txtOverrunPriceTarget.Location = new System.Drawing.Point(18, 566);
+            this.txtOverrunPriceTarget.Multiline = true;
+            this.txtOverrunPriceTarget.Name = "txtOverrunPriceTarget";
+            this.txtOverrunPriceTarget.Size = new System.Drawing.Size(961, 56);
+            this.txtOverrunPriceTarget.TabIndex = 14;
+            // 
+            // label17
+            // 
+            this.label17.AutoSize = true;
+            this.label17.Location = new System.Drawing.Point(18, 545);
+            this.label17.Name = "label17";
+            this.label17.Size = new System.Drawing.Size(708, 18);
+            this.label17.TabIndex = 13;
+            this.label17.Text = "Describe to what extent can the fund managers overrun these set prices before tri" +
+    "mming/selling off the position?";
+            // 
+            // chkPriceTarget
+            // 
+            this.chkPriceTarget.AutoSize = true;
+            this.chkPriceTarget.Location = new System.Drawing.Point(18, 510);
+            this.chkPriceTarget.Name = "chkPriceTarget";
+            this.chkPriceTarget.Size = new System.Drawing.Size(395, 22);
+            this.chkPriceTarget.TabIndex = 12;
+            this.chkPriceTarget.Text = "Are price targets assigned to every security in the portfolio?";
+            this.chkPriceTarget.UseVisualStyleBackColor = true;
+            this.chkPriceTarget.CheckedChanged += new System.EventHandler(this.chkPriceTarget_CheckedChanged);
+            // 
             // chkDerivatesForLeverage
             // 
             this.chkDerivatesForLeverage.AutoSize = true;
@@ -565,6 +642,7 @@
             this.chkUseDerivatives.TabIndex = 6;
             this.chkUseDerivatives.Text = "Does the fund actually use derivatives for now?";
             this.chkUseDerivatives.UseVisualStyleBackColor = true;
+            this.chkUseDerivatives.CheckedChanged += new System.EventHandler(this.chkUseDerivatives_CheckedChanged);
             // 
             // chkAllowDerivatives
             // 
@@ -581,20 +659,21 @@
             // 
             this.btnUploadProcessDiagram.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
-            this.btnUploadProcessDiagram.Location = new System.Drawing.Point(955, 260);
+            this.btnUploadProcessDiagram.Location = new System.Drawing.Point(925, 260);
             this.btnUploadProcessDiagram.Name = "btnUploadProcessDiagram";
-            this.btnUploadProcessDiagram.Size = new System.Drawing.Size(75, 23);
+            this.btnUploadProcessDiagram.Size = new System.Drawing.Size(54, 23);
             this.btnUploadProcessDiagram.TabIndex = 3;
             this.btnUploadProcessDiagram.Text = "Upload";
             this.btnUploadProcessDiagram.UseVisualStyleBackColor = true;
+            this.btnUploadProcessDiagram.Click += new System.EventHandler(this.btnUploadProcessDiagram_Click);
             // 
             // btnDeleteProcessDiagram
             // 
             this.btnDeleteProcessDiagram.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
-            this.btnDeleteProcessDiagram.Location = new System.Drawing.Point(874, 260);
+            this.btnDeleteProcessDiagram.Location = new System.Drawing.Point(816, 260);
             this.btnDeleteProcessDiagram.Name = "btnDeleteProcessDiagram";
-            this.btnDeleteProcessDiagram.Size = new System.Drawing.Size(75, 23);
+            this.btnDeleteProcessDiagram.Size = new System.Drawing.Size(54, 23);
             this.btnDeleteProcessDiagram.TabIndex = 2;
             this.btnDeleteProcessDiagram.Text = "Delete";
             this.btnDeleteProcessDiagram.UseVisualStyleBackColor = true;
@@ -606,7 +685,7 @@
             this.picFundProcess.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
             this.picFundProcess.Location = new System.Drawing.Point(18, 36);
             this.picFundProcess.Name = "picFundProcess";
-            this.picFundProcess.Size = new System.Drawing.Size(1012, 218);
+            this.picFundProcess.Size = new System.Drawing.Size(961, 218);
             this.picFundProcess.TabIndex = 1;
             this.picFundProcess.TabStop = false;
             // 
@@ -647,13 +726,9 @@
             this.tabPerformance.Text = "Performance";
             this.tabPerformance.UseVisualStyleBackColor = true;
             // 
-            // label16
+            // ofdProcessDiagram
             // 
-            this.label16.AutoSize = true;
-            this.label16.Location = new System.Drawing.Point(24, 936);
-            this.label16.Name = "label16";
-            this.label16.Size = new System.Drawing.Size(0, 18);
-            this.label16.TabIndex = 14;
+            this.ofdProcessDiagram.FileName = "*.png";
             // 
             // FundQ
             // 
@@ -741,5 +816,11 @@
         private System.Windows.Forms.CheckBox chkUseDerivatives;
         private System.Windows.Forms.Panel panGeneralInfoMain;
         private System.Windows.Forms.Label label16;
+        private System.Windows.Forms.CheckBox chkPriceTarget;
+        private System.Windows.Forms.Label label18;
+        private System.Windows.Forms.TextBox txtOverrunPriceTarget;
+        private System.Windows.Forms.Label label17;
+        private System.Windows.Forms.OpenFileDialog ofdProcessDiagram;
+        private System.Windows.Forms.Button btnAddManager;
     }
 }

+ 157 - 87
FundQ.cs

@@ -10,6 +10,7 @@ using System.Windows.Forms;
 using System.Text.Json;
 using System.Text.Json.Serialization;
 using System.Drawing.Text;
+using System.IO;
 
 
 namespace ddq
@@ -18,15 +19,18 @@ namespace ddq
     {
 
         private string fundId;
-        private int userId = 123;
+        private string companyId;
+        private int userId;
         private DataTable fundInfoTable;
 
 
-        public FundQ(string fundId)
+        public FundQ(string fundId, string companyId, int userId)
         {
             InitializeComponent();
 
             this.fundId = fundId;
+            this.companyId = companyId;
+            this.userId = userId;
 
             InitializeData();
             
@@ -63,17 +67,19 @@ namespace ddq
 
                 if (root.ValueKind != JsonValueKind.Undefined)
                 {
-
-                    this.txtInvestmentObjective.Text = Json2Text(root, "investmentObjective");
-                    this.txtBenchmark.Text = Json2Text(root, "benchmark");
-                    this.txtInvestmentPhilosophy.Text = Json2Text(root, "investmentPhilosophy");
+                    //
+                    // General Info
+                    //
+                    this.txtInvestmentObjective.Text = Utility.Json2Text(root, "investmentObjective");
+                    this.txtBenchmark.Text = Utility.Json2Text(root, "benchmark");
+                    this.txtInvestmentPhilosophy.Text = Utility.Json2Text(root, "investmentPhilosophy");
 
                     JsonElement elmPM;
                     hasPM = root.TryGetProperty("portfolioManagers", out elmPM);
                     
                     if (hasPM == true)
                     {
-                        dtPM = Json2Table(elmPM);
+                        dtPM = Utility.Json2Table(elmPM);
                         InitPortfolioManagerGrid(dtPM);
                     }
 
@@ -82,11 +88,29 @@ namespace ddq
 
                     if (hasTER == true)
                     {
-                        dtTER = Json2Table(elmTER);
+                        dtTER = Utility.Json2Table(elmTER);
                         InitTERGrid(dtTER);
                     }
 
-                    
+                    //
+                    // Process
+                    //
+                    this.chkAllowDerivatives.Checked = Utility.Json2Text(root, "allowDerivatives").ToLower() == "true" ? true : false;
+                    this.chkUseDerivatives.Checked = Utility.Json2Text(root, "useDerivatives").ToLower() == "true" ? true : false;
+                    this.chkDerivativesForEfficent.Checked = this.chkUseDerivatives.Checked == true ? Utility.Json2Text(root, "drvForEffPM").ToLower() == "true" ? true : false : false;
+                    if (this.chkUseDerivatives.Checked == true)
+                    {
+                        this.chkDerivativesForEfficent.Checked = Utility.Json2Text(root, "drvForEffPM").ToLower() == "true" ? true : false;
+                        this.chkDerivatesForHedging.Checked = Utility.Json2Text(root, "drvForHedging").ToLower() == "true" ? true : false;
+                        this.chkDerivativesForMarket.Checked = Utility.Json2Text(root, "drvForMktAcs").ToLower() == "true" ? true : false;
+                        this.chkDerivatesForLeverage.Checked = Utility.Json2Text(root, "drvForLeverage").ToLower() == "true" ? true : false;
+                    }
+                    this.chkPriceTarget.Checked = Utility.Json2Text(root, "priceTarget").ToLower() == "true" ? true : false;
+                    if (this.chkPriceTarget.Checked == true)
+                    {
+                        this.txtOverrunPriceTarget.Text = Utility.Json2Text(root, "overrunPriceTarget");
+                    }
+
                 }
 
             }
@@ -96,6 +120,7 @@ namespace ddq
                 dtPM = new DataTable();
 
                 // 没有基金经理数据时,初始化表
+                dtPM.Columns.Add("personnel_id", typeof(string));
                 dtPM.Columns.Add("name", typeof(string));
                 dtPM.Columns.Add("startDate", typeof(DateTime));
                 dtPM.Columns.Add("endDate", typeof(DateTime));
@@ -128,11 +153,14 @@ namespace ddq
         private void InitPortfolioManagerGrid(DataTable dt)
         {
             this.grdPortfolioManager.DataSource = dt;
+
+            this.grdPortfolioManager.Columns["personnel_id"].Visible = false;
+
             this.grdPortfolioManager.Columns["name"].HeaderText = "Manager Name";
             this.grdPortfolioManager.Columns["name"].DisplayIndex = 0;
 
             this.grdPortfolioManager.Columns["startDate"].HeaderText = "Start Date";
-            this.grdPortfolioManager.Columns["startDate"].DefaultCellStyle.Format = "yyyy-MM-dd";
+            this.grdPortfolioManager.Columns["startDate"].DefaultCellStyle.Format = "d";
             this.grdPortfolioManager.Columns["startDate"].DisplayIndex = 1;
 
             this.grdPortfolioManager.Columns["endDate"].HeaderText = "End Date";
@@ -155,81 +183,6 @@ namespace ddq
 
         }
 
-
-        /// <summary>
-        /// JsonElment 转为字符串,若输入为空则输出""
-        /// </summary>
-        /// <param name="jsonElement"></param>
-        /// <returns></returns>
-        public static string Json2Text(JsonElement jsonElement, string propertyName)
-        {
-            string str = "";
-            JsonElement elm;
-
-            if (propertyName == null) return str;
-
-            bool hasProperty = jsonElement.TryGetProperty(propertyName, out elm);
-
-            if (hasProperty == true && elm.ValueKind != JsonValueKind.Undefined)
-            {
-                str = elm.ToString().Trim();
-            }
-
-            return str;
-        }
-
-        public static DataTable Json2Table(JsonElement jsonElement)
-        {
-            DataTable dataTable = new DataTable();
-
-            // 如果解析出的是数组
-            if (jsonElement.ValueKind == JsonValueKind.Array)
-            {
-                // 遍历数组元素
-                foreach (JsonElement element in jsonElement.EnumerateArray())
-                {
-                    // 如果是第一次遍历,元素包含列定义信息,需要创建列
-                    if (dataTable.Columns.Count == 0)
-                    {
-                        // 遍历第一个对象的属性来创建列
-                        foreach (JsonProperty property in element.EnumerateObject())
-                        {
-                            dataTable.Columns.Add(property.Name);
-                        }
-                    }
-
-                    // 创建新行并填充数据
-                    DataRow newRow = dataTable.NewRow();
-                    foreach (JsonProperty property in element.EnumerateObject())
-                    {
-                        newRow[property.Name] = property.Value.ToString();
-                    }
-                    dataTable.Rows.Add(newRow);
-                }
-            }
-
-            return dataTable;
-
-        }
-
-        public static List<Dictionary<string, object>> DataTable2List(DataTable dataTable)
-        {
-            var records = new List<Dictionary<string, object>>();
-
-            foreach (DataRow row in dataTable.Rows)
-            {
-                var record = new Dictionary<string, object>();
-                foreach (DataColumn col in dataTable.Columns)
-                {
-                    // 处理DBNull值
-                    record[col.ColumnName] = row[col] == DBNull.Value ? null : row[col];
-                }
-                records.Add(record);
-            }
-
-            return records;
-        }
-
         private void FundQ_Load(object sender, EventArgs e)
         {
         }
@@ -246,8 +199,16 @@ namespace ddq
                     investmentObjective = this.txtInvestmentObjective.Text,
                     benchmark = this.txtBenchmark.Text,
                     investmentPhilosophy = this.txtInvestmentPhilosophy.Text,
-                    portfolioManagers = DataTable2List((DataTable)this.grdPortfolioManager.DataSource),
-                    ter = DataTable2List((DataTable)this.grdTER.DataSource),
+                    portfolioManagers = Utility.DataTable2List((DataTable)this.grdPortfolioManager.DataSource),
+                    ter = Utility.DataTable2List((DataTable)this.grdTER.DataSource),
+                    allowDerivatives = this.chkAllowDerivatives.Checked,
+                    useDerivatives = this.chkUseDerivatives.Checked,
+                    drvForEffPM = this.chkDerivativesForEfficent.Checked,
+                    drvForHedging = this.chkDerivatesForHedging.Checked,
+                    drvForMktAcs = this.chkDerivativesForMarket.Checked,
+                    drvForLeverage = this.chkDerivatesForLeverage.Checked,
+                    priceTarget = this.chkPriceTarget.Checked,
+                    overrunPriceTarget = this.txtOverrunPriceTarget.Text,
                     updateTime = DateTime.Now
                 };
 
@@ -319,5 +280,114 @@ namespace ddq
         {
           
         }
+
+        private void chkUseDerivatives_CheckedChanged(object sender, EventArgs e)
+        {
+
+            bool isChecked = chkUseDerivatives.Checked;
+
+            this.chkDerivativesForEfficent.Enabled = isChecked;
+            this.chkDerivatesForHedging.Enabled = isChecked;
+            this.chkDerivativesForMarket.Enabled = isChecked;
+            this.chkDerivatesForLeverage.Enabled = isChecked;
+
+            if (isChecked == false) 
+            {
+                this.chkDerivativesForEfficent.Checked = false;
+                this.chkDerivatesForHedging.Checked = false;
+                this.chkDerivativesForMarket.Checked = false;
+                this.chkDerivatesForLeverage.Checked = false;
+            }
+
+        }
+
+        private void chkPriceTarget_CheckedChanged(object sender, EventArgs e)
+        {
+            bool isChecked = chkPriceTarget.Checked;
+
+            if (!isChecked) { this.txtOverrunPriceTarget.Text = ""; }
+        }
+
+        private void btnUploadProcessDiagram_Click(object sender, EventArgs e)
+        {
+            this.ofdProcessDiagram.Title = "Upload Diagram File -- FAKE";
+
+            if (this.ofdProcessDiagram.ShowDialog() == DialogResult.OK)
+            {
+                // TODO: upload files to server. let's fake it for now
+                string filePath = ofdProcessDiagram.FileName;
+                string fileName = Path.GetFileName(filePath);
+
+                try
+                {
+                }
+                catch (Exception ex)
+                {
+                    MessageBox.Show("File was not able to be uploaded:" + ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
+                }
+
+            }
+        }
+
+        private void btnAddManager_Click(object sender, EventArgs e)
+        {
+            using (PersonSelectionDialog dialog = new PersonSelectionDialog(companyId))
+            {
+                dialog.StartPosition = FormStartPosition.CenterParent;
+                DialogResult result = dialog.ShowDialog(this);
+
+                if (result == DialogResult.OK && dialog.PersonnelId != "")
+                {
+                    DataTable dt = (DataTable)this.grdPortfolioManager.DataSource;
+                    
+                    DataRow row = dt.NewRow();
+                    row["personnel_id"] = dialog.PersonnelId;
+                    row["name"] = dialog.PersonnelName;
+                    row["startDate"] = dialog.StartDate.Date;
+                    dt.Rows.Add(row);
+                }
+                
+            }
+        }
+
+        private void grdPortfolioManager_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
+        {
+            int rowIndex = e.RowIndex;
+            int columnIndex = e.ColumnIndex;
+
+            if (rowIndex < 0 || columnIndex < 0) { return; }
+
+
+            // 先清除可能存在的旧错误提示
+            grdPortfolioManager.Rows[rowIndex].ErrorText = "";
+
+            // 如果转换失败,说明输入的不是有效日期
+            bool isPass = DateTime.TryParse(grdPortfolioManager.Rows[rowIndex].Cells["startDate"].Value.ToString(), out DateTime newDate);
+
+            if (!isPass || newDate < new DateTime(1900, 1, 1) || newDate > DateTime.Today)
+            {
+                e.Cancel = true;
+                grdPortfolioManager.Rows[columnIndex].ErrorText = "Please enter a proper start date";
+                return;
+            }
+
+
+            if (grdPortfolioManager.Rows[rowIndex].Cells["endDate"].Value.ToString() == "") return;
+
+            isPass = DateTime.TryParse(grdPortfolioManager.Rows[rowIndex].Cells["endDate"].Value.ToString(), out newDate);
+
+            if (!isPass || newDate < new DateTime(1900, 1, 1) || newDate > DateTime.Today)
+            {
+                e.Cancel = true;
+                grdPortfolioManager.Rows[columnIndex].ErrorText = "Please enter a proper end date"; ;
+                return;
+            }
+
+        }
+
+        private void grdPortfolioManager_Validating(object sender, CancelEventArgs e)
+        {
+
+        }
     }
 }

+ 3 - 0
FundQ.resx

@@ -117,4 +117,7 @@
   <resheader name="writer">
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
+  <metadata name="ofdProcessDiagram.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
 </root>

+ 184 - 0
PersonSelection.Designer.cs

@@ -0,0 +1,184 @@
+namespace ddq
+{
+    partial class PersonSelectionDialog
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.panel1 = new System.Windows.Forms.Panel();
+            this.label1 = new System.Windows.Forms.Label();
+            this.label2 = new System.Windows.Forms.Label();
+            this.chkAll = new System.Windows.Forms.CheckBox();
+            this.chkPM = new System.Windows.Forms.CheckBox();
+            this.chkResearcher = new System.Windows.Forms.CheckBox();
+            this.grdStaffList = new System.Windows.Forms.DataGridView();
+            this.btnOK = new System.Windows.Forms.Button();
+            this.lblMessageForNoStaff = new System.Windows.Forms.Label();
+            this.panel1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.grdStaffList)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // panel1
+            // 
+            this.panel1.Controls.Add(this.lblMessageForNoStaff);
+            this.panel1.Controls.Add(this.btnOK);
+            this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom;
+            this.panel1.Location = new System.Drawing.Point(0, 368);
+            this.panel1.Name = "panel1";
+            this.panel1.Size = new System.Drawing.Size(519, 46);
+            this.panel1.TabIndex = 0;
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Font = new System.Drawing.Font("Calibri", 11.25F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label1.Location = new System.Drawing.Point(22, 21);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(182, 18);
+            this.label1.TabIndex = 1;
+            this.label1.Text = "Select a staff in the list below";
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(25, 60);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(36, 18);
+            this.label2.TabIndex = 2;
+            this.label2.Text = "Role";
+            // 
+            // chkAll
+            // 
+            this.chkAll.AutoSize = true;
+            this.chkAll.Checked = true;
+            this.chkAll.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chkAll.Location = new System.Drawing.Point(77, 59);
+            this.chkAll.Name = "chkAll";
+            this.chkAll.Size = new System.Drawing.Size(44, 22);
+            this.chkAll.TabIndex = 3;
+            this.chkAll.Text = "All";
+            this.chkAll.UseVisualStyleBackColor = true;
+            this.chkAll.CheckedChanged += new System.EventHandler(this.chkAll_CheckedChanged);
+            // 
+            // chkPM
+            // 
+            this.chkPM.AutoSize = true;
+            this.chkPM.Location = new System.Drawing.Point(146, 59);
+            this.chkPM.Name = "chkPM";
+            this.chkPM.Size = new System.Drawing.Size(138, 22);
+            this.chkPM.TabIndex = 4;
+            this.chkPM.Text = "Portfolio Manager";
+            this.chkPM.UseVisualStyleBackColor = true;
+            this.chkPM.CheckedChanged += new System.EventHandler(this.chkPM_CheckedChanged);
+            // 
+            // chkResearcher
+            // 
+            this.chkResearcher.AutoSize = true;
+            this.chkResearcher.Location = new System.Drawing.Point(304, 59);
+            this.chkResearcher.Name = "chkResearcher";
+            this.chkResearcher.Size = new System.Drawing.Size(96, 22);
+            this.chkResearcher.TabIndex = 5;
+            this.chkResearcher.Text = "Researcher";
+            this.chkResearcher.UseVisualStyleBackColor = true;
+            this.chkResearcher.CheckedChanged += new System.EventHandler(this.chkResearcher_CheckedChanged);
+            // 
+            // grdStaffList
+            // 
+            this.grdStaffList.AllowUserToAddRows = false;
+            this.grdStaffList.AllowUserToDeleteRows = false;
+            this.grdStaffList.AllowUserToOrderColumns = true;
+            this.grdStaffList.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+            this.grdStaffList.Location = new System.Drawing.Point(28, 106);
+            this.grdStaffList.Name = "grdStaffList";
+            this.grdStaffList.ReadOnly = true;
+            this.grdStaffList.RowTemplate.Height = 23;
+            this.grdStaffList.Size = new System.Drawing.Size(458, 234);
+            this.grdStaffList.TabIndex = 6;
+            this.grdStaffList.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.grdStaffList_CellClick);
+            this.grdStaffList.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.grdStaffList_CellContentClick);
+            // 
+            // btnOK
+            // 
+            this.btnOK.Location = new System.Drawing.Point(411, 12);
+            this.btnOK.Name = "btnOK";
+            this.btnOK.Size = new System.Drawing.Size(75, 23);
+            this.btnOK.TabIndex = 0;
+            this.btnOK.Text = "OK";
+            this.btnOK.UseVisualStyleBackColor = true;
+            this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
+            // 
+            // lblMessageForNoStaff
+            // 
+            this.lblMessageForNoStaff.AutoSize = true;
+            this.lblMessageForNoStaff.ForeColor = System.Drawing.Color.Red;
+            this.lblMessageForNoStaff.Location = new System.Drawing.Point(15, 14);
+            this.lblMessageForNoStaff.Name = "lblMessageForNoStaff";
+            this.lblMessageForNoStaff.Size = new System.Drawing.Size(280, 18);
+            this.lblMessageForNoStaff.TabIndex = 1;
+            this.lblMessageForNoStaff.Text = "Please add at least one staff in <People> Tab";
+            this.lblMessageForNoStaff.Visible = false;
+            // 
+            // PersonSelectionDialog
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 18F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.BackColor = System.Drawing.Color.WhiteSmoke;
+            this.ClientSize = new System.Drawing.Size(519, 414);
+            this.Controls.Add(this.grdStaffList);
+            this.Controls.Add(this.chkResearcher);
+            this.Controls.Add(this.chkPM);
+            this.Controls.Add(this.chkAll);
+            this.Controls.Add(this.label2);
+            this.Controls.Add(this.label1);
+            this.Controls.Add(this.panel1);
+            this.Font = new System.Drawing.Font("Calibri", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+            this.MaximizeBox = false;
+            this.MinimizeBox = false;
+            this.Name = "PersonSelectionDialog";
+            this.ShowInTaskbar = false;
+            this.Text = "Staff Selection";
+            this.panel1.ResumeLayout(false);
+            this.panel1.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.grdStaffList)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Panel panel1;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.CheckBox chkAll;
+        private System.Windows.Forms.CheckBox chkPM;
+        private System.Windows.Forms.CheckBox chkResearcher;
+        private System.Windows.Forms.DataGridView grdStaffList;
+        private System.Windows.Forms.Button btnOK;
+        private System.Windows.Forms.Label lblMessageForNoStaff;
+    }
+}

+ 125 - 0
PersonSelection.cs

@@ -0,0 +1,125 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace ddq
+{
+    public partial class PersonSelectionDialog : Form
+    {
+
+        private string companyId;
+        public string PersonnelId { get; private set; }
+        public string PersonnelName { get; private set; }
+        public DateTime StartDate { get; private set; }
+
+        private DataTable peopleDataTable;
+
+        public PersonSelectionDialog(string companyId)
+        {
+            InitializeComponent();
+
+            this.companyId = companyId;
+
+            InitializeData();
+        }
+
+
+        private void InitializeData()
+        {
+            LoadPeopleList(companyId);
+        }
+
+
+        private void LoadPeopleList(string companyId)
+        {
+            peopleDataTable = DataAccess.Get_dd_personnel_info(null, companyId);
+
+            InitPeopleListGrid(peopleDataTable);
+
+        }
+
+        private void InitPeopleListGrid(DataTable dataTable)
+        {
+
+            if (dataTable == null || dataTable.Rows.Count == 0)
+            {
+                this.lblMessageForNoStaff.Visible = true;
+
+                return;
+            }
+
+            DataView dw = new DataView(dataTable);
+
+            string filter = null;
+            if (chkPM.Checked)
+            {
+                filter = "role = 'Portfolio Manager'";
+                if (chkResearcher.Checked) { filter += "or role = 'Researcher'"; }
+            } else if (chkResearcher.Checked) { filter = "role = 'Researcher'"; }
+
+            dw.RowFilter = filter;
+
+            this.grdStaffList.DataSource = dw;
+
+            this.grdStaffList.Columns["personnel_id"].Visible = false;
+            this.grdStaffList.Columns["company_id"].Visible = false;
+
+            this.grdStaffList.Columns["name"].HeaderText = "Name";
+            this.grdStaffList.Columns["role"].Visible = false;
+            this.grdStaffList.Columns["title"].HeaderText = "Title";
+            this.grdStaffList.Columns["industry_start_year"].Visible = false;
+            this.grdStaffList.Columns["company_start_year"].HeaderText = "Company Start Year";
+            this.grdStaffList.Columns["bio"].Visible = false;
+
+        }
+
+
+        private void btnOK_Click(object sender, EventArgs e)
+        {
+            this.DialogResult = DialogResult.OK;
+        }
+
+        private void chkAll_CheckedChanged(object sender, EventArgs e)
+        {
+            
+            this.chkPM.Checked = this.chkAll.Checked;
+            this.chkResearcher.Checked = chkAll.Checked;
+
+            InitPeopleListGrid(peopleDataTable);
+
+        }
+
+        private void chkPM_CheckedChanged(object sender, EventArgs e)
+        {
+            InitPeopleListGrid(peopleDataTable);
+        }
+
+        private void chkResearcher_CheckedChanged(object sender, EventArgs e)
+        {
+            InitPeopleListGrid(peopleDataTable);
+        }
+
+        private void grdStaffList_CellContentClick(object sender, DataGridViewCellEventArgs e)
+        {
+        }
+
+        private void grdStaffList_CellClick(object sender, DataGridViewCellEventArgs e)
+        {
+            int rowIndex = e.RowIndex;
+
+            if (rowIndex < 0) return;
+
+            DataRow row = ((DataView)this.grdStaffList.DataSource).Table.Rows[rowIndex];
+
+            PersonnelId = row["personnel_id"].ToString();
+            PersonnelName = row["name"].ToString();
+            StartDate = DateTime.Today.AddDays(-1);
+        }
+    }
+}

+ 120 - 0
PersonSelection.resx

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

+ 255 - 0
PersonnelQ.Designer.cs

@@ -0,0 +1,255 @@
+namespace ddq
+{
+    partial class PersonnelQ
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.label1 = new System.Windows.Forms.Label();
+            this.txtName = new System.Windows.Forms.TextBox();
+            this.panPersonnelBottom = new System.Windows.Forms.Panel();
+            this.label2 = new System.Windows.Forms.Label();
+            this.cmbRole = new System.Windows.Forms.ComboBox();
+            this.label3 = new System.Windows.Forms.Label();
+            this.txtIndustryStartYear = new System.Windows.Forms.TextBox();
+            this.label4 = new System.Windows.Forms.Label();
+            this.txtCompanyStartYear = new System.Windows.Forms.TextBox();
+            this.label5 = new System.Windows.Forms.Label();
+            this.label6 = new System.Windows.Forms.Label();
+            this.label7 = new System.Windows.Forms.Label();
+            this.txtTitle = new System.Windows.Forms.TextBox();
+            this.label8 = new System.Windows.Forms.Label();
+            this.txtBio = new System.Windows.Forms.TextBox();
+            this.btnSavePersonnel = new System.Windows.Forms.Button();
+            this.btnDeletePersonnel = new System.Windows.Forms.Button();
+            this.panPersonnelBottom.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(28, 27);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(45, 18);
+            this.label1.TabIndex = 0;
+            this.label1.Text = "Name";
+            // 
+            // txtName
+            // 
+            this.txtName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.txtName.Location = new System.Drawing.Point(152, 24);
+            this.txtName.Name = "txtName";
+            this.txtName.Size = new System.Drawing.Size(384, 26);
+            this.txtName.TabIndex = 1;
+            // 
+            // panPersonnelBottom
+            // 
+            this.panPersonnelBottom.BackColor = System.Drawing.Color.WhiteSmoke;
+            this.panPersonnelBottom.Controls.Add(this.btnDeletePersonnel);
+            this.panPersonnelBottom.Controls.Add(this.btnSavePersonnel);
+            this.panPersonnelBottom.Dock = System.Windows.Forms.DockStyle.Bottom;
+            this.panPersonnelBottom.Location = new System.Drawing.Point(0, 629);
+            this.panPersonnelBottom.Name = "panPersonnelBottom";
+            this.panPersonnelBottom.Size = new System.Drawing.Size(600, 46);
+            this.panPersonnelBottom.TabIndex = 2;
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(32, 156);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(86, 18);
+            this.label2.TabIndex = 4;
+            this.label2.Text = "Current Role";
+            // 
+            // cmbRole
+            // 
+            this.cmbRole.FormattingEnabled = true;
+            this.cmbRole.Location = new System.Drawing.Point(153, 153);
+            this.cmbRole.Name = "cmbRole";
+            this.cmbRole.Size = new System.Drawing.Size(234, 26);
+            this.cmbRole.TabIndex = 5;
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.Location = new System.Drawing.Point(32, 201);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(106, 18);
+            this.label3.TabIndex = 6;
+            this.label3.Text = "Industry started";
+            // 
+            // txtIndustryStartYear
+            // 
+            this.txtIndustryStartYear.Location = new System.Drawing.Point(153, 198);
+            this.txtIndustryStartYear.Name = "txtIndustryStartYear";
+            this.txtIndustryStartYear.Size = new System.Drawing.Size(100, 26);
+            this.txtIndustryStartYear.TabIndex = 7;
+            // 
+            // label4
+            // 
+            this.label4.AutoSize = true;
+            this.label4.Location = new System.Drawing.Point(32, 244);
+            this.label4.Name = "label4";
+            this.label4.Size = new System.Drawing.Size(113, 18);
+            this.label4.TabIndex = 9;
+            this.label4.Text = "Company started";
+            // 
+            // txtCompanyStartYear
+            // 
+            this.txtCompanyStartYear.Location = new System.Drawing.Point(153, 241);
+            this.txtCompanyStartYear.Name = "txtCompanyStartYear";
+            this.txtCompanyStartYear.Size = new System.Drawing.Size(100, 26);
+            this.txtCompanyStartYear.TabIndex = 10;
+            // 
+            // label5
+            // 
+            this.label5.AutoSize = true;
+            this.label5.Location = new System.Drawing.Point(280, 201);
+            this.label5.Name = "label5";
+            this.label5.Size = new System.Drawing.Size(123, 18);
+            this.label5.TabIndex = 8;
+            this.label5.Text = "(year with 4 digits)";
+            // 
+            // label6
+            // 
+            this.label6.AutoSize = true;
+            this.label6.Location = new System.Drawing.Point(280, 244);
+            this.label6.Name = "label6";
+            this.label6.Size = new System.Drawing.Size(123, 18);
+            this.label6.TabIndex = 11;
+            this.label6.Text = "(year with 4 digits)";
+            // 
+            // label7
+            // 
+            this.label7.AutoSize = true;
+            this.label7.Location = new System.Drawing.Point(32, 83);
+            this.label7.Name = "label7";
+            this.label7.Size = new System.Drawing.Size(36, 18);
+            this.label7.TabIndex = 2;
+            this.label7.Text = "Title";
+            // 
+            // txtTitle
+            // 
+            this.txtTitle.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.txtTitle.Location = new System.Drawing.Point(152, 80);
+            this.txtTitle.Name = "txtTitle";
+            this.txtTitle.Size = new System.Drawing.Size(384, 26);
+            this.txtTitle.TabIndex = 3;
+            // 
+            // label8
+            // 
+            this.label8.AutoSize = true;
+            this.label8.Location = new System.Drawing.Point(32, 292);
+            this.label8.Name = "label8";
+            this.label8.Size = new System.Drawing.Size(28, 18);
+            this.label8.TabIndex = 12;
+            this.label8.Text = "Bio";
+            // 
+            // txtBio
+            // 
+            this.txtBio.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.txtBio.Location = new System.Drawing.Point(153, 289);
+            this.txtBio.Multiline = true;
+            this.txtBio.Name = "txtBio";
+            this.txtBio.Size = new System.Drawing.Size(383, 296);
+            this.txtBio.TabIndex = 13;
+            // 
+            // btnSavePersonnel
+            // 
+            this.btnSavePersonnel.Location = new System.Drawing.Point(490, 13);
+            this.btnSavePersonnel.Name = "btnSavePersonnel";
+            this.btnSavePersonnel.Size = new System.Drawing.Size(75, 23);
+            this.btnSavePersonnel.TabIndex = 0;
+            this.btnSavePersonnel.Text = "Save";
+            this.btnSavePersonnel.UseVisualStyleBackColor = true;
+            this.btnSavePersonnel.Click += new System.EventHandler(this.btnSavePersonnel_Click);
+            // 
+            // btnDeletePersonnel
+            // 
+            this.btnDeletePersonnel.ForeColor = System.Drawing.Color.Red;
+            this.btnDeletePersonnel.Location = new System.Drawing.Point(31, 13);
+            this.btnDeletePersonnel.Name = "btnDeletePersonnel";
+            this.btnDeletePersonnel.Size = new System.Drawing.Size(75, 23);
+            this.btnDeletePersonnel.TabIndex = 1;
+            this.btnDeletePersonnel.Text = "Delete";
+            this.btnDeletePersonnel.UseVisualStyleBackColor = true;
+            // 
+            // PersonnelQ
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 18F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(600, 675);
+            this.Controls.Add(this.txtBio);
+            this.Controls.Add(this.label8);
+            this.Controls.Add(this.txtTitle);
+            this.Controls.Add(this.label7);
+            this.Controls.Add(this.label6);
+            this.Controls.Add(this.label5);
+            this.Controls.Add(this.txtCompanyStartYear);
+            this.Controls.Add(this.label4);
+            this.Controls.Add(this.txtIndustryStartYear);
+            this.Controls.Add(this.label3);
+            this.Controls.Add(this.cmbRole);
+            this.Controls.Add(this.label2);
+            this.Controls.Add(this.panPersonnelBottom);
+            this.Controls.Add(this.txtName);
+            this.Controls.Add(this.label1);
+            this.Font = new System.Drawing.Font("Calibri", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+            this.MinimizeBox = false;
+            this.Name = "PersonnelQ";
+            this.Text = "Personnel Data";
+            this.panPersonnelBottom.ResumeLayout(false);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.TextBox txtName;
+        private System.Windows.Forms.Panel panPersonnelBottom;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.ComboBox cmbRole;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.TextBox txtIndustryStartYear;
+        private System.Windows.Forms.Label label4;
+        private System.Windows.Forms.TextBox txtCompanyStartYear;
+        private System.Windows.Forms.Label label5;
+        private System.Windows.Forms.Label label6;
+        private System.Windows.Forms.Label label7;
+        private System.Windows.Forms.TextBox txtTitle;
+        private System.Windows.Forms.Label label8;
+        private System.Windows.Forms.TextBox txtBio;
+        private System.Windows.Forms.Button btnSavePersonnel;
+        private System.Windows.Forms.Button btnDeletePersonnel;
+    }
+}

+ 95 - 0
PersonnelQ.cs

@@ -0,0 +1,95 @@
+using Org.BouncyCastle.Asn1;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace ddq
+{
+    public partial class PersonnelQ : Form
+    {
+
+        private string personnelId;
+        private string companyId;
+        private int userId;
+
+
+        public PersonnelQ(string personnelId, string companyId, int userId)
+        {
+
+            InitializeComponent();
+
+            this.personnelId = personnelId;
+            this.companyId = companyId;
+            this.userId = userId;
+
+            InitializeData();
+            
+        }
+
+        private void InitializeData()
+        {
+
+            //int role_type;
+            BindingSource bs = new BindingSource();
+            Dictionary<int, string> d = new Dictionary<int, string>(Utility.RoleType);
+            bs.DataSource = d;
+            this.cmbRole.DataSource = bs;
+            this.cmbRole.DisplayMember = "Value";
+            this.cmbRole.ValueMember = "Key";
+            this.cmbRole.SelectedValue = 1;
+
+            if (personnelId != null)
+            {
+                DataTable dt = DataAccess.Get_dd_personnel_info(personnelId, companyId);
+
+                if (dt != null && dt.Rows.Count > 0)
+                {
+
+                    this.txtName.Text = dt.Rows[0]["name"].ToString();
+                    this.txtTitle.Text = dt.Rows[0]["title"].ToString();
+                    this.txtIndustryStartYear.Text = dt.Rows[0]["industry_start_year"].ToString();
+                    this.txtCompanyStartYear.Text = dt.Rows[0]["company_start_year"].ToString();
+                    this.txtBio.Text = dt.Rows[0]["bio"].ToString();
+
+                    string strRole = dt.Rows[0]["role"].ToString();
+                    int.TryParse(strRole, out int role);
+                    this.cmbRole.SelectedValue = role;
+
+                }
+
+            }
+
+
+        }
+
+
+        private void btnSavePersonnel_Click(object sender, EventArgs e)
+        {
+
+            int? companyStartYear = null;
+            int? industryStartYear = null;
+
+            if (int.TryParse(this.txtCompanyStartYear.Text, out int newYear)) { companyStartYear = newYear; }
+            if (int.TryParse(this.txtIndustryStartYear.Text, out int newYear2)) { industryStartYear = newYear2; }
+
+            DataAccess.Set_dd_personnel_info(personnelId, DateTime.Today, companyId, 
+                this.txtName.Text.Trim(),
+                int.Parse(this.cmbRole.SelectedValue.ToString()),
+                this.txtTitle.Text.Trim(),
+                companyStartYear,
+                industryStartYear,
+                this.txtBio.Text.Trim(),
+                1, 1, userId, out string personnel_id);
+
+            this.DialogResult = DialogResult.OK;
+
+        }
+    }
+}

+ 120 - 0
PersonnelQ.resx

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

+ 106 - 0
Utility.cs

@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+
+namespace ddq
+{
+    public class Utility
+    {
+
+        public static readonly Dictionary<int, string> RoleType = new Dictionary<int, string>
+        {
+            { 1, "Portfolio Manager" },
+            { 2, "Researcher"},
+            { 3, "Contactor"},
+            { 4, "Marketing"},
+            { 5, "Risk & Compliance"},
+            { 6, "Executive"},
+            { 7, "Legal"},
+            { 8, "Trading"},
+            { 9, "Technology"},
+            { 0, "Other"}
+
+        };
+
+
+        /// <summary>
+        /// JsonElment 转为字符串,若输入为空则输出""
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        public static string Json2Text(JsonElement jsonElement, string propertyName)
+        {
+            string str = "";
+            JsonElement elm;
+
+            if (propertyName == null) return str;
+
+            bool hasProperty = jsonElement.TryGetProperty(propertyName, out elm);
+
+            if (hasProperty == true && elm.ValueKind != JsonValueKind.Undefined)
+            {
+                str = elm.ToString().Trim();
+            }
+
+            return str;
+        }
+
+        public static DataTable Json2Table(JsonElement jsonElement)
+        {
+            DataTable dataTable = new DataTable();
+
+            // 如果解析出的是数组
+            if (jsonElement.ValueKind == JsonValueKind.Array)
+            {
+                // 遍历数组元素
+                foreach (JsonElement element in jsonElement.EnumerateArray())
+                {
+                    // 如果是第一次遍历,元素包含列定义信息,需要创建列
+                    if (dataTable.Columns.Count == 0)
+                    {
+                        // 遍历第一个对象的属性来创建列
+                        foreach (JsonProperty property in element.EnumerateObject())
+                        {
+                            dataTable.Columns.Add(property.Name);
+                        }
+                    }
+
+                    // 创建新行并填充数据
+                    DataRow newRow = dataTable.NewRow();
+                    foreach (JsonProperty property in element.EnumerateObject())
+                    {
+                        newRow[property.Name] = property.Value.ToString();
+                    }
+                    dataTable.Rows.Add(newRow);
+                }
+            }
+
+            return dataTable;
+
+        }
+
+        public static List<Dictionary<string, object>> DataTable2List(DataTable dataTable)
+        {
+            var records = new List<Dictionary<string, object>>();
+
+            foreach (DataRow row in dataTable.Rows)
+            {
+                var record = new Dictionary<string, object>();
+                foreach (DataColumn col in dataTable.Columns)
+                {
+                    // 处理DBNull值
+                    record[col.ColumnName] = row[col] == DBNull.Value ? null : row[col];
+                }
+                records.Add(record);
+            }
+
+            return records;
+        }
+    }
+
+
+}

+ 19 - 0
ddq.csproj

@@ -120,14 +120,33 @@
     <Compile Include="FundQ.Designer.cs">
       <DependentUpon>FundQ.cs</DependentUpon>
     </Compile>
+    <Compile Include="PersonnelQ.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="PersonnelQ.Designer.cs">
+      <DependentUpon>PersonnelQ.cs</DependentUpon>
+    </Compile>
+    <Compile Include="PersonSelection.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="PersonSelection.Designer.cs">
+      <DependentUpon>PersonSelection.cs</DependentUpon>
+    </Compile>
     <Compile Include="Program.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Utility.cs" />
     <EmbeddedResource Include="DDQ.resx">
       <DependentUpon>DDQ.cs</DependentUpon>
     </EmbeddedResource>
     <EmbeddedResource Include="FundQ.resx">
       <DependentUpon>FundQ.cs</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="PersonnelQ.resx">
+      <DependentUpon>PersonnelQ.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="PersonSelection.resx">
+      <DependentUpon>PersonSelection.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="Properties\Resources.resx">
       <Generator>ResXFileCodeGenerator</Generator>
       <LastGenOutput>Resources.Designer.cs</LastGenOutput>