OdooAutomation/OdooTool/Program.cs
2026-01-14 16:15:44 +01:00

340 lines
12 KiB
C#

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<int> 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<List<OdooProduct>> 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<OdooProduct>();
var list = new List<OdooProduct>();
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<int?> GetOdooPartnerId(HttpClient http, string url, string db, int uid, string password, int levId)
{
return levId;
}
static async Task<int?> GetOdooSupplierInfoId(HttpClient http, string url, string db, int uid, string password, int productId, int partnerId)
{
return null;
}
static async Task<bool> 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<bool> 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<Artikel> Artikels { get; set; } = null!;
public DbSet<LevArtikel> LevArtikels { get; set; } = null!;
public DbSet<Leverancier> 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<LevArtikel> 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; }
}
}