# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Overview CEL Payroll is a .NET Framework 4.5 WinForms desktop payroll/HR application (C#) backed by SQL Server. Solution: `CEL Payroll.sln` (VS 2019 format; folder name refers to the original VS2015 port). There are no test projects and no linter. ## Build Build from Visual Studio, or with MSBuild from a Developer Command Prompt: ```bash msbuild "CEL Payroll.sln" /p:Configuration=Debug ``` Startup project is `Payroll.UI` (WinExe, entry `Payroll.UI/Payroll.UI/Program.cs` → `frmMain`). Third-party and in-house framework assemblies (`Ease.CoreV35`, `Ease.Controls`, `Ease.Report`, ReportViewer, NPOI, ClosedXML, iTextSharp, etc.) are checked in as binaries under `Library/` and referenced by HintPath, not NuGet. Crystal Reports 10.5 runtime must be installed for `Payroll.Report` to build. ## Architecture Layered, with project dependencies flowing downward: - **Payroll.UI** — WinForms screens, grouped by module folder (Salary, Tax, Bonus, Leave, PF, Gratuity, FinalSettlement, …). - **Payroll.Report** — report classes (`Class/rpt*.cs`), the report viewer (`UI/fReportViewer.cs`), typed datasets (`PayrollDataSet`), and `.rdlc` files under `RDLC/` (plus some Crystal reports). - **Ease.UICreator** — generic, config-driven master/detail form generator used for simple setup screens. - **Payroll.Controls** — shared custom WinForms controls. - **Payroll.Service** — service implementations + data access (SQL). - **Payroll.BO** — business objects and the service interfaces. - **Ease.SvcHost** — Windows service exposing `Payroll.Service` over .NET Remoting (TCP) for a 3-tier deployment. - **Payroll.NotifProcessInterface** — console exe that runs notification/mail processing. ### BO / Service / DA pattern Each entity spans three files that share a module folder name across projects, e.g. Bonus: 1. `Payroll.BO/Bonus/Bonus.cs` — class deriving from `BasicBaseObject` (or similar Ease.CoreV35 base), properties call `OnPropertyChange`, static `Get(...)`/instance `Save()`/`Delete()` methods that use a per-type `Cache` and delegate to `Service`. The **service interface (`IBonusService`) is declared at the bottom of the same BO file**. `Service` is resolved via `Services.Factory.CreateService(...)`. 2. `Payroll.Service/Bonus/Service/BonusService.cs` — `ServiceTemplate` subclass implementing the interface. Every method wraps work in `TransactionContext.Begin()` / `tc.End()`, with `tc.HandleError()` + `ExceptionLog.Write(e)` + `throw new ServiceException(...)` in the catch. `MapObject` maps `DataReader` columns to BO properties and sets `ObjectState.Saved`. 3. `Payroll.Service/Bonus/DA/BonusDA.cs` — `internal static` class of raw SQL. Queries use Ease's placeholder formatting, not SqlParameters: `%n` number, `%s` string, `%d` date (e.g. `tc.ExecuteNonQuery("UPDATE Bonus SET code=%s WHERE BonusID=%n", ...)`). Adding a method to an entity means touching all three: interface + BO wrapper, service implementation, DA query. IDs use the Ease `ID` type (`.Integer` for the int value). Many queries are scoped by `SystemInformation.CurrentSysInfo.PayrollTypeID`. Service location is controlled by `serviceHandler` in `Payroll.UI/Payroll.UI/App.config`: `Payroll.Service.dll/conn` loads the services in-process using the `conn` entry in ``; a `host:port/Payroll.Service` value goes through `Ease.SvcHost` remoting instead. ### Menus and forms The main menu is driven by `Payroll.UI/Payroll.UI/Menu.xml`. Each `` names a `` and ``; `frmMain` resolves the form type by reflection (`Payroll.UI.` unless the name is assembly-qualified) and invokes the parameterless show method. Simple setup screens use `BasicUIForms` (`CreateUI.cs`), whose `show*` methods build forms through `Ease.UICreator`. Adding a screen to the menu means adding a Menu.xml entry whose names match exactly. ### Reports RDLC files are compiled as **EmbeddedResource** in `Payroll.Report.csproj` and loaded by manifest name, e.g. `"Payroll.Report.RDLC.BankAdvice.rdlc"` (see `Class/rptBankAdvice.cs`, `UI/fReportViewer.cs`). A new `.rdlc` must be added to the csproj as an EmbeddedResource, and its dataset fields must match the `DataTable` passed in (typed datasets live in `PayrollDataSet`). ## Repository conventions - Branching: work on `dev_shahadat`, PRs into `devqc` (Gitea-hosted). - Commit messages are prefixed with the ticket ID in the form `YYYYMMDD-NNNN `, e.g. `20260929-3216 Bank advice Salary Report Modification`. - Release commits typically bump `AssemblyVersion`/`AssemblyFileVersion` in `Payroll.UI/Payroll.UI/Properties/AssemblyInfo.cs` to a date-based `YY.M.DD.0` value. - `App.config` contains live DB connection strings and is frequently changed per environment; don't commit connection-string changes unless intended.