Add project files.
This commit is contained in:
parent
7fd695f5c4
commit
de36f710df
25
OdooAPI.sln
Normal file
25
OdooAPI.sln
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.14.36623.8 d17.14
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OdooAPI", "OdooAPI\OdooAPI.csproj", "{AC50ACEB-8209-4330-B8BA-DB84922F8226}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{AC50ACEB-8209-4330-B8BA-DB84922F8226}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AC50ACEB-8209-4330-B8BA-DB84922F8226}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AC50ACEB-8209-4330-B8BA-DB84922F8226}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{AC50ACEB-8209-4330-B8BA-DB84922F8226}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {B1E1DA3F-BBFA-44B2-9C16-F05361CE4C27}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
7
OdooAPI/DataAccess/Odoo/Dtos/OdooProductDto.cs
Normal file
7
OdooAPI/DataAccess/Odoo/Dtos/OdooProductDto.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace OdooAPI.DataAccess.Odoo.Dtos;
|
||||||
|
|
||||||
|
public class OdooProductDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string DefaultCode { get; set; } = "";
|
||||||
|
}
|
||||||
10
OdooAPI/DataAccess/Odoo/Dtos/OdooSupplierDto.cs
Normal file
10
OdooAPI/DataAccess/Odoo/Dtos/OdooSupplierDto.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace OdooAPI.DataAccess.Odoo.Dtos;
|
||||||
|
|
||||||
|
public class OdooSupplierDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public int PartnerId { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
}
|
||||||
63
OdooAPI/DataAccess/Odoo/OdooLogin.cs
Normal file
63
OdooAPI/DataAccess/Odoo/OdooLogin.cs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace OdooAPI.DataAccess.Odoo;
|
||||||
|
|
||||||
|
public class OdooLogin
|
||||||
|
{
|
||||||
|
private const string Url = "https://odooapi1.odoo.com/jsonrpc";
|
||||||
|
|
||||||
|
private const string Database = "odooapi1";
|
||||||
|
private const string Username = "luca@corsie.nl";
|
||||||
|
private const string Password = "XS82ns23!";
|
||||||
|
|
||||||
|
private readonly HttpClient _http;
|
||||||
|
|
||||||
|
public OdooLogin(HttpClient http)
|
||||||
|
{
|
||||||
|
_http = http;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int?> LoginAsync()
|
||||||
|
{
|
||||||
|
var payload = new
|
||||||
|
{
|
||||||
|
jsonrpc = "2.0",
|
||||||
|
method = "call",
|
||||||
|
id = 1,
|
||||||
|
@params = new
|
||||||
|
{
|
||||||
|
service = "common",
|
||||||
|
method = "login",
|
||||||
|
args = new object[]
|
||||||
|
{
|
||||||
|
Database,
|
||||||
|
Username,
|
||||||
|
Password
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var content = new StringContent(
|
||||||
|
JsonSerializer.Serialize(payload),
|
||||||
|
Encoding.UTF8,
|
||||||
|
"application/json");
|
||||||
|
|
||||||
|
var response = await _http.PostAsync(Url, content);
|
||||||
|
|
||||||
|
var json = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
Console.WriteLine("LOGIN RESPONSE:");
|
||||||
|
Console.WriteLine(json);
|
||||||
|
|
||||||
|
using var doc = JsonDocument.Parse(json);
|
||||||
|
|
||||||
|
if (!doc.RootElement.TryGetProperty("result", out var result))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return result.ValueKind == JsonValueKind.Number
|
||||||
|
? result.GetInt32()
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
249
OdooAPI/DataAccess/Odoo/Repositories/OdooProductRepository.cs
Normal file
249
OdooAPI/DataAccess/Odoo/Repositories/OdooProductRepository.cs
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace OdooAPI.DataAccess.Odoo.Repositories;
|
||||||
|
|
||||||
|
public class OdooProductRepository
|
||||||
|
{
|
||||||
|
private readonly HttpClient _http;
|
||||||
|
|
||||||
|
private const string Url = "https://odooapi1.odoo.com/jsonrpc";
|
||||||
|
private const string Database = "odooapi1";
|
||||||
|
private const string Username = "luca@corsie.nl";
|
||||||
|
private const string Password = "XS82ns23!";
|
||||||
|
|
||||||
|
private int _uid;
|
||||||
|
|
||||||
|
// ================================
|
||||||
|
// PROPERTY (fix voor jouw error)
|
||||||
|
// ================================
|
||||||
|
public int Uid => _uid;
|
||||||
|
|
||||||
|
public OdooProductRepository(HttpClient http)
|
||||||
|
{
|
||||||
|
_http = http;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================
|
||||||
|
// LOGIN
|
||||||
|
// =========================================
|
||||||
|
public async Task LoginAsync()
|
||||||
|
{
|
||||||
|
var result = await CallAsync(
|
||||||
|
"common",
|
||||||
|
"login",
|
||||||
|
new object[] { Database, Username, Password });
|
||||||
|
|
||||||
|
_uid = result.GetInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================
|
||||||
|
// PRODUCTEN OPHALEN (fix voor jouw error)
|
||||||
|
// =========================================
|
||||||
|
public async Task<List<string>> GetAllProductsAsync()
|
||||||
|
{
|
||||||
|
var result = await CallAsync(
|
||||||
|
"object",
|
||||||
|
"execute_kw",
|
||||||
|
new object[]
|
||||||
|
{
|
||||||
|
Database, _uid, Password,
|
||||||
|
"product.product",
|
||||||
|
"search_read",
|
||||||
|
new object[] { new object[] { } }
|
||||||
|
},
|
||||||
|
new { fields = new[] { "default_code" } }
|
||||||
|
);
|
||||||
|
|
||||||
|
var list = new List<string>();
|
||||||
|
|
||||||
|
foreach (var p in result.EnumerateArray())
|
||||||
|
{
|
||||||
|
if (p.TryGetProperty("default_code", out var code) &&
|
||||||
|
code.ValueKind == JsonValueKind.String)
|
||||||
|
{
|
||||||
|
list.Add(code.GetString()!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================
|
||||||
|
// UPSERT SUPPLIER (CREATE of UPDATE)
|
||||||
|
// =========================================
|
||||||
|
public async Task UpsertSupplierAsync(
|
||||||
|
string defaultCode,
|
||||||
|
string supplierName,
|
||||||
|
string leverancierProductCode,
|
||||||
|
decimal price,
|
||||||
|
int delay)
|
||||||
|
{
|
||||||
|
var partnerId = await GetPartnerIdAsync(supplierName);
|
||||||
|
if (partnerId == null)
|
||||||
|
throw new Exception($"Supplier '{supplierName}' niet gevonden.");
|
||||||
|
|
||||||
|
// product template ophalen (VERPLICHT in Odoo)
|
||||||
|
var tmplId = await GetProductTemplateIdAsync(defaultCode);
|
||||||
|
if (tmplId == null)
|
||||||
|
throw new Exception($"Product template niet gevonden voor {defaultCode}");
|
||||||
|
|
||||||
|
var existingId =
|
||||||
|
await GetExistingSupplierInfoId(partnerId.Value, leverancierProductCode);
|
||||||
|
|
||||||
|
var values = new
|
||||||
|
{
|
||||||
|
partner_id = partnerId,
|
||||||
|
product_tmpl_id = tmplId, // ⭐ BELANGRIJKSTE FIX
|
||||||
|
product_code = leverancierProductCode,
|
||||||
|
price = price,
|
||||||
|
delay = delay,
|
||||||
|
product_uom_id = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
if (existingId != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine(" ␦ UPDATE in Odoo");
|
||||||
|
|
||||||
|
await CallAsync(
|
||||||
|
"object",
|
||||||
|
"execute_kw",
|
||||||
|
new object[]
|
||||||
|
{
|
||||||
|
Database,_uid,Password,
|
||||||
|
"product.supplierinfo",
|
||||||
|
"write",
|
||||||
|
new object[] { new [] { existingId }, values }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine(" ␦ CREATE in Odoo");
|
||||||
|
|
||||||
|
await CallAsync(
|
||||||
|
"object",
|
||||||
|
"execute_kw",
|
||||||
|
new object[]
|
||||||
|
{
|
||||||
|
Database,_uid,Password,
|
||||||
|
"product.supplierinfo",
|
||||||
|
"create",
|
||||||
|
new object[] { values }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================
|
||||||
|
// TEMPLATE ID (nieuw – verplicht)
|
||||||
|
// =========================================
|
||||||
|
private async Task<int?> GetProductTemplateIdAsync(string defaultCode)
|
||||||
|
{
|
||||||
|
var result = await CallAsync(
|
||||||
|
"object",
|
||||||
|
"execute_kw",
|
||||||
|
new object[]
|
||||||
|
{
|
||||||
|
Database,_uid,Password,
|
||||||
|
"product.product",
|
||||||
|
"search_read",
|
||||||
|
new object[]
|
||||||
|
{
|
||||||
|
new object[]
|
||||||
|
{
|
||||||
|
new object[] { "default_code", "=", defaultCode }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new { fields = new[] { "product_tmpl_id" }, limit = 1 }
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach (var r in result.EnumerateArray())
|
||||||
|
{
|
||||||
|
return r.GetProperty("product_tmpl_id")[0].GetInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<int?> GetExistingSupplierInfoId(int partnerId, string code)
|
||||||
|
{
|
||||||
|
var result = await CallAsync(
|
||||||
|
"object",
|
||||||
|
"execute_kw",
|
||||||
|
new object[]
|
||||||
|
{
|
||||||
|
Database,_uid,Password,
|
||||||
|
"product.supplierinfo",
|
||||||
|
"search",
|
||||||
|
new object[]
|
||||||
|
{
|
||||||
|
new object[]
|
||||||
|
{
|
||||||
|
new object[] { "partner_id", "=", partnerId },
|
||||||
|
new object[] { "product_code", "=", code }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var ids = result.EnumerateArray().ToList();
|
||||||
|
|
||||||
|
return ids.Count == 0 ? null : ids[0].GetInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<int?> GetPartnerIdAsync(string name)
|
||||||
|
{
|
||||||
|
var result = await CallAsync(
|
||||||
|
"object",
|
||||||
|
"execute_kw",
|
||||||
|
new object[]
|
||||||
|
{
|
||||||
|
Database,_uid,Password,
|
||||||
|
"res.partner",
|
||||||
|
"search",
|
||||||
|
new object[]
|
||||||
|
{
|
||||||
|
new object[]
|
||||||
|
{
|
||||||
|
new object[] { "name", "=", name }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var ids = result.EnumerateArray().ToList();
|
||||||
|
|
||||||
|
return ids.Count == 0 ? null : ids[0].GetInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================
|
||||||
|
// CORE JSON RPC
|
||||||
|
// =========================================
|
||||||
|
private async Task<JsonElement> CallAsync(
|
||||||
|
string service,
|
||||||
|
string method,
|
||||||
|
object[] args,
|
||||||
|
object? kwargs = null)
|
||||||
|
{
|
||||||
|
var payload = new
|
||||||
|
{
|
||||||
|
jsonrpc = "2.0",
|
||||||
|
method = "call",
|
||||||
|
id = 1,
|
||||||
|
@params = new { service, method, args, kwargs }
|
||||||
|
};
|
||||||
|
|
||||||
|
var json = JsonSerializer.Serialize(payload);
|
||||||
|
|
||||||
|
var response = await _http.PostAsync(
|
||||||
|
Url,
|
||||||
|
new StringContent(json, Encoding.UTF8, "application/json"));
|
||||||
|
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
using var doc = JsonDocument.Parse(content);
|
||||||
|
|
||||||
|
if (doc.RootElement.TryGetProperty("error", out var error))
|
||||||
|
throw new Exception(error.ToString());
|
||||||
|
|
||||||
|
return doc.RootElement.GetProperty("result").Clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
OdooAPI/DataAccess/Repositories/ArtikelRepository.cs
Normal file
15
OdooAPI/DataAccess/Repositories/ArtikelRepository.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using OdooAPI.Database;
|
||||||
|
|
||||||
|
public class ArtikelRepository
|
||||||
|
{
|
||||||
|
public async Task<List<string>> GetSupplierNamesAsync(int artikelId)
|
||||||
|
{
|
||||||
|
using var db = new AppDbContext();
|
||||||
|
|
||||||
|
return await db.LevArtikelen
|
||||||
|
.Where(x => x.ArtikelId == artikelId)
|
||||||
|
.Select(x => x.Leverancier.Naam)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
32
OdooAPI/DataAccess/Repositories/LevArtikelRepository.cs
Normal file
32
OdooAPI/DataAccess/Repositories/LevArtikelRepository.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using OdooAPI.Database;
|
||||||
|
using OdooAPI.Database.Tabellen;
|
||||||
|
|
||||||
|
namespace OdooAPI.DataAccess.Repositories;
|
||||||
|
|
||||||
|
public class LevArtikelRepository
|
||||||
|
{
|
||||||
|
private readonly AppDbContext _db;
|
||||||
|
|
||||||
|
public LevArtikelRepository(AppDbContext db)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<(int, int), LevArtikel> GetAllLookup()
|
||||||
|
{
|
||||||
|
return _db.LevArtikelen
|
||||||
|
.AsNoTracking()
|
||||||
|
.ToDictionary(x => (x.LeverancierId, x.ArtikelId), x => x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRange(List<LevArtikel> items)
|
||||||
|
{
|
||||||
|
_db.LevArtikelen.AddRange(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateRange(List<LevArtikel> items)
|
||||||
|
{
|
||||||
|
_db.LevArtikelen.UpdateRange(items);
|
||||||
|
}
|
||||||
|
}
|
||||||
27
OdooAPI/DataAccess/Repositories/LeverancierRepository.cs
Normal file
27
OdooAPI/DataAccess/Repositories/LeverancierRepository.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using OdooAPI.Database;
|
||||||
|
using OdooAPI.Database.Tabellen;
|
||||||
|
|
||||||
|
namespace OdooAPI.DataAccess.Repositories;
|
||||||
|
|
||||||
|
public class LeverancierRepository
|
||||||
|
{
|
||||||
|
private readonly AppDbContext _db;
|
||||||
|
|
||||||
|
public LeverancierRepository(AppDbContext db)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Leverancier? GetByNaam(string naam)
|
||||||
|
{
|
||||||
|
return _db.Leveranciers.FirstOrDefault(x => x.Naam == naam);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Leverancier Add(string naam)
|
||||||
|
{
|
||||||
|
var lev = new Leverancier { Naam = naam };
|
||||||
|
_db.Leveranciers.Add(lev);
|
||||||
|
return lev;
|
||||||
|
}
|
||||||
|
}
|
||||||
10
OdooAPI/DataAccess/Xml/XmlItemDto.cs
Normal file
10
OdooAPI/DataAccess/Xml/XmlItemDto.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace OdooAPI.DataAccess.Xml;
|
||||||
|
|
||||||
|
public class XmlItemDto
|
||||||
|
{
|
||||||
|
public string VendorId { get; set; } = "";
|
||||||
|
public string Naam { get; set; } = "";
|
||||||
|
public decimal Prijs { get; set; }
|
||||||
|
public int Stock { get; set; }
|
||||||
|
public string? Ean { get; set; }
|
||||||
|
}
|
||||||
32
OdooAPI/DataAccess/Xml/XmlItemMapper.cs
Normal file
32
OdooAPI/DataAccess/Xml/XmlItemMapper.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using OdooAPI.Database.Tabellen;
|
||||||
|
|
||||||
|
namespace OdooAPI.DataAccess.Xml;
|
||||||
|
|
||||||
|
public class XmlItemMapper
|
||||||
|
{
|
||||||
|
public Artikel MapToArtikel(XmlItemDto dto)
|
||||||
|
{
|
||||||
|
return new Artikel
|
||||||
|
{
|
||||||
|
ArtikelNummer = dto.VendorId,
|
||||||
|
Naam = dto.Naam,
|
||||||
|
Ean = dto.Ean,
|
||||||
|
InOdoo = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public LevArtikel MapToLevArtikel(XmlItemDto dto, int leverancierId, int artikelId)
|
||||||
|
{
|
||||||
|
return new LevArtikel
|
||||||
|
{
|
||||||
|
LeverancierId = leverancierId,
|
||||||
|
ArtikelId = artikelId,
|
||||||
|
ArtikelNummerLev = dto.VendorId,
|
||||||
|
Inkoopprijs = dto.Prijs,
|
||||||
|
Levertijd = 1,
|
||||||
|
Omschrijving = "",
|
||||||
|
Leverbaar = dto.Stock > 0,
|
||||||
|
Korting = null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
38
OdooAPI/DataAccess/Xml/XmlSupplierReader.cs
Normal file
38
OdooAPI/DataAccess/Xml/XmlSupplierReader.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using System.Xml.Linq;
|
||||||
|
using OdooAPI.Services.Helpers;
|
||||||
|
|
||||||
|
namespace OdooAPI.DataAccess.Xml;
|
||||||
|
|
||||||
|
public class XmlSupplierReader
|
||||||
|
{
|
||||||
|
public List<XmlItemDto> ReadFolder(string supplierFolder)
|
||||||
|
{
|
||||||
|
var result = new List<XmlItemDto>();
|
||||||
|
|
||||||
|
var files = Directory.GetFiles(supplierFolder, "*.xml");
|
||||||
|
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
result.AddRange(ReadFile(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<XmlItemDto> ReadFile(string filePath)
|
||||||
|
{
|
||||||
|
var doc = XDocument.Load(filePath);
|
||||||
|
|
||||||
|
foreach (var item in doc.Descendants("item"))
|
||||||
|
{
|
||||||
|
yield return new XmlItemDto
|
||||||
|
{
|
||||||
|
VendorId = item.Element("vendor_id")?.Value ?? "",
|
||||||
|
Naam = item.Element("long_desc")?.Value ?? "",
|
||||||
|
Prijs = DecimalHelper.Parse(item.Element("price")?.Value),
|
||||||
|
Stock = int.TryParse(item.Element("stock")?.Value, out var s) ? s : 0,
|
||||||
|
Ean = item.Element("EAN_code")?.Value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
OdooAPI/Database/AppDbContext.cs
Normal file
41
OdooAPI/Database/AppDbContext.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using OdooAPI.Database.Tabellen;
|
||||||
|
|
||||||
|
namespace OdooAPI.Database;
|
||||||
|
|
||||||
|
public class AppDbContext : DbContext
|
||||||
|
{
|
||||||
|
public DbSet<Artikel> Artikelen => Set<Artikel>();
|
||||||
|
public DbSet<Leverancier> Leveranciers => Set<Leverancier>();
|
||||||
|
public DbSet<LevArtikel> LevArtikelen => Set<LevArtikel>();
|
||||||
|
public DbSet<Marge> Marges => Set<Marge>();
|
||||||
|
|
||||||
|
protected override void OnConfiguring(DbContextOptionsBuilder options)
|
||||||
|
{
|
||||||
|
var path = Path.Combine(AppContext.BaseDirectory, "database.db");
|
||||||
|
options.UseSqlite($"Data Source={path}");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder.Entity<Artikel>()
|
||||||
|
.HasIndex(x => x.ArtikelNummer)
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
modelBuilder.Entity<LevArtikel>()
|
||||||
|
.HasIndex(x => new { x.LeverancierId, x.ArtikelId })
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
modelBuilder.Entity<LevArtikel>()
|
||||||
|
.HasOne(x => x.Artikel)
|
||||||
|
.WithMany(x => x.LevArtikelen)
|
||||||
|
.HasForeignKey(x => x.ArtikelId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
modelBuilder.Entity<LevArtikel>()
|
||||||
|
.HasOne(x => x.Leverancier)
|
||||||
|
.WithMany(x => x.LevArtikelen)
|
||||||
|
.HasForeignKey(x => x.LeverancierId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
}
|
||||||
|
}
|
||||||
21
OdooAPI/Database/ArtikelRepository.cs
Normal file
21
OdooAPI/Database/ArtikelRepository.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace OdooAPI.Database;
|
||||||
|
|
||||||
|
public class ArtikelRepository
|
||||||
|
{
|
||||||
|
private readonly AppDbContext _db;
|
||||||
|
|
||||||
|
public ArtikelRepository(AppDbContext db)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<string>> GetAllArtikelNummersAsync()
|
||||||
|
{
|
||||||
|
return await _db.Artikelen
|
||||||
|
.Where(a => a.ArtikelNummer != null)
|
||||||
|
.Select(a => a.ArtikelNummer!)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
10
OdooAPI/Database/DbInitializer.cs
Normal file
10
OdooAPI/Database/DbInitializer.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace OdooAPI.Database;
|
||||||
|
|
||||||
|
public static class DbInitializer
|
||||||
|
{
|
||||||
|
public static void Initialize()
|
||||||
|
{
|
||||||
|
using var db = new AppDbContext();
|
||||||
|
db.Database.EnsureCreated();
|
||||||
|
}
|
||||||
|
}
|
||||||
16
OdooAPI/Database/Tabellen/Artkel.cs
Normal file
16
OdooAPI/Database/Tabellen/Artkel.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
namespace OdooAPI.Database.Tabellen;
|
||||||
|
|
||||||
|
public class Artikel
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public string Naam { get; set; } = "";
|
||||||
|
|
||||||
|
public string ArtikelNummer { get; set; } = "";
|
||||||
|
|
||||||
|
public string? Ean { get; set; }
|
||||||
|
|
||||||
|
public bool InOdoo { get; set; }
|
||||||
|
|
||||||
|
public List<LevArtikel> LevArtikelen { get; set; } = new();
|
||||||
|
}
|
||||||
24
OdooAPI/Database/Tabellen/LevArtikel.cs
Normal file
24
OdooAPI/Database/Tabellen/LevArtikel.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
namespace OdooAPI.Database.Tabellen;
|
||||||
|
|
||||||
|
public class LevArtikel
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public int LeverancierId { get; set; }
|
||||||
|
public Leverancier Leverancier { get; set; } = null!;
|
||||||
|
|
||||||
|
public int ArtikelId { get; set; }
|
||||||
|
public Artikel Artikel { get; set; } = null!;
|
||||||
|
|
||||||
|
public string ArtikelNummerLev { get; set; } = "";
|
||||||
|
|
||||||
|
public decimal Inkoopprijs { get; set; }
|
||||||
|
|
||||||
|
public int Levertijd { get; set; } = 1;
|
||||||
|
|
||||||
|
public string Omschrijving { get; set; } = "";
|
||||||
|
|
||||||
|
public bool Leverbaar { get; set; }
|
||||||
|
|
||||||
|
public decimal? Korting { get; set; }
|
||||||
|
}
|
||||||
10
OdooAPI/Database/Tabellen/Leverancier.cs
Normal file
10
OdooAPI/Database/Tabellen/Leverancier.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace OdooAPI.Database.Tabellen;
|
||||||
|
|
||||||
|
public class Leverancier
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public string Naam { get; set; } = "";
|
||||||
|
|
||||||
|
public List<LevArtikel> LevArtikelen { get; set; } = new();
|
||||||
|
}
|
||||||
10
OdooAPI/Database/Tabellen/Marge.cs
Normal file
10
OdooAPI/Database/Tabellen/Marge.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace OdooAPI.Database.Tabellen;
|
||||||
|
|
||||||
|
public class Marge
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public int ArtikelId { get; set; }
|
||||||
|
|
||||||
|
public decimal Percentage { get; set; }
|
||||||
|
}
|
||||||
12
OdooAPI/Import/OdooSycnProcessor.cs
Normal file
12
OdooAPI/Import/OdooSycnProcessor.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace OdooAPI.Import
|
||||||
|
{
|
||||||
|
internal class OdooSycnProcessor
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
119
OdooAPI/Import/SupplierImportProcessor.cs
Normal file
119
OdooAPI/Import/SupplierImportProcessor.cs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
using OdooAPI.Database;
|
||||||
|
using OdooAPI.Database.Tabellen;
|
||||||
|
using OdooAPI.DataAccess.Xml;
|
||||||
|
|
||||||
|
namespace OdooAPI.Import;
|
||||||
|
|
||||||
|
public class SupplierImportProcessor
|
||||||
|
{
|
||||||
|
private readonly AppDbContext _db;
|
||||||
|
|
||||||
|
public SupplierImportProcessor(AppDbContext db)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Process(string supplierFolder)
|
||||||
|
{
|
||||||
|
var supplierName = Path.GetFileName(supplierFolder);
|
||||||
|
|
||||||
|
Console.WriteLine($"Start import: {supplierName}");
|
||||||
|
|
||||||
|
var leverancier = _db.Leveranciers
|
||||||
|
.FirstOrDefault(x => x.Naam == supplierName);
|
||||||
|
|
||||||
|
if (leverancier == null)
|
||||||
|
{
|
||||||
|
leverancier = new Leverancier { Naam = supplierName };
|
||||||
|
_db.Leveranciers.Add(leverancier);
|
||||||
|
_db.SaveChanges();
|
||||||
|
Console.WriteLine("Nieuwe leverancier aangemaakt");
|
||||||
|
}
|
||||||
|
|
||||||
|
var reader = new XmlSupplierReader();
|
||||||
|
var items = reader.ReadFolder(supplierFolder);
|
||||||
|
|
||||||
|
Console.WriteLine($"XML items gevonden: {items.Count}");
|
||||||
|
|
||||||
|
var bestaandeArtikelen = _db.Artikelen
|
||||||
|
.ToDictionary(x => x.ArtikelNummer);
|
||||||
|
|
||||||
|
int nieuweArtikelen = 0;
|
||||||
|
|
||||||
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
if (!bestaandeArtikelen.ContainsKey(item.VendorId))
|
||||||
|
{
|
||||||
|
var artikel = new Artikel
|
||||||
|
{
|
||||||
|
Naam = item.Naam,
|
||||||
|
ArtikelNummer = item.VendorId,
|
||||||
|
Ean = item.Ean,
|
||||||
|
InOdoo = false
|
||||||
|
};
|
||||||
|
|
||||||
|
_db.Artikelen.Add(artikel);
|
||||||
|
bestaandeArtikelen[item.VendorId] = artikel;
|
||||||
|
|
||||||
|
nieuweArtikelen++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_db.SaveChanges();
|
||||||
|
|
||||||
|
Console.WriteLine($"Nieuwe artikelen: {nieuweArtikelen}");
|
||||||
|
|
||||||
|
var bestaandeLevArtikelen = _db.LevArtikelen
|
||||||
|
.Where(x => x.LeverancierId == leverancier.Id)
|
||||||
|
.ToDictionary(x => x.ArtikelId);
|
||||||
|
|
||||||
|
var gezienArtikelIds = new HashSet<int>();
|
||||||
|
|
||||||
|
int nieuweLev = 0;
|
||||||
|
int updates = 0;
|
||||||
|
|
||||||
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
var artikel = bestaandeArtikelen[item.VendorId];
|
||||||
|
|
||||||
|
if (!bestaandeLevArtikelen.TryGetValue(artikel.Id, out var levArtikel))
|
||||||
|
{
|
||||||
|
levArtikel = new LevArtikel
|
||||||
|
{
|
||||||
|
LeverancierId = leverancier.Id,
|
||||||
|
ArtikelId = artikel.Id,
|
||||||
|
ArtikelNummerLev = item.VendorId,
|
||||||
|
Inkoopprijs = item.Prijs,
|
||||||
|
Levertijd = 1,
|
||||||
|
Leverbaar = true,
|
||||||
|
Omschrijving = "",
|
||||||
|
Korting = null
|
||||||
|
};
|
||||||
|
|
||||||
|
_db.LevArtikelen.Add(levArtikel);
|
||||||
|
nieuweLev++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
levArtikel.Inkoopprijs = item.Prijs;
|
||||||
|
levArtikel.Leverbaar = true;
|
||||||
|
updates++;
|
||||||
|
}
|
||||||
|
|
||||||
|
gezienArtikelIds.Add(artikel.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var lev in bestaandeLevArtikelen.Values)
|
||||||
|
{
|
||||||
|
if (!gezienArtikelIds.Contains(lev.ArtikelId))
|
||||||
|
lev.Leverbaar = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_db.SaveChanges();
|
||||||
|
|
||||||
|
Console.WriteLine($"Nieuwe leverancier-artikelen: {nieuweLev}");
|
||||||
|
Console.WriteLine($"Updates: {updates}");
|
||||||
|
Console.WriteLine($"Klaar met: {supplierName}");
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
19
OdooAPI/Import/XMLImportRunner.cs
Normal file
19
OdooAPI/Import/XMLImportRunner.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using OdooAPI.Database;
|
||||||
|
|
||||||
|
namespace OdooAPI.Import;
|
||||||
|
|
||||||
|
public class XmlImportRunner
|
||||||
|
{
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
using var db = new AppDbContext();
|
||||||
|
|
||||||
|
|
||||||
|
db.Database.EnsureCreated();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var importer = new XmlImporter(db);
|
||||||
|
importer.Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
41
OdooAPI/Import/XmlImporter.cs
Normal file
41
OdooAPI/Import/XmlImporter.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using OdooAPI.Database;
|
||||||
|
using OdooAPI.Services;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace OdooAPI.Import;
|
||||||
|
|
||||||
|
public class XmlImporter
|
||||||
|
{
|
||||||
|
private readonly AppDbContext _db;
|
||||||
|
|
||||||
|
public XmlImporter(AppDbContext db)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
var baseDir = Path.Combine(AppContext.BaseDirectory, "Leveranciers");
|
||||||
|
|
||||||
|
Console.WriteLine($"Zoeken naar leveranciers in: {baseDir}");
|
||||||
|
|
||||||
|
if (!Directory.Exists(baseDir))
|
||||||
|
{
|
||||||
|
Console.WriteLine("Leveranciers map niet gevonden");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var scanner = new LeverancierScanner();
|
||||||
|
var supplierFolders = scanner.GetSupplierFolders(baseDir);
|
||||||
|
|
||||||
|
foreach (var folder in supplierFolders)
|
||||||
|
{
|
||||||
|
var name = Path.GetFileName(folder);
|
||||||
|
|
||||||
|
Console.WriteLine($"Leverancier gevonden: {name}");
|
||||||
|
|
||||||
|
var processor = new SupplierImportProcessor(_db);
|
||||||
|
processor.Process(folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
OdooAPI/OdooAPI.csproj
Normal file
20
OdooAPI/OdooAPI.csproj
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.23" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.23" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.23">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
44
OdooAPI/Program.cs
Normal file
44
OdooAPI/Program.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using OdooAPI.Import;
|
||||||
|
using OdooAPI.Services;
|
||||||
|
|
||||||
|
internal class Program
|
||||||
|
{
|
||||||
|
static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// =====================================
|
||||||
|
// 1️⃣ XML IMPORT
|
||||||
|
// =====================================
|
||||||
|
Console.WriteLine("=================================");
|
||||||
|
Console.WriteLine("XML IMPORT START");
|
||||||
|
Console.WriteLine("=================================");
|
||||||
|
|
||||||
|
var xml = new XmlImportRunner();
|
||||||
|
xml.Run();
|
||||||
|
|
||||||
|
Console.WriteLine("XML IMPORT KLAAR\n");
|
||||||
|
|
||||||
|
|
||||||
|
// =====================================
|
||||||
|
// 2️⃣ ODOO SYNC
|
||||||
|
// =====================================
|
||||||
|
Console.WriteLine("=================================");
|
||||||
|
Console.WriteLine("ODOO SYNC START");
|
||||||
|
Console.WriteLine("=================================");
|
||||||
|
|
||||||
|
var app = new OdooSyncApp();
|
||||||
|
await app.RunAsync();
|
||||||
|
|
||||||
|
Console.WriteLine("\nKlaar.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("\nFOUT:");
|
||||||
|
Console.WriteLine(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("\nDruk op een toets om te sluiten...");
|
||||||
|
Console.ReadKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
13
OdooAPI/Services/ArtikelMatcher.cs
Normal file
13
OdooAPI/Services/ArtikelMatcher.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
namespace OdooAPI.Services;
|
||||||
|
|
||||||
|
public class ArtikelMatcher
|
||||||
|
{
|
||||||
|
public bool IsMatch(string artikelNummerA, string artikelNummerB)
|
||||||
|
{
|
||||||
|
return string.Equals(
|
||||||
|
artikelNummerA?.Trim(),
|
||||||
|
artikelNummerB?.Trim(),
|
||||||
|
StringComparison.OrdinalIgnoreCase
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
OdooAPI/Services/AvailabilityRules.cs
Normal file
9
OdooAPI/Services/AvailabilityRules.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace OdooAPI.Services;
|
||||||
|
|
||||||
|
public static class AvailabilityRules
|
||||||
|
{
|
||||||
|
public static bool IsAvailable(int stock)
|
||||||
|
{
|
||||||
|
return stock > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
OdooAPI/Services/EanValidator.cs
Normal file
12
OdooAPI/Services/EanValidator.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace OdooAPI.Services;
|
||||||
|
|
||||||
|
public static class EanValidator
|
||||||
|
{
|
||||||
|
public static bool IsValid(string? ean)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(ean))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return ean.All(char.IsDigit);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
OdooAPI/Services/Helpers/DecimalHelper.cs
Normal file
18
OdooAPI/Services/Helpers/DecimalHelper.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace OdooAPI.Services.Helpers;
|
||||||
|
|
||||||
|
public static class DecimalHelper
|
||||||
|
{
|
||||||
|
public static decimal Parse(string? value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(value))
|
||||||
|
return 0m;
|
||||||
|
|
||||||
|
value = value.Replace(",", ".");
|
||||||
|
|
||||||
|
decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
9
OdooAPI/Services/Helpers/Keybuilder.cs
Normal file
9
OdooAPI/Services/Helpers/Keybuilder.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace OdooAPI.Services.Helpers;
|
||||||
|
|
||||||
|
public static class Keybuilder
|
||||||
|
{
|
||||||
|
public static string Build(string leverancier, string artikelNummer)
|
||||||
|
{
|
||||||
|
return $"{leverancier}_{artikelNummer}".ToLowerInvariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
12
OdooAPI/Services/Helpers/Normalizer.cs
Normal file
12
OdooAPI/Services/Helpers/Normalizer.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace OdooAPI.Services.Helpers;
|
||||||
|
|
||||||
|
public static class Normalizer
|
||||||
|
{
|
||||||
|
public static string Clean(string? value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(value))
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
return value.Trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
14
OdooAPI/Services/LeverancierScanner.cs
Normal file
14
OdooAPI/Services/LeverancierScanner.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace OdooAPI.Services;
|
||||||
|
|
||||||
|
public class LeverancierScanner
|
||||||
|
{
|
||||||
|
public IEnumerable<string> GetSupplierFolders(string baseDir)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(baseDir))
|
||||||
|
return Enumerable.Empty<string>();
|
||||||
|
|
||||||
|
return Directory.GetDirectories(baseDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
OdooAPI/Services/MatchResult.cs
Normal file
12
OdooAPI/Services/MatchResult.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace OdooAPI.Services
|
||||||
|
{
|
||||||
|
internal class MatchResult
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
57
OdooAPI/Services/OdooSyncApp.cs
Normal file
57
OdooAPI/Services/OdooSyncApp.cs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
using OdooAPI.DataAccess.Odoo.Repositories;
|
||||||
|
using OdooAPI.Database;
|
||||||
|
|
||||||
|
namespace OdooAPI.Services;
|
||||||
|
|
||||||
|
public class OdooSyncApp
|
||||||
|
{
|
||||||
|
public async Task RunAsync()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Inloggen in Odoo...");
|
||||||
|
|
||||||
|
var http = new HttpClient();
|
||||||
|
var repo = new OdooProductRepository(http);
|
||||||
|
|
||||||
|
await repo.LoginAsync();
|
||||||
|
|
||||||
|
Console.WriteLine($"Ingelogd bij Odoo (UID = {repo.Uid})");
|
||||||
|
|
||||||
|
// =========================================
|
||||||
|
// PRODUCTEN OPHALEN
|
||||||
|
// =========================================
|
||||||
|
|
||||||
|
Console.WriteLine("\nProducten ophalen...");
|
||||||
|
|
||||||
|
var odooProducts = await repo.GetAllProductsAsync(); // List<string>
|
||||||
|
|
||||||
|
Console.WriteLine($"Odoo producten: {odooProducts.Count}");
|
||||||
|
|
||||||
|
var db = new AppDbContext();
|
||||||
|
|
||||||
|
var localCodes = db.LevArtikelen
|
||||||
|
.Select(x => x.ArtikelNummerLev)
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
Console.WriteLine($"Database producten: {localCodes.Count}");
|
||||||
|
|
||||||
|
// ✅ BELANGRIJK: strings vergelijken (GEEN DefaultCode meer!)
|
||||||
|
var matches = odooProducts
|
||||||
|
.Where(code => localCodes.Contains(code))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
Console.WriteLine($"Matches: {matches.Count}");
|
||||||
|
|
||||||
|
// =========================================
|
||||||
|
// SUPPLIER MATCHING
|
||||||
|
// =========================================
|
||||||
|
|
||||||
|
Console.WriteLine("\nSUPPLIER MATCHING");
|
||||||
|
|
||||||
|
var supplierMatch = new SupplierMatchService(db, repo);
|
||||||
|
|
||||||
|
await supplierMatch.RunAsync(matches);
|
||||||
|
|
||||||
|
Console.WriteLine("Klaar.");
|
||||||
|
}
|
||||||
|
}
|
||||||
27
OdooAPI/Services/OdooXmlMatchService.cs
Normal file
27
OdooAPI/Services/OdooXmlMatchService.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using OdooAPI.DataAccess.Odoo.Dtos;
|
||||||
|
|
||||||
|
namespace OdooAPI.Services;
|
||||||
|
|
||||||
|
public class OdooXmlMatchService
|
||||||
|
{
|
||||||
|
public List<string> GetMatchedCodes(
|
||||||
|
List<OdooProductDto> odooProducts,
|
||||||
|
List<string> localCodes)
|
||||||
|
{
|
||||||
|
var localSet = new HashSet<string>(localCodes);
|
||||||
|
|
||||||
|
var matches = odooProducts
|
||||||
|
.Where(p =>
|
||||||
|
!string.IsNullOrEmpty(p.DefaultCode) &&
|
||||||
|
localSet.Contains(p.DefaultCode))
|
||||||
|
.Select(p => p.DefaultCode)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
Console.WriteLine($"Aantal matches: {matches.Count}");
|
||||||
|
|
||||||
|
foreach (var m in matches)
|
||||||
|
Console.WriteLine($"MATCH: {m}");
|
||||||
|
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
}
|
||||||
9
OdooAPI/Services/PriceComparer.cs
Normal file
9
OdooAPI/Services/PriceComparer.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace OdooAPI.Services;
|
||||||
|
|
||||||
|
public static class PriceComparer
|
||||||
|
{
|
||||||
|
public static bool HasChanged(decimal oldPrice, decimal newPrice)
|
||||||
|
{
|
||||||
|
return oldPrice != newPrice;
|
||||||
|
}
|
||||||
|
}
|
||||||
50
OdooAPI/Services/SupplierMatchService.cs
Normal file
50
OdooAPI/Services/SupplierMatchService.cs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using OdooAPI.Database;
|
||||||
|
using OdooAPI.DataAccess.Odoo.Repositories;
|
||||||
|
|
||||||
|
namespace OdooAPI.Services;
|
||||||
|
|
||||||
|
public class SupplierMatchService
|
||||||
|
{
|
||||||
|
private readonly AppDbContext _db;
|
||||||
|
private readonly OdooProductRepository _repo;
|
||||||
|
|
||||||
|
public SupplierMatchService(AppDbContext db, OdooProductRepository repo)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
_repo = repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RunAsync(List<string> matchedCodes)
|
||||||
|
{
|
||||||
|
Console.WriteLine("SUPPLIER MATCHING");
|
||||||
|
|
||||||
|
foreach (var code in matchedCodes)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\nProduct: {code}");
|
||||||
|
|
||||||
|
var localSuppliers = await _db.LevArtikelen
|
||||||
|
.Where(x => x.ArtikelNummerLev == code)
|
||||||
|
.Select(x => new
|
||||||
|
{
|
||||||
|
Naam = x.Leverancier.Naam,
|
||||||
|
Code = x.ArtikelNummerLev,
|
||||||
|
Prijs = x.Inkoopprijs,
|
||||||
|
Delay = x.Leverbaar ? 1 : 0
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
foreach (var s in localSuppliers)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"UPSERT {s.Naam}");
|
||||||
|
|
||||||
|
await _repo.UpsertSupplierAsync(
|
||||||
|
code,
|
||||||
|
s.Naam,
|
||||||
|
s.Code,
|
||||||
|
s.Prijs,
|
||||||
|
s.Delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user