Sozer.Logo
2.0.2
dotnet add package Sozer.Logo --version 2.0.2
NuGet\Install-Package Sozer.Logo -Version 2.0.2
<PackageReference Include="Sozer.Logo" Version="2.0.2" />
<PackageVersion Include="Sozer.Logo" Version="2.0.2" />
<PackageReference Include="Sozer.Logo" />
paket add Sozer.Logo --version 2.0.2
#r "nuget: Sozer.Logo, 2.0.2"
#:package Sozer.Logo@2.0.2
#addin nuget:?package=Sozer.Logo&version=2.0.2
#tool nuget:?package=Sozer.Logo&version=2.0.2
Sözer Logo
<a name="tr"></a>
🇹🇷 Türkçe
Sözer Logo, 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'yu NuGet üzerinden projelerinize ekleyebilirsiniz:
dotnet add package Sozer.Logo
veya Visual Studio NuGet Paket Yöneticisi'nden ekleyin:
- Tools > NuGet Package Manager > Manage NuGet Packages for Solution...
- Browse sekmesinde
Sozer Logo Objectsaratın ve projeye ekleyin.
🚀 Kullanım
Paketin kullanımı basittir. Genel işlemler için bir LogoClient, TaxPayerCode (VKN) doğrulaması için bir ELogoClient ve verileri XML'e aktarmak için bir XmlService 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
{
"ELogoService": {
"username": "Kullanıcı_adi",
"password": "parola"
}
}
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.AddSozerLogoObjects("<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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, [ new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.AccountsRP()
{
Code = "Cari Hesap Kodu",
TaxPayerCode = "1234567890" // Hesap türünü doğrular ve belirler
} ], cancellationToken));
[HttpPut]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Update(CancellationToken cancellationToken) => Ok(await logoClient.PostAccountsRPs(new SozerLogoPackage.SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, [
new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.AccountsRP() {
InternalReference = 7, // Var olan kaydı güncleller
Title = "Güncelleme"
}
], cancellationToken));
}
3. Cari Hesap Sevkiyat Adresi Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem INTERNAL_REFERENCE değerini kullanarak Logo'dan veriyi çeker ve 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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, [new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.ArpShipLic() {
ArpCode = "Cari Hesap Kodu",
Code = "Sevkiyat Adresi Kodu"
}], cancellationToken));
[HttpPut]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Update(CancellationToken cancellationToken) => Ok(await logoClient.PostArpShipLics(new SozerLogoPackage.SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, [
new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.ArpShipLic() {
InternalReference = 12, // Var olan kaydı güncleller
Title = "Güncelleme"
}
], cancellationToken));
}
4. Satış Siparişi Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem INTERNAL_REFERENCE değerini kullanarak Logo'dan veriyi çeker ve 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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, [
new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.Order() {
Number = "Satış Siparişi Numarası"
}
], cancellationToken));
[HttpPut]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Update(CancellationToken cancellationToken) => Ok(await logoClient.PostOrders(new SozerLogoPackage.SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, [
new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.Order() {
InternalReference = 1, // Var olan kaydı güncleller
DocNumber = "Güncelleme"
}
], cancellationToken));
}
5. Satınalma Siparişi Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem INTERNAL_REFERENCE değerini kullanarak Logo'dan veriyi çeker ve 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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, [new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.PurchOrder() {
Number = "Satınalma Siparişi Numarası"
}], cancellationToken));
[HttpPut]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Update(CancellationToken cancellationToken) => Ok(await logoClient.PostPurchOrders(new SozerLogoPackage.SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, [
new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.PurchOrder() {
InternalReference = 2004, // Var olan kaydı güncleller
DocNumber = "Güncelleme"
}
], cancellationToken));
}
6. Malzeme Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem INTERNAL_REFERENCE değerini kullanarak Logo'dan veriyi çeker ve 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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, [new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.Material() {
Code = "Malzeme Kodu"
}], cancellationToken));
[HttpPut]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Update(CancellationToken cancellationToken) => Ok(await logoClient.PostMaterials(new SozerLogoPackage.SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, [
new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.Material() {
InternalReference = 2003, // Var olan kaydı güncleller
Name = "Güncelleme"
}
], cancellationToken));
}
7. Satış Faturaları Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem INTERNAL_REFERENCE değerini kullanarak Logo'dan veriyi çeker ve verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
using Microsoft.AspNetCore.Mvc;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, [new SalesInvoice() {
Type = 3,
DocTrackNr = "Dokuman Izleme Numarasi",
DocNumber = "Belge No",
AuxilCode = "Ozel Kod",
AuthCode = "1",
Arp_Code = "1341911",
PostFlags = 247
}], cancellationToken));
}
[HttpPut]
[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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, [new SalesInvoice() {
InternalReference = 2003, // Var olan kaydı güncleller
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 INTERNAL_REFERENCE değerini kullanarak Logo'dan veriyi çeker ve verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
using Microsoft.AspNetCore.Mvc;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, [new() {
Group = 3,
Type = 12,
Date = "29.09.2025",
CurrselTotals = 1,
Transactions = new() {
Transaction = [new() {
ItemCode = "Malzeme Kodu",
Quantity = 5, // Miktar
UnitCode = "Birim Kodu",
UnitConv1 = 1,
UnitConv2 = 1
}]
}
}], cancellationToken));
}
}
9. TaxPayerCode (VKN) Doğrulama
ELogoClient`, Gelir İdaresi Başkanlığı (GİB) hizmetini kullanarak VKN'leri doğrulamak için basit bir yöntem sağlar.
using Microsoft.AspNetCore.Mvc;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ELogoServicesController(ELogoClient eLogoClient) : ControllerBase
{
private readonly ELogoClient eLogoClient = eLogoClient;
[HttpPost]
public async Task<IActionResult> CheckGibUser([FromBody] string vkn) => Ok(await eLogoClient.CheckGibUser(vkn));
}
}
Dönüş sınıfı. Eğer geçersiz bir vergi kimlik numarası verilmişse, Vkn = vkn; diğer proplar varsayılan değerleri alırlar.
public class VknInfos
{
public string? Vkn { get; set; }
public string? InvoiceGbLink { get; set; }
public string? InvoicePkLink { get; set; }
public string? DespatcheGbLink { get; set; }
public string? DespatchePkLink { get; set; }
public int Invoice { get; set; }
public int Despatch { get; set; }
}
10. Verileri XML'e Aktarma
XmlService, herhangi bir DataBase nesnesini bir XML dizesine dönüştürmenize olanak tanır.
[Route("api/[controller]/[action]")]
[ApiController]
public class AccountsRpController(LogoClient logoClient, XmlService xmlService) : ControllerBase
{
private readonly XmlService xmlService = xmlService;
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(string))]
public IActionResult GetXml() => Ok(xmlService.ExportToXmlStr(new SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.AccountsRP()
{
AccountType = 3,
Title = "Earchive_Test_Tc_2"
}));
}
11. 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ı
PeriodNr = null // dönemNumarası
}, 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"
12. Fatura İptali
Daha önce, bir faturayı iptal etmek için yalnızca XML veya LObjects üzerinden CANCELLED alanına 1 değeri verilmesi yeterli görülüyordu. Ancak bu yöntem, Logo ERP arayüzünde iptal işlemi sırasında gerçekleştirilen kontrolleri ve ek işlemleri atladığı için yanlış bir kullanım olarak tespit edilmiştir.
Bu nedenle, sistemin ERP arayüzü ile aynı şekilde davranmasını sağlamak amacıyla CancelInvoice adında yeni bir fonksiyon eklenmiştir. Bu fonksiyon kullanılarak yapılan iptaller, ERP’deki kontrol ve süreçlerden geçerek güvenilir ve doğru bir şekilde tamamlanır.
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class UnityApplicationController(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> CancelInvoice(CancellationToken cancellationToken) => Ok(await logoClient.CancelInvoice(new SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
},
8, // İptal edilecek fatura referansı
cancellationToken));
}
}
13. SelectQuery ile Dinamik Sorgular
Logo veritabanı üzerinde gelişmiş dinamik sorgular çalıştırmak için kullanılır. Bu fonksiyon ile;
- Seçilecek kolonlar (
SelectClause), - Tablo alias (takma ad),
WHEREkoşulları,JOINişlemleri,ORDER BYsıralamaları
tanımlanarak esnek SQL sorguları oluşturulabilir.
Fonksiyon, sorgu sonucunu IList<object> olarak döndürür. Dönen her kayıt JSON tabanlı nesne formatındadır.
Bu nedenle tip güvenliği bulunmaz; sonuçlar kullanım sırasında ilgili modele cast edilmelidir.
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class UnityApplicationController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<object>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> SelectQuery(CancellationToken cancellationToken) => Ok((await logoClient.SelectQuery(new SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
},
[new() {
FieldName = "ORD.DATE_"
}, new() {
FieldName = "ORD.LOGICALREF"
}, new() {
FieldName = "ORD.PRICE",
FieldAlias = "Price" // İsteğe bağlı alana takma ad verilebilir
}], SozerLogoAPI.Core.Application.Models.UnityObjectModels.TableName.ORFLINE, cancellationToken,
whereClauses: [new() {
LeftValue = "CARDTYPE", // Where ifadesindeki soldaki kolumn adı (örnektir)
RelationalOperator = SozerLogoAPI.Core.Application.Models.UnityObjectModels.RelationalOperator.Equal, // Where ifadesindeki ilişkisel operatör
RightValue = "3", // Where ifadesindeki sağdaki kontrol değeri (örnektir)
LogicalOperator = SozerLogoAPI.Core.Application.Models.UnityObjectModels.LogicalOperator.AND // Where ifadelerini bağlayan mantıksal operatör
},
"ORD", // İsteğe bağlı Tabloya takma ad verilebilir
joinClauses: [new() {
TableName = "LG_999_ITEMS",
TableAlias = "ITM",
MainField = "ORD.STOCKREF", // Ana tablonun bağlanacağı kolumn adı takma ad ile birlikte
JoinField = "ITM.LOGICALREF", // Yan tablonun bağlanacağı kolumn adı takma ad ile birlikte
RelationalOperator = SozerLogoAPI.Core.Application.Models.UnityObjectModels.RelationalOperator.Equal,
TableJoinType = SozerLogoAPI.Core.Application.Models.UnityObjectModels.TableJoinType.LeftOuter
}], orderClauses: [new() {
FieldName = "ORD.DATE_", // sıralama alan adı takma ad ile birlikte olabilir
SortOrderType = SozerLogoAPI.Core.Application.Models.UnityObjectModels.SortOrderType.Desc
}, new() {
FieldName = "ORD.LOGICALREF",
SortOrderType = SozerLogoAPI.Core.Application.Models.UnityObjectModels.SortOrderType.Desc
}])).Select(o =>
{
JObject keyValuePairs = (JObject)o;
return new Join()
{
Date_ = keyValuePairs.GetValue("ORD.DATE_")!.Value<string>()!,
Logicalref = keyValuePairs.GetValue("ORD.LOGICALREF")!.Value<string>()!,
Price = keyValuePairs.GetValue("ORD.PRICE")!.Value<string>()!,
};
}));
}
}
14. 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.
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[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ı
PeriodNr = null // dönemNumarası
}, [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));
15. ConvertDate ile Logo için Date'e Dönüştürme
Tarih bilgisi veri tabanında bazı alanlarda Long integer değer olarak tutulur. Bu yöntem tarih bilgisinden kaynaklanabilecek sorunları minimize eder.
Tarih bilgisini LBS Long integer formatına dönüştürmek için bu metodu kullanırız. Methoda DateTime bilgisini geçeriz. Tarihin formatlanmış hali Object değer olarak döner. Aşağıda Tarih formatlama işlemi sırasında kullanılan formül anlatılmıştır.
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class UnityApplicationController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Object))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> ConvertDate(CancellationToken cancellationToken) => Ok(await logoClient.ConvertDate(new DateTime(2025, 10, 23), cancellationToken));
}
}
16. Satış İrsaliyesi Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem INTERNAL_REFERENCE değerini kullanarak Logo'dan veriyi çeker ve verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
using Microsoft.AspNetCore.Mvc;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, [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));
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(string))]
public IActionResult GetXml(SalesDispatche salesDispatche) => Ok(xmlService.ExportToXmlStr(new SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, salesDispatche));
}
}
17. Cari Hesap Fişi Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem INTERNAL_REFERENCE değerini kullanarak Logo'dan veriyi çeker ve verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
using Microsoft.AspNetCore.Mvc;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, [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));
}
}
18. Ürün Reçetesi Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem INTERNAL_REFERENCE değerini kullanarak Logo'dan veriyi çeker ve verilen alanlarla günceller. INTERNAL_REFERENCE null ise yeni bir kayıt oluşturulur.
using Microsoft.AspNetCore.Mvc;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "kullanıcıAdı",
Password = "şifre",
FirmNo = 0, // firmaNumarası
PeriodNr = null // dönemNumarası
}, [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 ilgili kaydın satırları (Lines) mevcutsa, güncelleme sırasında bu satırlar tamamen silinir ve gönderilen yeni satır listesi 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.
19. Seri Lot Tablosu Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem INTERNAL_REFERENCE değerini kullanarak Logo'dan veriyi çeker ve 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ı
PeriodNr = null // dönemNumarası
}, [new() {
Code = "Kodu",
Description = "Aciklama",
ItemCode = "MalzemeKodu",
Type = 2
}], cancellationToken));
}
20. Satınalma İrsaliye Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem INTERNAL_REFERENCE değerini kullanarak Logo'dan veriyi çeker ve 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ı
PeriodNr = null // dönemNumarası
}, [
new() {
Type = 1,
Number = "Numara",
CurrselTotals = 1,
Date = "08.06.2026",
Transactions = [
new() {
MasterCode = "MalzemeKodu",
Quantity = 15,
UnitCode = "BirimKodu",
UnitConv1 = 15,
UnitConv2 = 15,
VatRate = 20,
Sldetails = [
new() {
IOCODE = 1,
SlType = 1,
SlCode = "000001",
MuQuantity = 5,
UnitCode = "BirimKodu",
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 = "MalzemeTanimi",
}
],
Deductionpart1 = 2,
Deductionpart2 = 3,
DispStatus = 1,
ShipDate = "27.03.2026",
}], cancellationToken));
}
21. Banka Fişi Ekleme Ve Güncelleme
Yeni INTERNAL_REFERENCE alanı ile eğer alan null değilse sistem INTERNAL_REFERENCE değerini kullanarak Logo'dan veriyi çeker ve 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ı
PeriodNr = null // dönemNumarası
}, [new() {
Number = "Numara",
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 = "Proje Adi"
}],
Specode2 = "HareketÖzelKodu2",
VatFlag = 1,
}],
ProjectCode = "ProjeKodu"
}], cancellationToken));
}
📑 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. |
| Vergi Mükellefi Kodu Doğrulama | Gelir İdaresi Başkanlığı aracılığıyla VKN'yi doğrulayın. |
| XML Export | Herhangi bir DataBase nesnesini XML formatına dönüştürün. |
| Hata İşleme | Ayrıntılı hata raporlaması için özel PostException. |
| Fatura İptali | Fatura referansı ile Fatura İptali. |
| SelectQuery ile Dinamik Sorgular | Logo veritabanı üzerinde dinamik sorgular. |
| OrderBilling ile Sipariş Faturalarını Faturalamak | Sipariş fişlerini faturalar. |
| ConvertDate ile Logo için Date'e Dönüştürme | DateTime'ı dönüştürür. |
| 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. |
| Seri Lot Tablosu | Seri Lot Tablosu ekleme ve güncelleme işlemi. |
| Satınalma İrsaliye | Satınalma İrsaliye ekleme ve güncelleme işlemi. |
| Banka Fişi | Banka Fişi ekleme ve güncelleme işlemi. |
🛠️ Geliştirme
- Programlama Dili: C#
- Platform: .NET 6+
- Bağımlılık: UnityObjects Library
🙏 Teşekkür
Bu proje, ekibimin işbirliği ve çabaları olmadan mümkün olamazdı.
Geliştirici olarak olağanüstü katkıları için Ahmet Balaman'a özel teşekkürler.
- LinkedIn: Ahmet Balaman
- GitHub: Ahmet Balaman
📄 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:
- Cari Hesap Fişi: Bu sürümle birlikte Cari Hesap Fişi'ne yeni alanlar eklenmiştir.
<a name="en"></a>
🇺🇸 English
Sözer Logo is a .NET library developed for integration with Logo Software products. This API 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 API to your projects via NuGet:
dotnet add package Sozer.Logo
or add it through Visual Studio NuGet Package Manager:
- Tools > NuGet Package Manager > Manage NuGet Packages for Solution...
- Search for
Sozer Logo Objectsin the Browse tab and add it to your project.
🚀 Usage
The package is straightforward to use. It includes a LogoClient for general operations, an ELogoClient for validating TaxPayerCode (VKN), and an XmlService for exporting data to XML.
1. Connection Setup
You need to provide the following information in the appsettings.json file for ELogoClient login procedures:
{
"ELogoService": {
"username": "username",
"password": "password"
}
}
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.AddSozerLogoObjects("<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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, [ new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.AccountsRP()
{
Code = "Current Account Code",
TaxPayerCode = "1234567890", // Validates and determines account type
} ], cancellationToken));
[HttpPut]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Update(CancellationToken cancellationToken) => Ok(await logoClient.PostAccountsRPs(new SozerLogoPackage.SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, [
new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.AccountsRP() {
InternalReference = 7, // Updates existing record
Title = "Update"
}
], cancellationToken));
}
3. Adding And Updating Account Shipping Addresses
With the new INTERNAL_REFERENCE field, if the field is not null, the system retrieves the data from Logo using the INTERNAL_REFERENCE value and updates it with the provided 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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, [new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.ArpShipLic() {
ArpCode = "Current Account Code",
Code = "Shipping Address Code"
}], cancellationToken));
[HttpPut]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Update(CancellationToken cancellationToken) => Ok(await logoClient.PostArpShipLics(new SozerLogoPackage.SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, [
new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.ArpShipLic() {
InternalReference = 12, // Updates existing record
Title = "Update"
}
], cancellationToken));
}
4. Adding And Updating Sales Orders
With the new INTERNAL_REFERENCE field, if the field is not null, the system retrieves the data from Logo using the INTERNAL_REFERENCE value and updates it with the provided 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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, [
new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.Order() {
Number = "Sales Order Number"
}
], cancellationToken));
[HttpPut]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Update(CancellationToken cancellationToken) => Ok(await logoClient.PostOrders(new SozerLogoPackage.SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, [
new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.Order() {
InternalReference = 1, // Updates existing record
DocNumber = "Update"
}
], cancellationToken));
}
5. Adding And Updating Purchase Order
With the new INTERNAL_REFERENCE field, if the field is not null, the system retrieves the data from Logo using the INTERNAL_REFERENCE value and updates it with the provided 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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, [new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.PurchOrder() {
Number = "Purchase Order Number"
}], cancellationToken));
[HttpPut]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Update(CancellationToken cancellationToken) => Ok(await logoClient.PostPurchOrders(new SozerLogoPackage.SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, [
new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.PurchOrder() {
InternalReference = 2004, // Updates existing record
DocNumber = "Update"
}
], cancellationToken));
}
6. Adding And Updating Material
With the new INTERNAL_REFERENCE field, if the field is not null, the system retrieves the data from Logo using the INTERNAL_REFERENCE value and updates it with the provided 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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, [new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.Material() {
Code = "Material Code"
}], cancellationToken));
[HttpPut]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<PostResult>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> Update(CancellationToken cancellationToken) => Ok(await logoClient.PostMaterials(new SozerLogoPackage.SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, [
new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.Material() {
InternalReference = 2003, // Updates existing record
Name = "Update"
}
], cancellationToken));
}
7. Adding And Updating Sales Invoice
With the new INTERNAL_REFERENCE field, if the field is not null, the system retrieves the data from Logo using the INTERNAL_REFERENCE value and updates it with the provided fields. If INTERNAL_REFERENCE is null, a new record is created.
using Microsoft.AspNetCore.Mvc;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, [new SalesInvoice() {
Type = 3,
}], cancellationToken));
}
[HttpPut]
[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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, [new SalesInvoice() {
InternalReference = 2003, // Updates existing record
Type = 3,
}], cancellationToken));
}
}
8. Adding and Updating Material Slips
With the new INTERNAL_REFERENCE field, if the field is not null, the system retrieves the data from Logo using the INTERNAL_REFERENCE value and updates it with the provided fields. If INTERNAL_REFERENCE is null, a new record is created.
using Microsoft.AspNetCore.Mvc;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, [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. Validating a TaxPayerCode (VKN)
The ELogoClient provides a simple method to validate VKNs using the Turkish Revenue Administration (GIB) service.
using Microsoft.AspNetCore.Mvc;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ELogoServicesController(ELogoClient eLogoClient) : ControllerBase
{
private readonly ELogoClient eLogoClient = eLogoClient;
[HttpPost]
public async Task<IActionResult> CheckGibUser([FromBody] string vkn) => Ok(await eLogoClient.CheckGibUser(vkn));
}
}
Return class. If an invalid tax ID number is provided, Vkn = vkn; other properties take their default values.
public class VknInfos
{
public string? Vkn { get; set; }
public string? InvoiceGbLink { get; set; }
public string? InvoicePkLink { get; set; }
public string? DespatcheGbLink { get; set; }
public string? DespatchePkLink { get; set; }
public int Invoice { get; set; }
public int Despatch { get; set; }
}
10. Exporting Data to XML
The XmlService allows you to convert any DataBase entity to an XML string.
[Route("api/[controller]/[action]")]
[ApiController]
public class AccountsRpController(LogoClient logoClient, XmlService xmlService) : ControllerBase
{
private readonly XmlService xmlService = xmlService;
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(string))]
public IActionResult GetXml() => Ok(xmlService.ExportToXmlStr(new SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, new SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities.AccountsRP()
{
AccountType = 3,
Title = "Earchive_Test_Tc_2"
}));
}
11. 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
PeriodNr = null // periodNumber
}, 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"
12. Cancel Invoice
Previously, to cancel an invoice, it was considered sufficient to simply set the value of the CANCELLED field to 1 via XML or LObjects. However, this method has been identified as incorrect usage because it bypasses the checks and additional processes performed during the cancellation process in the Logo ERP interface.
Therefore, a new function called CancelInvoice has been added to ensure that the system behaves in the same way as the ERP interface. Cancellations made using this function are completed reliably and accurately, passing through the controls and processes in the ERP.
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class UnityApplicationController(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> CancelInvoice(CancellationToken cancellationToken) => Ok(await logoClient.CancelInvoice(new SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
},
8, // Reference of the invoice to be canceled
cancellationToken));
}
}
13. Dynamic Queries with SelectQuery
It is used to run advanced dynamic queries on the logo database. With this function, you can create flexible SQL queries by defining:
- Columns to select (
SelectClause), - Table alias (nickname),
WHEREconditions,JOINoperations,ORDER BYsorting.
The function returns the query result as an IList<object>. Each returned record is in a JSON-based object format.
Therefore, there is no type safety; results must be cast to the relevant model during use.
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class UnityApplicationController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IList<object>))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> SelectQuery(CancellationToken cancellationToken) => Ok((await logoClient.SelectQuery(new SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
},
[new() {
FieldName = "ORD.DATE_"
}, new() {
FieldName = "ORD.LOGICALREF"
}, new() {
FieldName = "ORD.PRICE",
FieldAlias = "Price" // A field alias can be assigned to the optional field
}], SozerLogoAPI.Core.Application.Models.UnityObjectModels.TableName.ORFLINE, cancellationToken,
whereClauses: [new() {
LeftValue = "CARDTYPE", // The column name on the left in the WHERE clause (example)
RelationalOperator = SozerLogoAPI.Core.Application.Models.UnityObjectModels.RelationalOperator.Equal, // Relational operator in the where clause
RightValue = "3", // The control value on the right side of the where clause (example)
LogicalOperator = SozerLogoAPI.Core.Application.Models.UnityObjectModels.LogicalOperator.AND // Logical operators connecting where statements
},
"ORD", // Optional A alias can be given to the table
joinClauses: [new() {
TableName = "LG_999_ITEMS",
TableAlias = "ITM",
MainField = "ORD.STOCKREF", // The column name to which the main table will be joined, along with the alias
JoinField = "ITM.LOGICALREF", // The column name to which the side table will be joined, along with the alias
RelationalOperator = SozerLogoAPI.Core.Application.Models.UnityObjectModels.RelationalOperator.Equal,
TableJoinType = SozerLogoAPI.Core.Application.Models.UnityObjectModels.TableJoinType.LeftOuter
}], orderClauses: [new() {
FieldName = "ORD.DATE_", // The sorting field name can be combined with a alias.
SortOrderType = SozerLogoAPI.Core.Application.Models.UnityObjectModels.SortOrderType.Desc
}, new() {
FieldName = "ORD.LOGICALREF",
SortOrderType = SozerLogoAPI.Core.Application.Models.UnityObjectModels.SortOrderType.Desc
}])).Select(o =>
{
JObject keyValuePairs = (JObject)o;
return new Join()
{
Date_ = keyValuePairs.GetValue("ORD.DATE_")!.Value<string>()!,
Logicalref = keyValuePairs.GetValue("ORD.LOGICALREF")!.Value<string>()!,
Price = keyValuePairs.GetValue("ORD.PRICE")!.Value<string>()!,
};
}));
}
}
14. 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.
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[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
PeriodNr = null // periodNumber
}, [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));
15. Converting to Date for Logo Using ConvertDate
Date information is stored as a long integer value in some fields in the database. This method minimizes problems that may arise from date information.
We use this method to convert date information to LBS Long integer format. We pass the DateTime information to the method. The formatted date returns as an Object value. The formula used during the date formatting process is explained below.
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class UnityApplicationController(LogoClient logoClient) : ControllerBase
{
private readonly LogoClient logoClient = logoClient;
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Object))]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ExceptionModel))]
public async Task<IActionResult> ConvertDate(CancellationToken cancellationToken) => Ok(await logoClient.ConvertDate(new DateTime(2025, 10, 23), cancellationToken));
}
}
16. Adding and Updating Sales Dispatche
With the new INTERNAL_REFERENCE field, if the field is not null, the system pulls the data from Logo using the INTERNAL_REFERENCE value and updates it with the given fields. If INTERNAL_REFERENCE is null, a new record is created.
using Microsoft.AspNetCore.Mvc;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Core.Domain.Entities;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, [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));
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(string))]
public IActionResult GetXml(SalesDispatche salesDispatche) => Ok(xmlService.ExportToXmlStr(new SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, salesDispatche));
}
}
17. Adding And Updating Arp Voucher
With the new INTERNAL_REFERENCE field, if the field is not null, the system retrieves the data from Logo using the INTERNAL_REFERENCE value and updates it with the provided fields. If INTERNAL_REFERENCE is null, a new record is created.
using Microsoft.AspNetCore.Mvc;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, [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));
}
}
18. Adding And Updating Bom
With the new INTERNAL_REFERENCE field, if the field is not null, the system retrieves the data from Logo using the INTERNAL_REFERENCE value and updates it with the provided fields. If INTERNAL_REFERENCE is null, a new record is created.
using Microsoft.AspNetCore.Mvc;
using SozerLogoPackage.SozerLogoAPI.Core.Application.Exceptions;
using SozerLogoPackage.SozerLogoAPI.Presentation;
namespace SozerLogoPackage.API.Controllers
{
[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 SozerLogoAPI.Core.Application.Models.LogoAuth
{
Username = "username",
Password = "password",
FirmNo = 0, // firmNumber
PeriodNr = null // periodNumber
}, [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 relevant record has lines, these lines are completely deleted during the update and recreated from scratch with the new list of lines sent.
⚠ 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.
19. Adding And Updating Serial Lot Records
With the new INTERNAL_REFERENCE field, if the field is not null, the system retrieves the data from Logo using the INTERNAL_REFERENCE value and updates it with the provided 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
PeriodNr = null // periodNumber
}, [new() {
Code = "Code",
Description = "Description",
ItemCode = "ItemCode",
Type = 2
}], cancellationToken));
}
20. Adding And Updating Purchase Dispatches
With the new INTERNAL_REFERENCE field, if the field is not null, the system retrieves the data from Logo using the INTERNAL_REFERENCE value and updates it with the provided 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
PeriodNr = null // periodNumber
}, [
new() {
Type = 1,
Number = "Number",
CurrselTotals = 1,
Date = "08.06.2026",
Transactions = [
new() {
MasterCode = "ItemCode",
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 = "ItemDefinition",
}
],
Deductionpart1 = 2,
Deductionpart2 = 3,
DispStatus = 1,
ShipDate = "27.03.2026",
}], cancellationToken));
}
21. Adding And Updating Bank Vouchers
With the new INTERNAL_REFERENCE field, if the field is not null, the system retrieves the data from Logo using the INTERNAL_REFERENCE value and updates it with the provided 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
PeriodNr = null // periodNumber
}, [new() {
Number = "Number",
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 = "DocumentCode",
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"
}],
Specode2 = "SpecialCode2",
VatFlag = 1,
}],
ProjectCode = "ProjectCode"
}], cancellationToken));
}
📑 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. |
| TaxPayerCode Validation | Validate VKN via the Turkish Revenue Administration. |
| XML Export | Convert any DataBase entity to XML format. |
| Error Handling | Custom PostException for detailed error reporting. |
| Cancel Invoice | Canceling a Invoice. |
| Dynamic Queries with SelectQuery | Run dynamic queries on the Logo database. |
| OrderBilling: Billing Order Invoices | Invoices for order slips. |
| ConvertDate to Date for Logo | Converts DateTime. |
| Sales Dispatches | Adding and updating sales dispatches. |
| Arp Vouchers | Adding and Updating arp vouchers. |
| Bom | Adding and Updating boms. |
| Serial Lot Records | Adding and Updating serial lot records. |
| Purchase Dispatche | Adding and Updating purchase dispatches. |
| Bank Vouchers | Adding and Updating bank vouchers. |
🛠️ Development
- Programming Language: C#
- Platform: .NET 6+
- Dependency: UnityObjects Library
🙏 Acknowledgments
This project would not have been possible without the collaboration and efforts of my team.
Special thanks to Ahmet Balaman for his exceptional contributions as a Developer.
- LinkedIn: Ahmet Balaman
- GitHub: Ahmet Balaman
📄 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:
- Arp Voucher: With this release, Arp Voucher's new props have been added.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. 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. |
-
net8.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.Options.ConfigurationExtensions (>= 9.0.10)
- 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 |
|---|---|---|
| 2.0.2 | 0 | 6/10/2026 |
| 2.0.1 | 34 | 6/9/2026 |
| 2.0.0 | 52 | 6/8/2026 |
| 1.9.991 | 113 | 4/13/2026 |
| 1.9.990 | 99 | 4/9/2026 |
| 1.9.99 | 101 | 4/9/2026 |
| 1.9.98 | 113 | 2/17/2026 |
| 1.9.97 | 108 | 2/17/2026 |
| 1.9.96 | 103 | 2/17/2026 |
| 1.9.95 | 97 | 2/17/2026 |
| 1.9.94 | 141 | 2/17/2026 |
| 1.9.93 | 109 | 2/17/2026 |
| 1.9.92 | 110 | 2/17/2026 |
| 1.9.91 | 107 | 2/17/2026 |
| 1.9.9 | 108 | 2/17/2026 |
| 1.9.8 | 114 | 2/16/2026 |
| 1.9.7 | 101 | 2/16/2026 |
| 1.9.6 | 107 | 2/16/2026 |
| 1.9.5 | 107 | 2/16/2026 |
| 1.9.4 | 118 | 2/16/2026 |
Bu sürümle birlikte Cari Hesap Fişi'ne yeni alanlar eklenmiştir.