Commit 653ba1f5 by jianshuqin

新增服务:同步4K接口的Amazon广告费

parent 8bc95152
......@@ -42,7 +42,7 @@ namespace Bailun.DC.Common
/// </summary>
public static string DcJavaUrl = "http://finance-balance-sheet.data-center-job:8080";
#endif
public static string OAUrl = "http://www.bailuntec.com";
public static string OAUrl = "http://oa.bailuntec.com";
/// <summary>
/// 数据仓库
......
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<LangVersion>latest</LangVersion>
<AssemblyName>Bailun.DC.SyncAmazonAdFee</AssemblyName>
<RootNamespace>Bailun.DC.SyncAmazonAdFee</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Dapper" Version="2.0.35" />
<PackageReference Include="Dapper.SimpleCRUD" Version="2.2.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.7" />
<PackageReference Include="MySql.Data" Version="8.0.21" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Bailun.DC.Common\Bailun.DC.Common.csproj" />
</ItemGroup>
</Project>
FROM microsoft/dotnet:2.1-runtime AS base
WORKDIR /app
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY Bailun.DC.SyncAmazonAdFee/Bailun.DC.SyncAmazonAdFee.csproj Bailun.DC.SyncAmazonAdFee/
COPY Bailun.DC.Common/Bailun.DC.Common.csproj Bailun.DC.Common/
RUN dotnet restore Bailun.DC.SyncAmazonAdFee/Bailun.DC.SyncAmazonAdFee.csproj
COPY . .
WORKDIR /src/Bailun.DC.SyncAmazonAdFee
RUN dotnet build Bailun.DC.SyncAmazonAdFee.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish Bailun.DC.SyncAmazonAdFee.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "Bailun.DC.SyncAmazonAdFee.dll"]
namespace Bailun.DC.SyncAmazonAdFee.Models
{
public class dc_base_company_account
{
/// <summary>
/// ID
/// </summary>
public int id { get; set; }
/// <summary>
/// 公司ID
/// </summary>
public int company_id { get; set; }
/// <summary>
/// 账号ID
/// </summary>
public int account_id { get; set; }
/// <summary>
/// 站点
/// </summary>
public string site_en { get; set; }
/// <summary>
/// 销售账号ID
/// </summary>
public string seller_id { get; set; }
}
}
using Newtonsoft.Json;
using System;
namespace Bailun.DC.SyncAmazonAdFee.Models
{
public class dc_base_finance_amazon_ad_product : response_amazon_ad_fee
{
/// <summary>
///
/// </summary>
[JsonIgnore]
public long id { get; set; }
/// <summary>
/// 帐号ID
/// </summary>
public int account_id { get; set; }
/// <summary>
/// 公司ID
/// </summary>
public int company_id { get; set; }
/// <summary>
/// 本地创建时间
/// </summary>
public DateTime bj_create_time { get; set; }
/// <summary>
/// 本地更新时间
/// </summary>
public DateTime bj_modify_time { get; set; }
/// <summary>
/// 转人民币汇率
/// </summary>
public decimal exchange_rate { get; set; }
/// <summary>
/// 转美元汇率
/// </summary>
public decimal exchange_rate_usd { get; set; }
}
}
using Newtonsoft.Json;
using System;
using System.ComponentModel;
namespace Bailun.DC.SyncAmazonAdFee.Models
{
public class response_amazon_ad_fee
{
/// <summary>
/// 数据ID
/// </summary>
[JsonProperty("id")]
public long? data_id { get; set; }
/// <summary>
/// 广告系列名称
/// </summary>
[JsonProperty("campaignName")]
public string campaign_name { get; set; }
/// <summary>
/// 广告系列唯一ID
/// </summary>
[JsonProperty("campaignId")]
public string campaign_id { get; set; }
/// <summary>
/// 广告组名称
/// </summary>
[JsonProperty("adGroupName")]
public string ad_group_name { get; set; }
/// <summary>
/// 广告组唯一ID
/// </summary>
[JsonProperty("adGroupId")]
public string ad_group_id { get; set; }
/// <summary>
/// 广告总展示次数
/// </summary>
public int? impressions { get; set; }
/// <summary>
/// 广告总点击次数
/// </summary>
public int? clicks { get; set; }
/// <summary>
/// 所有点击总费用
/// </summary>
public decimal? cost { get; set; }
/// <summary>
/// 币种
/// </summary>
public string currency { get; set; }
/// <summary>
/// ASIN
/// </summary>
public string asin { get; set; }
/// <summary>
/// 平台SKU
/// </summary>
public string sku { get; set; }
/// <summary>
/// 7天内归因转化事件数
/// </summary>
[JsonProperty("AttributedConversions7d")]
public int? attributed_conversions_sevenday { get; set; }
/// <summary>
///
/// </summary>
[JsonProperty("AttributedConversions7dSameSKU")]
public string attributed_conversions_sevenday_same_sku { get; set; }
/// <summary>
/// 7天内订购归属单位数量
/// </summary>
[JsonProperty("AttributedUnitsOrdered7d")]
public int? attributed_units_ordered_sevenday { get; set; }
/// <summary>
/// 7天内归因销售数量
/// </summary>
[JsonProperty("AttributedSales7d")]
public int? attributed_sales_sevenday { get; set; }
/// <summary>
///
/// </summary>
[JsonProperty("AttributedSales7dSameSKU")]
public string attributed_sales_sevenday_same_sku { get; set; }
/// <summary>
///
/// </summary>
[JsonProperty("AttributedUnitsOrdered7dSameSKU")]
public string attributed_units_ordered_sevenday_same_sku { get; set; }
/// <summary>
/// 报告时间
/// </summary>
[JsonProperty("belongDate")]
public DateTime? report_date { get; set; }
/// <summary>
/// 4K数据更新时间
/// </summary>
[JsonProperty("updateTime")]
public DateTime? operation_time { get; set; }
/// <summary>
/// 广告类型 0:sp广告,1:sd广告 ,2:sb广告,3:sbv广告
/// </summary>
public int? type { get; set; }
}
}
using System;
namespace Bailun.DC.SyncAmazonAdFee.Models
{
public class response_exchange_rate
{
public decimal Rate { get; set; }
public string ToCurName { get; set; }
public DateTime CreateTime { get; set; }
}
}
using Newtonsoft.Json;
using System.Collections.Generic;
namespace Bailun.DC.SyncAmazonAdFee.Models
{
public class response_result
{
public int code { get; set; }
[JsonProperty("msg")]
public string message { get; set; }
public response_result_detail details { get; set; }
}
public class response_result_detail
{
public int total { get; set; }
public IList<response_amazon_ad_fee> list { get; set; }
}
}
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Threading.Tasks;
namespace Bailun.DC.SyncAmazonAdFee
{
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("启动新数据中心同步任务 " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
var builder = new HostBuilder().ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Services>();
});
await builder.RunConsoleAsync();
}
//测试
//static void Main(string[] args)
//{
// Console.WriteLine("开始启动 " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
// DateTime? btime = new DateTime(2021, 8, 1);
// DateTime? etime = DateTime.Today;
// try
// {
// var _service = new Services();
// _service.Init(btime, etime);
// }
// catch (Exception ex)
// {
// Console.WriteLine(ex.Message);
// }
// Console.WriteLine("任务运行完成 " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
//}
}
}
using Bailun.DC.Common;
using Bailun.DC.SyncAmazonAdFee.Models;
using Dapper;
using Microsoft.Extensions.Hosting;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Bailun.DC.SyncAmazonAdFee
{
public class Services : BackgroundService
{
/// <summary>
/// 4K提供的APP_KEY
/// </summary>
string appkey = "4k_&934dfjkdf)(9048390";
/// <summary>
/// 4K AmazonAdFee接口地址
/// </summary>
string url = "https://www.4kmiles.com/api2/api/campaignService/getReport";
private Timer _timer;
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
//每60分钟执行一次任务
_timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromMinutes(60));
return Task.CompletedTask;
}
private void DoWork(object state)
{
try
{
var now = DateTime.Now;
if (now.Hour == 17) //每天月的1日0点1分启动
{
Console.WriteLine("开始启动 " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
Init();
Console.WriteLine("任务运行完成 " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
}
else
{
Console.WriteLine($"目前时间是{now.Hour}小时,还没到设定的同步时间");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public Services()
{
Dapper.SimpleCRUD.SetDialect(SimpleCRUD.Dialect.MySQL);
}
public void Init(DateTime? startDate = null, DateTime? endDate = null)
{
IList<dc_base_company_account> listAccount = this.GetListAccount();
if (listAccount?.Count > 0)
{
if (!startDate.HasValue)
{
startDate = this.GetSyncDate();
Console.WriteLine($"同步开始日期{startDate.Value.ToString("yyyy-MM-dd")}");
}
if (!endDate.HasValue)
{
endDate = DateTime.Today.AddDays(-1);
}
for (DateTime date = startDate.Value; date <= endDate.Value; date = date.AddDays(1))
{
Console.WriteLine($"同步日期{date.ToString("yyyy-MM-dd")}");
foreach (dc_base_company_account account in listAccount)
{
var page = 1;
var pagesize = 1000;
var count = 0;
while (page == 1 || (page > 1 && count > 0))
{
try
{
long timeStamp = (long)(DateTime.Now.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
string sign = CommonHelper.md5Encrypt($"{this.appkey}{timeStamp}{account.seller_id}{account.site_en.ToLower()}{this.appkey}").ToUpper();
string url = $"{this.url}?pageIndex={page}&pageSize={pagesize}&sellerId={account.seller_id}&site={account.site_en.ToLower()}&timeStamp={timeStamp}&updateDate={date.ToString("yyyy-MM-dd")}&sign={sign}";
string result = HttpHelper.NetHelper.Request(url);
Console.WriteLine($"接口地址:{url}");
if (!string.IsNullOrEmpty(result))
{
var json = JsonConvert.DeserializeObject<response_result>(result);
count = json?.details?.list?.Count ?? 0;
if (json.code == 100 && count > 0)
{
//保存数据
this.Save(json.details.list, account);
Console.WriteLine($"已保存{count}条记录数据!");
}
page++;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Thread.Sleep(60 * 1000);
}
}
}
}
}
}
public IList<dc_base_company_account> GetListAccount()
{
IList<dc_base_company_account> list = default(IList<dc_base_company_account>);
//Amazon平台
int platform_id = 15;
string sql = "select id, company_id, account_id, site_en, seller_id from dc_base_company_account where status = 1 and site_en > '' and platform_id = @platform_id";
using (var db = new MySqlConnection(GlobalConfig.ConnectionString))
{
if (db.State == System.Data.ConnectionState.Closed)
{
db.Open();
}
list = db.Query<dc_base_company_account>(sql, new { platform_id = platform_id }).ToList();
}
return list;
}
public DateTime GetSyncDate()
{
DateTime date = DateTime.Today.AddDays(-1);
using (var db = new MySqlConnection(GlobalConfig.ConnectionString))
{
if (db.State == System.Data.ConnectionState.Closed)
{
db.Open();
}
date = db.QueryFirstOrDefault<DateTime?>("SELECT MAX(DATE_FORMAT(t1.operation_time,'%Y-%m-%d')) FROM dc_base_finance_amazon_ad_product t1") ?? DateTime.Today.AddDays(-1);
}
return date;
}
public decimal GetExchangeRate(string fromCur, string toCur, DateTime? date)
{
decimal rate = 0m;
using (var db = new MySqlConnection(GlobalConfig.ConnectionString))
{
if (db.State == System.Data.ConnectionState.Closed)
{
db.Open();
}
rate = db.QueryFirstOrDefault<decimal?>("select exchange_rate from dc_exchange_rate where init_curreny = @init_curreny and final_curreny = @final_curreny and record_time = @record_time", new { init_curreny = fromCur, final_curreny = toCur, record_time = (date ?? DateTime.Now).ToString("yyyy-MM-dd") }) ?? 0m;
}
if (rate == 0m)
{
var url = $"{GlobalConfig.OAUrl}/api/ExchangeRate/GetExchangeRateByCurAndDate?fromCur={fromCur}&toCur={toCur}&data={(date ?? DateTime.Now).ToString("yyyy-MM-dd")}";
var result = HttpHelper.NetHelper.Request(url);
try
{
rate = JsonConvert.DeserializeObject<response_exchange_rate>(result)?.Rate ?? 0m;
}
catch (Exception ex)
{
Console.WriteLine($"获取OA汇率异常:{ex.Message}");
}
}
return rate;
}
public void Save(IList<response_amazon_ad_fee> list, dc_base_company_account account)
{
using (var db = new MySqlConnection(GlobalConfig.ConnectionString))
{
if (db.State == System.Data.ConnectionState.Closed)
{
db.Open();
}
foreach (var item in list)
{
var m = JsonConvert.DeserializeObject<dc_base_finance_amazon_ad_product>(JsonConvert.SerializeObject(item));
m.account_id = account.account_id;
m.company_id = account.company_id;
m.exchange_rate = this.GetExchangeRate(m.currency, "CNY", m.report_date);
m.exchange_rate_usd = this.GetExchangeRate(m.currency, "USD", m.report_date);
m.campaign_name = m.campaign_name ?? string.Empty;
m.campaign_id = m.campaign_id ?? string.Empty;
m.ad_group_name = m.ad_group_name ?? string.Empty;
m.ad_group_id = m.ad_group_id ?? string.Empty;
m.impressions = m.impressions ?? 0;
m.clicks = m.clicks ?? 0;
m.cost = m.cost ?? 0;
m.currency = m.currency ?? string.Empty;
m.asin = m.asin ?? string.Empty;
m.sku = m.sku ?? string.Empty;
m.attributed_conversions_sevenday = m.attributed_conversions_sevenday ?? 0;
m.attributed_conversions_sevenday_same_sku = m.attributed_conversions_sevenday_same_sku ?? string.Empty;
m.attributed_units_ordered_sevenday = m.attributed_units_ordered_sevenday ?? 0;
m.attributed_sales_sevenday = m.attributed_sales_sevenday ?? 0;
m.attributed_sales_sevenday_same_sku = m.attributed_sales_sevenday_same_sku ?? string.Empty;
m.attributed_units_ordered_sevenday_same_sku = m.attributed_units_ordered_sevenday_same_sku ?? string.Empty;
m.bj_modify_time = DateTime.Now;
switch (m.type)
{
case null:
m.type = 0;
break;
case 0:
m.type = 1;
break;
case 1:
m.type = 4;
break;
}
int count = 0;
if (m.data_id.HasValue && m.data_id.Value > 0)
{
count = db.Execute($@"update dc_base_finance_amazon_ad_product
set
campaign_name = @campaign_name
, campaign_id = @campaign_id
, ad_group_name = @ad_group_name
, ad_group_id = @ad_group_id
, impressions = @impressions
, clicks = @clicks
, cost = @cost
, currency = @currency
, asin = @asin
, sku = @sku
, attributed_conversions_sevenday = @attributed_conversions_sevenday
, attributed_conversions_sevenday_same_sku = @attributed_conversions_sevenday_same_sku
, attributed_units_ordered_sevenday = @attributed_units_ordered_sevenday
, attributed_sales_sevenday = @attributed_sales_sevenday
, attributed_sales_sevenday_same_sku = @attributed_sales_sevenday_same_sku
, attributed_units_ordered_sevenday_same_sku = @attributed_units_ordered_sevenday_same_sku
, report_date = @report_date
, operation_time = @operation_time
, type = @type
, account_id = @account_id
, company_id = @company_id
, bj_modify_time = @bj_modify_time
, exchange_rate = @exchange_rate
, exchange_rate_usd = @exchange_rate_usd
where data_id=@data_id", m);
}
if (count == 0)
{
m.bj_create_time = DateTime.Now;
db.Insert(m);
}
}
}
}
}
}
......@@ -97,6 +97,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bailun.DC.SyncMonthStockWei
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bailun.DC.SyncShopifyFee", "Bailun.DC.SyncShopifyFee\Bailun.DC.SyncShopifyFee.csproj", "{9A19AF60-5891-4C35-A021-2DE58415373D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bailun.DC.SyncAmazonAdFee", "Bailun.DC.SyncAmazonAdFee\Bailun.DC.SyncAmazonAdFee.csproj", "{6FD93D1A-ABF6-4DE1-96A6-5D48BB756A04}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -287,6 +289,10 @@ Global
{9A19AF60-5891-4C35-A021-2DE58415373D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9A19AF60-5891-4C35-A021-2DE58415373D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9A19AF60-5891-4C35-A021-2DE58415373D}.Release|Any CPU.Build.0 = Release|Any CPU
{6FD93D1A-ABF6-4DE1-96A6-5D48BB756A04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6FD93D1A-ABF6-4DE1-96A6-5D48BB756A04}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6FD93D1A-ABF6-4DE1-96A6-5D48BB756A04}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6FD93D1A-ABF6-4DE1-96A6-5D48BB756A04}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......@@ -331,6 +337,7 @@ Global
{C4C4990D-14DC-4B76-A7EB-6F3FC5BE8B94} = {AE2CE86A-8538-4142-920F-684DCF47C064}
{66D159A3-63A6-4900-AB21-C04ADE5A3D01} = {AE2CE86A-8538-4142-920F-684DCF47C064}
{9A19AF60-5891-4C35-A021-2DE58415373D} = {AE2CE86A-8538-4142-920F-684DCF47C064}
{6FD93D1A-ABF6-4DE1-96A6-5D48BB756A04} = {AE2CE86A-8538-4142-920F-684DCF47C064}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6E53AF28-A282-4FB0-A769-EAEA9769C02A}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment