Hi, Morning everyone.
I am looking for some help from more experienced php coders.
I am trying to create a Stamp Duty Land Taxes script that will automatically calculate stamp duty on the sale of a house or flat.

The amount of stamp duty is worked out as follows
Nothing on the first £125,000 of the property price
2% on the next £125,000
5% on the next £675,000
10% on the next £575,000
12 on the rest above £1.5m

Example:
If we buy a property for £275,000 we will pay £3,750 of Stamp Duty on that property
Nothing paid on the first £125,000
£2,500 on the next £125,000
£1,250 on the remaining £25,000

I have tried using a switch case statement without success as I am struggling how to find / deduct the amount in each range of taxable sale price.

Any advice or pointers would be appreciated...
Thanks
Lloyd

Member Avatar for diafol

I was a bit bored today. So here's a simple class. It's not production code - so don't just swipe and use. There are loads of things that should be done differently, but it's a quick and dirty effort.

<?php

class duty
{
    private $ranges = [];
    private $lastIndex = 0;

    public function __construct(dutyObject $dutyObject)
    {
        $this->ranges = $dutyObject->getArray();
        $this->lastIndex = $dutyObject->getCount() - 1;
    }

    public function getDuty($value, $precision=2)
    {
        $duty = 0;
        $remainder = $value;

        foreach($this->ranges as $i=>$range)
        {
            $isLast = ($i == $this->lastIndex);
            if(($remainder > 0 && $remainder < $range->ceiling) || $isLast)
            {
                $duty += $this->getTax($remainder,$range->percentage);
                break;
            }elseif($remainder >= $range->ceiling){
                $duty += $this->getTax($range->ceiling,$range->percentage);
            }
            $remainder -= $range->ceiling;
        }
        return number_format($duty,$precision,'.','');
    }

    private function getTax($amount, $percentage)
    {
        return $amount * $percentage /100;
    }

}


//CREATE DATA OBJECT

class dutyObject
{
    private $arr = [];

    public function addItem($ceiling,$percentage)
    {
        $myClass = new stdClass();
        $myClass->ceiling = $ceiling;
        $myClass->percentage = $percentage;
        $this->arr[] = $myClass;
    }

    public function addArrayOfArrays($arrayOfArrays)
    {
        foreach($array as $a) $this->addItem($a[0],$a[1]);
    }

    public function getArray()
    {
        return $this->arr;
    }

    public function getCount()
    {
        return count($this->arr);
    }
}

//THIS IS YOUR WHOLE DATA (ARRAY FORMAT) - ceiling amount, followed by percentage
//Arrays in order to be processed - note last one = 0 because it has no ceiling
//Typical of the sort of data from a DB resultset with something like PDO::FETCH_NUM

$data = array(
    array(125000,0),
    array(125000,2),
    array(675000,5),
    array(575000,10),
    array(0,12)
);

//CREATE DATA OBJECT
$dataObj = new dutyObject();
//ADD ARRAY OF ARRAYS DATA
$dataObj->addArrayOfArrays($data);
//CREATE DUTY OBJECT
$d = new duty($dataObj);
//SHOW DUTY ON £275000
echo $d->getDuty(275000);

There are two classes. One as the data object (dataObject) to pass to the other (duty). If given it a cursory test and it seems to work.
Mind that this is just an example.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.