Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

562 lines
22KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Reflection;
  5. using System.Linq;
  6. using System.Text.RegularExpressions;
  7. using OpenQA.Selenium;
  8. using OpenQA.Selenium.Chrome;
  9. using OpenQA.Selenium.Support.UI;
  10. using SeleniumExtras.WaitHelpers;
  11. using CSVDownloader.Code;
  12. using CSVDownloader.File;
  13. using CSVDownloader.Store;
  14. using CSVDownloader.Store.CreditCSVData;
  15. using CSVDownloader.Store.QRCSVData;
  16. using CSVDownloader.Store.ElectronicMoneyDataStore;
  17. using CSVDownloader.Web;
  18. using CSVDownloader.Exceptions;
  19. using MySql.Data.MySqlClient;
  20. namespace CSVDownloader {
  21. class Program {
  22. static void Main(string[] args) {
  23. // 作業ディレクトリを実行ファイルに合わせる。
  24. var exe_path = Assembly.GetEntryAssembly().Location;
  25. var exe_directory_path = Path.GetDirectoryName(exe_path);
  26. Directory.SetCurrentDirectory(exe_directory_path);
  27. var controller = new Controller(args);
  28. String ret = controller.Start();
  29. if (ret.Length != 0) {
  30. // エラー検知
  31. Console.WriteLine(ret);
  32. Console.WriteLine("エラー発生 詳細はログを参照");
  33. Environment.Exit(1);
  34. }
  35. }
  36. }
  37. class Controller {
  38. private log4net.ILog logger_ = log4net.LogManager.GetLogger("");
  39. private List<WebController> web_controller_list_ = new List<WebController>();
  40. private HistoryDAO history_dao_;
  41. private ParkingCreditCardAgenciesSpotIDDAO parking_credit_card_agencies_spotID_dao_;
  42. private DaitoCreitDataStore daito_credit_store_;
  43. private ZeusCreditDataStore zeus_credit_store_;
  44. private ItecCreditDataStore itec_credit_store_;
  45. private HelloTechnoCreditDataStore hello_techno_credit_store_;
  46. private DaitoQRDataStore daito_qr_store_;
  47. private DaitoElectronicMoneyDataStore daito_electronic_money_store_;
  48. private CreditCSVDataGMOStore gmo_credit_store_;
  49. private GMOElectronicMoneyDataStore gmo_electronic_money_store_;
  50. private ParkingCreditCardAgenciesSpotIDErrorDAO parking_credit_card_agencies_spotID_error_dao_;
  51. private IConfigReader config_;
  52. private ChromeDriver driver_;
  53. private MySqlConnection conn_;
  54. private MySqlTransaction transaction_;
  55. private Dictionary<Code.CreditAgent, CreditCSVDataStore> credit_datastore_map_ = new Dictionary<Code.CreditAgent, CreditCSVDataStore>();
  56. private Dictionary<Code.CreditAgent, QRCSVDataStore> qr_datastore_map_ = new Dictionary<Code.CreditAgent, QRCSVDataStore>();
  57. private Dictionary<Code.CreditAgent, ElectronicMoneyCSVDataStore> electronic_money_datastore_map_ = new Dictionary<Code.CreditAgent, ElectronicMoneyCSVDataStore>();
  58. private int save_chunk_num_ = 100;
  59. // パラメータあり起動時の動作条件------ START
  60. private bool hasParam_ = false;
  61. private DateTime paramDateFrom_ = DateTime.Today;
  62. private DateTime paramDateTo_ = DateTime.Today;
  63. private string paramAgentCode_ = "";
  64. // パラメータあり起動時の動作条件------ END
  65. public Controller(string[] args) {
  66. // 引数なしは通常動作
  67. if (args.Count() == 0) {
  68. return;
  69. }
  70. // 開始終了日付指定 決済会社コード指定
  71. if (args.Count() == 3) {
  72. DateTime from = DateTime.Today;
  73. DateTime to = DateTime.Today;
  74. var fromStr = args[0];
  75. var toStr = args[1];
  76. var dateReg = new Regex(@"^\d{4}/\d{2}/\d{2}$");
  77. if (dateReg.IsMatch(fromStr) && !DateTime.TryParse(fromStr, out from)) {
  78. throw new Exception("起動引数不正 FROM 日付フォーマット");
  79. }
  80. if (dateReg.IsMatch(toStr) && !DateTime.TryParse(toStr, out to)) {
  81. throw new Exception("起動引数不正 TO 日付フォーマット");
  82. }
  83. if (to < from) {
  84. throw new Exception("起動引数不正 FROMが大きい");
  85. }
  86. hasParam_ = true;
  87. paramDateFrom_ = from;
  88. paramDateTo_ = to;
  89. paramAgentCode_ = args[2];
  90. var message = $"★★★★★★起動引数あり FROM:{fromStr} TO:{toStr} AGENT:{paramAgentCode_}★★★★★★";
  91. Console.WriteLine(message);
  92. logger_.Info(message);
  93. return;
  94. }
  95. throw new Exception("起動引数不正");
  96. }
  97. public String Start() {
  98. Console.WriteLine("★★★★★★自動CSVダウンロード 起動★★★★★");
  99. logger_.Info("★★★★★★自動CSVダウンロード 起動★★★★★");
  100. String returnable = "";
  101. // 各種ストアを用意
  102. history_dao_ = new HistoryDAO();
  103. config_ = new ConfigReader("config/config.ini");
  104. var mysql_param = new MySqlConnectionParameter() {
  105. host = "192.168.0.28",
  106. port = 3306,
  107. database = "ypark",
  108. user = "ypuser2",
  109. password = "ypp@ssw0rd2"
  110. };
  111. //var mysql_param = new MySqlConnectionParameter() {
  112. // host = "localhost",
  113. // port = 3306,
  114. // database = "yp",
  115. // user = "docker",
  116. // password = "docker",
  117. //};
  118. try {
  119. conn_ = MySQL.GetConnection(mysql_param);
  120. parking_credit_card_agencies_spotID_dao_ = new ParkingCreditCardAgenciesSpotIDDAO(conn_);
  121. parking_credit_card_agencies_spotID_error_dao_ = new ParkingCreditCardAgenciesSpotIDErrorDAO(conn_);
  122. daito_credit_store_ = new DaitoCreitDataStore(conn_);
  123. zeus_credit_store_ = new ZeusCreditDataStore(conn_);
  124. itec_credit_store_ = new ItecCreditDataStore(conn_);
  125. hello_techno_credit_store_ = new HelloTechnoCreditDataStore(conn_);
  126. daito_qr_store_ = new DaitoQRDataStore(conn_);
  127. gmo_credit_store_ = new CreditCSVDataGMOStore(conn_);
  128. gmo_electronic_money_store_ = new GMOElectronicMoneyDataStore(conn_);
  129. daito_electronic_money_store_ = new DaitoElectronicMoneyDataStore(conn_);
  130. } catch (Exception e) {
  131. logger_.Error("DB接続失敗");
  132. logger_.Error(e.Message);
  133. return "DBへのコネクト失敗";
  134. }
  135. // エラーリストを初期化する(全削除)
  136. parking_credit_card_agencies_spotID_error_dao_.DeleteAll();
  137. // サイトごとにコントローラーを用意する。
  138. MakeConttollers();
  139. // 各コントローラーを起動する。
  140. foreach (var web_controller in web_controller_list_) {
  141. var ret = HandleWebController(web_controller);
  142. if (ret == Code.ResultCode.NG) {
  143. logger_.Error($"処理失敗 {web_controller.GetCreditAgent().ToString()}");
  144. returnable = "処理失敗";
  145. }
  146. }
  147. // ブラウザの終了
  148. if (driver_ != null) {
  149. driver_.Quit();
  150. }
  151. // 終了
  152. logger_.Info("処理成功");
  153. return returnable;
  154. }
  155. private void MakeConttollers() {
  156. driver_ = DriverFactory.GetDriver();
  157. // CREVAS
  158. {
  159. var controller = new DaitoController(driver_);
  160. if (!hasParam_ || paramAgentCode_ == controller.GetCreditAgentCode()) {
  161. var dic = parking_credit_card_agencies_spotID_dao_.GetDictionary(controller.GetCreditAgent());
  162. controller.SetParkingDic(dic);
  163. web_controller_list_.Add(controller);
  164. credit_datastore_map_.Add(controller.GetCreditAgent(), daito_credit_store_);
  165. qr_datastore_map_.Add(controller.GetCreditAgent(), daito_qr_store_);
  166. electronic_money_datastore_map_.Add(controller.GetCreditAgent(), daito_electronic_money_store_);
  167. }
  168. }
  169. // Zeus
  170. {
  171. var controller = new ZeusController(driver_);
  172. if (!hasParam_ || paramAgentCode_ == controller.GetCreditAgentCode()) {
  173. var dic = parking_credit_card_agencies_spotID_dao_.GetDictionary(controller.GetCreditAgent());
  174. controller.SetParkingDic(dic);
  175. web_controller_list_.Add(controller);
  176. credit_datastore_map_.Add(controller.GetCreditAgent(), zeus_credit_store_);
  177. }
  178. }
  179. // Itec
  180. {
  181. //var controller = new ItecController(driver_);
  182. //var dic = parking_credit_card_agencies_spotID_dao_.GetDictionary(controller.GetCreditAgent());
  183. //controller.SetParkingDic(dic);
  184. //web_controller_list_.Add(controller);
  185. //credit_datastore_map_.Add(controller.GetCreditAgent(), itec_credit_store_);
  186. }
  187. // HelloTechno
  188. {
  189. //var controller = new HelloTechnoController(driver_);
  190. //var dic = parking_credit_card_agencies_spotID_dao_.GetDictionary(controller.GetCreditAgent());
  191. //controller.SetParkingDic(dic);
  192. //web_controller_list_.Add(controller);
  193. //credit_datastore_map_.Add(controller.GetCreditAgent(), hello_techno_credit_store_);
  194. }
  195. // HelloTechno(GMO)
  196. {
  197. //var controller = new GMOController(driver_);
  198. //if (!hasParam_ || paramAgentCode_ == controller.GetCreditAgentCode()) {
  199. // var dic = parking_credit_card_agencies_spotID_dao_.GetDictionary(controller.GetCreditAgent());
  200. // controller.SetParkingDic(dic);
  201. // web_controller_list_.Add(controller);
  202. // credit_datastore_map_.Add(controller.GetCreditAgent(), gmo_credit_store_);
  203. // electronic_money_datastore_map_.Add(controller.GetCreditAgent(), gmo_electronic_money_store_);
  204. //}
  205. }
  206. }
  207. private Code.ResultCode HandleWebController(WebController web_controller) {
  208. Code.ResultCode result_code = Code.ResultCode.OK;
  209. // 実行対象日判定
  210. if (hasParam_) {
  211. logger_.Info($"起動引数ありのため実行対象日判定をスキップ");
  212. } else if (!web_controller.IsWorkDate()) {
  213. logger_.Info($"処理対象日外:{ web_controller.GetCreditAgent()}");
  214. return result_code;
  215. }
  216. try {
  217. // 各ダウンロードディレクトリをクリーンする。
  218. CreanDirectries();
  219. // カード会社を特定する。
  220. Code.CreditAgent agent = web_controller.GetCreditAgent();
  221. logger_.Info($"ダウンロード開始 対象:{agent}");
  222. // 履歴を参照する。
  223. var history = history_dao_.GetHistory(agent);
  224. // 履歴から取得範囲を特定する。
  225. (var from, var to) = GetFromTo(agent, history);
  226. logger_.Info($"取得範囲 {from.ToString("yyyy/MM/dd")} ~ {to.ToString("yyyy/MM/dd")}");
  227. // ログイン情報を取得
  228. var login_info = GetLoginInfo(agent);
  229. // ログインを開始
  230. result_code = web_controller.Login(login_info);
  231. if (result_code != Code.ResultCode.OK) {
  232. throw new Exception("ログイン失敗");
  233. }
  234. logger_.Info("ログイン成功");
  235. // ダウンロード開始
  236. result_code = web_controller.Download(from, to);
  237. if (result_code != Code.ResultCode.OK) {
  238. throw new Exception("ダウンロード失敗");
  239. }
  240. logger_.Info("ダウンロード成功");
  241. // ログアウト
  242. result_code = web_controller.Logout();
  243. if (result_code != Code.ResultCode.OK) {
  244. throw new Exception("ログアウト失敗");
  245. }
  246. logger_.Info("ログアウト成功");
  247. // ロード画面の表示
  248. var load_html_path = Path.GetFullPath(@"static\html\load.html");
  249. driver_.Navigate().GoToUrl($"file://{load_html_path}");
  250. // データリストの取得
  251. // 取得に失敗したものはエラーリストとして登録する。
  252. bool list_get_success = true;
  253. List<CreditCSVData> credit_info_list = null;
  254. List<QRCSVData> qr_info_list = null;
  255. List<ElectronicMoneyCSVData> electronic_money_info_list = null;
  256. try {
  257. credit_info_list = web_controller.GetCreditCSVDataList();
  258. } catch (SpotNameNotMatchException e) {
  259. list_get_success = false;
  260. parking_credit_card_agencies_spotID_error_dao_.Save(e.GetList());
  261. }
  262. try {
  263. qr_info_list = web_controller.GetQRCSVDataList();
  264. } catch (SpotNameNotMatchException e) {
  265. list_get_success = false;
  266. parking_credit_card_agencies_spotID_error_dao_.Save(e.GetList());
  267. }
  268. try {
  269. electronic_money_info_list = web_controller.GetElectronicMoneyCSVDataList();
  270. } catch (SpotNameNotMatchException e) {
  271. list_get_success = false;
  272. parking_credit_card_agencies_spotID_error_dao_.Save(e.GetList());
  273. }
  274. if (!list_get_success) {
  275. throw new Exception("データリスト取得失敗");
  276. }
  277. // データ保存
  278. int delete_count_credit = 0;
  279. int delete_count_qr = 0;
  280. int delete_count_electronic_money = 0;
  281. transaction_ = conn_.BeginTransaction();
  282. // クレジット
  283. if (0 < credit_info_list.Count) {
  284. ShowTotalCount(credit_info_list.Count);
  285. var store = credit_datastore_map_[agent];
  286. delete_count_credit = store.Delete(from, to);
  287. var current_count = 0;
  288. ShowCurrentCount(current_count);
  289. var chunk_data_list = credit_info_list.Select((CreditCSVData data, int index) => new { data, index })
  290. .GroupBy(x => x.index / save_chunk_num_)
  291. .Select(g => g.Select(r => r.data));
  292. foreach (var data_list in chunk_data_list) {
  293. var list = data_list.ToList();
  294. store.Save(list);
  295. current_count += list.Count;
  296. ShowCurrentCount(current_count);
  297. }
  298. }
  299. // QR
  300. if (0 < qr_info_list.Count) {
  301. ShowTotalCount(qr_info_list.Count);
  302. var store = qr_datastore_map_[agent];
  303. delete_count_qr = store.Delete(from, to);
  304. var current_count = 0;
  305. ShowCurrentCount(current_count);
  306. var chunk_data_list = qr_info_list.Select((QRCSVData data, int index) => new { data, index })
  307. .GroupBy(x => x.index / save_chunk_num_)
  308. .Select(g => g.Select(r => r.data));
  309. foreach (var data_list in chunk_data_list) {
  310. var list = data_list.ToList();
  311. store.Save(list);
  312. current_count += list.Count;
  313. ShowCurrentCount(current_count);
  314. }
  315. }
  316. // 電子マネー
  317. if (0 < electronic_money_info_list.Count) {
  318. ShowTotalCount(electronic_money_info_list.Count);
  319. var store = electronic_money_datastore_map_[agent];
  320. delete_count_electronic_money = store.Delete(from, to);
  321. var current_count = 0;
  322. ShowCurrentCount(current_count);
  323. var chunk_data_list = electronic_money_info_list.Select((ElectronicMoneyCSVData data, int index) => new { data, index })
  324. .GroupBy(x => x.index / save_chunk_num_)
  325. .Select(g => g.Select(r => r.data));
  326. foreach (var data_list in chunk_data_list) {
  327. var list = data_list.ToList();
  328. store.Save(list);
  329. current_count += list.Count;
  330. ShowCurrentCount(current_count);
  331. }
  332. }
  333. // コミット処理
  334. transaction_.Commit();
  335. logger_.Info($"削除件数 CREDIT :{delete_count_credit}");
  336. logger_.Info($"削除件数 QR :{delete_count_qr}");
  337. logger_.Info($"削除件数 電子マネー :{delete_count_electronic_money}");
  338. logger_.Info($"登録件数 CREDIT :{credit_info_list.Count}");
  339. logger_.Info($"登録件数 QR :{qr_info_list.Count}");
  340. logger_.Info($"登録件数 電子マネー :{electronic_money_info_list.Count}");
  341. web_controller.Archive(GetArchiveFilename(agent, DateTime.Now));
  342. // 履歴の登録
  343. if (!hasParam_) {
  344. history_dao_.Save(agent, DateTime.Now);
  345. } else {
  346. logger_.Info("パラメータ指定起動のため、取得履歴は保存しない");
  347. }
  348. logger_.Info($"ダウンロード終了 対象:{agent}");
  349. } catch (Exception e) {
  350. // ロールバック処理
  351. logger_.Error(e.Message);
  352. logger_.Error(e.StackTrace);
  353. if (transaction_ != null) {
  354. transaction_.Rollback();
  355. }
  356. transaction_ = null;
  357. return Code.ResultCode.NG;
  358. }
  359. transaction_ = null;
  360. return Code.ResultCode.OK;
  361. }
  362. /// <summary>
  363. /// データ取得範囲を特定する。<br/>
  364. /// </summary>
  365. /// <param name="history"></param>
  366. /// <returns></returns>
  367. private (DateTime, DateTime) GetFromTo(Code.CreditAgent agent, List<History> history) {
  368. // 起動パラメータがある場合はそれを設定する
  369. if (hasParam_) {
  370. return (paramDateFrom_, paramDateTo_);
  371. }
  372. DateTime from, to;
  373. if (agent == Code.CreditAgent.Zeus) {
  374. // Zeusの場合は、データが修正されるケースがあるため
  375. // 期間を制御する
  376. // 前回取得日から1か月遡る。
  377. // var prev_date = DateTime.Now.AddMonths(-1);
  378. // from = new DateTime(prev_date.Year, prev_date.Month, 1);
  379. // to = from.AddMonths(1).AddDays(-1);
  380. var now_date = DateTime.Now.Date;
  381. from = now_date.AddMonths(-1);
  382. to = now_date;
  383. } else {
  384. var now_date = DateTime.Now.Date;
  385. from = now_date.AddDays(-20);
  386. to = now_date;
  387. if (history.Count != 0) {
  388. var prev_date = history[0].date;
  389. if (from < prev_date) {
  390. from = prev_date.Date;
  391. }
  392. }
  393. }
  394. return (from, to);
  395. }
  396. /// <summary>
  397. /// コンフィグファイルよりログイン情報を取得する。
  398. /// </summary>
  399. /// <param name="agent"></param>
  400. /// <returns></returns>
  401. private LoginInfo GetLoginInfo(Code.CreditAgent agent) {
  402. var login_info = new LoginInfo();
  403. String sesction = $"LOGIN_INFO_{agent.ToString()}";
  404. login_info.user_name = config_.Read(sesction, "user");
  405. if (login_info.user_name.Length == 0) {
  406. throw new Exception($"ログイン情報不足 host {agent.ToString()}");
  407. }
  408. login_info.password = config_.Read(sesction, "password");
  409. if (login_info.password.Length == 0) {
  410. throw new Exception($"ログイン情報不足 password {agent.ToString()}");
  411. }
  412. login_info.company_name = config_.Read(sesction, "company");
  413. return login_info;
  414. }
  415. private String GetArchiveFilename(Code.CreditAgent agent, DateTime now) {
  416. return $"{agent}_{now.ToString("yyyyMMddHHmmss")}.zip";
  417. }
  418. private void CreanDirectries() {
  419. var dir_download = new DirectoryInfo(DriverFactory.GetDownloadDir());
  420. foreach (var file in dir_download.GetFiles()) {
  421. file.Delete();
  422. }
  423. var tmp_download = new DirectoryInfo(DriverFactory.GetTmpDownloadDir());
  424. foreach (var file in tmp_download.GetFiles()) {
  425. file.Delete();
  426. }
  427. }
  428. private void ShowTotalCount(int num) {
  429. driver_.ExecuteScript($"setTotal({num})");
  430. }
  431. private void ShowCurrentCount(int num) {
  432. driver_.ExecuteScript($"setCount({num})");
  433. }
  434. }
  435. }