| @@ -0,0 +1,25 @@ | |||
| | |||
| Microsoft Visual Studio Solution File, Format Version 12.00 | |||
| # Visual Studio Version 16 | |||
| VisualStudioVersion = 16.0.30907.101 | |||
| MinimumVisualStudioVersion = 10.0.40219.1 | |||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSVDownloader", "CSVDownloader\CSVDownloader.csproj", "{ED01BF6B-81D2-46D8-B89D-6570F53C38B8}" | |||
| EndProject | |||
| Global | |||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
| Debug|Any CPU = Debug|Any CPU | |||
| Release|Any CPU = Release|Any CPU | |||
| EndGlobalSection | |||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | |||
| {ED01BF6B-81D2-46D8-B89D-6570F53C38B8}.Debug|Any CPU.ActiveCfg = Release|Any CPU | |||
| {ED01BF6B-81D2-46D8-B89D-6570F53C38B8}.Debug|Any CPU.Build.0 = Release|Any CPU | |||
| {ED01BF6B-81D2-46D8-B89D-6570F53C38B8}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
| {ED01BF6B-81D2-46D8-B89D-6570F53C38B8}.Release|Any CPU.Build.0 = Release|Any CPU | |||
| EndGlobalSection | |||
| GlobalSection(SolutionProperties) = preSolution | |||
| HideSolutionNode = FALSE | |||
| EndGlobalSection | |||
| GlobalSection(ExtensibilityGlobals) = postSolution | |||
| SolutionGuid = {99BAA057-2423-4D72-AAE0-4430C67F56F6} | |||
| EndGlobalSection | |||
| EndGlobal | |||
| @@ -0,0 +1,52 @@ | |||
| <Project Sdk="Microsoft.NET.Sdk"> | |||
| <PropertyGroup> | |||
| <OutputType>Exe</OutputType> | |||
| <TargetFramework>netcoreapp3.1</TargetFramework> | |||
| </PropertyGroup> | |||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | |||
| <DebugType>none</DebugType> | |||
| <DebugSymbols>false</DebugSymbols> | |||
| <DocumentationFile></DocumentationFile> | |||
| <DefineConstants>DEBUG;TRACE</DefineConstants> | |||
| </PropertyGroup> | |||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | |||
| <DocumentationFile></DocumentationFile> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <PackageReference Include="DotNetSeleniumExtras.WaitHelpers" Version="3.11.0" /> | |||
| <PackageReference Include="log4net" Version="2.0.12" /> | |||
| <PackageReference Include="MySql.Data" Version="8.0.23" /> | |||
| <PackageReference Include="Selenium.Support" Version="3.141.0" /> | |||
| <PackageReference Include="Selenium.WebDriver" Version="3.141.0" /> | |||
| <PackageReference Include="System.Data.SQLite.Core" Version="1.0.113.7" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <Compile Update="Properties\Resources.Designer.cs"> | |||
| <DesignTime>True</DesignTime> | |||
| <AutoGen>True</AutoGen> | |||
| <DependentUpon>Resources.resx</DependentUpon> | |||
| </Compile> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <EmbeddedResource Update="Properties\Resources.resx"> | |||
| <Generator>ResXFileCodeGenerator</Generator> | |||
| <LastGenOutput>Resources.Designer.cs</LastGenOutput> | |||
| </EmbeddedResource> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <None Update="chromedriver.exe"> | |||
| <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | |||
| </None> | |||
| <None Update="log4net.config"> | |||
| <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | |||
| </None> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -0,0 +1,24 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| namespace CSVDownloader.Code { | |||
| enum CreditAgent { | |||
| ITEC, Zeus, HT, Daito | |||
| } | |||
| static class CreditAgenciesMap { | |||
| private static IDictionary<CreditAgent, String> map_ = new Dictionary<CreditAgent, String>() { | |||
| {CreditAgent.ITEC, "01" }, | |||
| {CreditAgent.Zeus, "02" }, | |||
| {CreditAgent.HT, "03" }, | |||
| {CreditAgent.Daito, "04" } | |||
| }; | |||
| public static String GetID(CreditAgent agent) { | |||
| return map_[agent]; | |||
| } | |||
| }; | |||
| } | |||
| @@ -0,0 +1,7 @@ | |||
| | |||
| namespace CSVDownloader.Code { | |||
| enum ResultCode { | |||
| OK,NG | |||
| } | |||
| } | |||
| @@ -0,0 +1,38 @@ | |||
| using System; | |||
| using System.Text; | |||
| using System.Runtime.InteropServices; | |||
| namespace CSVDownloader.File { | |||
| class ConfigReader : IConfigReader{ | |||
| [DllImport("kernel32.dll", EntryPoint = "GetPrivateProfileStringW", CharSet = CharSet.Unicode, SetLastError = true)] | |||
| static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, uint nSize, string lpFileName); | |||
| private String filepath_; | |||
| private uint buff_size = 256; | |||
| /// <summary> | |||
| /// ファイルパスを設定する | |||
| /// </summary> | |||
| /// <param name="filepath"></param> | |||
| public ConfigReader(String filepath) | |||
| { | |||
| filepath_ = filepath; | |||
| } | |||
| /// <summary> | |||
| /// ファイルの値を取得する | |||
| /// </summary> | |||
| /// <param name="section">セクション名</param> | |||
| /// <param name="key">キー名</param> | |||
| /// <returns>取得値</returns> | |||
| public String Read(String section, String key) | |||
| { | |||
| StringBuilder sb = new StringBuilder(Convert.ToInt32(buff_size)); | |||
| GetPrivateProfileString(section, key, "", sb, buff_size, filepath_); | |||
| return sb.ToString(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,12 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| namespace CSVDownloader.File { | |||
| interface IConfigReader { | |||
| String Read(String section, String key); | |||
| } | |||
| } | |||
| @@ -0,0 +1,349 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.IO; | |||
| using System.Reflection; | |||
| using System.Threading; | |||
| using OpenQA.Selenium; | |||
| using OpenQA.Selenium.Chrome; | |||
| using OpenQA.Selenium.Support.UI; | |||
| using SeleniumExtras.WaitHelpers; | |||
| using CSVDownloader.File; | |||
| using CSVDownloader.Store; | |||
| using CSVDownloader.Store.CreditCSVData; | |||
| using CSVDownloader.Store.QRCSVData; | |||
| using CSVDownloader.Web; | |||
| using MySql.Data.MySqlClient; | |||
| namespace CSVDownloader { | |||
| class Program { | |||
| static void Main(string[] args) { | |||
| var controller = new Controller(); | |||
| String ret = controller.Start(); | |||
| if (ret.Length != 0) { | |||
| // エラー検知 | |||
| Console.WriteLine(ret); | |||
| Console.WriteLine("エラー発生 詳細はログを参照"); | |||
| Environment.Exit(1); | |||
| } | |||
| } | |||
| } | |||
| class Controller { | |||
| private log4net.ILog logger_ = log4net.LogManager.GetLogger(""); | |||
| private List<WebController> web_controller_list_ = new List<WebController>(); | |||
| private HistoryDAO history_dao_; | |||
| private ParkingCreditCardAgenciesSpotIDDAO parking_credit_card_agencies_spotID_dao_; | |||
| private DaitoCreitDataStore daito_credit_store_; | |||
| private ZeusCreditDataStore zeus_credit_store_; | |||
| private ItecCreditDataStore itec_credit_store_; | |||
| private HelloTechnoCreditDataStore hello_techno_credit_store_; | |||
| private DaitoQRDataStore daito_qr_store_; | |||
| private IConfigReader config_; | |||
| private ChromeDriver driver_; | |||
| private MySqlConnection conn_; | |||
| private MySqlTransaction transaction_; | |||
| private Dictionary<Code.CreditAgent, CreditCSVDataStore> credit_datastore_map_ = new Dictionary<Code.CreditAgent, CreditCSVDataStore>(); | |||
| private Dictionary<Code.CreditAgent, QRCSVDataStore> qr_datastore_map_ = new Dictionary<Code.CreditAgent, QRCSVDataStore>(); | |||
| public String Start() { | |||
| Console.WriteLine("★★★★★★自動CSVダウンロード 起動★★★★★"); | |||
| logger_.Info("★★★★★★自動CSVダウンロード 起動★★★★★"); | |||
| String returnable = ""; | |||
| // 各種ストアを用意 | |||
| history_dao_ = new HistoryDAO(); | |||
| config_ = new ConfigReader("config/config.ini"); | |||
| var mysql_param = new MySqlConnectionParameter() { | |||
| host = "192.168.1.17", | |||
| port = 3306, | |||
| database = "yp", | |||
| user = "sosuke", | |||
| password = ".1Satellite" | |||
| }; | |||
| try { | |||
| conn_ = MySQL.GetConnection(mysql_param); | |||
| parking_credit_card_agencies_spotID_dao_ = new ParkingCreditCardAgenciesSpotIDDAO(conn_); | |||
| daito_credit_store_ = new DaitoCreitDataStore(conn_); | |||
| zeus_credit_store_ = new ZeusCreditDataStore(conn_); | |||
| itec_credit_store_ = new ItecCreditDataStore(conn_); | |||
| hello_techno_credit_store_ = new HelloTechnoCreditDataStore(conn_); | |||
| daito_qr_store_ = new DaitoQRDataStore(conn_); | |||
| } catch (Exception e) { | |||
| logger_.Error("DB接続失敗"); | |||
| logger_.Error(e.Message); | |||
| return "DBへのコネクト失敗"; | |||
| } | |||
| // サイトごとにコントローラーを用意する。 | |||
| MakeConttollers(); | |||
| // 各コントローラーを起動する。 | |||
| foreach (var web_controller in web_controller_list_) { | |||
| var ret = HandleWebController(web_controller); | |||
| if (ret == Code.ResultCode.NG) { | |||
| logger_.Error($"処理失敗 {web_controller.GetCreditAgent().ToString()}"); | |||
| returnable = "処理失敗"; | |||
| } | |||
| } | |||
| // ブラウザの終了 | |||
| if (driver_ != null) { | |||
| driver_.Quit(); | |||
| } | |||
| // 終了 | |||
| logger_.Info("処理成功"); | |||
| return returnable; | |||
| } | |||
| private void MakeConttollers() { | |||
| driver_ = DriverFactory.GetDriver(); | |||
| // CREVAS | |||
| { | |||
| var controller = new DaitoController(driver_); | |||
| var dic = parking_credit_card_agencies_spotID_dao_.GetDictionary(controller.GetCreditAgent()); | |||
| controller.SetParkingDic(dic); | |||
| web_controller_list_.Add(controller); | |||
| credit_datastore_map_.Add(controller.GetCreditAgent(), daito_credit_store_); | |||
| qr_datastore_map_.Add(controller.GetCreditAgent(), daito_qr_store_); | |||
| } | |||
| // Zeus | |||
| { | |||
| var controller = new ZeusController(driver_); | |||
| var dic = parking_credit_card_agencies_spotID_dao_.GetDictionary(controller.GetCreditAgent()); | |||
| controller.SetParkingDic(dic); | |||
| web_controller_list_.Add(controller); | |||
| credit_datastore_map_.Add(controller.GetCreditAgent(), zeus_credit_store_); | |||
| } | |||
| // Itec | |||
| { | |||
| var controller = new ItecController(driver_); | |||
| var dic = parking_credit_card_agencies_spotID_dao_.GetDictionary(controller.GetCreditAgent()); | |||
| controller.SetParkingDic(dic); | |||
| web_controller_list_.Add(controller); | |||
| credit_datastore_map_.Add(controller.GetCreditAgent(), itec_credit_store_); | |||
| } | |||
| // HelloTechno | |||
| { | |||
| var controller = new HelloTechnoController(driver_); | |||
| var dic = parking_credit_card_agencies_spotID_dao_.GetDictionary(controller.GetCreditAgent()); | |||
| controller.SetParkingDic(dic); | |||
| web_controller_list_.Add(controller); | |||
| credit_datastore_map_.Add(controller.GetCreditAgent(), hello_techno_credit_store_); | |||
| } | |||
| } | |||
| private Code.ResultCode HandleWebController(WebController web_controller) { | |||
| Code.ResultCode result_code = Code.ResultCode.OK; | |||
| try { | |||
| // 各ダウンロードディレクトリをクリーンする。 | |||
| CreanDirectries(); | |||
| // カード会社を特定する。 | |||
| Code.CreditAgent agent = web_controller.GetCreditAgent(); | |||
| logger_.Info($"ダウンロード開始 対象:{agent}"); | |||
| // 履歴を参照する。 | |||
| var history = history_dao_.GetHistory(agent); | |||
| // 履歴から取得範囲を特定する。 | |||
| (var from, var to) = GetFromTo(agent, history); | |||
| logger_.Info($"取得範囲 {from.ToString("yyyy/MM/dd")} ~ {to.ToString("yyyy/MM/dd")}"); | |||
| // ログイン情報を取得 | |||
| var login_info = GetLoginInfo(agent); | |||
| // ログインを開始 | |||
| result_code = web_controller.Login(login_info); | |||
| if (result_code != Code.ResultCode.OK) { | |||
| throw new Exception("ログイン失敗"); | |||
| } | |||
| logger_.Info("ログイン成功"); | |||
| // ダウンロード開始 | |||
| result_code = web_controller.Download(from, to); | |||
| if (result_code != Code.ResultCode.OK) { | |||
| throw new Exception("ダウンロード失敗"); | |||
| } | |||
| logger_.Info("ダウンロード成功"); | |||
| // ログアウト | |||
| result_code = web_controller.Logout(); | |||
| if (result_code != Code.ResultCode.OK) { | |||
| throw new Exception("ログアウト失敗"); | |||
| } | |||
| logger_.Info("ログアウト成功"); | |||
| // データ保存 | |||
| int delete_count_credit = 0; | |||
| int delete_count_qr = 0; | |||
| transaction_ = conn_.BeginTransaction(); | |||
| // クレジット | |||
| var credit_info_list = web_controller.GetCreditCSVDataList(); | |||
| if (0 < credit_info_list.Count) { | |||
| var store = credit_datastore_map_[agent]; | |||
| delete_count_credit = store.Delete(from, to); | |||
| foreach (var credit_info in credit_info_list) { | |||
| store.Save(credit_info); | |||
| } | |||
| } | |||
| // QR | |||
| var qr_info_list = web_controller.GetQRCSVDataList(); | |||
| if (0 < qr_info_list.Count) { | |||
| var store = qr_datastore_map_[agent]; | |||
| delete_count_qr = store.Delete(from, to); | |||
| foreach (var qr_info in qr_info_list) { | |||
| store.Save(qr_info); | |||
| } | |||
| } | |||
| // コミット処理 | |||
| transaction_.Commit(); | |||
| logger_.Info($"削除件数 CREDIT:{delete_count_credit}"); | |||
| logger_.Info($"削除件数 QR: {delete_count_qr}"); | |||
| logger_.Info($"登録件数 CREDIT:{credit_info_list.Count}"); | |||
| logger_.Info($"登録件数 QR :{qr_info_list.Count}"); | |||
| web_controller.Archive(GetArchiveFilename(agent, DateTime.Now)); | |||
| // 履歴の登録 | |||
| history_dao_.Save(agent, DateTime.Now); | |||
| logger_.Info($"ダウンロード終了 対象:{agent}"); | |||
| } catch (Exception e) { | |||
| // ロールバック処理 | |||
| logger_.Error(e.Message); | |||
| if (transaction_ != null) { | |||
| transaction_.Rollback(); | |||
| } | |||
| return Code.ResultCode.NG; | |||
| } | |||
| transaction_ = null; | |||
| return Code.ResultCode.OK; | |||
| } | |||
| /// <summary> | |||
| /// データ取得範囲を特定する。<br/> | |||
| /// </summary> | |||
| /// <param name="history"></param> | |||
| /// <returns></returns> | |||
| private (DateTime, DateTime) GetFromTo(Code.CreditAgent agent, List<History> history) { | |||
| DateTime from, to; | |||
| if (agent == Code.CreditAgent.Zeus) { | |||
| // Zeusの場合は、データが修正されるケースがあるため | |||
| // 期間を制御する | |||
| // 前回取得日から1か月遡る。 | |||
| // var prev_date = DateTime.Now.AddMonths(-1); | |||
| // from = new DateTime(prev_date.Year, prev_date.Month, 1); | |||
| // to = from.AddMonths(1).AddDays(-1); | |||
| var now_date = DateTime.Now.Date; | |||
| from = now_date.AddMonths(-1); | |||
| to = now_date; | |||
| if (history.Count != 0) { | |||
| var prev_date = history[0].date; | |||
| from = prev_date.AddMonths(-1); | |||
| } | |||
| } else { | |||
| var now_date = DateTime.Now.Date; | |||
| from = now_date.AddDays(-20); | |||
| to = now_date; | |||
| if (history.Count != 0) { | |||
| var prev_date = history[0].date; | |||
| if (from < prev_date) { | |||
| from = prev_date.Date; | |||
| } | |||
| } | |||
| } | |||
| return (from, to); | |||
| } | |||
| /// <summary> | |||
| /// コンフィグファイルよりログイン情報を取得する。 | |||
| /// </summary> | |||
| /// <param name="agent"></param> | |||
| /// <returns></returns> | |||
| private LoginInfo GetLoginInfo(Code.CreditAgent agent) { | |||
| var login_info = new LoginInfo(); | |||
| String sesction = $"LOGIN_INFO_{agent.ToString()}"; | |||
| login_info.user_name = config_.Read(sesction, "user"); | |||
| if (login_info.user_name.Length == 0) { | |||
| throw new Exception($"ログイン情報不足 host {agent.ToString()}"); | |||
| } | |||
| login_info.password = config_.Read(sesction, "password"); | |||
| if (login_info.password.Length == 0) { | |||
| throw new Exception($"ログイン情報不足 password {agent.ToString()}"); | |||
| } | |||
| return login_info; | |||
| } | |||
| private String GetArchiveFilename(Code.CreditAgent agent, DateTime now) { | |||
| return $"{agent.ToString()}_{now.ToString("yyyyMMddHHmmss")}.zip"; | |||
| } | |||
| private void CreanDirectries() { | |||
| var dir_download = new DirectoryInfo(DriverFactory.GetDownloadDir()); | |||
| foreach (var file in dir_download.GetFiles()) { | |||
| file.Delete(); | |||
| } | |||
| var tmp_download = new DirectoryInfo(DriverFactory.GetTmpDownloadDir()); | |||
| foreach (var file in tmp_download.GetFiles()) { | |||
| file.Delete(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| using System.Runtime.InteropServices; | |||
| // このような SDK スタイルのプロジェクトの場合、以前はこのファイルで定義していたいくつかのアセンブリ属性がビルド時に自動的に追加されて、プロジェクトのプロパティで定義されている値がそれに設定されるようになりました。組み込まれる属性と、このプロセスをカスタマイズする方法の詳細については、次を参照してください: | |||
| // https://aka.ms/assembly-info-properties | |||
| // ComVisible を false に設定すると、このアセンブリ内の型は COM コンポーネントから参照できなくなります。このアセンブリ内の型に COM からアクセスする必要がある場合は、その型の | |||
| // ComVisible 属性を true に設定してください。 | |||
| [assembly: ComVisible(false)] | |||
| // このプロジェクトが COM に公開される場合、次の GUID が typelib の ID になります。 | |||
| [assembly: Guid("21417377-1820-46d0-9e17-fc9528dd3c5b")] | |||
| [assembly: log4net.Config.XmlConfigurator(Watch = true, ConfigFile = "log4net.config")] | |||
| @@ -0,0 +1,63 @@ | |||
| //------------------------------------------------------------------------------ | |||
| // <auto-generated> | |||
| // このコードはツールによって生成されました。 | |||
| // ランタイム バージョン:4.0.30319.42000 | |||
| // | |||
| // このファイルへの変更は、以下の状況下で不正な動作の原因になったり、 | |||
| // コードが再生成されるときに損失したりします。 | |||
| // </auto-generated> | |||
| //------------------------------------------------------------------------------ | |||
| namespace CSVDownloader.Properties { | |||
| using System; | |||
| /// <summary> | |||
| /// ローカライズされた文字列などを検索するための、厳密に型指定されたリソース クラスです。 | |||
| /// </summary> | |||
| // このクラスは StronglyTypedResourceBuilder クラスが ResGen | |||
| // または Visual Studio のようなツールを使用して自動生成されました。 | |||
| // メンバーを追加または削除するには、.ResX ファイルを編集して、/str オプションと共に | |||
| // ResGen を実行し直すか、または VS プロジェクトをビルドし直します。 | |||
| [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] | |||
| [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] | |||
| [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] | |||
| internal class Resources { | |||
| private static global::System.Resources.ResourceManager resourceMan; | |||
| private static global::System.Globalization.CultureInfo resourceCulture; | |||
| [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] | |||
| internal Resources() { | |||
| } | |||
| /// <summary> | |||
| /// このクラスで使用されているキャッシュされた ResourceManager インスタンスを返します。 | |||
| /// </summary> | |||
| [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] | |||
| internal static global::System.Resources.ResourceManager ResourceManager { | |||
| get { | |||
| if (object.ReferenceEquals(resourceMan, null)) { | |||
| global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CSVDownloader.Properties.Resources", typeof(Resources).Assembly); | |||
| resourceMan = temp; | |||
| } | |||
| return resourceMan; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// すべてについて、現在のスレッドの CurrentUICulture プロパティをオーバーライドします | |||
| /// 現在のスレッドの CurrentUICulture プロパティをオーバーライドします。 | |||
| /// </summary> | |||
| [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] | |||
| internal static global::System.Globalization.CultureInfo Culture { | |||
| get { | |||
| return resourceCulture; | |||
| } | |||
| set { | |||
| resourceCulture = value; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,101 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <root> | |||
| <!-- | |||
| Microsoft ResX Schema | |||
| Version 1.3 | |||
| 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">1.3</resheader> | |||
| <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> | |||
| <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> | |||
| <data name="Name1">this is my long string</data> | |||
| <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> | |||
| <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> | |||
| [base64 mime encoded serialized .NET Framework object] | |||
| </data> | |||
| <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> | |||
| [base64 mime encoded string representing a byte array form of the .NET Framework object] | |||
| </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.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:element name="root" msdata:IsDataSet="true"> | |||
| <xsd:complexType> | |||
| <xsd:choice maxOccurs="unbounded"> | |||
| <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" msdata:Ordinal="1" /> | |||
| <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> | |||
| <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> | |||
| </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>1.3</value> | |||
| </resheader> | |||
| <resheader name="reader"> | |||
| <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </resheader> | |||
| <resheader name="writer"> | |||
| <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
| </resheader> | |||
| </root> | |||
| @@ -0,0 +1,26 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using MySql.Data.MySqlClient; | |||
| namespace CSVDownloader.Store.CreditCSVData { | |||
| class CreditCSVData { | |||
| public String spot_id = ""; | |||
| public DateTime upd_date = DateTime.Now; | |||
| public String upd_staff = "auto_tool"; | |||
| public DateTime reg_date = DateTime.Now; | |||
| public String reg_staff = "auto_tool"; | |||
| } | |||
| abstract class CreditCSVDataStore : MySQL { | |||
| public CreditCSVDataStore(MySqlConnection conn) : base(conn) { | |||
| } | |||
| abstract public void Save(CreditCSVData obj); | |||
| abstract public int Delete(DateTime from, DateTime to); | |||
| } | |||
| } | |||
| @@ -0,0 +1,132 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using MySql.Data.MySqlClient; | |||
| namespace CSVDownloader.Store.CreditCSVData { | |||
| class CreditCSVDataDaito : CreditCSVData { | |||
| public String parking_name = ""; | |||
| public String developer = ""; | |||
| public String adjust_type = ""; | |||
| public String fee_type = ""; | |||
| public DateTime reception_datetime = DateTime.Now; | |||
| public int amount = 0; | |||
| public String reception_no = ""; | |||
| public String response_no = ""; | |||
| public String error_code1 = ""; | |||
| public String error_code2 = ""; | |||
| public enum ColName { | |||
| SpotID = 100, | |||
| ParkingName = 0, | |||
| Developer, | |||
| AdjustType, | |||
| FeeType, | |||
| ReceptionDatetime, | |||
| Amount, | |||
| ReceptionNo, | |||
| ResponseNo, | |||
| ErrorCode1, | |||
| ErrorCode2, | |||
| UpdDate, | |||
| UpdStaff, | |||
| RegDate, | |||
| RegStaff | |||
| }; | |||
| } | |||
| class DaitoCreitDataStore : CreditCSVDataStore { | |||
| private static readonly String table_name_ = "creditcard_download_data_daito"; | |||
| private static readonly String insert_sql = $"insert into {table_name_} (" + | |||
| $"{CreditCSVDataDaito.ColName.SpotID.ToString()}," + | |||
| $"{CreditCSVDataDaito.ColName.ParkingName.ToString()}," + | |||
| $"{CreditCSVDataDaito.ColName.Developer.ToString()}," + | |||
| $"{CreditCSVDataDaito.ColName.AdjustType.ToString()}," + | |||
| $"{CreditCSVDataDaito.ColName.FeeType.ToString()}," + | |||
| $"{CreditCSVDataDaito.ColName.ReceptionDatetime.ToString()}," + | |||
| $"{CreditCSVDataDaito.ColName.Amount.ToString()}," + | |||
| $"{CreditCSVDataDaito.ColName.ReceptionNo.ToString()}," + | |||
| $"{CreditCSVDataDaito.ColName.ResponseNo.ToString()}," + | |||
| $"{CreditCSVDataDaito.ColName.ErrorCode1.ToString()}," + | |||
| $"{CreditCSVDataDaito.ColName.ErrorCode2.ToString()}," + | |||
| //$"{CSVDataDaito.ColName.UpdDate.ToString()}," + | |||
| $"{CreditCSVDataDaito.ColName.UpdStaff.ToString()}," + | |||
| //$"{CSVDataDaito.ColName.RegDate.ToString()}," + | |||
| $"{CreditCSVDataDaito.ColName.RegStaff.ToString()}" + | |||
| $" ) values (" + | |||
| $"@{CreditCSVDataDaito.ColName.SpotID.ToString()}," + | |||
| $"@{CreditCSVDataDaito.ColName.ParkingName.ToString()}," + | |||
| $"@{CreditCSVDataDaito.ColName.Developer.ToString()}," + | |||
| $"@{CreditCSVDataDaito.ColName.AdjustType.ToString()}," + | |||
| $"@{CreditCSVDataDaito.ColName.FeeType.ToString()}," + | |||
| $"@{CreditCSVDataDaito.ColName.ReceptionDatetime.ToString()}," + | |||
| $"@{CreditCSVDataDaito.ColName.Amount.ToString()}," + | |||
| $"@{CreditCSVDataDaito.ColName.ReceptionNo.ToString()}," + | |||
| $"@{CreditCSVDataDaito.ColName.ResponseNo.ToString()}," + | |||
| $"@{CreditCSVDataDaito.ColName.ErrorCode1.ToString()}," + | |||
| $"@{CreditCSVDataDaito.ColName.ErrorCode2.ToString()}," + | |||
| //$"@{CSVDataDaito.ColName.UpdDate.ToString()}," + | |||
| $"@{CreditCSVDataDaito.ColName.UpdStaff.ToString()}," + | |||
| //$"@{CSVDataDaito.ColName.RegDate.ToString()}" + | |||
| $"@{CreditCSVDataDaito.ColName.RegStaff.ToString()}" + | |||
| $");"; | |||
| private String delete_sql_ = $"delete from {table_name_} where " + | |||
| $"{CreditCSVDataDaito.ColName.ReceptionDatetime.ToString()} between " + | |||
| $"@From{CreditCSVDataDaito.ColName.ReceptionDatetime.ToString()} and " + | |||
| $"@To{CreditCSVDataDaito.ColName.ReceptionDatetime.ToString()};"; | |||
| public DaitoCreitDataStore(MySqlConnection conn) : base(conn) { | |||
| } | |||
| public override void Save(CreditCSVData obj) { | |||
| var data = (CreditCSVDataDaito)obj; | |||
| var bindlist = new List<(String, object)> { | |||
| (CreditCSVDataDaito.ColName.SpotID.ToString(), data.spot_id), | |||
| (CreditCSVDataDaito.ColName.ParkingName.ToString(), data.parking_name), | |||
| (CreditCSVDataDaito.ColName.Developer.ToString(), data.developer), | |||
| (CreditCSVDataDaito.ColName.AdjustType.ToString(), data.adjust_type), | |||
| (CreditCSVDataDaito.ColName.FeeType.ToString(), data.fee_type), | |||
| (CreditCSVDataDaito.ColName.ReceptionDatetime.ToString(), data.reception_datetime), | |||
| (CreditCSVDataDaito.ColName.Amount.ToString(), data.amount), | |||
| (CreditCSVDataDaito.ColName.ReceptionNo.ToString(), data.reception_no), | |||
| (CreditCSVDataDaito.ColName.ResponseNo.ToString(), data.response_no), | |||
| (CreditCSVDataDaito.ColName.ErrorCode1.ToString(), data.error_code1), | |||
| (CreditCSVDataDaito.ColName.ErrorCode2.ToString(), data.error_code2), | |||
| (CreditCSVDataDaito.ColName.UpdStaff.ToString(), data.upd_staff), | |||
| (CreditCSVDataDaito.ColName.RegStaff.ToString(), data.reg_staff) | |||
| }; | |||
| var ret = InsertData(insert_sql, bindlist); | |||
| if (ret != Code.ResultCode.OK) { | |||
| throw new Exception("登録失敗 大都"); | |||
| } | |||
| } | |||
| public override int Delete(DateTime from, DateTime to) { | |||
| var bindlist = new List<(String, object)> { | |||
| ("From"+CreditCSVDataDaito.ColName.ReceptionDatetime.ToString(), from.ToString("yyyy-MM-dd")), | |||
| ("To"+CreditCSVDataDaito.ColName.ReceptionDatetime.ToString(), to.AddDays(1).ToString("yyyy-MM-dd")) | |||
| }; | |||
| var delete_count = DeleteData(delete_sql_, bindlist); | |||
| if (delete_count == -1) { | |||
| throw new Exception("削除失敗 大都"); | |||
| } | |||
| return delete_count; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,138 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using MySql.Data.MySqlClient; | |||
| namespace CSVDownloader.Store.CreditCSVData { | |||
| class CSVDataHelloTechno : CreditCSVData { | |||
| public String spot_i_d = ""; | |||
| public DateTime register_datetime = DateTime.Now; | |||
| public String user_code = ""; | |||
| public String parking_code = ""; | |||
| public String device_no = ""; | |||
| public String adjust_no = ""; | |||
| public String trade = ""; | |||
| public int amount = 0; | |||
| public String card_company_name = ""; | |||
| public String approval_no = ""; | |||
| public String response_no = ""; | |||
| public DateTime? cancel_date = null; | |||
| public String error = ""; | |||
| public enum ColName { | |||
| SpotID = 100, | |||
| RegisterDatetime = 0, | |||
| UserCode, | |||
| ParkingCode, | |||
| DeviceNo, | |||
| AdjustNo, | |||
| Trade, | |||
| Amount, | |||
| CardCompanyName, | |||
| ApprovalNo, | |||
| ResponseNo, | |||
| CancelDate, | |||
| Error, | |||
| UpdDate, | |||
| UpdStaff, | |||
| RegDate, | |||
| RegStaff | |||
| } | |||
| } | |||
| class HelloTechnoCreditDataStore : CreditCSVDataStore { | |||
| private static readonly String table_name_ = "creditcard_download_data_hellotechno"; | |||
| private static readonly String insert_sql = $"insert into {table_name_} (" + | |||
| $"{CSVDataHelloTechno.ColName.SpotID}, " + | |||
| $"{CSVDataHelloTechno.ColName.RegisterDatetime}, " + | |||
| $"{CSVDataHelloTechno.ColName.UserCode}, " + | |||
| $"{CSVDataHelloTechno.ColName.ParkingCode}, " + | |||
| $"{CSVDataHelloTechno.ColName.DeviceNo}, " + | |||
| $"{CSVDataHelloTechno.ColName.AdjustNo}, " + | |||
| $"{CSVDataHelloTechno.ColName.Trade}, " + | |||
| $"{CSVDataHelloTechno.ColName.Amount}, " + | |||
| $"{CSVDataHelloTechno.ColName.CardCompanyName}, " + | |||
| $"{CSVDataHelloTechno.ColName.ApprovalNo}, " + | |||
| $"{CSVDataHelloTechno.ColName.ResponseNo}, " + | |||
| $"{CSVDataHelloTechno.ColName.CancelDate}, " + | |||
| $"{CSVDataHelloTechno.ColName.Error}, " + | |||
| //$"{CSVDataHelloTechno.ColName.UpdDate}, " + | |||
| $"{CSVDataHelloTechno.ColName.UpdStaff}, " + | |||
| //$"{CSVDataHelloTechno.ColName.RegDate}, " + | |||
| $"{CSVDataHelloTechno.ColName.RegStaff} " + | |||
| $" ) values (" + | |||
| $"@{CSVDataHelloTechno.ColName.SpotID}, " + | |||
| $"@{CSVDataHelloTechno.ColName.RegisterDatetime}, " + | |||
| $"@{CSVDataHelloTechno.ColName.UserCode}, " + | |||
| $"@{CSVDataHelloTechno.ColName.ParkingCode}, " + | |||
| $"@{CSVDataHelloTechno.ColName.DeviceNo}, " + | |||
| $"@{CSVDataHelloTechno.ColName.AdjustNo}, " + | |||
| $"@{CSVDataHelloTechno.ColName.Trade}, " + | |||
| $"@{CSVDataHelloTechno.ColName.Amount}, " + | |||
| $"@{CSVDataHelloTechno.ColName.CardCompanyName}, " + | |||
| $"@{CSVDataHelloTechno.ColName.ApprovalNo}, " + | |||
| $"@{CSVDataHelloTechno.ColName.ResponseNo}, " + | |||
| $"@{CSVDataHelloTechno.ColName.CancelDate}, " + | |||
| $"@{CSVDataHelloTechno.ColName.Error}, " + | |||
| //$"@{CSVDataHelloTechno.ColName.UpdDate}, " + | |||
| $"@{CSVDataHelloTechno.ColName.UpdStaff}, " + | |||
| //$"@{CSVDataHelloTechno.ColName.RegDate}, " + | |||
| $"@{CSVDataHelloTechno.ColName.RegStaff} " + | |||
| $");"; | |||
| private String delete_sql_ = $"delete from {table_name_} where " + | |||
| $"{CSVDataHelloTechno.ColName.RegisterDatetime} between " + | |||
| $"@From{CSVDataHelloTechno.ColName.RegisterDatetime} and " + | |||
| $"@To{CSVDataHelloTechno.ColName.RegisterDatetime};"; | |||
| public HelloTechnoCreditDataStore(MySqlConnection conn) : base(conn) { | |||
| } | |||
| public override void Save(CreditCSVData obj) { | |||
| var data = (CSVDataHelloTechno)obj; | |||
| var bindlist = new List<(String, object)> { | |||
| (CSVDataHelloTechno.ColName.SpotID.ToString(), data.spot_id), | |||
| (CSVDataHelloTechno.ColName.RegisterDatetime.ToString(), data.register_datetime.ToString()), | |||
| (CSVDataHelloTechno.ColName.UserCode.ToString(), data.user_code), | |||
| (CSVDataHelloTechno.ColName.ParkingCode.ToString(), data.parking_code), | |||
| (CSVDataHelloTechno.ColName.DeviceNo.ToString(), data.device_no), | |||
| (CSVDataHelloTechno.ColName.AdjustNo.ToString(), data.adjust_no), | |||
| (CSVDataHelloTechno.ColName.Trade.ToString(), data.trade), | |||
| (CSVDataHelloTechno.ColName.Amount.ToString(), data.amount), | |||
| (CSVDataHelloTechno.ColName.CardCompanyName.ToString(), data.card_company_name), | |||
| (CSVDataHelloTechno.ColName.ApprovalNo.ToString(), data.approval_no), | |||
| (CSVDataHelloTechno.ColName.ResponseNo.ToString(), data.response_no), | |||
| (CSVDataHelloTechno.ColName.CancelDate.ToString(), data.cancel_date != null ? ((DateTime)data.cancel_date).ToString(): null), | |||
| (CSVDataHelloTechno.ColName.Error.ToString(), data.error), | |||
| (CSVDataHelloTechno.ColName.UpdStaff.ToString(), data.upd_staff), | |||
| (CSVDataHelloTechno.ColName.RegStaff.ToString(), data.reg_staff), | |||
| }; | |||
| var ret = InsertData(insert_sql, bindlist); | |||
| if (ret != Code.ResultCode.OK) { | |||
| throw new Exception("登録失敗 Zeus"); | |||
| } | |||
| } | |||
| public override int Delete(DateTime from, DateTime to) { | |||
| var bindlist = new List<(String, object)> { | |||
| ("From"+CSVDataHelloTechno.ColName.RegisterDatetime.ToString(), from.ToString("yyyy-MM-dd")), | |||
| ("To"+CSVDataHelloTechno.ColName.RegisterDatetime.ToString(), to.AddDays(1).ToString("yyyy-MM-dd")) | |||
| }; | |||
| var delete_count = DeleteData(delete_sql_, bindlist); | |||
| if (delete_count == -1) { | |||
| throw new Exception("削除失敗 Zeus"); | |||
| } | |||
| return delete_count; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,127 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using MySql.Data.MySqlClient; | |||
| namespace CSVDownloader.Store.CreditCSVData { | |||
| class CSVDataItec : CreditCSVData { | |||
| public String code = ""; | |||
| public String parking_name = ""; | |||
| public String device_type = ""; | |||
| public DateTime use_datetime = DateTime.Now; | |||
| public String trade = ""; | |||
| public String card_company_name = ""; | |||
| public int amount = 0; | |||
| public int tax_send_fee = 0; | |||
| public int total_amount = 0; | |||
| public String error_code = ""; | |||
| public enum ColName { | |||
| SpotID = 100, | |||
| Code = 0, | |||
| ParkingName, | |||
| DeviceType, | |||
| UseDatetime, | |||
| Trade, | |||
| CardCompanyName, | |||
| Amount, | |||
| TaxSendFee, | |||
| TotalAmount, | |||
| ErrorCode, | |||
| UpdDate, | |||
| UpdStaff, | |||
| RegDate, | |||
| RegStaff | |||
| }; | |||
| } | |||
| class ItecCreditDataStore : CreditCSVDataStore { | |||
| private static readonly String table_name_ = "creditcard_download_data_itec"; | |||
| private static readonly String insert_sql = $"insert into {table_name_} (" + | |||
| $"{CSVDataItec.ColName.SpotID}," + | |||
| $"{CSVDataItec.ColName.Code}," + | |||
| $"{CSVDataItec.ColName.ParkingName}," + | |||
| $"{CSVDataItec.ColName.DeviceType}," + | |||
| $"{CSVDataItec.ColName.UseDatetime}," + | |||
| $"{CSVDataItec.ColName.Trade}," + | |||
| $"{CSVDataItec.ColName.CardCompanyName}," + | |||
| $"{CSVDataItec.ColName.Amount}," + | |||
| $"{CSVDataItec.ColName.TaxSendFee}," + | |||
| $"{CSVDataItec.ColName.TotalAmount}," + | |||
| $"{CSVDataItec.ColName.ErrorCode}," + | |||
| //$"{CSVDataItec.ColName.UpdDate}," + | |||
| $"{CSVDataItec.ColName.UpdStaff}," + | |||
| //$"{CSVDataItec.ColName.RegDate}," + | |||
| $"{CSVDataItec.ColName.RegStaff}" + | |||
| $" ) values (" + | |||
| $"@{CSVDataItec.ColName.SpotID}," + | |||
| $"@{CSVDataItec.ColName.Code}," + | |||
| $"@{CSVDataItec.ColName.ParkingName}," + | |||
| $"@{CSVDataItec.ColName.DeviceType}," + | |||
| $"@{CSVDataItec.ColName.UseDatetime}," + | |||
| $"@{CSVDataItec.ColName.Trade}," + | |||
| $"@{CSVDataItec.ColName.CardCompanyName}," + | |||
| $"@{CSVDataItec.ColName.Amount}," + | |||
| $"@{CSVDataItec.ColName.TaxSendFee}," + | |||
| $"@{CSVDataItec.ColName.TotalAmount}," + | |||
| $"@{CSVDataItec.ColName.ErrorCode}," + | |||
| //$"@{CSVDataItec.ColName.UpdDate}," + | |||
| $"@{CSVDataItec.ColName.UpdStaff}," + | |||
| //$"@{CSVDataItec.ColName.RegDate}," + | |||
| $"@{CSVDataItec.ColName.RegStaff}" + | |||
| $");"; | |||
| private String delete_sql_ = $"delete from {table_name_} where " + | |||
| $"{CSVDataItec.ColName.UseDatetime} between " + | |||
| $"@From{CSVDataItec.ColName.UseDatetime} and " + | |||
| $"@To{CSVDataItec.ColName.UseDatetime};"; | |||
| public ItecCreditDataStore(MySqlConnection conn) : base(conn) { | |||
| } | |||
| public override void Save(CreditCSVData obj) { | |||
| var data = (CSVDataItec)obj; | |||
| var bindlist = new List<(String, object)> { | |||
| (CSVDataItec.ColName.SpotID.ToString(), data.spot_id), | |||
| (CSVDataItec.ColName.Code.ToString(), data.code), | |||
| (CSVDataItec.ColName.ParkingName.ToString(), data.parking_name), | |||
| (CSVDataItec.ColName.DeviceType.ToString(), data.device_type), | |||
| (CSVDataItec.ColName.UseDatetime.ToString(), data.use_datetime.ToString()), | |||
| (CSVDataItec.ColName.Trade.ToString(), data.trade), | |||
| (CSVDataItec.ColName.CardCompanyName.ToString(), data.card_company_name), | |||
| (CSVDataItec.ColName.Amount.ToString(), data.amount), | |||
| (CSVDataItec.ColName.TaxSendFee.ToString(), data.tax_send_fee), | |||
| (CSVDataItec.ColName.TotalAmount.ToString(), data.total_amount), | |||
| (CSVDataItec.ColName.ErrorCode.ToString(), data.error_code), | |||
| (CSVDataItec.ColName.UpdStaff.ToString(), data.upd_staff), | |||
| (CSVDataItec.ColName.RegStaff.ToString(), data.reg_staff) | |||
| }; | |||
| var ret = InsertData(insert_sql, bindlist); | |||
| if (ret != Code.ResultCode.OK) { | |||
| throw new Exception("登録失敗 Zeus"); | |||
| } | |||
| } | |||
| public override int Delete(DateTime from, DateTime to) { | |||
| var bindlist = new List<(String, object)> { | |||
| ("From"+CSVDataItec.ColName.UseDatetime.ToString(), from.ToString("yyyy-MM-dd")), | |||
| ("To"+CSVDataItec.ColName.UseDatetime.ToString(), to.AddDays(1).ToString("yyyy-MM-dd")) | |||
| }; | |||
| var delete_count = DeleteData(delete_sql_, bindlist); | |||
| if (delete_count == -1) { | |||
| throw new Exception("削除失敗 Zeus"); | |||
| } | |||
| return delete_count; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,158 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using MySql.Data.MySqlClient; | |||
| namespace CSVDownloader.Store.CreditCSVData { | |||
| class CreditCSVDataZeus : CreditCSVData { | |||
| public DateTime use_datetime = DateTime.Now; | |||
| public String ip = ""; | |||
| public String device_no = ""; | |||
| public String receipt_no = ""; | |||
| public String certificate_no = ""; | |||
| public String status = ""; | |||
| public String error_message = ""; | |||
| public int amount = 0; | |||
| public String card_no = ""; | |||
| public String expiration_date = ""; | |||
| public String brand = ""; | |||
| public String payment_type = ""; | |||
| public String jis_info = ""; | |||
| public String test = ""; | |||
| public String order_no = ""; | |||
| public enum ColName { | |||
| SpotID = 100, | |||
| UseDatetime = 0, | |||
| IP, | |||
| DeviceNo, | |||
| ReceiptNo, | |||
| CertificateNo, | |||
| Status, | |||
| ErrorMessage, | |||
| Amount, | |||
| CardNo, | |||
| ExpirationDate, | |||
| Brand, | |||
| PaymentType, | |||
| JISInfo, | |||
| Test, | |||
| OrderNo, | |||
| UpdDate, | |||
| UpdStaff, | |||
| RegDate, | |||
| RegStaff | |||
| }; | |||
| } | |||
| class ZeusCreditDataStore : CreditCSVDataStore { | |||
| private static readonly String table_name_ = "creditcard_download_data_zeus"; | |||
| private static readonly String insert_sql = $"insert into {table_name_} (" + | |||
| $"{CreditCSVDataZeus.ColName.SpotID}," + | |||
| $"{CreditCSVDataZeus.ColName.UseDatetime}," + | |||
| $"{CreditCSVDataZeus.ColName.IP}," + | |||
| $"{CreditCSVDataZeus.ColName.DeviceNo}," + | |||
| $"{CreditCSVDataZeus.ColName.ReceiptNo}," + | |||
| $"{CreditCSVDataZeus.ColName.CertificateNo}," + | |||
| $"{CreditCSVDataZeus.ColName.Status}," + | |||
| $"{CreditCSVDataZeus.ColName.ErrorMessage}," + | |||
| $"{CreditCSVDataZeus.ColName.Amount}," + | |||
| $"{CreditCSVDataZeus.ColName.CardNo}," + | |||
| $"{CreditCSVDataZeus.ColName.ExpirationDate}," + | |||
| $"{CreditCSVDataZeus.ColName.Brand}," + | |||
| $"{CreditCSVDataZeus.ColName.PaymentType}," + | |||
| $"{CreditCSVDataZeus.ColName.JISInfo}," + | |||
| $"{CreditCSVDataZeus.ColName.Test}," + | |||
| $"{CreditCSVDataZeus.ColName.OrderNo}," + | |||
| //$"{CSVDataZeus.ColName.UpdDate}," + | |||
| $"{CreditCSVDataZeus.ColName.UpdStaff}," + | |||
| //$"{CSVDataZeus.ColName.RegDate.ToString()}," + | |||
| $"{CreditCSVDataZeus.ColName.RegStaff}" + | |||
| $" ) values (" + | |||
| $"@{CreditCSVDataZeus.ColName.SpotID}," + | |||
| $"@{CreditCSVDataZeus.ColName.UseDatetime}," + | |||
| $"@{CreditCSVDataZeus.ColName.IP}," + | |||
| $"@{CreditCSVDataZeus.ColName.DeviceNo}," + | |||
| $"@{CreditCSVDataZeus.ColName.ReceiptNo}," + | |||
| $"@{CreditCSVDataZeus.ColName.CertificateNo}," + | |||
| $"@{CreditCSVDataZeus.ColName.Status}," + | |||
| $"@{CreditCSVDataZeus.ColName.ErrorMessage}," + | |||
| $"@{CreditCSVDataZeus.ColName.Amount}," + | |||
| $"@{CreditCSVDataZeus.ColName.CardNo}," + | |||
| $"@{CreditCSVDataZeus.ColName.ExpirationDate}," + | |||
| $"@{CreditCSVDataZeus.ColName.Brand}," + | |||
| $"@{CreditCSVDataZeus.ColName.PaymentType}," + | |||
| $"@{CreditCSVDataZeus.ColName.JISInfo}," + | |||
| $"@{CreditCSVDataZeus.ColName.Test}," + | |||
| $"@{CreditCSVDataZeus.ColName.OrderNo}," + | |||
| //$"{CSVDataZeus.ColName.UpdDate}," + | |||
| $"@{CreditCSVDataZeus.ColName.UpdStaff}," + | |||
| //$"{CSVDataZeus.ColName.RegDate}," + | |||
| $"@{CreditCSVDataZeus.ColName.RegStaff}" + | |||
| $");"; | |||
| private String delete_sql_ = $"delete from {table_name_} where " + | |||
| $"{CreditCSVDataZeus.ColName.UseDatetime} between " + | |||
| $"@From{CreditCSVDataZeus.ColName.UseDatetime} and " + | |||
| $"@To{CreditCSVDataZeus.ColName.UseDatetime};"; | |||
| public ZeusCreditDataStore(MySqlConnection conn) : base(conn) { | |||
| } | |||
| public override void Save(CreditCSVData obj) { | |||
| var data = (CreditCSVDataZeus)obj; | |||
| var bindlist = new List<(String, object)> { | |||
| (CreditCSVDataZeus.ColName.SpotID.ToString(), data.spot_id), | |||
| (CreditCSVDataZeus.ColName.UseDatetime.ToString(), data.use_datetime.ToString()), | |||
| (CreditCSVDataZeus.ColName.IP.ToString(), data.ip), | |||
| (CreditCSVDataZeus.ColName.DeviceNo.ToString(), data.device_no), | |||
| (CreditCSVDataZeus.ColName.ReceiptNo.ToString(), data.receipt_no), | |||
| (CreditCSVDataZeus.ColName.CertificateNo.ToString(), data.certificate_no), | |||
| (CreditCSVDataZeus.ColName.Status.ToString(), data.status), | |||
| (CreditCSVDataZeus.ColName.ErrorMessage.ToString(), data.error_message), | |||
| (CreditCSVDataZeus.ColName.Amount.ToString(), data.amount), | |||
| (CreditCSVDataZeus.ColName.CardNo.ToString(), data.card_no), | |||
| (CreditCSVDataZeus.ColName.ExpirationDate.ToString(), data.expiration_date), | |||
| (CreditCSVDataZeus.ColName.Brand.ToString(), data.brand), | |||
| (CreditCSVDataZeus.ColName.PaymentType.ToString(), data.payment_type), | |||
| (CreditCSVDataZeus.ColName.JISInfo.ToString(), data.jis_info), | |||
| (CreditCSVDataZeus.ColName.Test.ToString(), data.test), | |||
| (CreditCSVDataZeus.ColName.OrderNo.ToString(), data.order_no), | |||
| (CreditCSVDataZeus.ColName.UpdStaff.ToString(), data.upd_staff), | |||
| (CreditCSVDataZeus.ColName.RegStaff.ToString(), data.reg_staff) | |||
| }; | |||
| var ret = InsertData(insert_sql, bindlist); | |||
| if (ret != Code.ResultCode.OK) { | |||
| throw new Exception("登録失敗 Zeus"); | |||
| } | |||
| } | |||
| public override int Delete(DateTime from, DateTime to) { | |||
| var bindlist = new List<(String, object)> { | |||
| ("From"+CreditCSVDataZeus.ColName.UseDatetime.ToString(), from.ToString("yyyy-MM-dd")), | |||
| ("To"+CreditCSVDataZeus.ColName.UseDatetime.ToString(), to.AddDays(1).ToString("yyyy-MM-dd")) | |||
| }; | |||
| var delete_count = DeleteData(delete_sql_, bindlist); | |||
| if (delete_count == -1) { | |||
| throw new Exception("削除失敗 Zeus"); | |||
| } | |||
| return delete_count; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,86 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using System.IO; | |||
| using System.Data.SQLite; | |||
| namespace CSVDownloader.Store { | |||
| class History { | |||
| public DateTime date; | |||
| public String agent; | |||
| } | |||
| class HistoryDAO : SQLite3, IHistoryDAO { | |||
| private static readonly String tablename_ = "History"; | |||
| private static readonly String colname_date_ = "Datetime"; | |||
| private static readonly String colname_credit_agent_ = "CreditAgent"; | |||
| private static readonly String dir_ = "data"; | |||
| private static readonly String source_ = $"{dir_}/history.db"; | |||
| public HistoryDAO() { | |||
| if (!Directory.Exists(dir_)) { | |||
| Directory.CreateDirectory(dir_); | |||
| } | |||
| Open(source_); | |||
| String sql_create_table = "" + | |||
| $"CREATE TABLE IF NOT EXISTS {tablename_}(" + | |||
| $"{colname_date_} TEXT NOT NULL," + | |||
| $"{colname_credit_agent_} TEXT NOT NULL" + | |||
| ");"; | |||
| using (var cmd = new SQLiteCommand(sql_create_table, conn_)) { | |||
| cmd.ExecuteNonQuery(); | |||
| } | |||
| } | |||
| public void Save(Code.CreditAgent agent, DateTime datetime) { | |||
| using (var cmd = conn_.CreateCommand()) { | |||
| String replace_date = "@Datetime"; | |||
| String replace_credit_agent = "@CreditAgent"; | |||
| cmd.CommandText = $"insert into {tablename_} values ({replace_date},{replace_credit_agent});"; | |||
| String date_str = datetime.ToString(); | |||
| cmd.Parameters.Add(new SQLiteParameter(replace_date, date_str)); | |||
| cmd.Parameters.Add(new SQLiteParameter(replace_credit_agent, Code.CreditAgenciesMap.GetID(agent))); | |||
| cmd.Prepare(); | |||
| cmd.ExecuteNonQuery(); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 直近の履歴を1つだけ取得する。 | |||
| /// </summary> | |||
| /// <param name="agent"></param> | |||
| /// <returns></returns> | |||
| public List<History> GetHistory(Code.CreditAgent agent) { | |||
| var list = new List<History>(); | |||
| using (var cmd = conn_.CreateCommand()) { | |||
| String replace_credit_agent = "@CreditAgent"; | |||
| cmd.CommandText = $"select * from {tablename_} where {colname_credit_agent_} = {replace_credit_agent} order by {colname_date_} desc limit 1;"; | |||
| cmd.Parameters.Add(new SQLiteParameter(replace_credit_agent, Code.CreditAgenciesMap.GetID(agent))); | |||
| cmd.Prepare(); | |||
| using (var reader = cmd.ExecuteReader()) { | |||
| while (reader.Read()) { | |||
| var ele = new History(); | |||
| ele.date = DateTime.Parse(reader[colname_date_].ToString()); | |||
| ele.agent = reader[colname_credit_agent_].ToString(); | |||
| list.Add(ele); | |||
| } | |||
| } | |||
| } | |||
| return list; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,13 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| namespace CSVDownloader.Store { | |||
| interface IHistoryDAO { | |||
| public List<History> GetHistory(Code.CreditAgent agent); | |||
| public void Save(Code.CreditAgent agent, DateTime datetime); | |||
| } | |||
| } | |||
| @@ -0,0 +1,65 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using MySql.Data.MySqlClient; | |||
| namespace CSVDownloader.Store { | |||
| class MySqlConnectionParameter { | |||
| public String host; | |||
| public int port; | |||
| public String database; | |||
| public String user; | |||
| public String password; | |||
| } | |||
| class MySQL { | |||
| private log4net.ILog logger_ = log4net.LogManager.GetLogger(""); | |||
| protected MySqlConnection conn_; | |||
| public MySQL(MySqlConnection conn) { | |||
| conn_ = conn; | |||
| } | |||
| public static MySqlConnection GetConnection(MySqlConnectionParameter param) { | |||
| String conn_string = $"Server={param.host}; Port={param.port}; Database={param.database}; Uid={param.user}; Pwd={param.password}"; | |||
| var conn = new MySqlConnection(conn_string); | |||
| conn.Open(); | |||
| return conn; | |||
| } | |||
| private int ExecuteNonQuery(String sql, List<(String, object)> bindlist) { | |||
| // logger_.Debug($"{sql}"); | |||
| int ret = 0; | |||
| using (var cmd = conn_.CreateCommand()) { | |||
| cmd.CommandText = sql; | |||
| foreach (var ele in bindlist) { | |||
| // logger_.Debug($"bind @{ele.Item1} = {ele.Item2}"); | |||
| cmd.Parameters.AddWithValue($"@{ele.Item1}", ele.Item2); | |||
| } | |||
| cmd.Prepare(); | |||
| ret = cmd.ExecuteNonQuery(); | |||
| } | |||
| return ret; | |||
| } | |||
| protected Code.ResultCode InsertData(String sql, List<(String, object)> bindlist) { | |||
| var ret = ExecuteNonQuery(sql, bindlist); | |||
| if (ret == -1) { | |||
| return Code.ResultCode.NG; | |||
| } | |||
| return Code.ResultCode.OK; | |||
| } | |||
| protected int DeleteData(String sql, List<(String, object)> bindlist) { | |||
| return ExecuteNonQuery(sql, bindlist); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,44 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using System.Data; | |||
| using MySql.Data.MySqlClient; | |||
| namespace CSVDownloader.Store { | |||
| class ParkingCreditCardAgenciesSpotIDDAO : MySQL { | |||
| public ParkingCreditCardAgenciesSpotIDDAO(MySqlConnection conn) : base(conn) { | |||
| } | |||
| public Dictionary<String, String> GetDictionary(Code.CreditAgent agent) { | |||
| var dic = new Dictionary<String, String>(); | |||
| String code = Code.CreditAgenciesMap.GetID(agent); | |||
| var tbl = new DataTable(); | |||
| String replace_id = "@id"; | |||
| String sql = $"select CreditcardAgenciesSpotName, SpotID from parking_creditcard_agencies_spotid " + | |||
| $"where CreditcardAgenciesID = {replace_id};"; | |||
| using (var adpt = new MySqlDataAdapter(sql, conn_)) { | |||
| adpt.SelectCommand.Parameters.AddWithValue(replace_id, code); | |||
| adpt.SelectCommand.Prepare(); | |||
| adpt.Fill(tbl); | |||
| } | |||
| foreach (DataRow row in tbl.Rows) { | |||
| dic.Add(row[0].ToString(), row[1].ToString()); | |||
| } | |||
| return dic; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,117 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using MySql.Data.MySqlClient; | |||
| namespace CSVDownloader.Store.QRCSVData { | |||
| class QRCSVDataDaito : QRCSVData { | |||
| public String parking_name = ""; | |||
| public String developer = ""; | |||
| public DateTime reception_datetime = DateTime.Now; | |||
| public String company = ""; | |||
| public int amount = 0; | |||
| public String adjust_no = ""; | |||
| public String error_code = ""; | |||
| public enum ColName { | |||
| SpotID = 100, | |||
| ParkingName = 0, | |||
| Developer, | |||
| ReceptionDatetime, | |||
| Company, | |||
| Amount, | |||
| AdjustNo, | |||
| ErrorCode, | |||
| UpdDate, | |||
| UpdStaff, | |||
| RegDate, | |||
| RegStaff | |||
| }; | |||
| } | |||
| class DaitoQRDataStore : QRCSVDataStore { | |||
| private static readonly String table_name_ = "qrcode_download_data_daito"; | |||
| private static readonly String insert_sql = $"insert into {table_name_} (" + | |||
| $"{QRCSVDataDaito.ColName.SpotID.ToString()}," + | |||
| $"{QRCSVDataDaito.ColName.ParkingName.ToString()}," + | |||
| $"{QRCSVDataDaito.ColName.Developer.ToString()}," + | |||
| $"{QRCSVDataDaito.ColName.ReceptionDatetime.ToString()}," + | |||
| $"{QRCSVDataDaito.ColName.Company.ToString()}," + | |||
| $"{QRCSVDataDaito.ColName.Amount.ToString()}," + | |||
| $"{QRCSVDataDaito.ColName.AdjustNo.ToString()}," + | |||
| $"{QRCSVDataDaito.ColName.ErrorCode.ToString()}," + | |||
| //$"{CSVDataDaitoQR.ColName.UpdDate.ToString()}," + | |||
| $"{QRCSVDataDaito.ColName.UpdStaff.ToString()}," + | |||
| //$"{CSVDataDaitoQR.ColName.RegDate.ToString()}," + | |||
| $"{QRCSVDataDaito.ColName.RegStaff.ToString()}" + | |||
| $" ) values (" + | |||
| $"@{QRCSVDataDaito.ColName.SpotID.ToString()}," + | |||
| $"@{QRCSVDataDaito.ColName.ParkingName.ToString()}," + | |||
| $"@{QRCSVDataDaito.ColName.Developer.ToString()}," + | |||
| $"@{QRCSVDataDaito.ColName.ReceptionDatetime.ToString()}," + | |||
| $"@{QRCSVDataDaito.ColName.Company.ToString()}," + | |||
| $"@{QRCSVDataDaito.ColName.Amount.ToString()}," + | |||
| $"@{QRCSVDataDaito.ColName.AdjustNo.ToString()}," + | |||
| $"@{QRCSVDataDaito.ColName.ErrorCode.ToString()}," + | |||
| //$"@{CSVDataDaitoQR.ColName.UpdDate.ToString()}," + | |||
| $"@{QRCSVDataDaito.ColName.UpdStaff.ToString()}," + | |||
| //$"@{CSVDataDaitoQR.ColName.RegDate.ToString()}" + | |||
| $"@{QRCSVDataDaito.ColName.RegStaff.ToString()}" + | |||
| $");"; | |||
| private String delete_sql_ = $"delete from {table_name_} where " + | |||
| $"{QRCSVDataDaito.ColName.ReceptionDatetime.ToString()} between " + | |||
| $"@From{QRCSVDataDaito.ColName.ReceptionDatetime.ToString()} and " + | |||
| $"@To{QRCSVDataDaito.ColName.ReceptionDatetime.ToString()};"; | |||
| public DaitoQRDataStore(MySqlConnection conn) : base(conn) { | |||
| } | |||
| public override void Save(QRCSVData obj) { | |||
| var data = (QRCSVDataDaito)obj; | |||
| var bindlist = new List<(String, object)> { | |||
| (QRCSVDataDaito.ColName.SpotID.ToString(), data.spot_id), | |||
| (QRCSVDataDaito.ColName.ParkingName.ToString(), data.parking_name), | |||
| (QRCSVDataDaito.ColName.Developer.ToString(), data.developer), | |||
| (QRCSVDataDaito.ColName.ReceptionDatetime.ToString(), data.reception_datetime), | |||
| (QRCSVDataDaito.ColName.Company.ToString(), data.company), | |||
| (QRCSVDataDaito.ColName.Amount.ToString(), data.amount), | |||
| (QRCSVDataDaito.ColName.AdjustNo.ToString(), data.adjust_no), | |||
| (QRCSVDataDaito.ColName.ErrorCode.ToString(), data.error_code), | |||
| (QRCSVDataDaito.ColName.UpdStaff.ToString(), data.upd_staff), | |||
| (QRCSVDataDaito.ColName.RegStaff.ToString(), data.reg_staff) | |||
| }; | |||
| var ret = InsertData(insert_sql, bindlist); | |||
| if (ret != Code.ResultCode.OK) { | |||
| throw new Exception("登録失敗 大都QR"); | |||
| } | |||
| } | |||
| public override int Delete(DateTime from, DateTime to) { | |||
| var bindlist = new List<(String, object)> { | |||
| ("From"+QRCSVDataDaito.ColName.ReceptionDatetime.ToString(), from.ToString("yyyy-MM-dd")), | |||
| ("To"+QRCSVDataDaito.ColName.ReceptionDatetime.ToString(), to.AddDays(1).ToString("yyyy-MM-dd")) | |||
| }; | |||
| var delete_count = DeleteData(delete_sql_, bindlist); | |||
| if (delete_count == -1) { | |||
| throw new Exception("削除失敗 大都QR"); | |||
| } | |||
| return delete_count; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,26 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using MySql.Data.MySqlClient; | |||
| namespace CSVDownloader.Store.QRCSVData { | |||
| class QRCSVData { | |||
| public String spot_id = ""; | |||
| public DateTime upd_date = DateTime.Now; | |||
| public String upd_staff = "auto_tool"; | |||
| public DateTime reg_date = DateTime.Now; | |||
| public String reg_staff = "auto_tool"; | |||
| } | |||
| abstract class QRCSVDataStore : MySQL { | |||
| public QRCSVDataStore(MySqlConnection conn) : base(conn) { | |||
| } | |||
| abstract public void Save(QRCSVData obj); | |||
| abstract public int Delete(DateTime from, DateTime to); | |||
| } | |||
| } | |||
| @@ -0,0 +1,24 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using System.Data.SQLite; | |||
| namespace CSVDownloader.Store { | |||
| abstract class SQLite3 { | |||
| protected SQLiteConnection conn_; | |||
| ~SQLite3() { | |||
| if (conn_ != null) { | |||
| conn_.Close(); | |||
| } | |||
| } | |||
| protected void Open(String source) { | |||
| conn_ = new SQLiteConnection($"Data Source={source}"); | |||
| conn_.Open(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,200 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.IO; | |||
| using System.Text; | |||
| using OpenQA.Selenium; | |||
| using OpenQA.Selenium.Chrome; | |||
| using CSVDownloader.Code; | |||
| using CSVDownloader.Store.CreditCSVData; | |||
| using CSVDownloader.Store.QRCSVData; | |||
| using ExpectedConditions = OpenQA.Selenium.Support.UI.ExpectedConditions; | |||
| namespace CSVDownloader.Web { | |||
| class DaitoController : WebController { | |||
| private readonly String url_ = "https://crevation.net"; | |||
| private readonly String home_url_ = "https://crevation.net/"; | |||
| private readonly String filename_credit = "daito_credit.csv"; | |||
| private readonly String filename_qr = "daito_qr.csv"; | |||
| private enum XpathKey { | |||
| INPUT_LOGIN_USERNAME, | |||
| INPUT_LOGIN_PASSWORD, | |||
| BUTTON_MENU, | |||
| BUTTON_KESSAI_KANRI, | |||
| BUTTON_CREDIT_KESSAI, | |||
| BUTTON_QR_KESSAI, | |||
| INPUT_TARGET_FROM, | |||
| INPUT_TARGET_TO, | |||
| BUTTON_DOWNLOAD_CSV, | |||
| BUTTON_LOGOUT, | |||
| }; | |||
| private IDictionary<XpathKey, string> xpath_map_ = new Dictionary<XpathKey, string>() | |||
| { | |||
| {XpathKey.INPUT_LOGIN_USERNAME,@"//*[@id='wrapper']/div/div/div/div/div[2]/form/fieldset/div[1]/input" }, | |||
| {XpathKey.INPUT_LOGIN_PASSWORD,@"//*[@id='wrapper']/div/div/div/div/div[2]/form/fieldset/div[2]/input" }, | |||
| {XpathKey.BUTTON_MENU,@"//*[@id='js-show-popup']" }, | |||
| {XpathKey.BUTTON_KESSAI_KANRI,@"//*[@id='side-menu']/li[4]/a" }, | |||
| {XpathKey.BUTTON_CREDIT_KESSAI,@"//*[@id='side-menu']/li[4]/ul/li[1]/a" }, | |||
| {XpathKey.BUTTON_QR_KESSAI,@"//*[@id='side-menu']/li[4]/ul/li[2]/a" }, | |||
| {XpathKey.INPUT_TARGET_FROM,@"//*[@id='settlementTimeFrom']" }, | |||
| {XpathKey.INPUT_TARGET_TO,@"//*[@id='settlementTimeTo']" }, | |||
| {XpathKey.BUTTON_DOWNLOAD_CSV,@"//*[@id='submitCreateCsv']" }, | |||
| {XpathKey.BUTTON_LOGOUT,@"//*[@id='side-menu']/li[11]/a" }, | |||
| }; | |||
| public DaitoController(ChromeDriver driver) : base(driver) { | |||
| agent_ = CreditAgent.Daito; | |||
| } | |||
| public override ResultCode Login(LoginInfo info) { | |||
| bool enter = true; | |||
| try { | |||
| driver_.Navigate().GoToUrl(url_); | |||
| Send(xpath_map_[XpathKey.INPUT_LOGIN_USERNAME], info.user_name); | |||
| Send(xpath_map_[XpathKey.INPUT_LOGIN_PASSWORD], info.password, enter); | |||
| // ログイン後のメニューボタンが表示されることを確認する。 | |||
| wait_.Until(ExpectedConditions.ElementExists(By.XPath(xpath_map_[XpathKey.BUTTON_MENU]))); | |||
| } catch (Exception e) { | |||
| logger_.Error(e.Message); | |||
| return ResultCode.NG; | |||
| } | |||
| return ResultCode.OK; | |||
| } | |||
| public override ResultCode Download(DateTime from, DateTime to) { | |||
| // クレジットカード承認結果一覧画面に移行 | |||
| Click(xpath_map_[XpathKey.BUTTON_MENU]); | |||
| Click(xpath_map_[XpathKey.BUTTON_KESSAI_KANRI]); | |||
| Click(xpath_map_[XpathKey.BUTTON_CREDIT_KESSAI]); | |||
| // 承認処理日のFrom-Toを入力 | |||
| const String date_format = "yyyy年MM月dd日"; | |||
| Send(xpath_map_[XpathKey.INPUT_TARGET_FROM], from.ToString(date_format)); | |||
| Send(xpath_map_[XpathKey.INPUT_TARGET_TO], to.ToString(date_format)); | |||
| // CSV吐き出しボタンをクリックし、CSVをダウンロード | |||
| wait_.Until(ExpectedConditions.ElementToBeClickable(By.XPath(xpath_map_[XpathKey.BUTTON_DOWNLOAD_CSV]))); | |||
| Click(xpath_map_[XpathKey.BUTTON_DOWNLOAD_CSV]); | |||
| WaitForDownload(filename_credit); | |||
| // QR決済結果結果一覧画面に移行 | |||
| Click(xpath_map_[XpathKey.BUTTON_MENU]); | |||
| Click(xpath_map_[XpathKey.BUTTON_KESSAI_KANRI]); | |||
| Click(xpath_map_[XpathKey.BUTTON_QR_KESSAI]); | |||
| // 承認処理日のFrom-Toを入力 | |||
| Send(xpath_map_[XpathKey.INPUT_TARGET_FROM], from.ToString(date_format)); | |||
| Send(xpath_map_[XpathKey.INPUT_TARGET_TO], to.ToString(date_format)); | |||
| // CSV吐き出しボタンをクリックし、CSVをダウンロード | |||
| wait_.Until(ExpectedConditions.ElementToBeClickable(By.XPath(xpath_map_[XpathKey.BUTTON_DOWNLOAD_CSV]))); | |||
| Click(xpath_map_[XpathKey.BUTTON_DOWNLOAD_CSV]); | |||
| WaitForDownload(filename_qr); | |||
| return ResultCode.OK; | |||
| } | |||
| public override ResultCode Logout() { | |||
| driver_.Navigate().GoToUrl(home_url_); | |||
| Click(xpath_map_[XpathKey.BUTTON_MENU]); | |||
| Click(xpath_map_[XpathKey.BUTTON_LOGOUT]); | |||
| wait_.Until(ExpectedConditions.ElementIsVisible(By.XPath(xpath_map_[XpathKey.INPUT_LOGIN_USERNAME]))); | |||
| return ResultCode.OK; | |||
| } | |||
| public override List<CreditCSVData> GetCreditCSVDataList() { | |||
| var result_list = new List<CreditCSVData>(); | |||
| var list = GetFileContents(filename_credit); | |||
| foreach (var line in list) { | |||
| result_list.Add(new CreditCSVDataDaito() { | |||
| spot_id = GetSpotID(line[(int)CreditCSVDataDaito.ColName.ParkingName]), | |||
| parking_name = line[(int)CreditCSVDataDaito.ColName.ParkingName], | |||
| developer = line[(int)CreditCSVDataDaito.ColName.Developer], | |||
| adjust_type = line[(int)CreditCSVDataDaito.ColName.AdjustType], | |||
| fee_type = line[(int)CreditCSVDataDaito.ColName.FeeType], | |||
| reception_datetime = DateTime.Parse(line[(int)CreditCSVDataDaito.ColName.ReceptionDatetime]), | |||
| amount = int.Parse(line[(int)CreditCSVDataDaito.ColName.Amount]), | |||
| reception_no = line[(int)CreditCSVDataDaito.ColName.ReceptionNo], | |||
| response_no = line[(int)CreditCSVDataDaito.ColName.ResponseNo], | |||
| error_code1 = line[(int)CreditCSVDataDaito.ColName.ErrorCode1], | |||
| error_code2 = line[(int)CreditCSVDataDaito.ColName.ErrorCode2] | |||
| }); | |||
| } | |||
| return result_list; | |||
| } | |||
| public override List<QRCSVData> GetQRCSVDataList() { | |||
| var result_list = new List<QRCSVData>(); | |||
| var list = GetFileContents(filename_qr); | |||
| foreach (var line in list) { | |||
| result_list.Add(new QRCSVDataDaito() { | |||
| spot_id = GetSpotID(line[(int)QRCSVDataDaito.ColName.ParkingName]), | |||
| parking_name = line[(int)QRCSVDataDaito.ColName.ParkingName], | |||
| developer = line[(int)QRCSVDataDaito.ColName.Developer], | |||
| reception_datetime = DateTime.Parse(line[(int)QRCSVDataDaito.ColName.ReceptionDatetime]), | |||
| company = line[(int)QRCSVDataDaito.ColName.Company], | |||
| amount = int.Parse(line[(int)QRCSVDataDaito.ColName.Amount]), | |||
| adjust_no = line[(int)QRCSVDataDaito.ColName.AdjustNo], | |||
| error_code = line[(int)QRCSVDataDaito.ColName.ErrorCode], | |||
| }); | |||
| } | |||
| return result_list; | |||
| } | |||
| private List<String[]> GetFileContents(String filename) { | |||
| var list = new List<String[]>(); | |||
| var dir = new DirectoryInfo(DriverFactory.GetDownloadDir()); | |||
| var config = new CSVConfig() { | |||
| header = true, | |||
| }; | |||
| config.remove_char.Add("\""); | |||
| var sjis_enc = Encoding.GetEncoding("Shift-JIS"); | |||
| foreach (var file in dir.GetFiles()) { | |||
| if (file.Name.Contains(filename)) { | |||
| var result = ReadCsv(file.FullName, config, sjis_enc); | |||
| list.AddRange(result); | |||
| } | |||
| } | |||
| return list; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,55 @@ | |||
| using System; | |||
| using System.Reflection; | |||
| using System.IO; | |||
| using OpenQA.Selenium; | |||
| using OpenQA.Selenium.Chrome; | |||
| using OpenQA.Selenium.Support.UI; | |||
| using SeleniumExtras.WaitHelpers; | |||
| namespace CSVDownloader.Web { | |||
| class DriverFactory { | |||
| public static ChromeDriver GetDriver() | |||
| { | |||
| CreateDir(); | |||
| var options = new ChromeOptions(); | |||
| // options.AddArgument("--headless"); | |||
| String download_dir = GetTmpDownloadDir(); | |||
| options.AddUserProfilePreference("download.default_directory", download_dir); | |||
| ChromeDriver driver = new ChromeDriver(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), options); | |||
| WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10)); | |||
| return driver; | |||
| } | |||
| public static String GetTmpDownloadDir() | |||
| { | |||
| return Path.GetFullPath("tmp_download"); | |||
| } | |||
| public static String GetDownloadDir() | |||
| { | |||
| return Path.GetFullPath("download"); | |||
| } | |||
| private static void CreateDir() | |||
| { | |||
| String tmpdownload_dir = GetTmpDownloadDir(); | |||
| String download_dir = GetDownloadDir(); | |||
| if (!Directory.Exists(tmpdownload_dir)) | |||
| { | |||
| Directory.CreateDirectory(tmpdownload_dir); | |||
| } | |||
| if (!Directory.Exists(download_dir)) | |||
| { | |||
| Directory.CreateDirectory(download_dir); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,190 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.IO; | |||
| using System.Text; | |||
| using OpenQA.Selenium; | |||
| using OpenQA.Selenium.Chrome; | |||
| using CSVDownloader.Code; | |||
| using CSVDownloader.Store.CreditCSVData; | |||
| using ExpectedConditions = OpenQA.Selenium.Support.UI.ExpectedConditions; | |||
| namespace CSVDownloader.Web { | |||
| class HelloTechnoController : WebController { | |||
| private readonly String url_ = "https://skysun.crepass.net/40599/hello-techno/index.php"; | |||
| private List<CreditCSVData> csv_data_list_ = new List<CreditCSVData>(); | |||
| private enum XpathKey { | |||
| INPUT_LOGIN_USERNAME, | |||
| INPUT_LOGIN_PASSWORD, | |||
| BUTTON_CREDIT_KESSAI, | |||
| RADIO_TARGET_SPAN, | |||
| SELECT_TARGET_FROM_YYYYMM, | |||
| SELECT_TARGET_FROM_DD, | |||
| SELECT_TARGET_TO_YYYYMM, | |||
| SELECT_TARGET_TO_DD, | |||
| BUTTON_CONFIRM_CSV, | |||
| TABLE_CSV, | |||
| PAGER, | |||
| BUTTON_LOGOUT, | |||
| }; | |||
| private IDictionary<XpathKey, string> xpath_map_ = new Dictionary<XpathKey, string>() | |||
| { | |||
| {XpathKey.INPUT_LOGIN_USERNAME,@"//*[@id='accountId']"}, | |||
| {XpathKey.INPUT_LOGIN_PASSWORD,@"//*[@id='myPassword']"}, | |||
| {XpathKey.BUTTON_CREDIT_KESSAI,@"//*[@id='history']/a"}, | |||
| {XpathKey.RADIO_TARGET_SPAN,@"//select[@name='yyyymm_s']/preceding-sibling::input[@name='term_type']"}, | |||
| {XpathKey.SELECT_TARGET_FROM_YYYYMM,$"//select[@name='yyyymm_s']" }, | |||
| {XpathKey.SELECT_TARGET_FROM_DD,$"//select[@name='dd_s']" }, | |||
| {XpathKey.SELECT_TARGET_TO_YYYYMM,$"//select[@name='yyyymm_e']" }, | |||
| {XpathKey.SELECT_TARGET_TO_DD,$"//select[@name='dd_e']" }, | |||
| {XpathKey.BUTTON_CONFIRM_CSV,$"//*[@id='mag_top3']/table/tbody/tr/td[1]/input" }, | |||
| {XpathKey.TABLE_CSV,$"/html/body/div[1]/div[5]/table[2]" }, | |||
| {XpathKey.PAGER,$"/html/body/div[1]/div[7]/p[1]" }, | |||
| {XpathKey.BUTTON_LOGOUT,$"//*[@id='log_out']/a/img" }, | |||
| }; | |||
| public HelloTechnoController(ChromeDriver driver) : base(driver) { | |||
| agent_ = CreditAgent.HT; | |||
| } | |||
| public override ResultCode Login(LoginInfo info) { | |||
| bool enter = true; | |||
| try { | |||
| driver_.Navigate().GoToUrl(url_); | |||
| Send(xpath_map_[XpathKey.INPUT_LOGIN_USERNAME], info.user_name); | |||
| Send(xpath_map_[XpathKey.INPUT_LOGIN_PASSWORD], info.password, enter); | |||
| // ログイン後の明細データダウンロードが表示されることを確認する。 | |||
| wait_.Until(ExpectedConditions.ElementToBeClickable(By.XPath(xpath_map_[XpathKey.BUTTON_CREDIT_KESSAI]))); | |||
| } catch (Exception e) { | |||
| logger_.Error(e.Message); | |||
| return ResultCode.NG; | |||
| } | |||
| return ResultCode.OK; | |||
| } | |||
| public override ResultCode Download(DateTime from, DateTime to) { | |||
| csv_data_list_.Clear(); | |||
| // クレジットカード承認結果一覧画面に移行 | |||
| Click(xpath_map_[XpathKey.BUTTON_CREDIT_KESSAI]); | |||
| // 承認処理日のFrom-Toを入力 | |||
| Select(xpath_map_[XpathKey.SELECT_TARGET_FROM_YYYYMM], from.ToString("yyyyMM")); | |||
| Select(xpath_map_[XpathKey.SELECT_TARGET_FROM_DD], from.ToString("dd")); | |||
| Select(xpath_map_[XpathKey.SELECT_TARGET_TO_YYYYMM], to.ToString("yyyyMM")); | |||
| Select(xpath_map_[XpathKey.SELECT_TARGET_TO_DD], to.ToString("dd")); | |||
| // 各種ラジオチェックを入力 | |||
| Click(xpath_map_[XpathKey.RADIO_TARGET_SPAN]); | |||
| // 条件確定 | |||
| Click(xpath_map_[XpathKey.BUTTON_CONFIRM_CSV]); | |||
| GetAllData(); | |||
| return ResultCode.OK; | |||
| } | |||
| public override ResultCode Logout() { | |||
| try { | |||
| Click(xpath_map_[XpathKey.BUTTON_LOGOUT]); | |||
| } catch (Exception e) { | |||
| logger_.Error(e.Message); | |||
| return ResultCode.NG; | |||
| } | |||
| return ResultCode.OK; | |||
| } | |||
| public override List<CreditCSVData> GetCreditCSVDataList() { | |||
| return csv_data_list_; | |||
| } | |||
| private void GetAllData() { | |||
| int page = 1; | |||
| while (true) { | |||
| // TABLEからデータを取得する。 | |||
| var table = wait_.Until(ExpectedConditions.ElementIsVisible(By.XPath(xpath_map_[XpathKey.TABLE_CSV]))); | |||
| var tag_tr = table.FindElements(By.TagName("tr")); | |||
| // ヘッダー行はスキップしたうえで進める。 | |||
| for (var i = 1; i < tag_tr.Count; i++) { | |||
| var tag_td = tag_tr[i].FindElements(By.TagName("td")); | |||
| if (tag_td.Count != 999) { | |||
| //throw new Exception("想定外の行構成"); | |||
| } | |||
| var data = new CSVDataHelloTechno() { | |||
| spot_id = GetSpotID(tag_td[(int)CSVDataHelloTechno.ColName.ParkingCode].Text), | |||
| register_datetime = DateTime.Parse(tag_td[(int)CSVDataHelloTechno.ColName.RegisterDatetime].Text), | |||
| user_code = tag_td[(int)CSVDataHelloTechno.ColName.UserCode].Text, | |||
| parking_code = tag_td[(int)CSVDataHelloTechno.ColName.ParkingCode].Text, | |||
| device_no = tag_td[(int)CSVDataHelloTechno.ColName.DeviceNo].Text, | |||
| adjust_no = tag_td[(int)CSVDataHelloTechno.ColName.AdjustNo].Text, | |||
| trade = tag_td[(int)CSVDataHelloTechno.ColName.Trade].Text, | |||
| amount = int.Parse(tag_td[(int)CSVDataHelloTechno.ColName.Amount].Text.Replace(",", "")), | |||
| card_company_name = tag_td[(int)CSVDataHelloTechno.ColName.CardCompanyName].Text, | |||
| approval_no = tag_td[(int)CSVDataHelloTechno.ColName.ApprovalNo].Text, | |||
| response_no = tag_td[(int)CSVDataHelloTechno.ColName.ResponseNo].Text, | |||
| error = tag_td[(int)CSVDataHelloTechno.ColName.Error].Text, | |||
| }; | |||
| var cancel_date = tag_td[(int)CSVDataHelloTechno.ColName.CancelDate].Text; | |||
| if (cancel_date.Length != 0) { | |||
| data.cancel_date = DateTime.Parse(cancel_date); | |||
| } | |||
| csv_data_list_.Add(data); | |||
| } | |||
| // リストに挿入する。 | |||
| // ページ操作 | |||
| // 戻ると進むのボタンの組み合わせで操作を行う。 | |||
| var pager = driver_.FindElementByXPath(xpath_map_[XpathKey.PAGER]); | |||
| var tag_a = pager.FindElements(By.TagName("a")); | |||
| if (page == 1 && tag_a.Count == 1) { | |||
| // 最初のページで次のボタン | |||
| Click(tag_a[0]); | |||
| page++; | |||
| } else if (page != 1 && tag_a.Count == 2) { | |||
| // 戻ると進むのボタンを検出 | |||
| Click(tag_a[1]); | |||
| page++; | |||
| } else if (page != 1 && tag_a.Count == 1) { | |||
| // 最終ページを検出 | |||
| break; | |||
| } else if (page == 1 && tag_a.Count == 0) { | |||
| // 1ページのみ | |||
| break; | |||
| } else { | |||
| // 想定外のパターン | |||
| throw new Exception("ページング不正検出"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,165 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.IO; | |||
| using System.Text; | |||
| using OpenQA.Selenium; | |||
| using OpenQA.Selenium.Chrome; | |||
| using CSVDownloader.Code; | |||
| using CSVDownloader.Store.CreditCSVData; | |||
| using ExpectedConditions = OpenQA.Selenium.Support.UI.ExpectedConditions; | |||
| namespace CSVDownloader.Web { | |||
| class ItecController : WebController { | |||
| private readonly String url_ = "https://www.itc-offerinfo.net/webap/Login"; | |||
| private enum XpathKey { | |||
| INPUT_LOGIN_USERNAME, | |||
| INPUT_LOGIN_PASSWORD, | |||
| BUTTON_LOGIN, | |||
| BUTTON_CREDIT_KESSAI, | |||
| RADIO_TARGET_SPAN, | |||
| SELECT_TARGET_FROM_YYYYMM, | |||
| SELECT_TARGET_FROM_DD, | |||
| SELECT_TARGET_TO_YYYYMM, | |||
| SELECT_TARGET_TO_DD, | |||
| BUTTON_CONFIRM_CSV, | |||
| BUTTON_DOWNLOAD_CSV, | |||
| BUTTON_LOGOUT, | |||
| }; | |||
| private IDictionary<XpathKey, string> xpath_map_ = new Dictionary<XpathKey, string>() | |||
| { | |||
| {XpathKey.INPUT_LOGIN_USERNAME,@"//*[@id='panel']/div[2]/input" }, | |||
| {XpathKey.INPUT_LOGIN_PASSWORD,@"//*[@id='panel']/div[4]/input"}, | |||
| {XpathKey.BUTTON_LOGIN,@"//*[@id='area_m']/form/div[2]/input[1]"}, | |||
| {XpathKey.BUTTON_CREDIT_KESSAI,@"//*[@id='menuRa']" }, | |||
| {XpathKey.RADIO_TARGET_SPAN,@"//*[@id='kikantype1']" }, | |||
| {XpathKey.SELECT_TARGET_FROM_YYYYMM,$"//*[@id='kikan_from_month']" }, | |||
| {XpathKey.SELECT_TARGET_FROM_DD,$"//*[@id='kikan_from_day']" }, | |||
| {XpathKey.SELECT_TARGET_TO_YYYYMM,$"//*[@id='kikan_to_month']" }, | |||
| {XpathKey.SELECT_TARGET_TO_DD,$"//*[@id='kikan_to_day']" }, | |||
| {XpathKey.BUTTON_CONFIRM_CSV,$"//*[@id='btn-exec']" }, | |||
| {XpathKey.BUTTON_DOWNLOAD_CSV,$"//*[@id='dl-detail']" }, | |||
| {XpathKey.BUTTON_LOGOUT,$"//*[@id='btn_logout']" }, | |||
| }; | |||
| public ItecController(ChromeDriver driver) : base(driver) { | |||
| agent_ = CreditAgent.ITEC; | |||
| } | |||
| public override void SetParkingDic(IDictionary<String, String> dic) { | |||
| dic_ = new Dictionary<String, String>(); | |||
| // IPコードと駐車場名を分離。プログラムではIPコードのみ利用する。 | |||
| foreach (var ele in dic) { | |||
| String parking_name = ele.Key.Split(" ")[0].Trim(); | |||
| dic_.Add(parking_name, ele.Value); | |||
| } | |||
| } | |||
| public override ResultCode Login(LoginInfo info) { | |||
| try { | |||
| driver_.Navigate().GoToUrl(url_); | |||
| Send(xpath_map_[XpathKey.INPUT_LOGIN_USERNAME], info.user_name); | |||
| Send(xpath_map_[XpathKey.INPUT_LOGIN_PASSWORD], info.password); | |||
| Click(xpath_map_[XpathKey.BUTTON_LOGIN]); | |||
| // ログイン後の明細データダウンロードが表示されることを確認する。 | |||
| wait_.Until(ExpectedConditions.ElementToBeClickable(By.XPath(xpath_map_[XpathKey.BUTTON_CREDIT_KESSAI]))); | |||
| } catch (Exception e) { | |||
| logger_.Error(e.Message); | |||
| return ResultCode.NG; | |||
| } | |||
| return ResultCode.OK; | |||
| } | |||
| public override ResultCode Download(DateTime from, DateTime to) { | |||
| // クレジットカード承認結果一覧画面に移行 | |||
| Click(xpath_map_[XpathKey.BUTTON_CREDIT_KESSAI]); | |||
| // 承認処理日のFrom-Toを入力 | |||
| Select(xpath_map_[XpathKey.SELECT_TARGET_FROM_YYYYMM], from.ToString("yyyyMM")); | |||
| Select(xpath_map_[XpathKey.SELECT_TARGET_FROM_DD], from.ToString("dd")); | |||
| Select(xpath_map_[XpathKey.SELECT_TARGET_TO_YYYYMM], to.ToString("yyyyMM")); | |||
| Select(xpath_map_[XpathKey.SELECT_TARGET_TO_DD], to.ToString("dd")); | |||
| // 各種ラジオチェックを入力 | |||
| Click(xpath_map_[XpathKey.RADIO_TARGET_SPAN]); | |||
| // 条件確定 | |||
| Click(xpath_map_[XpathKey.BUTTON_CONFIRM_CSV]); | |||
| // ダウンロード開始 | |||
| Click(xpath_map_[XpathKey.BUTTON_DOWNLOAD_CSV]); | |||
| String filename = $"itec.csv"; | |||
| WaitForDownload(filename); | |||
| return ResultCode.OK; | |||
| } | |||
| public override ResultCode Logout() { | |||
| Click(xpath_map_[XpathKey.BUTTON_LOGOUT]); | |||
| return ResultCode.OK; | |||
| } | |||
| public override List<CreditCSVData> GetCreditCSVDataList() { | |||
| var result_list = new List<CreditCSVData>(); | |||
| // csvファイルパスの取得 | |||
| var config = new CSVConfig() { | |||
| header = true, | |||
| }; | |||
| var dir = new DirectoryInfo(DriverFactory.GetDownloadDir()); | |||
| var sjis_enc = Encoding.GetEncoding("Shift-JIS"); | |||
| var list = new List<String[]>(); | |||
| foreach (var file in dir.GetFiles()) { | |||
| var result = ReadCsv(file.FullName, config, sjis_enc); | |||
| list.AddRange(result); | |||
| } | |||
| foreach (var line in list) { | |||
| // 空の行はスキップする | |||
| if (line.Length == 0) { | |||
| continue; | |||
| } | |||
| // 不要な行はスキップする | |||
| if (line.Length != 10) { | |||
| continue; | |||
| } | |||
| result_list.Add(new CSVDataItec() { | |||
| spot_id = GetSpotID(line[(int)CSVDataItec.ColName.ParkingName]), | |||
| code = line[(int)CSVDataItec.ColName.Code], | |||
| device_type = line[(int)CSVDataItec.ColName.DeviceType], | |||
| use_datetime = DateTime.Parse(line[(int)CSVDataItec.ColName.UseDatetime]), | |||
| trade = line[(int)CSVDataItec.ColName.Trade], | |||
| card_company_name = line[(int)CSVDataItec.ColName.CardCompanyName], | |||
| amount = int.Parse(line[(int)CSVDataItec.ColName.Amount]), | |||
| tax_send_fee = int.Parse(line[(int)CSVDataItec.ColName.TaxSendFee]), | |||
| total_amount = int.Parse(line[(int)CSVDataItec.ColName.TotalAmount]), | |||
| error_code = line[(int)CSVDataItec.ColName.ErrorCode], | |||
| }); | |||
| } | |||
| return result_list; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,8 @@ | |||
| using System; | |||
| namespace CSVDownloader.Web { | |||
| class LoginInfo { | |||
| public String user_name = ""; | |||
| public String password = ""; | |||
| } | |||
| } | |||
| @@ -0,0 +1,288 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using System.Threading; | |||
| using System.IO; | |||
| using System.IO.Compression; | |||
| using OpenQA.Selenium; | |||
| using OpenQA.Selenium.Chrome; | |||
| using OpenQA.Selenium.Support.UI; | |||
| using CSVDownloader.Code; | |||
| using CSVDownloader.Store.CreditCSVData; | |||
| using CSVDownloader.Store.QRCSVData; | |||
| using ExpectedConditions = OpenQA.Selenium.Support.UI.ExpectedConditions; | |||
| namespace CSVDownloader.Web { | |||
| abstract class WebController { | |||
| protected log4net.ILog logger_ = log4net.LogManager.GetLogger(""); | |||
| protected ChromeDriver driver_; | |||
| protected WebDriverWait wait_; | |||
| private const int interval_milisec_ = 1000; | |||
| protected CreditAgent agent_; | |||
| /// <summary> | |||
| /// 駐車場名とSpotIDのマッピング | |||
| /// </summary> | |||
| protected IDictionary<String, String> dic_; | |||
| public WebController(ChromeDriver driver) { | |||
| driver_ = driver; | |||
| wait_ = new WebDriverWait(driver_, TimeSpan.FromSeconds(10)); | |||
| } | |||
| public virtual void SetParkingDic(IDictionary<String, String> dic) { | |||
| dic_ = dic; | |||
| } | |||
| public CreditAgent GetCreditAgent() { | |||
| return agent_; | |||
| } | |||
| abstract public ResultCode Login(LoginInfo login_info); | |||
| abstract public ResultCode Download(DateTime from, DateTime to); | |||
| abstract public ResultCode Logout(); | |||
| public ResultCode Archive(String archive_filename) { | |||
| var dir_name = "archive"; | |||
| if (!Directory.Exists(dir_name)) { | |||
| Directory.CreateDirectory(dir_name); | |||
| } | |||
| String target = @$"{dir_name}\{archive_filename}"; | |||
| if (System.IO.File.Exists(target)) { | |||
| logger_.Info($"上書き:{target}"); | |||
| System.IO.File.Delete(target); | |||
| } | |||
| ZipFile.CreateFromDirectory("download", target); | |||
| return ResultCode.OK; | |||
| } | |||
| public virtual List<CreditCSVData> GetCreditCSVDataList() { | |||
| return new List<CreditCSVData>(); | |||
| } | |||
| public virtual List<QRCSVData> GetQRCSVDataList() { | |||
| return new List<QRCSVData>(); | |||
| } | |||
| protected void Click(String xpath, bool wait = true) { | |||
| if (wait) { | |||
| var ele = wait_.Until(ExpectedConditions.ElementToBeClickable(By.XPath(xpath))); | |||
| ele.Click(); | |||
| } else { | |||
| var ele = driver_.FindElementByXPath(xpath); | |||
| ele.Click(); | |||
| } | |||
| Console.WriteLine($"Click {xpath}"); | |||
| Wait(interval_milisec_); | |||
| } | |||
| protected void Click(IWebElement ele) { | |||
| ele.Click(); | |||
| Wait(interval_milisec_); | |||
| } | |||
| protected void Send(String xpath, String value, bool enter = false) { | |||
| var ele = wait_.Until(ExpectedConditions.ElementIsVisible(By.XPath(xpath))); | |||
| ele.SendKeys(value); | |||
| if (enter) { | |||
| ele.SendKeys(OpenQA.Selenium.Keys.Enter); | |||
| } | |||
| Wait(interval_milisec_); | |||
| } | |||
| protected void Select(String xpath, String value) { | |||
| try { | |||
| var ele = wait_.Until(ExpectedConditions.ElementIsVisible(By.XPath(xpath))); | |||
| var select = new SelectElement(ele); | |||
| var options = select.Options; | |||
| select.SelectByValue(value); | |||
| Wait(interval_milisec_); | |||
| } catch (Exception e) { | |||
| Console.WriteLine($" Select failed xpath:{xpath} value:{value}"); | |||
| throw e; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// ダウンロードを開始したファイルを完了まで監視する | |||
| /// 完了後はダウンロード完了ディレクトリに移動する | |||
| /// </summary> | |||
| /// <returns></returns> | |||
| protected void WaitForDownload(String filename) { | |||
| String tmpdownload_dir = DriverFactory.GetTmpDownloadDir(); | |||
| String download_dir = DriverFactory.GetDownloadDir(); | |||
| int limit_start = 0; | |||
| long last_size = 0; | |||
| String complete_filename = ""; | |||
| while (true) { | |||
| var dir = new DirectoryInfo(tmpdownload_dir); | |||
| var files = dir.GetFiles(); | |||
| if (files.Length != 0) { | |||
| var file = files[0]; | |||
| if (file.Length == last_size) { | |||
| // ダウンロード完了 | |||
| logger_.Info($"ダウンロード完了:{file.Name} size:{file.Length}"); | |||
| complete_filename = file.Name; | |||
| break; | |||
| } else { | |||
| // ダウンロード継続 | |||
| last_size = file.Length; | |||
| logger_.Info($"ダウンロード監視中:{file.Name} size:{file.Length}"); | |||
| } | |||
| } else { | |||
| // ファイルが存在しない場合は、一定回数リトライし | |||
| // 規定回数存在しない場合は失敗とする。 | |||
| if (10 < limit_start) { | |||
| throw new Exception("ダウンロード開始失敗"); | |||
| } | |||
| logger_.Info($"ダウンロード開始待ち"); | |||
| limit_start++; | |||
| } | |||
| Wait(500); | |||
| } | |||
| // ファイルの移動 | |||
| String source_filename = $@"{tmpdownload_dir}\{complete_filename}"; | |||
| String dest_filename = $@"{download_dir}\{filename}"; | |||
| System.IO.File.Move(source_filename, dest_filename, true); | |||
| } | |||
| protected void Wait(int milisec) { | |||
| Thread.Sleep(milisec); | |||
| } | |||
| protected String GetSpotID(String parking_name) { | |||
| if (!dic_.ContainsKey(parking_name)) { | |||
| throw new Exception($"該当するマスタなし 駐車場名:\"{parking_name}\""); | |||
| } | |||
| return dic_[parking_name]; | |||
| } | |||
| protected class CSVConfig { | |||
| public bool header = false; | |||
| public List<String> remove_char = new List<string>(); | |||
| } | |||
| protected List<String[]> ReadCsv(String csvpath, CSVConfig config, Encoding enc) { | |||
| var list = new List<String[]>(); | |||
| var fs = new FileStream(csvpath, FileMode.Open); | |||
| var data = new byte[fs.Length]; | |||
| fs.Read(data, 0, data.Length); | |||
| fs.Close(); | |||
| var content = enc.GetString(data); | |||
| var lines = content.Split("\n"); | |||
| bool header_skip = config.header; | |||
| foreach (var line in lines) { | |||
| var tmpline = line; | |||
| line.Trim(); | |||
| // 空の行はスキップ | |||
| if (line.Length == 0) { | |||
| continue; | |||
| } | |||
| // ヘッダー行のスキップ制御 | |||
| if (header_skip) { | |||
| header_skip = false; | |||
| continue; | |||
| } | |||
| // 囲み文字の削除 | |||
| if (config.remove_char != null) { | |||
| foreach (var remove_char in config.remove_char) { | |||
| tmpline = tmpline.Replace(remove_char, ""); | |||
| } | |||
| } | |||
| var values = tmpline.Split(","); | |||
| var elements = new String[values.Length]; | |||
| int index = 0; | |||
| foreach (var ele in values) { | |||
| elements[index++] = ele.Trim(); | |||
| } | |||
| list.Add(elements); | |||
| } | |||
| return list; | |||
| } | |||
| /// <summary> | |||
| /// デフォルトのフレームにもどる | |||
| /// </summary> | |||
| protected void SwitchToFrame() { | |||
| driver_.SwitchTo().DefaultContent(); | |||
| } | |||
| /// <summary> | |||
| /// フレームを切り替える。 | |||
| /// </summary> | |||
| /// <param name="xpath"></param> | |||
| protected void SwitchToFrame(String xpath) { | |||
| var frame = wait_.Until(ExpectedConditions.ElementExists(By.XPath(xpath))); | |||
| driver_.SwitchTo().Frame(frame); | |||
| } | |||
| /// <summary> | |||
| /// 空の可能性があるソースをDateTimeへ変換する際、Null許容型として変換する。 | |||
| /// </summary> | |||
| /// <param name="source"></param> | |||
| /// <returns></returns> | |||
| protected DateTime? GetDateTime(String source) { | |||
| if (source != null && 0 < source.Length) { | |||
| return DateTime.Parse(source); | |||
| } else { | |||
| return null; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,214 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.IO; | |||
| using System.Text; | |||
| using OpenQA.Selenium; | |||
| using OpenQA.Selenium.Chrome; | |||
| using CSVDownloader.Code; | |||
| using CSVDownloader.Store.CreditCSVData; | |||
| using ExpectedConditions = OpenQA.Selenium.Support.UI.ExpectedConditions; | |||
| namespace CSVDownloader.Web { | |||
| class ZeusController : WebController { | |||
| private readonly String url_ = "https://linkpt.cardservice.co.jp/merchant/"; | |||
| private readonly int max_download_num_ = 20; | |||
| private enum XpathKey { | |||
| INPUT_LOGIN_USERNAME, | |||
| INPUT_LOGIN_PASSWORD, | |||
| BUTTON_CREDIT_KESSAI, | |||
| CHECK_PARKING, | |||
| RADIO_TARGET_SPAN, | |||
| SELECT_TARGET_FROM_YYYY, | |||
| SELECT_TARGET_FROM_MM, | |||
| SELECT_TARGET_FROM_DD, | |||
| SELECT_TARGET_TO_YYYY, | |||
| SELECT_TARGET_TO_MM, | |||
| SELECT_TARGET_TO_DD, | |||
| BUTTON_DOWNLOAD_CSV, | |||
| BUTTON_LOGOUT, | |||
| SUBJECT, | |||
| FRAME_MENU, | |||
| FRAME_CONTENTS, | |||
| }; | |||
| private static String search_form_xpath = "//*[@id='deny_double_click']"; | |||
| private IDictionary<XpathKey, string> xpath_map_ = new Dictionary<XpathKey, string>() | |||
| { | |||
| {XpathKey.INPUT_LOGIN_USERNAME,"//form[@name='loginForm']//input[@name='ID']" }, | |||
| {XpathKey.INPUT_LOGIN_PASSWORD,"//*[@id='password']"}, | |||
| {XpathKey.BUTTON_CREDIT_KESSAI,"//a[contains(@href,'batch_download_face')]" }, | |||
| {XpathKey.CHECK_PARKING,$"{search_form_xpath}//input[@name='bang_list']" }, | |||
| {XpathKey.RADIO_TARGET_SPAN,$"{search_form_xpath}//input[@name='date' and @value='period']" }, | |||
| {XpathKey.SELECT_TARGET_FROM_YYYY,$"{search_form_xpath}//select[@name='spfy']" }, | |||
| {XpathKey.SELECT_TARGET_FROM_MM,$"{search_form_xpath}//select[@name='spfm']" }, | |||
| {XpathKey.SELECT_TARGET_FROM_DD,$"{search_form_xpath}//select[@name='spfd']" }, | |||
| {XpathKey.SELECT_TARGET_TO_YYYY,$"{search_form_xpath}//select[@name='epfy']" }, | |||
| {XpathKey.SELECT_TARGET_TO_MM,$"{search_form_xpath}//select[@name='epfm']" }, | |||
| {XpathKey.SELECT_TARGET_TO_DD,$"{search_form_xpath}//select[@name='epfd']" }, | |||
| {XpathKey.BUTTON_DOWNLOAD_CSV,$"{search_form_xpath}//input[@type='submit']" }, | |||
| {XpathKey.BUTTON_LOGOUT,"//a[contains(@href,'logout')]" }, | |||
| {XpathKey.FRAME_MENU,"//frame[@name='MENULIST']" }, | |||
| {XpathKey.FRAME_CONTENTS,"//frame[@name='CONTENTS']" }, | |||
| }; | |||
| public ZeusController(ChromeDriver driver) : base(driver) { | |||
| agent_ = CreditAgent.Zeus; | |||
| } | |||
| public override void SetParkingDic(IDictionary<String, String> dic) { | |||
| dic_ = new Dictionary<String, String>(); | |||
| // IPコードと駐車場名を分離。プログラムではIPコードのみ利用する。 | |||
| foreach (var ele in dic) { | |||
| String parking_name = ele.Key.Split(" ")[0].Trim(); | |||
| dic_.Add(parking_name, ele.Value); | |||
| } | |||
| } | |||
| public override ResultCode Login(LoginInfo info) { | |||
| bool enter = true; | |||
| try { | |||
| driver_.Navigate().GoToUrl(url_); | |||
| Send(xpath_map_[XpathKey.INPUT_LOGIN_USERNAME], info.user_name); | |||
| Send(xpath_map_[XpathKey.INPUT_LOGIN_PASSWORD], info.password, enter); | |||
| // ログイン後の「端末決済データダウンロード」が表示されることを確認する。 | |||
| SwitchToFrame(xpath_map_[XpathKey.FRAME_MENU]); | |||
| wait_.Until(ExpectedConditions.ElementToBeClickable(By.XPath(xpath_map_[XpathKey.BUTTON_CREDIT_KESSAI]))); | |||
| SwitchToFrame(); | |||
| } catch (Exception e) { | |||
| logger_.Error(e.Message); | |||
| return ResultCode.NG; | |||
| } | |||
| return ResultCode.OK; | |||
| } | |||
| public override ResultCode Download(DateTime from, DateTime to) { | |||
| // クレジットカード承認結果一覧画面に移行 | |||
| SwitchToFrame(xpath_map_[XpathKey.FRAME_MENU]); | |||
| Click(xpath_map_[XpathKey.BUTTON_CREDIT_KESSAI]); | |||
| SwitchToFrame(); | |||
| //期間のFrom-Toを入力 | |||
| SwitchToFrame(xpath_map_[XpathKey.FRAME_CONTENTS]); | |||
| Click(xpath_map_[XpathKey.RADIO_TARGET_SPAN]); | |||
| Select(xpath_map_[XpathKey.SELECT_TARGET_FROM_YYYY], from.ToString("yyyy")); | |||
| Select(xpath_map_[XpathKey.SELECT_TARGET_FROM_MM], from.ToString("MMM")); | |||
| Select(xpath_map_[XpathKey.SELECT_TARGET_FROM_DD], from.ToString("dd")); | |||
| Select(xpath_map_[XpathKey.SELECT_TARGET_TO_YYYY], to.ToString("yyyy")); | |||
| Select(xpath_map_[XpathKey.SELECT_TARGET_TO_MM], to.ToString("MMM")); | |||
| Select(xpath_map_[XpathKey.SELECT_TARGET_TO_DD], to.ToString("dd")); | |||
| // 駐車場一覧を取得 | |||
| var parking_list = driver_.FindElementsByXPath(xpath_map_[XpathKey.CHECK_PARKING]); | |||
| var tmp_list = new List<IWebElement>(); | |||
| int count = 0; | |||
| // 一定件数ごとにダウンロード | |||
| foreach (var parking in parking_list) { | |||
| tmp_list.Add(parking); | |||
| if (!parking.Selected) { | |||
| parking.Click(); | |||
| } | |||
| if (tmp_list.Count == max_download_num_) { | |||
| // ダウンロード処理 | |||
| String filename = $"zeus_{count}.csv"; | |||
| Click(xpath_map_[XpathKey.BUTTON_DOWNLOAD_CSV]); | |||
| WaitForDownload(filename); | |||
| // チェックを戻す | |||
| foreach (var check in tmp_list) { | |||
| if (check.Selected) { | |||
| check.Click(); | |||
| } | |||
| } | |||
| // クリアー処理 | |||
| count++; | |||
| tmp_list.Clear(); | |||
| } | |||
| } | |||
| if (tmp_list.Count != 0) { | |||
| String filename = $"zeus_{count}.csv"; | |||
| Click(xpath_map_[XpathKey.BUTTON_DOWNLOAD_CSV]); | |||
| WaitForDownload(filename); | |||
| tmp_list.Clear(); | |||
| } | |||
| SwitchToFrame(); | |||
| return ResultCode.OK; | |||
| } | |||
| public override ResultCode Logout() { | |||
| SwitchToFrame(xpath_map_[XpathKey.FRAME_MENU]); | |||
| Click(xpath_map_[XpathKey.BUTTON_LOGOUT]); | |||
| return ResultCode.OK; | |||
| } | |||
| public override List<CreditCSVData> GetCreditCSVDataList() { | |||
| var result_list = new List<CreditCSVData>(); | |||
| // csvファイルパスの取得 | |||
| var config = new CSVConfig() { | |||
| header = true, | |||
| }; | |||
| var dir = new DirectoryInfo(DriverFactory.GetDownloadDir()); | |||
| var sjis_enc = Encoding.GetEncoding("Shift-JIS"); | |||
| var list = new List<String[]>(); | |||
| foreach (var file in dir.GetFiles()) { | |||
| var result = ReadCsv(file.FullName, config, sjis_enc); | |||
| list.AddRange(result); | |||
| } | |||
| foreach (var line in list) { | |||
| // 決済金額は「-」でセットされている場合があるので | |||
| // その際は0とする。 | |||
| int amount = 0; | |||
| int.TryParse(line[(int)Store.CreditCSVData.CreditCSVDataZeus.ColName.Amount], out amount); | |||
| result_list.Add(new Store.CreditCSVData.CreditCSVDataZeus() { | |||
| spot_id = GetSpotID(line[(int)Store.CreditCSVData.CreditCSVDataZeus.ColName.IP]), | |||
| use_datetime = DateTime.Parse(line[(int)Store.CreditCSVData.CreditCSVDataZeus.ColName.UseDatetime]), | |||
| ip = line[(int)Store.CreditCSVData.CreditCSVDataZeus.ColName.IP], | |||
| device_no = line[(int)Store.CreditCSVData.CreditCSVDataZeus.ColName.DeviceNo], | |||
| receipt_no = line[(int)Store.CreditCSVData.CreditCSVDataZeus.ColName.ReceiptNo], | |||
| certificate_no = line[(int)Store.CreditCSVData.CreditCSVDataZeus.ColName.CertificateNo], | |||
| status = line[(int)Store.CreditCSVData.CreditCSVDataZeus.ColName.Status], | |||
| error_message = line[(int)Store.CreditCSVData.CreditCSVDataZeus.ColName.ErrorMessage], | |||
| amount = amount, | |||
| card_no = line[(int)Store.CreditCSVData.CreditCSVDataZeus.ColName.CardNo], | |||
| expiration_date = line[(int)Store.CreditCSVData.CreditCSVDataZeus.ColName.ExpirationDate], | |||
| brand = line[(int)Store.CreditCSVData.CreditCSVDataZeus.ColName.Brand], | |||
| payment_type = line[(int)Store.CreditCSVData.CreditCSVDataZeus.ColName.PaymentType], | |||
| jis_info = line[(int)Store.CreditCSVData.CreditCSVDataZeus.ColName.JISInfo], | |||
| test = line[(int)Store.CreditCSVData.CreditCSVDataZeus.ColName.Test], | |||
| order_no = line[(int)Store.CreditCSVData.CreditCSVDataZeus.ColName.OrderNo], | |||
| }); | |||
| } | |||
| return result_list; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,45 @@ | |||
| <?xml version="1.0" encoding="utf-8" ?> | |||
| <configuration> | |||
| <!-- app.configに記述する場合に必要 --> | |||
| <configSections> | |||
| <section | |||
| name="log4net" type= | |||
| "log4net.Config.Log4NetConfigurationSectionHandler,log4net" /> | |||
| </configSections> | |||
| <log4net> | |||
| <!-- ログ出力先の定義 --> | |||
| <appender name="LogFileAppender" | |||
| type="log4net.Appender.RollingFileAppender" > | |||
| <!-- 作成するログファイル --> | |||
| <param name="File" value="log/log.txt" /> | |||
| <!-- 最大バックアップファイル数 --> | |||
| <maxSizeRollBackups value="30" /> | |||
| <!-- ファイルサイズの上限 --> | |||
| <maximumFileSize value="1MB" /> | |||
| <!-- 追加 --> | |||
| <param name="AppendToFile" value="true" /> | |||
| <!-- ログの書式 --> | |||
| <layout type="log4net.Layout.PatternLayout"> | |||
| <param name="ConversionPattern" | |||
| value="[%d] %m%n" /> | |||
| </layout> | |||
| </appender> | |||
| <root> | |||
| <!-- ログのレベルを指定 --> | |||
| <!-- すべてのログ・レベルを出力 --> | |||
| <level value="INFO" /> | |||
| <!-- どのログ出力先を使用するか --> | |||
| <appender-ref ref="LogFileAppender" /> | |||
| </root> | |||
| </log4net> | |||
| </configuration> | |||