Business applications, written in plain C#.

Waybill.cs · WaybillBehavior.cs
[KandraDocumentEntity]
public partial class Waybill : DocumentBase, IEntityWithRows<WaybillRow>
{
    public override string Code { get; set; } = "";
    public override DateTime DateTime { get; set; }
    public Guid CounterpartyId { get; set; }
    public Guid WarehouseId { get; set; }
    public List<WaybillRow> Rows { get; set; } = [];
}

// Registers are written only inside a posting scope.
public class WaybillBehavior : DocumentBehavior<Waybill, WaybillDto>
{
    public override async ValueTask OnSubmitAsync(Waybill doc, ISubmitScope scope)
    {
        var inventory = scope.GetWriter<IInventoryRegisterWriter>();
        foreach (var row in doc.Rows)
            await inventory.ExpenseAsync(doc, row.ItemId, doc.WarehouseId, row.Quantity);
    }
}

// Controllers, API client, EF config, DI, Blazor pages: generated.
.NET 10 · C# 14EF Core · SQLite / SQL Server / PostgreSQLBlazor WebAssembly · MudBlazorRoslyn source generatorsQuartz.NET schedulerRefit API clients

DocumentBase

DictionaryBase

BalanceRegister<T> · InfoRegister

[KandraReportForm]

[KandraDataProcessorForm]

Constant<T>

Waybill : DocumentBase
WaybillDto
WaybillBehavior
WaybillValidator

IPostingService · ChartOfAccounts

Quartz.NET · ICallerContext

[SupportedPrintForm]

[FilePicker] · IBlobService

JWT · API keys · policies

LocalizationChain · FeatureManagement

YourCompany.Domain · .Forms · .Application
ASP.NET Core
+ Blazor WASMPostgreSQL · SQL Server · SQLite
Photino
desktop app
Avalonia
desktop / mobile

❯ /create-document SalesOrder --rows --posts InventoryRegister
✓ SalesOrder : DocumentBase, IEntityWithRows<SalesOrderRow>
✓ SalesOrderDto · [KandraDocumentForm(ValidatorType = …)]
✓ SalesOrderBehavior · OnSubmitAsync → ISubmitScope
✓ SalesOrderValidator · resx EN/UK/RU · nav tree · migration ×3


kandra.reports.rests(warehouse: "Main", date: today)

Kandra WMS

Free ·
Developer

S
M
L

→ → →

1C:Enterprise
OdooPython / JS
Dynamics 365 BCAL ()
Frappe / ERPNextPython / JS
KandraC# / .NET 10

dotnet new install Kandra.ConfigTemplate --add-source https://nugets.kandra.tech/index.json
dotnet tool install -g Kandra.ConfigCreateTool --add-source https://nugets.kandra.tech/index.json
kandra-new-config
cd Acme && dotnet run --project src/Acme.WebApi