crmleaf/fnf-calculator

Full and final settlement: dues, gratuity, leave, notice pay and deductions.

Maintainers

Package info

github.com/CrmLeaf/fnf-calculator

Homepage

Issues

pkg:composer/crmleaf/fnf-calculator

Transparency log

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

v1.0.0 2026-08-14 11:04 UTC

This package is not auto-updated.

Last update: 2026-08-15 09:49:01 UTC


README

Full and final settlement: dues, gratuity, leave, notice pay and deductions.

Assembles a full and final settlement end to end: salary for the days worked, gratuity, leave encashment, notice pay or notice recovery, other earnings and recoveries, then the deductions on the lot.

One of the CRMLeaf payroll tools. The arithmetic and the dated statutory rate tables live in crmleaf/payroll-core; this package is the thin skin that makes one calculator installable, mountable and embeddable on its own.

Note

A wrong figure or an out-of-date rate is almost always a payroll-core matter, since that is where the tables live. Anything about this tool's routes, views or browser asset belongs here.

Install

Composer - Laravel auto-discovers the service provider, so this is the whole setup:

composer require crmleaf/fnf-calculator

npm - the same calculation, re-exported from @crmleaf/payroll-js so you can install this one tool and nothing else:

npm install @crmleaf/fnf-calculator

Note

Not on npm yet. The script-tag route below needs no registry and works today. Installing this package straight from git will not resolve @crmleaf/payroll-js, which is not published yet either.

A plain script tag - no build step, no bundler, no server. Build the browser bundle once and serve the file yourself:

<script src="/js/payroll.min.js"></script>
<script>
const result = CrmleafPayroll.fnf({
  monthlyGross: 75000,
  monthlyBasic: 30000,
  joiningDate: "2018-06-01",
  lastWorkingDate: "2025-08-14",
  leaveDaysBalance: 18,
});
console.log(result.explain);
</script>

payroll.min.js is the single-file browser build. Get it by running npm run build in @crmleaf/payroll-js and copying dist/payroll.min.js into whatever your site serves as static assets.

A hosted CDN build is coming soon, which will reduce this to a single URL. Serving the file yourself works today and keeps working afterwards - it is the only option that needs no third-party request, so plenty of projects will want to stay on it.

See it working first

demo/index.html in this repository is a working copy of F&F Settlement Calculator in one file: the form, the calculation and the working, with no build step and no server. Drop payroll.min.js beside it and open it from disk.

cp /path/to/payroll-js/dist/payroll.min.js demo/
open demo/index.html

Nothing on that page reaches the network, which is the point: it is a calculator people paste salary figures into.

Use it

Plain PHP, no framework and no container:

use Crmleaf\Payroll\Calculators\FnfCalculator;
use Crmleaf\Payroll\Money;

$result = (new FnfCalculator())->calculate(
    monthlyGross: Money::fromRupees(75_000),
    monthlyBasic: Money::fromRupees(30_000),
    joiningDate: new \DateTimeImmutable('2018-06-01'),
    lastWorkingDate: new \DateTimeImmutable('2025-08-14'),
    leaveDaysBalance: 18,
);

echo $result->explain();      // the formula with the real operands in it
echo $result->workings();     // every step, one per line, with its citation
print_r($result->toArray());  // snake_case, ready for JSON

Laravel - resolve it from the container, or type-hint it anywhere:

use Crmleaf\Payroll\Calculators\FnfCalculator;

public function show(FnfCalculator $calculator)
{
    return $calculator->calculate(
        monthlyGross: Money::fromRupees(75_000),
        monthlyBasic: Money::fromRupees(30_000),
        joiningDate: new \DateTimeImmutable('2018-06-01'),
        lastWorkingDate: new \DateTimeImmutable('2025-08-14'),
        leaveDaysBalance: 18,
    )->toArray();
}

Blade - one component, no controller:

<x-crmleaf::fnf-calculator />

HTTP - off by default. Publish the config and turn the route on:

php artisan vendor:publish --tag=fnf-calculator-config
// config/fnf-calculator.php
'route' => ['enabled' => true, 'prefix' => 'tools'],
curl -X POST https://example.test/tools/fnf-calculator \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -d '{"monthly_gross":75000,"monthly_basic":30000,"joining_date":"2018-06-01","last_working_date":"2025-08-14","leave_days_balance":18}'

The JSON response carries the figures, the working and the statutory citations:

{
  "tool": "fnf-calculator",
  "data": { "…": "every figure, snake_case, with a *_formatted twin" },
  "explain": "the formula with the real operands substituted",
  "working": [{ "label": "", "amount": 0, "formula": "", "citation": "" }],
  "citations": [""]
}

JavaScript:

import { fnf } from '@crmleaf/fnf-calculator';

const result = fnf({
  monthlyGross: 75000,
  monthlyBasic: 30000,
  joiningDate: "2018-06-01",
  lastWorkingDate: "2025-08-14",
  leaveDaysBalance: 18,
});

No server needed

The maths here is arithmetic over versioned rate tables, so it runs anywhere. The published asset binds the markup and computes in the browser:

php artisan vendor:publish --tag=fnf-calculator-assets
<section data-crmleaf-tool="fnf-calculator">
  <form data-crmleaf-form></form>
  <div data-crmleaf-output hidden></div>
</section>

<script src="/js/payroll.min.js"></script>
<script src="/vendor/fnf-calculator/fnf-calculator.js"></script>

If the browser build is absent the script does nothing and the form posts to the server instead, so the page works either way.

Inputs

Field Type Required Default Notes
monthly_gross money (₹) Yes 75000
monthly_basic money (₹) Yes 30000
joining_date date (YYYY-MM-DD) Yes "2018-06-01"
last_working_date date (YYYY-MM-DD) Yes "2025-08-14"
unpaid_days integer No 0
leave_days_balance integer No 18
notice_period_days integer No 60
notice_days_served integer No 60 Short notice becomes a recovery; notice waived by the employer becomes notice pay.
other_earnings money (₹) No - Incentives, reimbursements or an ex gratia amount.
recoveries money (₹) No - Advances, asset dues or a training bond.
separation_reason one of resignation, retirement, superannuation, termination, retrenchment, death, disablement No "resignation"
covered boolean No true
state string No "Karnataka"
as_of date (YYYY-MM-DD) No -

Optional fields you leave out are omitted from the call entirely, so the calculator's own documented defaults apply.

Every figure here rests on a statutory rate, so the call takes as_of. Set it and the calculation runs on the rates in force on that date, which is what makes a prior year recomputable rather than merely rememberable.

Statutory basis

Payment of Gratuity Act 1972; Income-tax Act 1961 section 10(10AA); the Shops and Establishments Act of the state for the settlement deadline; the professional tax schedule of the state for the final month.

Rates are data, not code: they live in dated tables with a cited source in crmleaf/payroll-core, so a rate change is a new dated entry rather than an edit to a constant.

Important

This package implements our reading of the applicable statutes and is provided without warranty. It is a calculation library, not tax advice. Verify against your own compliance obligations before relying on the output for statutory filing.

Publishing

Tag Publishes
fnf-calculator-config config/fnf-calculator.php
fnf-calculator-views resources/views/vendor/fnf-calculator
fnf-calculator-assets public/vendor/fnf-calculator

Licence

MIT © CRMLeaf. Use it commercially, embed it, fork it.