Sozer.Logo.Rest
1.3.792
dotnet add package Sozer.Logo.Rest --version 1.3.792
NuGet\Install-Package Sozer.Logo.Rest -Version 1.3.792
<PackageReference Include="Sozer.Logo.Rest" Version="1.3.792" />
<PackageVersion Include="Sozer.Logo.Rest" Version="1.3.792" />
<PackageReference Include="Sozer.Logo.Rest" />
paket add Sozer.Logo.Rest --version 1.3.792
#r "nuget: Sozer.Logo.Rest, 1.3.792"
#:package Sozer.Logo.Rest@1.3.792
#addin nuget:?package=Sozer.Logo.Rest&version=1.3.792
#tool nuget:?package=Sozer.Logo.Rest&version=1.3.792
Sözer Logo Rest
🇹🇷 Türkçe
Sözer Logo Rest, Logo Yazılım ürünleriyle entegrasyon sağlamak için geliştirilmiş bir .NET kütüphanesidir. Bu paket, Cari Hesap, Cari Sevkiyat Adresi, Satış Siparişi ve Satınalma Siparişi gibi verileri Logo sistemine kolayca entegre etmenize olanak tanır.
En son güncellemeyle birlikte kütüphane, gönderme işlemi sırasında herhangi bir hata oluştuğunda fırlatılan özel bir PostException ile geliştirilmiş hata işleme özelliğini içermektedir.
📦 Kurulum
Sözer Logo Rest'i NuGet üzerinden projelerinize ekleyebilirsiniz:
dotnet add package Sozer.Logo.Rest
veya Visual Studio NuGet Paket Yöneticisi'nden ekleyin:
- Tools > NuGet Package Manager > Manage NuGet Packages for Solution...
- Browse sekmesinde
Sozer Logo Restaratın ve projeye ekleyin.
🚀 Kullanım
Paketin kullanımı basittir. Genel işlemler için bir LogoClient içerir.
1. Bağlantı Kurulumu
ELogoClient oturum açma işlemleri için appsettings.json dosyasına aşağıdaki gibi bilgileri vermeniz gerekiyor
{
"FirmNo": "999",
"LogoRestAPI": {
"Url": "Logo/Rest/API/Url",
"Client": "Logo Rest API Authorization Token"
}
}
appsettings.json'daki bilgilerin okunabilmesi için Configuration'ı pakete vermeniz gerekiyor
var builder = WebApplication.CreateBuilder(args);
IWebHostEnvironment env = builder.Environment;
builder.Configuration.SetBasePath(env.ContentRootPath).AddJsonFile("appsettings.json", optional: false).AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
builder.Services.AddSozerLogoRestPackage("<lisans anahtarı buraya>", builder.Configuration);
// Hata Handling ve lisans kontrolü için şart
var app = builder.Build();
app.ConfigureExceptionHandlingMiddleware();
Sözer Bilgisayar adresinden lisans anahtarınız için kayıt olabilirsiniz
2. TaxPayerCode Doğrulaması ile Cari Hesap Ekleme veya Güncelleme
Bir hesap eklerken, TaxPayerCode alanı sağlanmışsa:
- TaxPayerCode Gelir İdaresi Başkanlığı (GİB) hizmeti aracılığıyla doğrulanır.
- Eğer geçerliyse:
TaxPayerCode10 karakter uzunluğundaysa, hesap kurumsal bir varlık olarak değerlendirilir.- Aksi takdirde, bireysel bir tüzel kişilik olarak değerlendirilir.
- Hizmetten gelen yanıt,
PostLabelveSenderLabelgibi belirli alanları günceller.
[Route("api/[controller]/[action]")]
[ApiController]
public class AccountsRpController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(bool))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostAccountsRPs(new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
}, [ new AccountsRP()
{
Code = "Cari Hesap Kodu",
TaxPayerCode = "1234567890" // Hesap türünü doğrular ve belirler
} ], cancellationToken));
}
3. Cari Hesap Sevkiyat Adresi Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem veriyi, verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
[Route("api/[controller]/[action]")]
[ApiController]
public class ArpShipLicsController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(bool))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostArpShipLics(new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
}, [ArpShipLic() {
ArpCode = "Cari Hesap Kodu",
Code = "Sevkiyat Adresi Kodu"
}], cancellationToken));
}
4. Satış Siparişi Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem veriyi, verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
[Route("api/[controller]/[action]")]
[ApiController]
public class OrdersController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(bool))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostOrders(new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
}, [
new Order() {
Number = "Satış Siparişi Numarası"
}
], cancellationToken));
}
5. Satınalma Siparişi Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem veriyi, verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
[Route("api/[controller]/[action]")]
[ApiController]
public class PurchOrdersController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(bool))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostPurchOrders(new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
}, [new PurchOrder() {
Number = "Satınalma Siparişi Numarası"
}], cancellationToken));
}
6. Malzeme Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem veriyi, verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
[Route("api/[controller]/[action]")]
[ApiController]
public class MaterialsController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(bool))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostMaterials(new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
}, [new Material() {
Code = "Malzeme Kodu"
}], cancellationToken));
}
7. Satış Faturaları Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem veriyi, verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
[Route("api/[controller]/[action]")]
[ApiController]
public class SalesInvoiceController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostSalesInvoices(new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
}, [new SalesInvoice() {
Type = 3,
DocTrackNr = "Dokuman Izleme Numarasi",
DocNumber = "Belge No",
AuxilCode = "Ozel Kod",
AuthCode = "1",
Arp_Code = "1341911",
PostFlags = 247
}], cancellationToken));
}
}
8. Malzeme Fişleri Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem veriyi, verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
[Route("api/[controller]/[action]")]
[ApiController]
public class MaterialSlipsController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostMaterialSlips(new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
}, [new() {
Group = 3,
Type = 12,
Date = "29.09.2025",
CurrselTotals = 1,
Transactions = [new() {
ItemCode = "Malzeme Kodu",
Quantity = 5, // Miktar
UnitCode = "Birim Kodu",
UnitConv1 = 1,
UnitConv2 = 1
}]
}], cancellationToken));
}
9. PostException ile Hata İşleme
Gönderme işlemi sırasında, herhangi bir hata meydana gelirse, özel bir PostException atılır. Bu istisna, öğe numarası ve hata mesajı da dahil olmak üzere başarısız gönderiler hakkında ayrıntılı bilgi içerir.
Örnek:
try
{
IList<PostResult> results = await logoClient.PostAccountsRPs(new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
}, new List<Account>
{
new()
{
InternalReference = null,
Title = "Invalid Account",
TaxPayerCode = "INVALID"
}
});
}
catch (PostException ex)
{
Console.WriteLine("An error occurred during the posting process:");
Console.WriteLine(ex.Message);
}
Bir Hata Sırasında Ne Olur:
- Doğrulama: Herhangi bir
PostResultbaşarısızlık gösterirse (IsSuccess == false), birPostExceptiontetiklenir. - Hata Detayları: İstisna mesajı şunları içerir:
- Öğe numarası (
Number). - Varlık adı (örneğin, “Cari Hesap”).
- Hata mesajı.
- Öğe numarası (
Örnek Hata Mesajı:
Hata Mesajı: 1 numaralı AccountsRP Hata: DBError(8) - Kayıt veritabanına aktarılamadı. 23000 : Cannot insert duplicate key row in object 'dbo.LG_999_CLCARD' with unique index 'I999_CLCARD_I13'. The duplicate key value is (1, 0, 1).\n"
10. OrderBilling ile Sipariş Faturalarını Faturalamak
Sipariş fişlerini faturalamak için kullanılan method'dur. Eğer işlem başarıyla gerçekleşmezse, dönüş nesnesinde error özelliği doldurulur.
[Route("api/[controller]/[action]")]
[ApiController]
public class UnityApplicationController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(OrderBillingResponse))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> OrderBilling(CancellationToken cancellationToken) => Ok(await logoClient.OrderBilling(new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
}, [new() {
OrderRef = 3229, // Faturalaştıracağınız siparişin Logical Reference'ı
Date = "02.10.2025", // Tarih gün.ay.yıl formatında olmalıdır
FicheType = 3, // Fatura Türü
DocumentCode = "Belge No",
SpecialCode = "Özel Kod",
AuthCode = "Yetki Kodu",
Description1 = "Açıklama 1",
Description2 = "Açıklama 2",
Description3 = "Açıklama 3",
Description4 = "Açıklama 4",
CheckUserRight = true, // Kullanıcı Yetkisi Kontrol Edilsin Mi?
SqlTransaction = true, // Sql Transaction
EInvoice = false, // Sipariş E-faturaya dönüştürülecek Mi?
VatExceptReason = "Vergi Muaf Nedeni"
}, new() {
OrderRef = 3230,
Date = "02.10.2025",
FicheType = 3,
DocumentCode = "SP00000000000003"
}, new() {
OrderRef = 2142,
Date = "02.10.2025",
FicheType = 3,
DocumentCode = "SP00000000000001"
},], cancellationToken));
11. Satış İrsaliyesi Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem veriyi, verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
[Route("api/[controller]/[action]")]
[ApiController]
public class SalesDispatchesController(LogoClient logoClient, XmlService xmlService) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
private readonly XmlService xmlService = xmlService;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostSalesDispatches(new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
}, [new() {
Type = 9,
Number = "~",
Date = "23.10.2025",
Time = 202052408,
ArpCode = "5000534",
Notes1 = "",
SourceWh = 0,
CreatedBy = 0,
RcRate = 0,
CurrselTotals = 1,
Salesmancode = "",
ShippingAgent = "",
Deductionpart1 = 0,
Deductionpart2 = 0,
Edespatch = 1,
ShipDate = "23.10.2025",
ShipTime = 202052408,
DocDate = "23.10.2025",
DocTime = 202052408,
Transactions =
{
new()
{
Type = 0,
Price = 0,
MasterCode = "DKPN12188",
Sourceindex = 0,
Quantity = 5,
RcXrate = 0,
UnitCode = "ADET",
UnitConv1 = 5,
UnitConv2 = 5,
VatRate = 20,
EdtCurr = 53,
OrderReference = "3001",
Sldetails =
{
new()
{
SourceMtReference = 380,
SourceSltReference = 1,
SourceQuantity = 1,
IOCODE = 4,
SourceWh = 0,
SlType = 1,
SlCode = "123456",
MuQuantity = 1,
UnitCode = "ADET",
Quantity = 1,
UnitConv1 = 1,
UnitConv2 = 1
}
}
}
}
}], cancellationToken));
12. Cari Hesap Fişi Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem veriyi, verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
[Route("api/[controller]/[action]")]
[ApiController]
public class ArpVouchersController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostArpVoucher(new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
}, [new() {
Number = "Numara",
Date = "26.01.2026",
Type = 70, // Tip
Notes1 = "Açıklama",
CurrselTotals = 1,
DataReference = 1,
Arp_Code = "Cari Hesap Kodu",
ProjectCode = "Proje Kodu",
AffectRisk = 0,
SalesmanCode = "Satış Elemanı Kodu"
}], cancellationToken));
}
13. Ürün Reçetesi Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem veriyi, verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
[Route("api/[controller]/[action]")]
[ApiController]
public class BomsController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostBom(new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
}, [new() {
Code = "Test3",
Type = 1,
RevCode = "REVIZYON - KODU",
RevRecordStatus = 1,
RevDate = "28.01.2026",
RevDataReference = 1,
Lines = [new() {
LineType = 4,
Uinfo1 = 1,
Uinfo2 = 1,
Amount = 1,
Scalable = 1,
InvenNo = -1,
Engineering = 1,
Production = 1,
Cost = 1,
CostRate = 1,
Formula = "1",
EffectOpTime = 1,
ItemCode = "EKMEK",
ItemName = "Ekmek",
UnitSetCode = "05",
UnitCode = "ADET",
BomType = 1,
OpCode = "ROTASIZ",
OpName = "ROTASIZ"
}, new() {
LineType = 0,
Uinfo1 = 1,
Uinfo2 = 1,
Amount = 1,
Scalable = 1,
InvenNo = -1,
Engineering = 1,
Production = 1,
Cost = 1,
Formula = "P1",
ItemCode = "SU",
ItemName = "Su",
UnitSetCode = "05",
UnitCode = "ADET",
BomType = 1,
OpCode = "ROTASIZ",
OpName = "ROTASIZ",
DefCostType = 5
}],
MpCode = "EKMEK",
MpName = "Ekmek",
RoutCode = "URETIM ROTASI KODU",
RoutName = "Uretim Rotasi Aciklamasi"
}], cancellationToken));
}
🔄 Satır (Lines) Güncelleme Davranışı
Aşağıdaki nesneler için güncelleme (Update) işlemi sırasında:
- Ürün Reçetesi
- Malzeme
- Malzeme Fişi
- Satış Siparişi
- Satın Alma Siparişi
- Satış İrsaliyesi
- Satış Faturası
Eğer güncellenecek kaydın satırları (Lines) mevcutsa, güncelleme sırasında bu kayıt tamamen silinir ve gönderilen kayıt ile baştan oluşturulur.
⚠ Önemli Uyarı
Bu nedenle güncelleme yaparken, eğer veri satır içeriyorsa:
- Kullanıcı tüm satırları yeniden göndermelidir.
- Her bir satır için tüm alanlar eksiksiz bir şekilde doldurulmalıdır.
- Aksi halde, gönderilmeyen alanlar veya satırlarlar silinmiş kabul edilir ve kayıtta yer almaz.
Bu yaklaşım, Logo tarafındaki satır senkronizasyonunu garanti altına almak için tercih edilmiştir.
14. SelectSql — Dinamik SQL Sorgu Yürütme
SelectSql, sağlam bir şekilde yapılandırılmış sorgu tanımı (SqlQueryDef) kullanarak Logo ERP tabloları/görünümleri üzerinde dinamik SQL sorguları çalıştırmanıza olanak tanır. Sonuç, kendi modellerinizle eşleştirebileceğiniz anahtar-değer çiftlerinden oluşan bir koleksiyon olarak döndürülür.
[Route("api/[controller]/[action]")]
[ApiController]
public class SqlsController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<TResponse>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> GetSelect(CancellationToken cancellationToken) => Ok((await logoClient.SelectSql(new()
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
}, new SqlQueryDef()
{
MainTable = "Ana Tablo",
WhereConditions = [
new WhereCondition() {
Column = "Code",
Operator = WhereOperators.Equal,
Value = "{Code}"
}
]
}, cancellationToken)).Select(d => new TResponse(d)));
}
🧱 Örnek Model Eşlemesi
Bunu kendi modelinize eşleştirmek sizin sorumluluğunuzdadır:
public class TResponse(Dictionary<string, JsonElement?> json)
{
public int Logicalref { get; set; } = int.Parse(json["LOGICALREF"].ToString()!);
public string Code { get; set; } = json["CODE"].ToString()!;
}
🧩 Sorgu Tanımı (SqlQueryDef)
SqlQueryDef, SQL sorguları oluşturmak için esnek bir yol sunar.
Özellikler
| Özellik | Açıklama |
|---|---|
MainTable |
Hedef tablo veya görünüm |
SelectColumns |
Seçilecek sütunlar (varsayılan: *) |
SqlJoins |
JOIN tanımları |
WhereConditions |
WHERE cümlesi koşulları |
HavingConditions |
HAVING cümlesi koşulları |
GroupBy |
GROUP BY sütunları |
OrderBys |
ORDER BY tanımları |
Limit |
LIMIT (TOP) |
OffSet |
OFFSET |
Desteklenen Operatörler
Equal,NotEqualGreaterThan,LessThan,Like,NotLikeIn,BetweenIsNull,IsNotNull
🔀 JOIN Örneği
SqlJoins =
[
new SqlJoin
{
JoinType = JoinType.Inner,
TableName = "LG_001_ITEMS",
Alias = "ITM",
OnClause = "ITM.LOGICALREF = CLCARD.LOGICALREF"
}
]
📊 ORDER BY Örneği
OrderBys =
[
new OrderBy
{
Column = "CODE",
Descending = false
}
]
WhereConditions Örneği
WhereConditions = [new() {
Column = "Line.LINETYPE",
Operator = WhereOperators.NotEqual,
Value = 1
}, new() {
Column = "Fiche.LOGICALREF",
Operator = WhereOperators.In,
Value = new List<int>() {
{2111 },
{2137 }
},
Connector = LogicalConnector.And
}]
15. Satınalma İrsaliye Ekleme ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem veriyi, verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
[Route("api/[controller]/[action]")]
[ApiController]
public class PurchaseDispatchesController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostPurchaseDispatches(new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
}, [
new() {
Type = 1,
Number = "Fiş No",
CurrselTotals = 1,
Date = "27.03.2026",
Transactions = [
new() {
MasterCode = "Malzeme-Kodu",
Quantity = 15,
UnitCode = "Birim-Kodu",
UnitConv1 = 15,
UnitConv2 = 15,
VatRate = 20,
Sldetails = [
new() {
IOCODE = 1,
SlType = 1,
SlCode = "000001",
MuQuantity = 5,
UnitCode = "Birim-Kodu",
Quantity = 5,
RemQuantity = 5,
LuRemQuantity = 5,
UnitConv1 = 5,
UnitConv2 = 5,
DateExpired = "27.04.2026",
DateUrt = "27.03.2026",
Tibbicihazurtdate = "27.03.2026",
}
],
EdtCurr = 1,
Month = 3,
Year = 2026,
AddTaxEffectKdv = 1,
MasterDef = "Malzeme Açıklaması",
}
],
Deductionpart1 = 2,
Deductionpart2 = 3,
DispStatus = 1,
ShipDate = "27.03.2026",
}], cancellationToken));
}
16. ELogo Belge Gönderme ve Alma
ELogo entegrasyonu için iki yeni fonksiyon eklenmiştir: ELogoSendDocument ve ELogoGetDocumentData. Bu fonksiyonlar sırasıyla e-Fatura, e-Arşiv, e-İrsaliye gibi ELogo belgelerini göndermek ve almak için kullanılır.
📄 Detaylı dokümantasyon:
[Route("api/[controller]/[action]")]
[ApiController]
public class ELogoController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(SendDocumentElogoCommandResponse))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Send(CancellationToken cancellationToken) => Ok(await logoClient.ELogoSendDocument(new SendDocumentElogoCommandRequest
{
LogoAuth = new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
},
Params = new SendDocumentParams
{
DocumentType = SendDocumentType.DESPATCHADVICE,
Alias = "urn:mail:defaultgb@firma.com.tr",
Signed = false
},
Document = new ELogoDocument
{
BinaryData = new Base64BinaryData { Value = zipFileBytes },
FileName = "irsaliye.zip"
}
}, cancellationToken));
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(GetDocumentDataELogoQueryResponse))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Get(CancellationToken cancellationToken) => Ok(await logoClient.ELogoGetDocumentData(new GetDocumentDataELogoQueryRequest
{
LogoAuth = new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
},
Uuid = "belge-uuid-degeri",
Params = new GetDocumentDataParams
{
DocumentType = GetDocumentDataDocumentType.EINVOICE,
Format = GetDocumentDataFormat.PDF,
Iscancel = false
}
}, cancellationToken));
}
17. Seri Lot Tablosu Ekleme ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem veriyi, verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
[Route("api/[controller]/[action]")]
[ApiController]
public class SerialAndLotNumbersController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostSerialAndLotNumbers(new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
}, [new() {
Code = "Test",
Description = "Test Description",
ItemCode = "1985003024",
Type = 1 // 1:Lot 2:Seri
}], cancellationToken));
}
18. Banka Fişi Ekleme ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem veriyi, verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
[Route("api/[controller]/[action]")]
[ApiController]
public class BankVouchersController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostBankVouchers(new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
}, [new() {
Number = "Fiş No",
AuxilCode = "OzelKod",
AuthCode = "YetkiKodu",
Type = 1,
TotalCredit = 100,
Notes1 = "Aciklama",
CurrselTotals = 1,
Transactions = [new() {
Type = 1,
BankaccCode = "KODU BANKAHKODU",
ArpCode = "CariHesapKodu",
Sourcefref = 1,
Sign = 1,
Trcode = 1,
Modulenr = 7,
AuxilCode = "OzelKod",
DocNumber = "BelgeNo",
Description = "Aciklama",
Credit = 100,
Amount = 100,
TcAmount = 100,
BnkTractingNr = "BankaTakipNo",
BankProcType = 1,
DueDate = "08.06.2026",
ProjectCode = "ProjeKodu",
BnCrdtype = 1,
Preacclines = [new() {
Linenr = 1,
Distrate = 100,
Date = "08.06.2026",
Month = 6,
Year = 2026,
Prevlinetype = 1,
Modulnr = 4,
Projectcode = "ProjeKodu",
Projectname = "ProjeAdı"
}],
Specode2 = "HareketÖzelKodu2",
VatFlag = 1,
}],
ProjectCode = "ProjeKodu"
}], cancellationToken));
}
19. GetEDocumentContent
GetEDocumentContent, Logo ERP (Cloud Connect) kullanıcıları için E-Doküman içeriklerini (PDF, HTML, XML vb.) almak amacıyla kullanılan bir servistir.
Bu metot sayesinde e-Fatura, e-Arşiv, e-İrsaliye gibi belgelerin içeriklerine farklı formatlarda erişebilirsiniz.
📌 Özellikler
- Birden fazla e-doküman türünü destekler
- Farklı çıktı formatlarında veri alımı (PDF, HTML, XML vb.)
- GUID bazlı doküman erişimi
- Logo REST servisleri ile uyumlu
📥 Parametreler
| Parametre | Açıklama |
|---|---|
| DocType | E-Doküman türü |
| OutFormat | Çıktı formatı |
| Guid | İlgili dokümanın benzersiz ID değeri |
📄 Desteklenen DocType Değerleri
| Değer | Açıklama |
|---|---|
EINVOICE |
E-Fatura |
APPLICATIONRESPONSE |
E-Fatura Uygulama Yanıtı |
EARCHIVEINVOICE |
E-Arşiv |
DESPATCHADVICE |
E-İrsaliye |
RECEIPTADVICE |
E-İrsaliye Yanıtı |
SERECEIPTCLF |
E-SMM (Cari Fiş) |
SERECEIPTCSH |
E-SMM (Kasa Fişi) |
EPRECEIPT |
E-Müstahsil |
📤 Desteklenen OutFormat Değerleri
| Değer | Açıklama |
|---|---|
XML |
XML format |
UBL |
UBL format |
HTML |
HTML çıktı |
JSON |
JSON çıktı |
HTMLBYGENERALFORMAT |
Genel format HTML |
PDF |
PDF doküman |
public async Task<IActionResult> GetEDocumentContent(CancellationToken cancellationToken)
{
var response = await logoClient.GetEDocumentContentAsync(
new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
},
[
new GetEDocumentContentRequest
{
DocType = DocType.DESPATCHADVICE,
OutFormat = OutFormat.HTML,
Guid = "5ede911c-5eb0-4282-b3cd-82e91d143712"
}
],
cancellationToken
);
return Ok(response);
}
⚠️ Notlar
PDFçıktısı çoğunlukla Base64 encoded olarak döner → decode edilmelidir- Büyük dokümanlar için async kullanım önerilir
- GUID değeri Logo tarafında oluşturulan benzersiz doküman ID’sidir
🎯 Kullanım Senaryoları
- E-Fatura PDF çıktısı alma
- E-Arşiv HTML görüntüleme
- UBL/XML entegrasyonları
- ERP dış sistem entegrasyonları
📌 Özet
GetEDocumentContent, Logo ERP sisteminden e-doküman içeriklerini güvenli ve esnek bir şekilde almak için kullanılan temel endpointlerden biridir. Farklı format desteği sayesinde hem görselleştirme hem de entegrasyon senaryolarında kullanılabilir.
20. ClearHtml
ClearHtml, GetEDocumentContent metodundan HTML formatında dönen kirli (escaped / bozulmuş) içeriği temizlemek için kullanılan yardımcı bir fonksiyondur.
Logo servislerinden alınan HTML çıktıları genellikle:
- JSON escape karakterleri içerir (
\",\\n) - HTML encode edilmiş olur (
",&) - Base64 image string’leri bozuk (boşluklu / satır kırıklı) gelir
- Baştan ve sondan
"karakterleri ile sarılmış olabilir
Bu fonksiyon tüm bu problemleri normalize ederek render edilebilir temiz HTML üretir.
🎯 Amaç
- HTML çıktıyı tarayıcıda düzgün render edilebilir hale getirmek
- Base64 image’ların bozulmasını engellemek
- Encoding ve escape problemlerini çözmek
⚙️ Nasıl Çalışır?
Fonksiyon aşağıdaki adımları uygular:
- Trim işlemi
- Baştaki ve sondaki
"karakterlerini kaldırır - JSON escape karakterlerini çözer (
Regex.Unescape) - HTML decode işlemi yapar (
WebUtility.HtmlDecode) - Base64 image içindeki whitespace karakterlerini temizler (kritik adım)
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(string))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> ClearHtml(string html, CancellationToken cancellationToken)
=> Ok(await logoClient.ClearHtml(html));
📥 Input (Kirli HTML)
\"<html><body><img src=\"data:image/png;base64,iVBORw0KGgo AAA...\" /></body></html>\"
📤 Output (Temiz HTML)
<html>
<body>
<img src="data:image/png;base64,iVBORw0KGgoAAA..." />
</body>
</html>
⚠️ Önemli Notlar
Base64 içindeki boşluklar temizlenmezse:
- Görseller render edilmez
- PDF conversion hatalı olur
Bu fonksiyon özellikle:
OutFormat = HTMLOutFormat = HTMLBYGENERALFORMAT
durumlarında kullanılmalıdır
🎯 Kullanım Senaryoları
- HTML → PDF dönüşüm öncesi temizlik
- WebView / Browser render
- Email template üretimi
- E-Fatura / E-Arşiv görüntüleme
📌 Özet
ClearHtml, Logo’dan gelen bozuk HTML çıktıyı tek adımda normalize eden kritik bir yardımcı fonksiyondur. Özellikle base64 image içeren dokümanlarda kullanılması zorunludur.
21. ConvertHtmlToPdf
ConvertHtmlToPdf, Logo GetEDocumentContent metodundan HTML formatında alınan e-dokümanları PDF'e dönüştürmek için kullanılan bir servistir.
Bu fonksiyon, özellikle Logo’dan gelen HTML çıktının doğrudan PDF'e çevrilemediği durumlarda, önce temizleme (ClearHtml) ardından render işlemi ile doğru PDF çıktısı üretir.
🎯 Amaç
- Logo’dan alınan HTML çıktıyı PDF’e dönüştürmek
- Base64 image içeren dokümanları doğru render etmek
- PDF çıktıyı byte[] olarak üretmek (disk IO olmadan)
🔄 Önerilen Akış
GetEDocumentContent (HTML)
↓
ClearHtml (zorunlu)
↓
ConvertHtmlToPdf
↓
byte[] (PDF)
⚠️ Neden ClearHtml Gerekli?
GetEDocumentContent HTML çıktısı genellikle:
- Escape edilmiş (
\",\\n) - HTML encode edilmiş (
") - Base64 image'lar bozuk (whitespace içerir)
👉 Bu nedenle ClearHtml() çağrılmadan PDF üretimi yapılması önerilmez
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(byte[]))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> ConvertHtmlToPdf(string html, CancellationToken cancellationToken)
=> Ok(await logoClient.ConvertHtmlToPdf(html, cancellationToken));
📥 Input
Temizlenmiş HTML (ClearHtml sonrası):
<html>
<body>
<img src="data:image/png;base64,iVBORw0KGgoAAA..." />
</body>
</html>
📤 Output
Tür:
byte[]İçerik: PDF binary data
Kullanım:
- API response
- File download
- Email attachment
🧠 Teknik Detaylar
- Chromium engine kullanır (Playwright)
- HTML’i gerçek browser ortamında render eder
- CSS ve Base64 image desteği tamdır
- Disk’e yazmadan memory üzerinden çalışır
⚠️ Dikkat Edilmesi Gerekenler
- Her çağrıda browser başlatmak maliyetlidir → Production’da browser reuse önerilir
- Büyük HTML içeriklerinde memory tüketimi artabilir
- Timeout yönetimi yapılmalıdır
🎯 Kullanım Senaryoları
- E-Fatura PDF üretimi
- E-Arşiv doküman arşivleme
- Email PDF attachment
- Rapor çıktıları
📌 Özet
ConvertHtmlToPdf, Logo’dan alınan HTML dokümanları güvenilir şekilde PDF’e dönüştüren bir servistir. Doğru sonuç için mutlaka ClearHtml ile birlikte kullanılmalıdır.
22. SendRecvEDispatchDocuments
SendRecvEDispatchDocuments, Logo ERP (Cloud Connect) kullanıcıları için E-İrsaliye gönderme ve alma işlemlerini gerçekleştiren bir servistir.
Bu metot sayesinde sistemdeki e-irsaliyeler:
- GİB’e gönderilebilir (Send)
- Gelen e-irsaliyeler alınabilir (Receive)
🎯 Amaç
- E-İrsaliye gönderim süreçlerini tetiklemek
- Gelen e-irsaliyeleri sisteme almak
- Tek veya toplu işlem desteği sağlamak
📥 Parametreler
| Parametre | Tip | Açıklama |
|---|---|---|
| IsSend | bool | true ise gönderim işlemi yapılır |
| IsReceive | bool | true ise alım işlemi yapılır |
| Referances | IList<string> | Fiş referansları veya GUID listesi |
🔍 Referans (Refs) Kullanımı
Liste içine:
- Fiş referansı
- veya GUID (36 karakter)
eklenebilir.
👉 Eğer değer 36 karakter ise, sistem bunu otomatik olarak GUID kabul eder ve ilgili fiş referansını kendi çözer.
⚠️ Önemli Davranış
IsSend = true
Referances = boş
👉 Bu durumda:
➡️ "Gönderilecek" sekmesindeki TÜM fişler gönderilir
📤 Return Type
| Tip | Açıklama |
|---|---|
| string | İşlem logu ve sonucu |
📄 Örnek Response
------------ 25.01.2021 20:32:29 ------------
20:32:29 İşlemler gönderiliyor...
20:32:31 Gönderilen paket sayısı : 1
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(SendRecvEDispatchDocumentsResponse))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> SendRecvEDispatchDocuments(CancellationToken cancellationToken)
=> Ok(await logoClient.SendRecvEDispatchDocumentsAsync(
new LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
},
[
new SendRecvEDispatchDocumentsRequest
{
IsSend = true,
IsReceive = false,
Referances = [
"5ede911c-5eb0-4282-b3cd-82e91d143712",
"e37586be-b652-42b6-b8a7-d29f594ca2fe",
"b90df056-c935-4478-8e6e-931fa4749007"
]
}
],
cancellationToken));
🧠 Teknik Detaylar
- Cloud Connect altyapısını kullanır
- İşlemler Logo Objects üzerinden yürütülür
- Batch işlem desteği vardır
- Hem GUID hem referans bazlı çalışabilir
⚠️ Dikkat Edilmesi Gerekenler
- Aynı anda hem
IsSendhemIsReceivetrue olabilir - Büyük listelerde işlem süresi uzayabilir
- Log string parse edilerek detaylı sonuç çıkarılabilir
- Hatalar response içinde string olarak dönebilir
🎯 Kullanım Senaryoları
- Toplu e-irsaliye gönderimi
- Gelen e-irsaliyeleri çekme
- Zamanlanmış job (cron) işlemleri
- ERP entegrasyonları
📌 Özet
SendRecvEDispatchDocuments, e-irsaliye gönderme ve alma işlemlerini merkezi olarak yöneten güçlü bir servistir. Referans veya GUID desteği sayesinde esnek kullanım sağlar ve toplu işlem senaryoları için idealdir.
📑 API Özellikleri
| Özellik | Açıklama |
|---|---|
| Cari Hesap | TaxPayerCode doğrulaması ile bir hesap oluşturma ve güncelleme. |
| Cari Sevkiyat Adresi | Müşteri sevkiyat adresi ekleme ve güncelleme işlemi. |
| Satış Siparişi | Satış siparişi oluşturma ve güncelleme işlemi. |
| Satınalma Siparişi | Satın alma siparişi ekleme ve güncelleme işlemi. |
| Malzeme | Malzeme ekleme ve güncelleme işlemi. |
| Satış Faturası | Satış Faturası ekleme ve güncelleme işlemi. |
| Malzeme Fişleri | Malzeme Fişleri ekleme ve güncelleme işlemi. |
| Hata İşleme | Ayrıntılı hata raporlaması için özel PostException. |
| Fatura İptali | Fatura referansı ile Fatura İptali. |
| OrderBilling ile Sipariş Faturalarını Faturalamak | Sipariş fişlerini faturalar. |
| Satış İrsaliyeleri | Satış İrsaliyeleri ekleme ve güncelleme işlemi. |
| Cari Hesap Fişi | Cari Hesap Fişi ekleme ve güncelleme işlemi. |
| Ürün Reçetesi | Ürün Reçetesi ekleme ve güncelleme işlemi. |
| SelectSql | SelectSql ile Dinamik SQL Sorgu Yürütme. |
| Satınalma İrsaliye | Satınalma İrsaliye ekleme ve güncelleme işlemi. |
| ELogoSendDocument | ELogo üzerinden e-Fatura, e-Arşiv, e-İrsaliye vb. belge gönderimi. |
| ELogoGetDocumentData | Elogo üzerinden gönderilen veya alınan belgelerin UBL/HTML/PDF formatında sorgulanması. |
| Seri Lot Tablosu | Seri Lot Tablosu ekleme ve güncelleme işlemi. |
| Banka Fişi | Banka Fişi ekleme ve güncelleme işlemi. |
| GetEDocumentContent | E-Doküman içeriklerini (PDF, HTML, XML vb.) almak. |
| ClearHtml | Kirli (escaped / bozulmuş) içeriği temizlemek. |
| ConvertHtmlToPdf | HTML formatında alınan e-dokümanları PDF'e dönüştürmek. |
| SendRecvEDispatchDocuments | E-İrsaliye gönderme ve alma işlemlerini gerçekleştirmek. |
🛠️ Geliştirme
- Programlama Dili: C#
- Platform: .NET 6+
📄 Lisans
Bu proje MIT Lisansı altında lisanslanmıştır. Daha fazla bilgi için LICENSE dosyasına bakabilirsiniz.
📫 İletişim
Bu projeyle ilgili herhangi bir sorunuz veya geri bildiriminiz varsa, lütfen bana ulaşın:
Hakkıcan Bülüç
- LinkedIn: Hakkıcan Bülüç
- GitHub: Hakkıcan Bülüç
Eklenen Özellikler:
- PostResult: Bu sürümle birlikte PostResult'a ToString()'u eklenmiştir.
🇺🇸 English
Sözer Logo Rest is a .NET library developed for integration with Logo Software products. This package allows you to easily integrate data such as Current Account, Current Shipping Address, Sales Order, and Purchase Order into the Logo system.
With the latest update, the library includes improved error handling with a custom PostException, which is thrown if any errors occur during the posting process.
📦 Installation
You can add the Sözer Logo Rest to your projects via NuGet:
dotnet add package Sozer.Logo.Rest
or add it through Visual Studio NuGet Package Manager:
- Tools > NuGet Package Manager > Manage NuGet Packages for Solution...
- Search for
Sozer Logo Restin the Browse tab and add it to your project.
🚀 Usage
The package is straightforward to use. It includes a LogoClient for general operations.
1. Connection Setup
You need to provide the following information in the appsettings.json file for ELogoClient login procedures:
{
"FirmNo": "999",
"LogoRestAPI": {
"Url": "Logo/Rest/API/Url",
"Client": "Logo Rest API Authorization Token"
}
}
You need to include Configuration in the package to be able to read the information in appsettings.json.
var builder = WebApplication.CreateBuilder(args);
IWebHostEnvironment env = builder.Environment;
builder.Configuration.SetBasePath(env.ContentRootPath).AddJsonFile("appsettings.json", optional: false).AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
builder.Services.AddSozerLogoRestPackage("<license key here>", builder.Configuration);
// Error handling and license verification requirements
var app = builder.Build();
app.ConfigureExceptionHandlingMiddleware();
You can register for your license key at Sözer Bilgisayar
2. Adding or Updating an Account with TaxPayerCode Validation
When adding an account, if the TaxPayerCode field is provided:
- The TaxPayerCode is validated through the Revenue Administration (GIB) service.
- If valid:
- If
TaxPayerCodeis 10 characters long, the account is treated as a corporate entity. - Otherwise, it is treated as an individual entity.
- If
- The response from the service updates specific fields such as
PostLabelandSenderLabel.
[Route("api/[controller]/[action]")]
[ApiController]
public class AccountsRpController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(bool))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostAccountsRPs(new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
}, [ new AccountsRP()
{
Code = "Current Account Code",
TaxPayerCode = "1234567890", // Validates and determines account type
} ], cancellationToken));
}
3. Adding And Updating Account Shipping Addresses
With the new INTERNAL_REFERENCE field, if the field is not null, the system updates the data with the given fields. If INTERNAL_REFERENCE is null, a new record is created.
[Route("api/[controller]/[action]")]
[ApiController]
public class ArpShipLicsController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(bool))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostArpShipLics(new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
}, [new ArpShipLic() {
ArpCode = "Current Account Code",
Code = "Shipping Address Code"
}], cancellationToken));
}
4. Adding And Updating Sales Orders
With the new INTERNAL_REFERENCE field, if the field is not null, the system updates the data with the given fields. If INTERNAL_REFERENCE is null, a new record is created.
[Route("api/[controller]/[action]")]
[ApiController]
public class OrdersController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(bool))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostOrders(new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
}, [
new Order() {
Number = "Sales Order Number"
}
], cancellationToken));
}
5. Adding And Updating Purchase Order
With the new INTERNAL_REFERENCE field, if the field is not null, the system updates the data with the given fields. If INTERNAL_REFERENCE is null, a new record is created.
[Route("api/[controller]/[action]")]
[ApiController]
public class PurchOrdersController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(bool))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostPurchOrders(new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
}, [new PurchOrder() {
Number = "Purchase Order Number"
}], cancellationToken));
}
6. Adding And Updating Material
With the new INTERNAL_REFERENCE field, if the field is not null, the system updates the data with the given fields. If INTERNAL_REFERENCE is null, a new record is created.
[Route("api/[controller]/[action]")]
[ApiController]
public class MaterialsController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(bool))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostMaterials(new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
}, [new Material() {
Code = "Material Code"
}], cancellationToken));
}
7. Adding And Updating Sales Invoice
With the new INTERNAL_REFERENCE field, if the field is not null, the system updates the data with the given fields. If INTERNAL_REFERENCE is null, a new record is created.
[Route("api/[controller]/[action]")]
[ApiController]
public class SalesInvoiceController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostSalesInvoices(new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
}, [new SalesInvoice() {
Type = 3,
}], cancellationToken));
}
}
8. Adding and Updating Material Slips
With the new INTERNAL_REFERENCE field, if the field is not null, the system updates the data with the given fields. If INTERNAL_REFERENCE is null, a new record is created.
[Route("api/[controller]/[action]")]
[ApiController]
public class MaterialSlipsController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostMaterialSlips(new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
}, [new() {
Group = 3,
Type = 12,
Date = "29.09.2025",
CurrselTotals = 1,
Transactions = new() {
Transaction = [new() {
ItemCode = "Item Code",
Quantity = 5,
UnitCode = "Unit Code",
UnitConv1 = 1,
UnitConv2 = 1
}]
}
}], cancellationToken));
}
9. Error Handling with PostException
During the posting process, if any errors occur, a custom PostException is thrown. This exception contains detailed information about the failed posts, including the item number and the error message.
Example:
try
{
IList<PostResult> results = await logoClient.PostAccountsRPs(new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
}, new List<Account>
{
new()
{
InternalReference = null,
Title = "Invalid Account",
TaxPayerCode = "INVALID"
}
});
}
catch (PostException ex)
{
Console.WriteLine("An error occurred during the posting process:");
Console.WriteLine(ex.Message);
}
What Happens During an Error:
- Validation: If any
PostResultindicates failure (IsSuccess == false), aPostExceptionis triggered. - Error Details: The exception message includes:
- The item number (
Number). - The entity name (e.g., "Account").
- The error message.
- The item number (
Example Error Message:
Hata Mesajı: 1 numaralı AccountsRP Hata: DBError(8) - Kayıt veritabanına aktarılamadı. 23000 : Cannot insert duplicate key row in object 'dbo.LG_999_CLCARD' with unique index 'I999_CLCARD_I13'. The duplicate key value is (1, 0, 1).\n"
10. Billing Orders with OrderBilling
This method is used to invoice order slips. If the operation does not succeed, the error property is filled in the return object.
[Route("api/[controller]/[action]")]
[ApiController]
public class UnityApplicationController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(OrderBillingResponse))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> OrderBilling(CancellationToken cancellationToken) => Ok(await logoClient.OrderBilling(new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
}, [new() {
OrderRef = 3229, // The Logical Reference of the order you will invoice
Date = "02.10.2025", // The date must be in the day.month.year format.
FicheType = 3, // Invoice Type
DocumentCode = "Document No.",
SpecialCode = "Special Code",
AuthCode = "Authorization Code",
Description1 = "Description 1",
Description2 = "Description 2",
Description3 = "Description 3",
Description4 = "Description 4",
CheckUserRight = true, // Should User Permissions Be Checked?
SqlTransaction = true, // Sql Transaction
EInvoice = false, // Will the order be converted to an e-invoice?
VatExceptReason = "Vat Except Reason"
}, new() {
OrderRef = 3230,
Date = "02.10.2025",
FicheType = 3,
DocumentCode = "SP00000000000003"
}, new() {
OrderRef = 2142,
Date = "02.10.2025",
FicheType = 3,
DocumentCode = "SP00000000000001"
},], cancellationToken));
11. Adding and Updating Sales Dispatches
With the new INTERNAL_REFERENCE field, if the field is not null, the system updates the data with the given fields. If INTERNAL_REFERENCE is null, a new record is created.
[Route("api/[controller]/[action]")]
[ApiController]
public class SalesDispatchesController(LogoClient logoClient, XmlService xmlService) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
private readonly XmlService xmlService = xmlService;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostSalesDispatches(new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
}, [new() {
Type = 9,
Number = "~",
Date = "23.10.2025",
Time = 202052408,
ArpCode = "5000534",
Notes1 = "",
SourceWh = 0,
CreatedBy = 0,
RcRate = 0,
CurrselTotals = 1,
Salesmancode = "",
ShippingAgent = "",
Deductionpart1 = 0,
Deductionpart2 = 0,
Edespatch = 1,
ShipDate = "23.10.2025",
ShipTime = 202052408,
DocDate = "23.10.2025",
DocTime = 202052408,
Transactions =
{
new()
{
Type = 0,
Price = 0,
MasterCode = "DKPN12188",
Sourceindex = 0,
Quantity = 5,
RcXrate = 0,
UnitCode = "ADET",
UnitConv1 = 5,
UnitConv2 = 5,
VatRate = 20,
EdtCurr = 53,
OrderReference = "3001",
Sldetails =
{
new()
{
SourceMtReference = 380,
SourceSltReference = 1,
SourceQuantity = 1,
IOCODE = 4,
SourceWh = 0,
SlType = 1,
SlCode = "123456",
MuQuantity = 1,
UnitCode = "ADET",
Quantity = 1,
UnitConv1 = 1,
UnitConv2 = 1
}
}
}
}
}], cancellationToken));
}
12. Adding And Updating Arp Voucher
With the new INTERNAL_REFERENCE field, if the field is not null, the system updates the data with the given fields. If INTERNAL_REFERENCE is null, a new record is created.
[Route("api/[controller]/[action]")]
[ApiController]
public class ArpVouchersController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostArpVoucher(new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
}, [new() {
Number = "Number",
Date = "26.01.2026",
Type = 70, // Type
Notes1 = "Description",
CurrselTotals = 1,
DataReference = 1,
Arp_Code = "Current Account Code",
ProjectCode = "Project Code",
AffectRisk = 0,
SalesmanCode = "Sales Representative Code"
}], cancellationToken));
}
13. Adding And Updating Bom
With the new INTERNAL_REFERENCE field, if the field is not null, the system updates the data with the given fields. If INTERNAL_REFERENCE is null, a new record is created.
[Route("api/[controller]/[action]")]
[ApiController]
public class BomsController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostBom(new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
}, [new() {
Code = "Test3",
Type = 1,
RevCode = "REVISION - CODE",
RevRecordStatus = 1,
RevDate = "28.01.2026",
RevDataReference = 1,
Lines = [new() {
LineType = 4,
Uinfo1 = 1,
Uinfo2 = 1,
Amount = 1,
Scalable = 1,
InvenNo = -1,
Engineering = 1,
Production = 1,
Cost = 1,
CostRate = 1,
Formula = "1",
EffectOpTime = 1,
ItemCode = "Main material code",
ItemName = "Primary material name",
UnitSetCode = "05",
UnitCode = "Unit Code",
BomType = 1,
OpCode = "Operation Code",
OpName = "Operation Description"
}, new() {
LineType = 0,
Uinfo1 = 1,
Uinfo2 = 1,
Amount = 1,
Scalable = 1,
InvenNo = -1,
Engineering = 1,
Production = 1,
Cost = 1,
Formula = "P1",
ItemCode = "Input material code",
ItemName = "Input material name",
UnitSetCode = "05",
UnitCode = "Unit Code",
BomType = 1,
OpCode = "Operation Code",
OpName = "Operation Description",
DefCostType = 5
}],
MpCode = "Main product code",
MpName = "Main product name",
RoutCode = "PRODUCTION ROUTE CODE",
RoutName = "PRODUCTION ROUTE Description"
}], cancellationToken));
}
🔄 Line Update Behavior
During the update process for the following objects:
- Bom
- Material
- MaterialSlip
- Order
- PurchOrder
- SalesDispatche
- SalesInvoice
If the record to be updated has lines, during the update this record is completely deleted and recreated from scratch with the submitted record.
⚠ Important Warning
Therefore, when updating, if the data contains lines:
- The user must resend all lines.
- All fields must be filled in completely for each line.
- Otherwise, any fields or lines that are not sent will be considered deleted and will not appear in the record.
This approach has been chosen to ensure line synchronization on the Logo side.
14. SelectSql — Dynamic SQL Query Execution
SelectSql allows you to execute dynamic SQL queries against Logo ERP tables/views using a strongly structured query definition (SqlQueryDef). The result is returned as a collection of key-value pairs, which you can map to your own models.
[Route("api/[controller]/[action]")]
[ApiController]
public class SqlsController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<TResponse>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> GetSelect(CancellationToken cancellationToken) => Ok((await logoClient.SelectSql(new()
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
}, new SqlQueryDef()
{
MainTable = "MainTable",
WhereConditions = [
new WhereCondition() {
Column = "Code",
Operator = WhereOperators.Equal,
Value = "{Code}"
}
]
}, cancellationToken)).Select(d => new TResponse(d)));
}
🧱 Example Model Mapping
You are responsible for mapping it to your domain model:
public class TResponse(Dictionary<string, JsonElement?> json)
{
public int Logicalref { get; set; } = int.Parse(json["LOGICALREF"].ToString()!);
public string Code { get; set; } = json["CODE"].ToString()!;
}
🧩 Query Definition (SqlQueryDef)
SqlQueryDef provides a flexible way to construct SQL queries.
Properties
| Property | Description |
|---|---|
MainTable |
Target table or view |
SelectColumns |
Columns to select (default: *) |
SqlJoins |
JOIN definitions |
WhereConditions |
WHERE clause conditions |
HavingConditions |
HAVING clause conditions |
GroupBy |
GROUP BY columns |
OrderBys |
ORDER BY definitions |
Limit |
LIMIT (TOP) |
OffSet |
OFFSET |
Supported Operators
Equal,NotEqualGreaterThan,LessThanLike,NotLikeIn,BetweenIsNull,IsNotNull
🔀 JOIN Example
SqlJoins =
[
new SqlJoin
{
JoinType = JoinType.Inner,
TableName = "LG_001_ITEMS",
Alias = "ITM",
OnClause = "ITM.LOGICALREF = CLCARD.LOGICALREF"
}
]
📊 ORDER BY Example
OrderBys =
[
new OrderBy
{
Column = "CODE",
Descending = false
}
]
WhereConditions Example
WhereConditions = [new() {
Column = "Line.LINETYPE",
Operator = WhereOperators.NotEqual,
Value = 1
}, new() {
Column = "Fiche.LOGICALREF",
Operator = WhereOperators.In,
Value = new List<int>() {
{2111 },
{2137 }
},
Connector = LogicalConnector.And
}]
15. Adding and Updating Purchase Dispatche
With the new INTERNAL_REFERENCE field, if the field is not null, the system updates the data with the given fields. If INTERNAL_REFERENCE is null, a new record is created.
[Route("api/[controller]/[action]")]
[ApiController]
public class PurchaseDispatchesController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostPurchaseDispatches(new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
}, [
new() {
Type = 1,
Number = "Fiche No",
CurrselTotals = 1,
Date = "27.03.2026",
Transactions = [
new() {
MasterCode = "MasterCode",
Quantity = 15,
UnitCode = "UnitCode",
UnitConv1 = 15,
UnitConv2 = 15,
VatRate = 20,
Sldetails = [
new() {
IOCODE = 1,
SlType = 1,
SlCode = "000001",
MuQuantity = 5,
UnitCode = "UnitCode",
Quantity = 5,
RemQuantity = 5,
LuRemQuantity = 5,
UnitConv1 = 5,
UnitConv2 = 5,
DateExpired = "27.04.2026",
DateUrt = "27.03.2026",
Tibbicihazurtdate = "27.03.2026",
}
],
EdtCurr = 1,
Month = 3,
Year = 2026,
AddTaxEffectKdv = 1,
MasterDef = "MasterDef",
}
],
Deductionpart1 = 2,
Deductionpart2 = 3,
DispStatus = 1,
ShipDate = "27.03.2026",
}], cancellationToken));
}
16. ELogo Send and Retrive Documents
Two new functions have been added for ELogo integration: ELogoSendDocument and ELogoGetDocumentData. These functions are used to send and retrive ELogo documents such as e-Invoice, e-Archive, e-Dispatch Advice, and more.
📄 Detailed documentation:
[Route("api/[controller]/[action]")]
[ApiController]
public class ELogoController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(SendDocumentElogoCommandResponse))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Send(CancellationToken cancellationToken) => Ok(await logoClient.ELogoSendDocument(new SendDocumentElogoCommandRequest
{
LogoAuth = new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
},
Params = new SendDocumentParams
{
DocumentType = SendDocumentType.DESPATCHADVICE,
Alias = "urn:mail:defaultgb@firma.com.tr",
Signed = false
},
Document = new ELogoDocument
{
BinaryData = new Base64BinaryData { Value = zipFileBytes },
FileName = "dispatch.zip"
}
}, cancellationToken));
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(GetDocumentDataELogoQueryResponse))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Get(CancellationToken cancellationToken) => Ok(await logoClient.ELogoGetDocumentData(new GetDocumentDataELogoQueryRequest
{
LogoAuth = new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
},
Uuid = "document-uuid-value",
Params = new GetDocumentDataParams
{
DocumentType = GetDocumentDataDocumentType.EINVOICE,
Format = GetDocumentDataFormat.PDF,
Iscancel = false
}
}, cancellationToken));
}
17. Adding and Updating Serial Lot Records
With the new INTERNAL_REFERENCE field, if the field is not null, the system updates the data with the given fields. If INTERNAL_REFERENCE is null, a new record is created.
[Route("api/[controller]/[action]")]
[ApiController]
public class SerialAndLotNumbersController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostSerialAndLotNumbers(new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
}, [new() {
Code = "Test",
Description = "Test Description",
ItemCode = "1985003024",
Type = 1 // 1:Lot 2:Serial
}], cancellationToken));
}
18. Adding and Updating Bank Vouchers
With the new INTERNAL_REFERENCE field, if the field is not null, the system updates the data with the given fields. If INTERNAL_REFERENCE is null, a new record is created.
[Route("api/[controller]/[action]")]
[ApiController]
public class BankVouchersController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Post(CancellationToken cancellationToken) => Ok(await logoClient.PostBankVouchers(new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
}, [new() {
Number = "Fiche No",
AuxilCode = "SpecialCode",
AuthCode = "AuthCode",
Type = 1,
TotalCredit = 100,
Notes1 = "Description",
CurrselTotals = 1,
Transactions = [new() {
Type = 1,
BankaccCode = "BankAccountCode",
ArpCode = "AccountCode",
Sourcefref = 1,
Sign = 1,
Trcode = 1,
Modulenr = 7,
AuxilCode = "SpecialCode",
DocNumber = "DocNo",
Description = "Description",
Credit = 100,
Amount = 100,
TcAmount = 100,
BnkTractingNr = "BankTractingNo",
BankProcType = 1,
DueDate = "08.06.2026",
ProjectCode = "ProjectCode",
BnCrdtype = 1,
Preacclines = [new() {
Linenr = 1,
Distrate = 100,
Date = "08.06.2026",
Month = 6,
Year = 2026,
Prevlinetype = 1,
Modulnr = 4,
Projectcode = "ProjectCode",
Projectname = "Project Name"
}, new() {
Linenr = 1,
Distrate = 100,
Date = "08.06.2026",
Month = 6,
Year = 2026,
Prevlinetype = 2,
Modulnr = 4,
Projectcode = "ProjectCode",
Projectname = "Project Name"
}],
Specode2 = "SpecialCode2",
VatFlag = 1,
}],
ProjectCode = "ProjectCode"
}], cancellationToken));
}
19. GetEDocumentContent
GetEDocumentContent is a service used by Logo ERP (Cloud Connect) users to retrieve e-document content (PDF, HTML, XML, etc.).
This method allows you to access the content of documents such as e-invoices, e-archives, and e-delivery notes in various formats.
📌 Features
- Supports multiple e-document types
- Data retrieval in various output formats (PDF, HTML, XML, etc.)
- GUID-based document access
- Compatible with Logo REST services
📥 Parameters
| Parameter | Description |
|---|---|
| DocType | E-document type |
| OutFormat | Output format |
| Guid | Unique ID value of the relevant document |
📄 Supported DocType Values
| Value | Description |
|---|---|
EINVOICE |
E-Invoice |
APPLICATIONRESPONSE |
E-Invoice Application Response |
EARCHIVEINVOICE |
E-Archive |
DESPATCHADVICE |
E-Delivery Note |
RECEIPTADVICE |
E-Delivery Note Response |
SERECEIPTCLF |
E-SMM (Accounts Receivable Voucher) |
SERECEIPTCSH |
E-SMM (Cash Voucher) |
EPRECEIPT |
E-Supplier |
📤 Supported OutFormat Values
| Value | Description |
|---|---|
XML |
XML format |
UBL |
UBL format |
HTML |
HTML output |
JSON |
JSON output |
HTMLBYGENERALFORMAT |
General-format HTML |
PDF |
PDF document |
public async Task<IActionResult> GetEDocumentContent(CancellationToken cancellationToken)
{
var response = await logoClient.GetEDocumentContentAsync(
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
},
[
new GetEDocumentContentRequest
{
DocType = DocType.DESPATCHADVICE,
OutFormat = OutFormat.HTML,
Guid = "5ede911c-5eb0-4282-b3cd-82e91d143712"
}
],
cancellationToken
);
return Ok(response);
}
⚠️ Notes
PDFoutput is usually returned as Base64-encoded → it must be decoded- Async usage is recommended for large documents
- The GUID value is a unique document ID generated by Logo
🎯 Use Cases
- Retrieving e-invoice PDF output
- Viewing e-Archive HTML
- UBL/XML integrations
- ERP third-party system integrations
📌 Summary
GetEDocumentContent is one of the core endpoints used to securely and flexibly retrieve e-document content from the Logo ERP system. Thanks to its support for various formats, it can be used in both visualization and integration scenarios.
20. ClearHtml
ClearHtml is a helper function used to clean up dirty (escaped/corrupted) content returned in HTML format by the GetEDocumentContent method.
HTML output from logo services typically:
- Contains JSON escape characters (
\",\\n) - Is HTML-encoded (
",&) - Contains corrupted Base64 image strings (with spaces or line breaks)
- May be wrapped in
"characters at the beginning and end
This function normalizes all these issues to produce clean, renderable HTML.
🎯 Objective
- To make the HTML output render properly in the browser
- To prevent Base64 images from becoming corrupted
- To resolve encoding and escape issues
⚙️ How Does It Work?
The function performs the following steps:
- Trim operation
- Removes leading and trailing
"characters - Unescapes JSON escape characters (
Regex.Unescape) - Performs HTML decoding (
WebUtility.HtmlDecode) - Removes whitespace characters from Base64 images (critical step)
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(string))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> ClearHtml(string html, CancellationToken cancellationToken)
=> Ok(await logoClient.ClearHtml(html));
📥 Input (Dirty HTML)
\"<html><body><img src=\"data:image/png;base64,iVBORw0KGgo AAA...\" /></body></html>\"
📤 Output (Clean HTML)
<html>
<body>
<img src="data:image/png;base64,iVBORw0KGgoAAA..." />
</body>
</html>
⚠️ Important Notes
If spaces in Base64 are not removed:
- Images will not render
- PDF conversion will fail
This function should be used specifically in the following cases:
OutFormat = HTMLOutFormat = HTMLBYGENERALFORMAT
🎯 Use Cases
- Pre-processing before HTML → PDF conversion
- WebView / Browser rendering
- Email template generation
- E-Invoice / E-Archive viewing
📌 Summary
ClearHtml is a critical helper function that normalizes corrupted HTML output from Logo in a single step. Its use is mandatory, especially for documents containing base64 images.
21. ConvertHtmlToPdf
ConvertHtmlToPdf is a service used to convert e-documents obtained in HTML format from Logo’s GetEDocumentContent method into PDF.
This function generates the correct PDF output by first cleaning the HTML (ClearHtml) and then rendering it, particularly in cases where HTML output from Logo cannot be converted directly to PDF.
🎯 Purpose
- To convert HTML output from Logo to PDF
- To correctly render documents containing Base64 images
- To generate the PDF output as a byte[] (without disk I/O)
🔄 Recommended Workflow
GetEDocumentContent (HTML)
↓
ClearHtml (required)
↓
ConvertHtmlToPdf
↓
byte[] (PDF)
⚠️ Why Is ClearHtml Required?
The HTML output from GetEDocumentContent is typically:
- Escaped (
\",\\n) - HTML-encoded (
") - Base64 images are corrupted (contain whitespace)
👉 Therefore, it is not recommended to generate a PDF without calling ClearHtml()
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(byte[]))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> ConvertHtmlToPdf(string html, CancellationToken cancellationToken)
=> Ok(await logoClient.ConvertHtmlToPdf(html, cancellationToken));
📥 Input
Cleaned-up HTML (after ClearHtml):
<html>
<body>
<img src="data:image/png;base64,iVBORw0KGgoAAA..." />
</body>
</html>
📤 Output
Type:
byte[]Content: PDF binary data
Usage:
- API response
- File download
- Email attachment
🧠 Technical Details
- Uses the Chromium engine (Playwright)
- Renders HTML in a real browser environment
- Full support for CSS and Base64 images
- Runs in memory without writing to disk
⚠️ Important Considerations
- Launching a browser for each call is resource-intensive → Browser reuse is recommended in production
- Memory consumption may increase with large HTML content
- Timeout management is required
🎯 Use Cases
- E-invoice PDF generation
- E-archive document archiving
- Email PDF attachments
- Report outputs
📌 Summary
ConvertHtmlToPdf is a service that reliably converts HTML documents obtained from Logo into PDFs. For accurate results, it must be used in conjunction with ClearHtml.
22. SendRecvEDispatchDocuments
SendRecvEDispatchDocuments is a service that performs e-invoice sending and receiving operations for Logo ERP (Cloud Connect) users.
Using this method, e-invoices in the system can be:
- Sent to the Turkish Revenue Administration (Send)
- Received (Receive)
🎯 Purpose
- To trigger e-invoice sending processes
- To import incoming e-invoices into the system
- To provide support for individual or batch processing
📥 Parameters
| Parameter | Type | Description |
|---|---|---|
| IsSend | bool | If true, the sending process is performed |
| IsReceive | bool | If true, the import process is performed |
| References | IList<string> | List of invoice references or GUIDs |
🔍 Using References (Refs)
The following can be added to the list:
- Invoice reference
- or GUID (36 characters)
can be added.
👉 If the value is 36 characters, the system automatically treats it as a GUID and resolves the corresponding receipt reference on its own.
⚠️ Important Behavior
IsSend = true
References = empty
👉 In this case:
➡️ ALL vouchers in the “To Be Sent” tab are sent
📤 Return Type
| Type | Description |
|---|---|
| string | Transaction log and result |
📄 Sample Response
------------ Jan 25, 2021 8:32:29 PM ------------
8:32:29 PM Sending transactions...
8:32:31 PM Number of packets sent: 1
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(SendRecvEDispatchDocumentsResponse))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> SendRecvEDispatchDocuments(CancellationToken cancellationToken)
=> Ok(await logoClient.SendRecvEDispatchDocumentsAsync(
new LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
},
[
new SendRecvEDispatchDocumentsRequest
{
IsSend = true,
IsReceive = false,
Referances = [
"5ede911c-5eb0-4282-b3cd-82e91d143712",
"e37586be-b652-42b6-b8a7-d29f594ca2fe",
"b90df056-c935-4478-8e6e-931fa4749007"
]
}
],
cancellationToken));
🧠 Technical Details
- Uses the Cloud Connect infrastructure
- Operations are executed via Logo Objects
- Supports batch processing
- Can operate using both GUID-based and reference-based methods
⚠️ Important Notes
- Both
IsSendandIsReceivecan be true at the same time - Processing time may increase with large lists
- Detailed results can be obtained by parsing the log string
- Errors may be returned as strings in the response
🎯 Use Cases
- Bulk e-invoice sending
- Retrieving incoming e-invoices
- Scheduled (cron) jobs
- ERP integrations
📌 Summary
SendRecvEDispatchDocuments is a powerful service that centrally manages e-invoice sending and receiving operations. It offers flexible usage thanks to reference or GUID support and is ideal for batch processing scenarios.
📑 API Features
| Feature | Description |
|---|---|
| Current Account | Create and update an account with TaxPayerCode validation. |
| Shipping Address | Add and update customer shipping addresses. |
| Sales Order | Create and update sales orders. |
| Purchase Order | Add and update purchase orders. |
| Material | Add and update materials. |
| Sales Invoice | Add and update sales invoices. |
| Material Slips | Add and update material slips. |
| Error Handling | Custom PostException for detailed error reporting. |
| OrderBilling: Billing Order Invoices | Invoices for order slips. |
| Sales Dispatches | Adding and updating sales dispatches. |
| Arp Vouchers | Adding and Updating arp vouchers. |
| Bom | Adding and Updating boms. |
| SelectSql | Dynamic SQL Query Execution. |
| Purchase Dispatche | Adding and Updating purchase dispatches. |
| ELogoSendDocument | Send e-Invoice, e-Archive, e-Dispatch Advice and other documents via ELogo. |
| ELogoGetDocumentData | Retrive sent or received document in UBL/HTML/PDF format via ELogo. |
| Serial Lot Records | Adding and Updating serial lot records. |
| Bank Vouchers | Adding and Updating bank vouchers. |
| GetEDocumentContent | Retrieve e-document content (PDF, HTML, XML, etc.). |
| ClearHtml | Clean up dirty (escaped/corrupted) content. |
| ConvertHtmlToPdf | Convert e-documents obtained in HTML format from GetEDocumentContent method into PDF. |
| SendRecvEDispatchDocuments | E-invoice sending and receiving operations. |
🛠️ Development
- Programming Language: C#
- Platform: .NET 6+
📄 License
This project is licensed under the MIT License. For more information, please see the LICENSE file.
📫 Contact
If you have any questions or feedback about this project, please reach out to me:
Hakkıcan Bülüç
- LinkedIn: Hakkıcan Bülüç
- GitHub: Hakkıcan Bülüç
Added Features:
- PostResult: With this release, ToString() has been added to PostResult.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- AutoMapper (>= 13.0.1)
- MediatR (>= 12.4.1)
- Microsoft.AspNetCore.Http.Abstractions (>= 2.1.1)
- Microsoft.Extensions.Configuration.Abstractions (>= 9.0.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.10)
- Microsoft.Extensions.Http (>= 8.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 9.0.10)
- Microsoft.Playwright (>= 1.60.0)
- SendGrid (>= 9.29.3)
- System.Security.Cryptography.Xml (>= 10.0.8)
- System.ServiceModel.Http (>= 8.1.2)
- System.ServiceModel.NetTcp (>= 8.1.2)
- System.ServiceModel.Primitives (>= 8.1.2)
- System.Text.Encodings.Web (>= 10.0.8)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.3.792 | 46 | 8/27/2026 |
| 1.3.791 | 152 | 8/20/2026 |
| 1.3.79 | 187 | 7/22/2026 |
| 1.3.78 | 99 | 7/21/2026 |
| 1.3.77 | 102 | 7/17/2026 |
| 1.3.76 | 104 | 7/17/2026 |
| 1.3.75 | 95 | 7/16/2026 |
| 1.3.74 | 105 | 7/10/2026 |
| 1.3.73 | 107 | 7/1/2026 |
| 1.3.72 | 113 | 6/29/2026 |
| 1.3.71 | 126 | 6/22/2026 |
| 1.3.7 | 118 | 6/22/2026 |
| 1.3.6 | 113 | 6/22/2026 |
| 1.3.5 | 113 | 6/19/2026 |
| 1.3.4 | 104 | 6/10/2026 |
| 1.3.3 | 123 | 6/9/2026 |
| 1.3.2 | 120 | 6/9/2026 |
| 1.3.1 | 120 | 6/9/2026 |
| 1.3.0 | 127 | 6/8/2026 |
| 1.2.9 | 109 | 5/14/2026 |
Bu sürümle birlikte PostResult'a ToString()'u eklenmiştir.