init
This commit is contained in:
commit
2ab789ac19
|
|
@ -0,0 +1,25 @@
|
||||||
|
**/.classpath
|
||||||
|
**/.dockerignore
|
||||||
|
**/.env
|
||||||
|
**/.git
|
||||||
|
**/.gitignore
|
||||||
|
**/.project
|
||||||
|
**/.settings
|
||||||
|
**/.toolstarget
|
||||||
|
**/.vs
|
||||||
|
**/.vscode
|
||||||
|
**/*.*proj.user
|
||||||
|
**/*.dbmdl
|
||||||
|
**/*.jfm
|
||||||
|
**/bin
|
||||||
|
**/charts
|
||||||
|
**/docker-compose*
|
||||||
|
**/compose*
|
||||||
|
**/Dockerfile*
|
||||||
|
**/node_modules
|
||||||
|
**/npm-debug.log
|
||||||
|
**/obj
|
||||||
|
**/secrets.dev.yaml
|
||||||
|
**/values.dev.yaml
|
||||||
|
LICENSE
|
||||||
|
README.md
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"ms-azuretools.vscode-azurefunctions",
|
||||||
|
"ms-dotnettools.csharp"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Attach to .NET Functions",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "attach",
|
||||||
|
"processId": "${command:azureFunctions.pickProcess}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": ".NET Core Launch (web)",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "build",
|
||||||
|
"program": "${workspaceFolder}/Migration/bin/Debug/net8.0/bigqueryconnector.dll",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}/Migration",
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"serverReadyAction": {
|
||||||
|
"action": "openExternally",
|
||||||
|
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
},
|
||||||
|
"sourceFileMap": {
|
||||||
|
"/Views": "${workspaceFolder}/Views"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": ".NET Core Attach",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "attach"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Docker .NET Launch",
|
||||||
|
"type": "docker",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "docker-run: debug",
|
||||||
|
"netCore": {
|
||||||
|
"appProject": "${workspaceFolder}/Migration/bigqueryconnector.csproj"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"azureFunctions.deploySubpath": "AzureFunction/bin/Release/net8.0/publish",
|
||||||
|
"azureFunctions.projectLanguage": "C#",
|
||||||
|
"azureFunctions.projectRuntime": "~4",
|
||||||
|
"debug.internalConsoleOptions": "neverOpen",
|
||||||
|
"azureFunctions.preDeployTask": "publish (functions)"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "clean (functions)",
|
||||||
|
"command": "dotnet",
|
||||||
|
"args": [
|
||||||
|
"clean",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
|
],
|
||||||
|
"type": "process",
|
||||||
|
"problemMatcher": "$msCompile",
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/AzureFunction"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "build (functions)",
|
||||||
|
"command": "dotnet",
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
|
],
|
||||||
|
"type": "process",
|
||||||
|
"dependsOn": "clean (functions)",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"problemMatcher": "$msCompile",
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/AzureFunction"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "clean release (functions)",
|
||||||
|
"command": "dotnet",
|
||||||
|
"args": [
|
||||||
|
"clean",
|
||||||
|
"--configuration",
|
||||||
|
"Release",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
|
],
|
||||||
|
"type": "process",
|
||||||
|
"problemMatcher": "$msCompile",
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/AzureFunction"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "publish (functions)",
|
||||||
|
"command": "dotnet",
|
||||||
|
"args": [
|
||||||
|
"publish",
|
||||||
|
"--configuration",
|
||||||
|
"Release",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
|
],
|
||||||
|
"type": "process",
|
||||||
|
"dependsOn": "clean release (functions)",
|
||||||
|
"problemMatcher": "$msCompile",
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/AzureFunction"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "func",
|
||||||
|
"dependsOn": "build (functions)",
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/AzureFunction/bin/Debug/net8.0"
|
||||||
|
},
|
||||||
|
"command": "host start",
|
||||||
|
"isBackground": true,
|
||||||
|
"problemMatcher": "$func-dotnet-watch"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "build",
|
||||||
|
"command": "dotnet",
|
||||||
|
"type": "process",
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"${workspaceFolder}/FeedDataverseBQ.sln",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary;ForceNoAlign"
|
||||||
|
],
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "publish",
|
||||||
|
"command": "dotnet",
|
||||||
|
"type": "process",
|
||||||
|
"args": [
|
||||||
|
"publish",
|
||||||
|
"${workspaceFolder}/FeedDataverseBQ.sln",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary;ForceNoAlign"
|
||||||
|
],
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "watch",
|
||||||
|
"command": "dotnet",
|
||||||
|
"type": "process",
|
||||||
|
"args": [
|
||||||
|
"watch",
|
||||||
|
"run",
|
||||||
|
"--project",
|
||||||
|
"${workspaceFolder}/FeedDataverseBQ.sln"
|
||||||
|
],
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "docker-build",
|
||||||
|
"label": "docker-build: debug",
|
||||||
|
"dependsOn": [
|
||||||
|
"build"
|
||||||
|
],
|
||||||
|
"dockerBuild": {
|
||||||
|
"tag": "feeddataversebq:dev",
|
||||||
|
"target": "base",
|
||||||
|
"dockerfile": "${workspaceFolder}/Migration/Dockerfile",
|
||||||
|
"context": "${workspaceFolder}",
|
||||||
|
"pull": true
|
||||||
|
},
|
||||||
|
"netCore": {
|
||||||
|
"appProject": "${workspaceFolder}/Migration/bigqueryconnector.csproj"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "docker-build",
|
||||||
|
"label": "docker-build: release",
|
||||||
|
"dependsOn": [
|
||||||
|
"build"
|
||||||
|
],
|
||||||
|
"dockerBuild": {
|
||||||
|
"tag": "feeddataversebq:latest",
|
||||||
|
"dockerfile": "${workspaceFolder}/Migration/Dockerfile",
|
||||||
|
"context": "${workspaceFolder}",
|
||||||
|
"platform": {
|
||||||
|
"os": "linux",
|
||||||
|
"architecture": "amd64"
|
||||||
|
},
|
||||||
|
"pull": true
|
||||||
|
},
|
||||||
|
"netCore": {
|
||||||
|
"appProject": "${workspaceFolder}/Migration/bigqueryconnector.csproj"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "docker-run",
|
||||||
|
"label": "docker-run: debug",
|
||||||
|
"dependsOn": [
|
||||||
|
"docker-build: debug"
|
||||||
|
],
|
||||||
|
"dockerRun": {},
|
||||||
|
"netCore": {
|
||||||
|
"appProject": "${workspaceFolder}/Migration/bigqueryconnector.csproj",
|
||||||
|
"enableDebugging": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "docker-run",
|
||||||
|
"label": "docker-run: release",
|
||||||
|
"dependsOn": [
|
||||||
|
"docker-build: release"
|
||||||
|
],
|
||||||
|
"dockerRun": {},
|
||||||
|
"netCore": {
|
||||||
|
"appProject": "${workspaceFolder}/Migration/bigqueryconnector.csproj"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,268 @@
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
|
# Azure Functions localsettings file
|
||||||
|
local.settings.json
|
||||||
|
osadkowski-hd-2f3bd9b0ab5d.json
|
||||||
|
appsettings.json
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Visual Studio 2015 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUNIT
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# DNX
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_i.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# JustCode is a .NET coding add-in
|
||||||
|
.JustCode
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
#*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/packages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/packages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/packages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignoreable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
node_modules/
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# JetBrains Rider
|
||||||
|
.idea/
|
||||||
|
*.sln.iml
|
||||||
|
|
||||||
|
# CodeRush
|
||||||
|
.cr/
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Net;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using Google.Cloud.BigQuery.V2;
|
||||||
|
using Microsoft.Azure.Functions.Worker;
|
||||||
|
using Microsoft.Azure.Functions.Worker.Http;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace OSAFeedXML
|
||||||
|
{
|
||||||
|
public class Function1
|
||||||
|
{
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
private readonly IBigQuery _bq;
|
||||||
|
private readonly string DomainRedirect, ShortDescription, Title;
|
||||||
|
|
||||||
|
public Function1(ILoggerFactory loggerFactory, IBigQuery bq)
|
||||||
|
{
|
||||||
|
_logger = loggerFactory.CreateLogger<Function1>();
|
||||||
|
DomainRedirect = Environment.GetEnvironmentVariable("DOMAIN_REDIRECT") ?? throw new Exception("Brak domeny przekierowania.");
|
||||||
|
ShortDescription = Environment.GetEnvironmentVariable("SHORT_DESCRIPTION") ?? throw new Exception("Brak krótkiego opisu.");
|
||||||
|
Title = Environment.GetEnvironmentVariable("TITLE") ?? throw new Exception("Brak tytułu.");
|
||||||
|
_bq = bq;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Function("getfeeds")]
|
||||||
|
public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequestData req)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var queryParams = System.Web.HttpUtility.ParseQueryString(req.Url.Query);
|
||||||
|
var sourceParam = queryParams["source"];
|
||||||
|
var destinationList = new List<Destinations>();
|
||||||
|
Boolean.TryParse(queryParams["withoutbg"], out var withoutbg);
|
||||||
|
|
||||||
|
if (sourceParam != null)
|
||||||
|
{
|
||||||
|
var sources = sourceParam.Split(',');
|
||||||
|
destinationList = sources
|
||||||
|
.Select(src => Enum.TryParse(typeof(Destinations), src, true, out var result) ? result : null)
|
||||||
|
.Where(v => v != null)
|
||||||
|
.Cast<Destinations>()
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
destinationList = new List<Destinations>() { Destinations.google, Destinations.facebook };
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = _bq.GetDataBigQuery(destinationList, withoutbg);
|
||||||
|
|
||||||
|
var jsonArray = new JArray(
|
||||||
|
((BigQueryResults)result).Select(row => new JObject(
|
||||||
|
row.Schema.Fields.Select(field => new JProperty(field.Name, JToken.FromObject(row[field.Name] ?? string.Empty)))
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
|
JArray products = JArray.Parse(jsonArray.ToString());
|
||||||
|
|
||||||
|
XNamespace g = "http://base.google.com/ns/1.0";
|
||||||
|
|
||||||
|
XDocument xmlDoc = new XDocument(
|
||||||
|
new XElement("rss", new XAttribute("version", "2.0"),
|
||||||
|
new XAttribute(XNamespace.Xmlns + "g", g),
|
||||||
|
new XElement("channel",
|
||||||
|
new XElement("title", Title),
|
||||||
|
new XElement("link", DomainRedirect),
|
||||||
|
new XElement("description", ShortDescription),
|
||||||
|
from product in products
|
||||||
|
select new XElement("item",
|
||||||
|
new XElement(g + "id", product["id"]?.ToString()),
|
||||||
|
new XElement(g + "title", product["title"]?.ToString()),
|
||||||
|
new XElement(g + "description", product["description"]?.ToString()),
|
||||||
|
new XElement(g + "link", product["link"]?.ToString()),
|
||||||
|
new XElement(g + "image_link", product["image_link"]?.ToString()),
|
||||||
|
new XElement(g + "availability", product["availability"]?.ToString()),
|
||||||
|
new XElement(g + "price", FormatPrice(product["price"] ?? 0)),
|
||||||
|
new XElement(g + "brand", product["brand"]?.ToString()),
|
||||||
|
new XElement(g + "gtin", product["gtin"]?.ToString()),
|
||||||
|
new XElement(g + "mpn", product["mpn"]?.ToString()),
|
||||||
|
new XElement(g + "product_type", product["product_type"]?.ToString()),
|
||||||
|
new XElement(g + "google_product_category", product["google_product_category"]?.ToString()),
|
||||||
|
new XElement(g + "unit_pricing_measure", product["unit_pricing_measure"]?.ToString()),
|
||||||
|
new XElement(g + "condition", product["condition"]?.ToString()),
|
||||||
|
product["gtin"]?.ToString() == "" ? new XElement(g + "identifier_exists", "no") : new XElement(g + "identifier_exists", "yes")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
var response = req.CreateResponse(HttpStatusCode.OK);
|
||||||
|
response.Headers.Add("Content-Type", "text/xml; charset=utf-8");
|
||||||
|
|
||||||
|
response.WriteString(xmlDoc.ToString());
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, ex.Message);
|
||||||
|
return req.CreateResponse(HttpStatusCode.InternalServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static string FormatPrice(JToken priceToken)
|
||||||
|
{
|
||||||
|
if (priceToken == null || string.IsNullOrWhiteSpace(priceToken.ToString()))
|
||||||
|
{
|
||||||
|
return "0.00 PLN";
|
||||||
|
}
|
||||||
|
|
||||||
|
decimal price = priceToken.Value<decimal>();
|
||||||
|
return price.ToString("0.00", CultureInfo.InvariantCulture) + " PLN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Google.Apis.Auth.OAuth2;
|
||||||
|
using Google.Cloud.BigQuery.V2;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
|
namespace OSAFeedXML
|
||||||
|
{
|
||||||
|
public interface IBigQuery
|
||||||
|
{
|
||||||
|
dynamic GetDataBigQuery(List<Destinations> destinations, bool withoutbg = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Destinations
|
||||||
|
{
|
||||||
|
google = 0,
|
||||||
|
facebook = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum PublicationStatus
|
||||||
|
{
|
||||||
|
HIDDEN = 1,
|
||||||
|
OFFLINE_OFFER = 2,
|
||||||
|
UNAVAILABLE = 3,
|
||||||
|
TEMPORARILY_UNAVAILABLE = 4,
|
||||||
|
SALE_IN_EC = 5,
|
||||||
|
PRESALE_IN_EC = 6
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum PriceConversion
|
||||||
|
{
|
||||||
|
NOT_CONVERTION = 0,
|
||||||
|
CONVERTION = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class GoogleBigQuery : IBigQuery
|
||||||
|
{
|
||||||
|
private readonly BigQueryClient bigqueryClient;
|
||||||
|
private readonly string DomainRedirect;
|
||||||
|
private readonly string GoogleProjectId, GoogleDatabase;
|
||||||
|
|
||||||
|
public GoogleBigQuery()
|
||||||
|
{
|
||||||
|
string googleCredentialsJson = Environment.GetEnvironmentVariable("GOOGLE_CREDENTIALS_JSON") ?? throw new Exception("Brak danych uwierzytelniających Google.");
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(googleCredentialsJson))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Brak danych uwierzytelniających Google.");
|
||||||
|
}
|
||||||
|
|
||||||
|
GoogleCredential googleCredential = GoogleCredential.FromJson(googleCredentialsJson);
|
||||||
|
|
||||||
|
GoogleProjectId = Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID") ?? throw new Exception("Brak identyfikatora projektu Google.");
|
||||||
|
GoogleDatabase = Environment.GetEnvironmentVariable("GOOGLE_DATABASE") ?? throw new Exception("Brak nazwy bazy danych Google.");
|
||||||
|
|
||||||
|
bigqueryClient = BigQueryClient.Create(GoogleProjectId, googleCredential);
|
||||||
|
DomainRedirect = Environment.GetEnvironmentVariable("DOMAIN_REDIRECT") ?? throw new Exception("Brak domeny przekierowania.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public dynamic GetDataBigQuery(List<Destinations> Destinations, bool WithoutBg = false)
|
||||||
|
{
|
||||||
|
var status = new List<PublicationStatus>() { PublicationStatus.SALE_IN_EC, PublicationStatus.PRESALE_IN_EC };
|
||||||
|
string sql = @$"
|
||||||
|
SELECT
|
||||||
|
bon_gid AS id,
|
||||||
|
bon_ec_name AS title,
|
||||||
|
bon_seo_description AS description,
|
||||||
|
CONCAT('{DomainRedirect}/produkt/', bon_slug_url, '--s-', bon_gid) AS link,
|
||||||
|
COALESCE(ic.bon_url, bn.bon_url) AS image_link,
|
||||||
|
CASE
|
||||||
|
WHEN bon_warehouse_state_central IS NULL OR bon_warehouse_state_central = 0 THEN 'out_of_stock'
|
||||||
|
WHEN NOT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM UNNEST(bon_marketplace) AS marketplace_value
|
||||||
|
WHERE marketplace_value IN UNNEST([{string.Join(", ", Destinations.Select(dest => (int)dest))}])
|
||||||
|
)
|
||||||
|
OR bon_ecommerce_status NOT IN ({string.Join(", ", status.Select(stat => (int)stat))}) THEN 'out_of_stock'
|
||||||
|
ELSE 'in_stock'
|
||||||
|
END AS availability,
|
||||||
|
ROUND(
|
||||||
|
bon_cash_price *
|
||||||
|
(CASE WHEN bon_price_for = {(int)PriceConversion.CONVERTION} THEN bon_converter ELSE 1 END) *
|
||||||
|
((100 + COALESCE(bon_vat_rate, 0)) / 100), 2
|
||||||
|
) AS price,
|
||||||
|
bon_category_path AS product_type,
|
||||||
|
bon_name AS brand,
|
||||||
|
bon_ean AS gtin,
|
||||||
|
bon_index AS mpn,
|
||||||
|
osa_gmc_id AS google_product_category
|
||||||
|
FROM `{GoogleProjectId}.{GoogleDatabase}.bon_main_product` bn
|
||||||
|
LEFT JOIN `{GoogleProjectId}.{GoogleDatabase}.images_clearbg` ic
|
||||||
|
ON bn.bon_commodity_indexid = ic.bon_commodity_indexid
|
||||||
|
";
|
||||||
|
|
||||||
|
BigQueryResults results = bigqueryClient.ExecuteQuery(sql, null);
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Google.Apis.Auth" Version="1.69.0" />
|
||||||
|
<PackageReference Include="Google.Cloud.BigQuery.V2" Version="3.11.0" />
|
||||||
|
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.3.0" />
|
||||||
|
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.23.0" />
|
||||||
|
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="2.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="host.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
using Microsoft.Azure.Functions.Worker;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using OSAFeedXML;
|
||||||
|
|
||||||
|
var host = new HostBuilder()
|
||||||
|
.ConfigureFunctionsWorkerDefaults()
|
||||||
|
.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
services.AddApplicationInsightsTelemetryWorkerService();
|
||||||
|
services.ConfigureFunctionsApplicationInsights();
|
||||||
|
services.AddSingleton<IBigQuery, GoogleBigQuery>();
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
host.Run();
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"OSAFeedXML": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"commandLineArgs": "--port 7168",
|
||||||
|
"launchBrowser": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"appInsights1": {
|
||||||
|
"type": "appInsights"
|
||||||
|
},
|
||||||
|
"storage1": {
|
||||||
|
"type": "storage",
|
||||||
|
"connectionId": "AzureWebJobsStorage"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"appInsights1": {
|
||||||
|
"type": "appInsights.sdk"
|
||||||
|
},
|
||||||
|
"storage1": {
|
||||||
|
"type": "storage.emulator",
|
||||||
|
"connectionId": "AzureWebJobsStorage"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"version": "2.0",
|
||||||
|
"logging": {
|
||||||
|
"applicationInsights": {
|
||||||
|
"samplingSettings": {
|
||||||
|
"isEnabled": true,
|
||||||
|
"excludedTypes": "Request"
|
||||||
|
},
|
||||||
|
"enableLiveMetricsFilters": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.5.2.0
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bigqueryconnector", "Migration\bigqueryconnector.csproj", "{BEEF5A15-8C35-8C55-4D84-2528FDF180FE}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OSAFeedXML", "AzureFunction\OSAFeedXML.csproj", "{8A2CD958-D8F3-48A4-BD25-792C9EC1E48E}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{BEEF5A15-8C35-8C55-4D84-2528FDF180FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{BEEF5A15-8C35-8C55-4D84-2528FDF180FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{BEEF5A15-8C35-8C55-4D84-2528FDF180FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{BEEF5A15-8C35-8C55-4D84-2528FDF180FE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{8A2CD958-D8F3-48A4-BD25-792C9EC1E48E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{8A2CD958-D8F3-48A4-BD25-792C9EC1E48E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{8A2CD958-D8F3-48A4-BD25-792C9EC1E48E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{8A2CD958-D8F3-48A4-BD25-792C9EC1E48E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {726D97D5-9D11-447F-BEB7-33A706B3BACF}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
|
|
@ -0,0 +1,268 @@
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
|
# Azure Functions localsettings file
|
||||||
|
local.settings.json
|
||||||
|
osadkowski-hd-2f3bd9b0ab5d.json
|
||||||
|
appsettings.Development.json
|
||||||
|
appsettings.Production.json
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Visual Studio 2015 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUNIT
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# DNX
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_i.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# JustCode is a .NET coding add-in
|
||||||
|
.JustCode
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
#*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/packages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/packages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/packages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignoreable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
node_modules/
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# JetBrains Rider
|
||||||
|
.idea/
|
||||||
|
*.sln.iml
|
||||||
|
|
||||||
|
# CodeRush
|
||||||
|
.cr/
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
|
||||||
|
WORKDIR /app
|
||||||
|
EXPOSE 5020
|
||||||
|
|
||||||
|
ENV ASPNETCORE_URLS=http://+:5020
|
||||||
|
|
||||||
|
USER app
|
||||||
|
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||||
|
ARG configuration=Release
|
||||||
|
WORKDIR /src
|
||||||
|
COPY ["Migration/bigqueryconnector.csproj", "Migration/"]
|
||||||
|
RUN dotnet restore "Migration/bigqueryconnector.csproj"
|
||||||
|
COPY . .
|
||||||
|
WORKDIR "/src/Migration"
|
||||||
|
RUN dotnet build "bigqueryconnector.csproj" -c $configuration -o /app/build
|
||||||
|
|
||||||
|
FROM build AS publish
|
||||||
|
ARG configuration=Release
|
||||||
|
RUN dotnet publish "bigqueryconnector.csproj" -c $configuration -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
|
FROM base AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
ENTRYPOINT ["dotnet", "bigqueryconnector.dll"]
|
||||||
|
|
@ -0,0 +1,412 @@
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Google.Apis.Auth.OAuth2;
|
||||||
|
using Google.Cloud.BigQuery.V2;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Migration.Services;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
|
||||||
|
public interface IBigQuery
|
||||||
|
{
|
||||||
|
Task<IActionResult> GetProducts();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GoogleBigQuery : IBigQuery
|
||||||
|
{
|
||||||
|
private readonly GoogleCredential googleCredential;
|
||||||
|
private readonly BigQueryClient bigqueryClient;
|
||||||
|
private readonly string GoogleProjectId, GoogleDatabase;
|
||||||
|
private readonly IHttpClientFactory httpClientFactory;
|
||||||
|
|
||||||
|
public GoogleBigQuery(IConfiguration configuration, IHttpClientFactory httpClientFactory)
|
||||||
|
{
|
||||||
|
GoogleProjectId = configuration.GetValue<string>("BigQuery:ProjectId") ?? throw new Exception("Nie podano parametru identyfikatora projektu Google.");
|
||||||
|
GoogleDatabase = configuration.GetValue<string>("BigQuery:DbName") ?? throw new Exception("Nie podano parametru nazwy bazy danych BigQuery w konfiguracji");
|
||||||
|
|
||||||
|
googleCredential = GoogleCredential.FromFile(configuration.GetValue<string>("GoogleCredentialFile"));
|
||||||
|
bigqueryClient = BigQueryClient.Create(GoogleProjectId, googleCredential);
|
||||||
|
this.httpClientFactory = httpClientFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IActionResult> GetProducts()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int from = 1, limit = 100;
|
||||||
|
string me = string.Empty;
|
||||||
|
var httpClient = httpClientFactory.CreateClient(DataverseProvider.HTTP_CLIENT);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var jsonBody = new JObject
|
||||||
|
{
|
||||||
|
{"entity_name", "bon_commodity_index"},
|
||||||
|
{"attributes", new JArray {
|
||||||
|
"bon_main_product_id",
|
||||||
|
"bon_index",
|
||||||
|
"bon_gid",
|
||||||
|
"bon_ean",
|
||||||
|
"bon_product_name",
|
||||||
|
"bon_slug_url",
|
||||||
|
"bon_warehouse_state_central",
|
||||||
|
"bon_vat_rate",
|
||||||
|
"bon_converter",
|
||||||
|
"bon_calculaltion_unit",
|
||||||
|
"bon_marketplace",
|
||||||
|
"bon_price_for"
|
||||||
|
}},
|
||||||
|
{"makeFilter", true},
|
||||||
|
{"conditions", new JArray {
|
||||||
|
new JObject {
|
||||||
|
{"attribute_name", "bon_slug_url"},
|
||||||
|
{"condition_operator", "NotNull"}
|
||||||
|
},
|
||||||
|
new JObject {
|
||||||
|
{"attribute_name", "bon_converter"},
|
||||||
|
{"condition_operator", "NotNull"}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
{"links", new JArray {
|
||||||
|
new JObject {
|
||||||
|
{"primary_entity_name", "bon_commodity_index"},
|
||||||
|
{"related_entity_name", "bon_main_product"},
|
||||||
|
{"primary_key", "bon_main_product_id"},
|
||||||
|
{"foreign_key", "bon_main_productid"},
|
||||||
|
{"join_operator", "Inner"},
|
||||||
|
{"columns", new JArray {
|
||||||
|
"bon_ec_name",
|
||||||
|
"bon_seo_description"
|
||||||
|
}},
|
||||||
|
{"entity_alias", "bon_main_product"}
|
||||||
|
},
|
||||||
|
new JObject {
|
||||||
|
{"primary_entity_name", "bon_commodity_index"},
|
||||||
|
{"related_entity_name", "bon_purchase_index"},
|
||||||
|
{"primary_key", "bon_commodity_indexid"},
|
||||||
|
{"foreign_key", "bon_commodity_index_id"},
|
||||||
|
{"join_operator", "LeftOuter"},
|
||||||
|
{"columns", new JArray {
|
||||||
|
"bon_ecommerce_status"
|
||||||
|
}},
|
||||||
|
{"entity_alias", "bon_purchase_index"}
|
||||||
|
},
|
||||||
|
new JObject {
|
||||||
|
{"primary_entity_name", "bon_main_product"},
|
||||||
|
{"related_entity_name", "bon_producer_farmer"},
|
||||||
|
{"primary_key", "bon_producer_id"},
|
||||||
|
{"foreign_key", "bon_producer_farmerid"},
|
||||||
|
{"join_operator", "Inner"},
|
||||||
|
{"columns", new JArray {
|
||||||
|
"bon_name"
|
||||||
|
}},
|
||||||
|
{"entity_alias", "bon_producer_farmer"}
|
||||||
|
},
|
||||||
|
new JObject {
|
||||||
|
{"primary_entity_name", "bon_commodity_index"},
|
||||||
|
{"related_entity_name", "bon_public_document"},
|
||||||
|
{"primary_key", "bon_commodity_indexid"},
|
||||||
|
{"foreign_key", "bon_commodity_index_id"},
|
||||||
|
{"join_operator", "Inner"},
|
||||||
|
{"columns", new JArray {
|
||||||
|
"bon_url"
|
||||||
|
}},
|
||||||
|
{"entity_alias", "bon_public_document"},
|
||||||
|
{"conditions", new JArray {
|
||||||
|
new JObject {
|
||||||
|
{"attribute_name", "bon_order"},
|
||||||
|
{"attribute_value", "1"},
|
||||||
|
{"condition_operator", "Equal"}
|
||||||
|
},
|
||||||
|
new JObject {
|
||||||
|
{"attribute_name", "bon_file_type_id"},
|
||||||
|
{"attribute_value", "c62765b3-2d0c-ee11-8f6e-6045bd8c9e0f"},
|
||||||
|
{"condition_operator", "Equal"}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
new JObject {
|
||||||
|
{"primary_entity_name", "bon_commodity_index"},
|
||||||
|
{"related_entity_name", "bon_sales_price_list"},
|
||||||
|
{"primary_key", "bon_commodity_indexid"},
|
||||||
|
{"foreign_key", "bon_commodity_index_id"},
|
||||||
|
{"join_operator", "Inner"},
|
||||||
|
{"columns", new JArray {
|
||||||
|
"bon_cash_price"
|
||||||
|
}},
|
||||||
|
{"entity_alias", "bon_sales_price_list"},
|
||||||
|
{"conditions", new JArray {
|
||||||
|
new JObject {
|
||||||
|
{"attribute_name", "bon_publication_type"},
|
||||||
|
{"attribute_value", "2"},
|
||||||
|
{"condition_operator", "Equal"}
|
||||||
|
},
|
||||||
|
new JObject {
|
||||||
|
{"attribute_name", "statuscode"},
|
||||||
|
{"attribute_value", new JArray {"1", "180430002"}},
|
||||||
|
{"condition_operator", "In"}
|
||||||
|
},
|
||||||
|
new JObject {
|
||||||
|
{"attribute_name", "bon_pricelistid"},
|
||||||
|
{"attribute_value", "48e17eb1-9495-e811-a835-000d3ab48443"},
|
||||||
|
{"condition_operator", "Equal"}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
},
|
||||||
|
new JObject {
|
||||||
|
{"primary_entity_name", "bon_main_product"},
|
||||||
|
{"related_entity_name", "bon_categories"},
|
||||||
|
{"primary_key", "bon_category_id"},
|
||||||
|
{"foreign_key", "bon_categoriesid"},
|
||||||
|
{"join_operator", "LeftOuter"},
|
||||||
|
{"columns", new JArray {
|
||||||
|
"bon_categoriesid",
|
||||||
|
"osa_gmc_id"
|
||||||
|
}},
|
||||||
|
{"entity_alias", "bon_categories"}
|
||||||
|
},
|
||||||
|
new JObject{
|
||||||
|
{"primary_entity_name", "bon_main_product"},
|
||||||
|
{"related_entity_name", "bon_categories"},
|
||||||
|
{"primary_key", "bon_category_id"},
|
||||||
|
{"foreign_key", "bon_categoriesid"},
|
||||||
|
{"join_operator", "LeftOuter"},
|
||||||
|
{"columns", new JArray {
|
||||||
|
"bon_short_name"
|
||||||
|
}},
|
||||||
|
{"entity_alias", "bon_category_path"},
|
||||||
|
{"recurece", true}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await httpClient.PostAsync($"getdata?enviroment=prod&from={from}&limit={limit}", new StringContent(
|
||||||
|
JsonConvert.SerializeObject(jsonBody, Formatting.None),
|
||||||
|
Encoding.UTF8,
|
||||||
|
"application/json"
|
||||||
|
));
|
||||||
|
|
||||||
|
if ((int)response.StatusCode == 500 && JObject.Parse(await response.Content.ReadAsStringAsync())?["errorCode"]?.Value<int>() == 501)
|
||||||
|
break;
|
||||||
|
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var content = await response.Content.ReadAsStringAsync() ?? throw new Exception("Brak odpowiedzi z Dataverse");
|
||||||
|
var jObject = JsonConvert.DeserializeObject<JObject>(content) ?? throw new Exception("Nieprawidłowy format JSON");
|
||||||
|
|
||||||
|
var resultArray = jObject["result"] as JArray ?? throw new Exception("Brak pola 'result' w odpowiedzi");
|
||||||
|
var resultList = resultArray.ToObject<List<Dictionary<string, object>>>() ?? new List<Dictionary<string, object>>();
|
||||||
|
|
||||||
|
List<BigQueryInsertRow> insertRows = resultArray!.ToObject<List<JObject>>()!
|
||||||
|
.ConvertAll(row => ConvertToBigQueryInsertRow(row));
|
||||||
|
|
||||||
|
string upsertQuery = $@"
|
||||||
|
MERGE `{GoogleDatabase}.bon_main_product` AS T
|
||||||
|
USING (
|
||||||
|
SELECT DISTINCT * FROM UNNEST([
|
||||||
|
{{0}}
|
||||||
|
])
|
||||||
|
) AS S
|
||||||
|
ON T.bon_commodity_indexid = S.bon_commodity_indexid
|
||||||
|
WHEN MATCHED THEN
|
||||||
|
UPDATE SET
|
||||||
|
bon_cash_price = S.bon_cash_price,
|
||||||
|
bon_categoriesid = S.bon_categoriesid,
|
||||||
|
transactioncurrencyid = S.transactioncurrencyid,
|
||||||
|
bon_warehouse_state_central = S.bon_warehouse_state_central,
|
||||||
|
bon_ec_name = S.bon_ec_name,
|
||||||
|
bon_ean = S.bon_ean,
|
||||||
|
bon_gid = S.bon_gid,
|
||||||
|
bon_index = S.bon_index,
|
||||||
|
bon_name = S.bon_name,
|
||||||
|
bon_url = S.bon_url,
|
||||||
|
bon_category_path = S.bon_category_path,
|
||||||
|
bon_seo_description = S.bon_seo_description,
|
||||||
|
bon_main_product_id = S.bon_main_product_id,
|
||||||
|
bon_slug_url = S.bon_slug_url,
|
||||||
|
bon_converter = S.bon_converter,
|
||||||
|
bon_vat_rate = S.bon_vat_rate,
|
||||||
|
bon_product_name = S.bon_product_name,
|
||||||
|
osa_gmc_id = S.osa_gmc_id,
|
||||||
|
bon_calculaltion_unit = S.bon_calculaltion_unit,
|
||||||
|
bon_marketplace = S.bon_marketplace,
|
||||||
|
bon_price_for = S.bon_price_for,
|
||||||
|
bon_ecommerce_status = S.bon_ecommerce_status
|
||||||
|
WHEN NOT MATCHED THEN
|
||||||
|
INSERT (
|
||||||
|
bon_commodity_indexid,
|
||||||
|
bon_cash_price,
|
||||||
|
bon_categoriesid,
|
||||||
|
transactioncurrencyid,
|
||||||
|
bon_warehouse_state_central,
|
||||||
|
bon_ec_name,
|
||||||
|
bon_ean,
|
||||||
|
bon_gid,
|
||||||
|
bon_index,
|
||||||
|
bon_name,
|
||||||
|
bon_url,
|
||||||
|
bon_category_path,
|
||||||
|
bon_seo_description,
|
||||||
|
bon_main_product_id,
|
||||||
|
bon_slug_url,
|
||||||
|
bon_converter,
|
||||||
|
bon_vat_rate,
|
||||||
|
bon_product_name,
|
||||||
|
osa_gmc_id,
|
||||||
|
bon_calculaltion_unit,
|
||||||
|
bon_marketplace,
|
||||||
|
bon_price_for,
|
||||||
|
bon_ecommerce_status
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
S.bon_commodity_indexid,
|
||||||
|
S.bon_cash_price,
|
||||||
|
S.bon_categoriesid,
|
||||||
|
S.transactioncurrencyid,
|
||||||
|
S.bon_warehouse_state_central,
|
||||||
|
S.bon_ec_name,
|
||||||
|
S.bon_ean,
|
||||||
|
S.bon_gid,
|
||||||
|
S.bon_index,
|
||||||
|
S.bon_name,
|
||||||
|
S.bon_url,
|
||||||
|
S.bon_category_path,
|
||||||
|
S.bon_seo_description,
|
||||||
|
S.bon_main_product_id,
|
||||||
|
S.bon_slug_url,
|
||||||
|
S.bon_converter,
|
||||||
|
S.bon_vat_rate,
|
||||||
|
S.bon_product_name,
|
||||||
|
S.osa_gmc_id,
|
||||||
|
S.bon_calculaltion_unit,
|
||||||
|
S.bon_marketplace,
|
||||||
|
S.bon_price_for,
|
||||||
|
S.bon_ecommerce_status
|
||||||
|
)";
|
||||||
|
|
||||||
|
await PutDataBigQuery(upsertQuery, insertRows);
|
||||||
|
|
||||||
|
from++;
|
||||||
|
}
|
||||||
|
while (true);
|
||||||
|
return new OkObjectResult(new { message = me });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"PutDataBigQuery_bon_commodity_index: {ex.Message}");
|
||||||
|
return new BadRequestObjectResult(new { message = ex.Message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task PutDataBigQuery(string upsertQuery, List<BigQueryInsertRow> rows)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var table = bigqueryClient.GetTable(GoogleDatabase, "bon_main_product");
|
||||||
|
|
||||||
|
string CleanString(object value)
|
||||||
|
{
|
||||||
|
return value != null
|
||||||
|
? Regex.Replace(value.ToString() ?? "", @"\t|\n|\r", "")
|
||||||
|
: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
var insertRows = rows.Select(row => new BigQueryInsertRow
|
||||||
|
{
|
||||||
|
{ "bon_commodity_indexid", row["bon_commodity_indexid"] },
|
||||||
|
{ "bon_cash_price", row["bon_cash_price"] },
|
||||||
|
{ "bon_categoriesid", row["bon_categoriesid"] },
|
||||||
|
{ "transactioncurrencyid", row["transactioncurrencyid"] },
|
||||||
|
{ "bon_warehouse_state_central", row["bon_warehouse_state_central"] },
|
||||||
|
{ "bon_ec_name", row["bon_ec_name"] },
|
||||||
|
{ "bon_ean", row["bon_ean"] },
|
||||||
|
{ "bon_gid", row["bon_gid"] },
|
||||||
|
{ "bon_index", row["bon_index"] },
|
||||||
|
{ "bon_name", row["bon_name"] },
|
||||||
|
{ "bon_url", row["bon_url"] },
|
||||||
|
{ "bon_category_path", row["bon_category_path"] },
|
||||||
|
{ "bon_seo_description", CleanString(row["bon_seo_description"]) },
|
||||||
|
{ "bon_main_product_id", row["bon_main_product_id"] },
|
||||||
|
{ "bon_slug_url", row["bon_slug_url"] },
|
||||||
|
{ "bon_converter", row["bon_converter"] },
|
||||||
|
{ "bon_vat_rate", row["bon_vat_rate"] },
|
||||||
|
{ "bon_product_name", row["bon_product_name"] },
|
||||||
|
{ "osa_gmc_id", row["osa_gmc_id"] },
|
||||||
|
{ "bon_calculaltion_unit", row["bon_calculaltion_unit"] },
|
||||||
|
{ "bon_marketplace", row["bon_marketplace"] },
|
||||||
|
{ "bon_price_for", row["bon_price_for"] },
|
||||||
|
{ "bon_ecommerce_status", row["bon_ecommerce_status"] }
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
var mergeValues = insertRows.Select(row =>
|
||||||
|
$"STRUCT('{row["bon_commodity_indexid"]}' as bon_commodity_indexid, " +
|
||||||
|
$"cast({row["bon_cash_price"] ?? "NULL"} as numeric) as bon_cash_price, " +
|
||||||
|
$"'{row["bon_categoriesid"]}' as bon_categoriesid, " +
|
||||||
|
$"'{row["transactioncurrencyid"]}' as transactioncurrencyid, " +
|
||||||
|
$"cast({row["bon_warehouse_state_central"] ?? "NULL"} as numeric) as bon_warehouse_state_central, " +
|
||||||
|
$"'{row["bon_ec_name"]}' as bon_ec_name, " +
|
||||||
|
$"'{row["bon_ean"]}' as bon_ean, " +
|
||||||
|
$"{row["bon_gid"] ?? "NULL"} as bon_gid, " +
|
||||||
|
$"'{row["bon_index"]}' as bon_index, " +
|
||||||
|
$"'{row["bon_name"]}' as bon_name, " +
|
||||||
|
$"'{row["bon_url"]}' as bon_url, " +
|
||||||
|
$"'{row["bon_category_path"]}' as bon_category_path, " +
|
||||||
|
$"'{row["bon_seo_description"]}' as bon_seo_description, " +
|
||||||
|
$"'{row["bon_main_product_id"]}' as bon_main_product_id, " +
|
||||||
|
$"'{row["bon_slug_url"]}' as bon_slug_url, " +
|
||||||
|
$"cast({row["bon_converter"] ?? "NULL"} as numeric) as bon_converter, " +
|
||||||
|
$"{row["bon_vat_rate"] ?? "NULL"} as bon_vat_rate, " +
|
||||||
|
$"'{row["bon_product_name"]}' as bon_product_name, " +
|
||||||
|
$"{row["osa_gmc_id"] ?? "NULL"} as osa_gmc_id, " +
|
||||||
|
$"'{row["bon_calculaltion_unit"]}' as bon_calculaltion_unit, " +
|
||||||
|
$"ARRAY[{row["bon_marketplace"]}] as bon_marketplace, " +
|
||||||
|
$"{row["bon_price_for"] ?? "NULL"} as bon_price_for, " +
|
||||||
|
$"{row["bon_ecommerce_status"] ?? "NULL"} as bon_ecommerce_status)");
|
||||||
|
|
||||||
|
var queryOptions = new QueryOptions { UseQueryCache = false };
|
||||||
|
await bigqueryClient.ExecuteQueryAsync(string.Format(upsertQuery, string.Join(", ", mergeValues)), null, queryOptions);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"PutDataBigQuery: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static BigQueryInsertRow ConvertToBigQueryInsertRow(JObject item)
|
||||||
|
{
|
||||||
|
BigQueryInsertRow insertRow = new BigQueryInsertRow();
|
||||||
|
insertRow.Add("bon_commodity_indexid", (string?)item["bon_commodity_indexid"]);
|
||||||
|
insertRow.Add("bon_cash_price", BigQueryNumeric.FromDecimal((decimal)item["bon_cash_price"]!, LossOfPrecisionHandling.Throw));
|
||||||
|
insertRow.Add("bon_categoriesid", (string?)item["bon_categoriesid"]);
|
||||||
|
insertRow.Add("transactioncurrencyid", (string?)item["transactioncurrencyid"]);
|
||||||
|
insertRow.Add("bon_warehouse_state_central", BigQueryNumeric.FromDecimal((decimal)item["bon_warehouse_state_central"]!, LossOfPrecisionHandling.Truncate));
|
||||||
|
insertRow.Add("bon_ec_name", (string?)item["bon_ec_name"]);
|
||||||
|
insertRow.Add("bon_ean", (string?)item["bon_ean"]);
|
||||||
|
insertRow.Add("bon_gid", (int?)item["bon_gid"]);
|
||||||
|
insertRow.Add("bon_index", (string?)item["bon_index"]);
|
||||||
|
insertRow.Add("bon_name", (string?)item["bon_name"]);
|
||||||
|
insertRow.Add("bon_url", (string?)item["bon_url"]);
|
||||||
|
insertRow.Add("bon_category_path", (string?)item["bon_category_path"]);
|
||||||
|
insertRow.Add("bon_seo_description", (string?)item["bon_seo_description"]);
|
||||||
|
insertRow.Add("bon_main_product_id", (string?)item["bon_main_product_id"]);
|
||||||
|
insertRow.Add("bon_slug_url", (string?)item["bon_slug_url"]);
|
||||||
|
insertRow.Add("bon_converter", BigQueryNumeric.FromDecimal((decimal)item["bon_converter"]!, LossOfPrecisionHandling.Truncate));
|
||||||
|
insertRow.Add("bon_vat_rate", (int?)item["bon_vat_rate"] ?? null);
|
||||||
|
insertRow.Add("bon_product_name", (string?)item["bon_product_name"]);
|
||||||
|
insertRow.Add("osa_gmc_id", (long?)item["osa_gmc_id"]);
|
||||||
|
insertRow.Add("bon_calculaltion_unit", (string?)item["bon_calculaltion_unit"]);
|
||||||
|
insertRow.Add("bon_marketplace",
|
||||||
|
item["bon_marketplace"] is JArray marketplaceArray
|
||||||
|
? string.Join(", ", marketplaceArray.Select(mp => mp["value"]?.ToString()))
|
||||||
|
: null);
|
||||||
|
insertRow.Add("bon_price_for",
|
||||||
|
item["bon_price_for"] is JObject priceForObject
|
||||||
|
? (int?)priceForObject["id"]
|
||||||
|
: null);
|
||||||
|
insertRow.Add("bon_ecommerce_status",
|
||||||
|
item["bon_ecommerce_status"] is JObject statusForObject
|
||||||
|
? (int?)statusForObject["id"]
|
||||||
|
: -1);
|
||||||
|
return insertRow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
using Migration.Services;
|
||||||
|
using Migration.Settings;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen();
|
||||||
|
builder.Services.AddSingleton<IBigQuery, GoogleBigQuery>();
|
||||||
|
builder.Services.Configure<MainSettings>(builder.Configuration.GetSection(MainSettings.ConfigName));
|
||||||
|
|
||||||
|
builder.Services.AddSingleton<IDataverseProvider, DataverseProvider>();
|
||||||
|
builder.Services.AddHttpClient(DataverseProvider.HTTP_CLIENT, DataverseProvider.Setup);
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
app.MapPut("/GetProducts", async (IBigQuery _bigQuery) =>
|
||||||
|
{
|
||||||
|
await _bigQuery.GetProducts();
|
||||||
|
})
|
||||||
|
.WithName("GetProducts");
|
||||||
|
|
||||||
|
app.Run();
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:33574",
|
||||||
|
"sslPort": 44377
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"http": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "http://localhost:5020",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"https": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "https://localhost:7027;http://localhost:5020",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
using Migration.Settings;
|
||||||
|
|
||||||
|
namespace Migration.Services
|
||||||
|
{
|
||||||
|
public interface IDataverseProvider
|
||||||
|
{
|
||||||
|
Uri Url { get; }
|
||||||
|
string Token { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Net.Mime;
|
||||||
|
using Migration.Settings;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Migration.Services;
|
||||||
|
|
||||||
|
public class DataverseProvider : IDataverseProvider
|
||||||
|
{
|
||||||
|
public const string HTTP_CLIENT = "FeedDataverseBQ";
|
||||||
|
|
||||||
|
private static readonly ProductInfoHeaderValue USER_AGENT = ProductInfoHeaderValue.Parse("FeedDataverseBQ");
|
||||||
|
private static readonly MediaTypeWithQualityHeaderValue JSON_MEDIA_TYPE = new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json);
|
||||||
|
public Uri Url { get; init; }
|
||||||
|
public string Token { get; init; }
|
||||||
|
|
||||||
|
public DataverseProvider(IOptions<MainSettings> mainSettingsOptions, IHttpClientFactory httpClientFactory)
|
||||||
|
{
|
||||||
|
var DataverseSettings = mainSettingsOptions.Value;
|
||||||
|
Url = new Uri(DataverseSettings.Url);
|
||||||
|
Token = DataverseSettings.Token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Setup(IServiceProvider serviceProvider, HttpClient httpClient)
|
||||||
|
{
|
||||||
|
var dataverseConnectionsProvider = serviceProvider.GetRequiredService<IDataverseProvider>();
|
||||||
|
httpClient.BaseAddress = dataverseConnectionsProvider.Url;
|
||||||
|
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", dataverseConnectionsProvider.Token);
|
||||||
|
httpClient.DefaultRequestHeaders.UserAgent.Add(USER_AGENT);
|
||||||
|
httpClient.DefaultRequestHeaders.Accept.Add(JSON_MEDIA_TYPE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DataverseDelegatingHandler : DelegatingHandler
|
||||||
|
{
|
||||||
|
protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return SendAsync(request, cancellationToken).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return await base.SendAsync(request, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Migration.Settings
|
||||||
|
{
|
||||||
|
public class MainSettings
|
||||||
|
{
|
||||||
|
internal const string ConfigName = "Dataverse";
|
||||||
|
public string Url { get; set; } = null!;
|
||||||
|
public string Token { get; set; } = null!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"GoogleCredentialFile": "osadkowski-hd-2f3bd9b0ab5d.json",
|
||||||
|
"Dataverse": {
|
||||||
|
"Url": "",
|
||||||
|
"Token": ""
|
||||||
|
},
|
||||||
|
"BigQuery": {
|
||||||
|
"ProjectId": "",
|
||||||
|
"DbName": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.14" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Google.Cloud.BigQuery.V2" Version="3.11.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
Loading…
Reference in New Issue