Sozer.Logo.Rest 1.3.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package Sozer.Logo.Rest --version 1.3.1
                    
NuGet\Install-Package Sozer.Logo.Rest -Version 1.3.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Sozer.Logo.Rest" Version="1.3.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Sozer.Logo.Rest" Version="1.3.1" />
                    
Directory.Packages.props
<PackageReference Include="Sozer.Logo.Rest" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Sozer.Logo.Rest --version 1.3.1
                    
#r "nuget: Sozer.Logo.Rest, 1.3.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Sozer.Logo.Rest@1.3.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Sozer.Logo.Rest&version=1.3.1
                    
Install as a Cake Addin
#tool nuget:?package=Sozer.Logo.Rest&version=1.3.1
                    
Install as a Cake Tool

Sözer Logo Rest

🇹🇷 Türkçe | 🇺🇸 English

<a name="tr"></a>

🇹🇷 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:

  1. Tools > NuGet Package Manager > Manage NuGet Packages for Solution...
  2. Browse sekmesinde Sozer Logo Rest aratı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:
    • TaxPayerCode 10 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, PostLabel ve SenderLabel gibi 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 PostResult başarısızlık gösterirse (IsSuccess == false), bir PostException tetiklenir.
  • Hata Detayları: İstisna mesajı şunları içerir:
    • Öğe numarası (Number).
    • Varlık adı (örneğin, “Cari Hesap”).
    • Hata mesajı.

Ö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, NotEqual
  • GreaterThan, LessThan,
  • Like, NotLike
  • In, Between
  • IsNull, 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
    }
]
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));
    }

📑 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.

🛠️ 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üç

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 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:

  1. Tools > NuGet Package Manager > Manage NuGet Packages for Solution...
  2. Search for Sozer Logo Rest in 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 TaxPayerCode is 10 characters long, the account is treated as a corporate entity.
    • Otherwise, it is treated as an individual entity.
  • The response from the service updates specific fields such as PostLabel and SenderLabel.
[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 PostResult indicates failure (IsSuccess == false), a PostException is triggered.
  • Error Details: The exception message includes:
    • The item number (Number).
    • The entity name (e.g., "Account").
    • The error message.

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, NotEqual
  • GreaterThan, LessThan
  • Like, NotLike
  • In, Between
  • IsNull, 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
    }
]
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));
    }

📑 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.

🛠️ 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üç

Added Features:

  • Arp Voucher: With this release, Arp Voucher's new props have been added.
Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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 55 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
Loading failed

Bu sürümle birlikte Cari Hesap Fişi'ne yeni alanlar eklenmiştir.