using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; using System.Text.Json; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; class Program { static async Task Main() { string url = "https://testsync1.odoo.com/jsonrpc"; string db = "testsync1"; string username = "*"; string password = "*"; using var http = new HttpClient(); Console.WriteLine("Verbinden met Odoo..."); int uid = await LoginOdoo(http, url, db, username, password); if (uid == -1) return; Console.WriteLine("Producten ophalen uit Odoo..."); var odooProducts = await GetOdooProducts(http, url, db, uid, password); Console.WriteLine($"{odooProducts.Count} Odoo producten gevonden"); using var dbContext = new ToolContext(); var dbArtikels = dbContext.Artikels.Include(a => a.LevArtikels).ToList(); Console.WriteLine($"{dbArtikels.Count} artikelen in DB"); int matchCount = 0; int supplierCreateCount = 0; int supplierUpdateCount = 0; foreach (var odoo in odooProducts) { if (string.IsNullOrWhiteSpace(odoo.Name) || string.IsNullOrWhiteSpace(odoo.DefaultCode)) continue; var matches = dbArtikels .Where(a => a.ArtikelNaam != null && a.FactoryNR != null && a.ArtikelNaam.Trim().Equals(odoo.Name.Trim(), StringComparison.OrdinalIgnoreCase) && a.FactoryNR.Trim().Equals(odoo.DefaultCode.Trim(), StringComparison.OrdinalIgnoreCase) && (string.IsNullOrEmpty(a.EAN) || string.IsNullOrEmpty(odoo.Barcode) || a.EAN == odoo.Barcode) ) .ToList(); foreach (var artikel in matches) { matchCount++; if (artikel.InOdoo == 0) artikel.InOdoo = 1; foreach (var lev in artikel.LevArtikels) { int? partnerId = await GetOdooPartnerId(http, url, db, uid, password, lev.LevID); if (partnerId == null) { Console.WriteLine($"Leverancier ID {lev.LevID} bestaat niet in Odoo"); continue; } int? supplierId = await GetOdooSupplierInfoId( http, url, db, uid, password, odoo.Id, partnerId.Value); if (supplierId.HasValue) { bool updated = await UpdateOdooSupplierInfo( http, url, db, uid, password, supplierId.Value, lev.Inkoopprijs ?? 0, lev.ArtikelNRLev ?? "" ); if (updated) supplierUpdateCount++; } else { bool created = await CreateOdooSupplierInfo( http, url, db, uid, password, odoo.TemplateId, partnerId.Value, lev.ArtikelNRLev ?? "", lev.Inkoopprijs ?? 0); if (created) supplierCreateCount++; } } } } dbContext.SaveChanges(); Console.WriteLine("------------ RESULTAAT ------------"); Console.WriteLine($"Matches gevonden: {matchCount}"); Console.WriteLine($"SupplierInfo aangemaakt: {supplierCreateCount}"); Console.WriteLine($"SupplierInfo geüpdatet: {supplierUpdateCount}"); Console.WriteLine("----------------------------------"); } static async Task LoginOdoo(HttpClient http, string url, string db, string username, string password) { var payload = new { jsonrpc = "2.0", method = "call", @params = new { service = "common", method = "authenticate", args = new object[] { db, username, password, new { } } }, id = 1 }; var response = await http.PostAsync( url, new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json")); var text = await response.Content.ReadAsStringAsync(); using var doc = JsonDocument.Parse(text); if (doc.RootElement.TryGetProperty("result", out var result) && result.ValueKind == JsonValueKind.Number) { Console.WriteLine($"Ingelogd (UID {result.GetInt32()})"); return result.GetInt32(); } Console.WriteLine("Login mislukt"); return -1; } class OdooProduct { public int Id { get; set; } public string? Name { get; set; } public string? DefaultCode { get; set; } public string? Barcode { get; set; } public decimal ListPrice { get; set; } public int TemplateId { get; set; } } static async Task> GetOdooProducts(HttpClient http, string url, string db, int uid, string password) { var payload = new { jsonrpc = "2.0", method = "call", @params = new { service = "object", method = "execute_kw", args = new object[] { db, uid, password, "product.product", "search_read", new object[] { }, new { fields = new[] { "id", "name", "default_code", "barcode", "list_price", "product_tmpl_id" } } } }, id = 2 }; var response = await http.PostAsync( url, new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json")); var text = await response.Content.ReadAsStringAsync(); using var doc = JsonDocument.Parse(text); if (!doc.RootElement.TryGetProperty("result", out var result) || result.ValueKind != JsonValueKind.Array) return new List(); var list = new List(); foreach (var item in result.EnumerateArray()) { if (!item.TryGetProperty("id", out var idElem) || idElem.ValueKind != JsonValueKind.Number) continue; int templateId = 0; if (item.TryGetProperty("product_tmpl_id", out var tmpl)) { var maybe = GetIntFromJsonElement(tmpl); if (maybe.HasValue) templateId = maybe.Value; } list.Add(new OdooProduct { Id = idElem.GetInt32(), Name = item.TryGetProperty("name", out var n) && n.ValueKind == JsonValueKind.String ? n.GetString() : null, DefaultCode = item.TryGetProperty("default_code", out var d) && d.ValueKind == JsonValueKind.String ? d.GetString() : null, Barcode = item.TryGetProperty("barcode", out var b) && b.ValueKind == JsonValueKind.String ? b.GetString() : null, ListPrice = item.TryGetProperty("list_price", out var p) && p.ValueKind == JsonValueKind.Number ? p.GetDecimal() : 0, TemplateId = templateId }); } return list; } static int? GetIntFromJsonElement(JsonElement e) { if (e.ValueKind == JsonValueKind.Number) return e.GetInt32(); if (e.ValueKind == JsonValueKind.Array) { var arr = e.EnumerateArray(); if (arr.MoveNext() && arr.Current.ValueKind == JsonValueKind.Number) return arr.Current.GetInt32(); } if (e.ValueKind == JsonValueKind.Object && e.TryGetProperty("id", out var idProp) && idProp.ValueKind == JsonValueKind.Number) return idProp.GetInt32(); return null; } static async Task GetOdooPartnerId(HttpClient http, string url, string db, int uid, string password, int levId) { return levId; } static async Task GetOdooSupplierInfoId(HttpClient http, string url, string db, int uid, string password, int productId, int partnerId) { return null; } static async Task CreateOdooSupplierInfo(HttpClient http, string url, string db, int uid, string password, int templateId, int partnerId, string productCode, decimal price) { var payload = new { jsonrpc = "2.0", method = "call", @params = new { service = "object", method = "execute_kw", args = new object[] { db, uid, password, "product.supplierinfo", "create", new { product_tmpl_id = templateId, name = partnerId, product_code = productCode, price = price, delay = 0 } } }, id = 3 }; var response = await http.PostAsync( url, new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json")); return response.IsSuccessStatusCode; } static async Task UpdateOdooSupplierInfo(HttpClient http, string url, string db, int uid, string password, int supplierId, decimal price, string productCode) { var payload = new { jsonrpc = "2.0", method = "call", @params = new { service = "object", method = "execute_kw", args = new object[] { db, uid, password, "product.supplierinfo", "write", new object[] { new int[] { supplierId }, new { price = price, product_code = productCode } } } }, id = 4 }; var response = await http.PostAsync( url, new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json")); return response.IsSuccessStatusCode; } public class ToolContext : DbContext { public DbSet Artikels { get; set; } = null!; public DbSet LevArtikels { get; set; } = null!; public DbSet Leveranciers { get; set; } = null!; protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseSqlite("Data Source=Tool.db"); } public class Artikel { public int ID { get; set; } public string? FactoryNR { get; set; } public string? ArtikelNaam { get; set; } public string? EAN { get; set; } public int InOdoo { get; set; } public List LevArtikels { get; set; } = new(); } public class LevArtikel { public int ID { get; set; } public int ArtikelID { get; set; } public int LevID { get; set; } public string? ArtikelNRLev { get; set; } public decimal? Inkoopprijs { get; set; } public decimal? Korting { get; set; } public string? LeverTijd { get; set; } public string? Omschrijving { get; set; } public bool Leverbaar { get; set; } } public class Leverancier { public int ID { get; set; } public string? Naam { get; set; } } }