Created
September 10, 2019 21:11
-
-
Save escapeboy/e36fa6104f0807459f97762ac6d5e8f2 to your computer and use it in GitHub Desktop.
POS Scanner
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace Src\PackItems; | |
final class Calculator | |
{ | |
/** | |
* @var Item[] | |
*/ | |
private $items; | |
/** | |
* @var array | |
*/ | |
private $pricing; | |
private function __construct(array $items, array $pricing) | |
{ | |
$this->items = $items; | |
$this->pricing = $pricing; | |
} | |
/** | |
* @return Calculator | |
*/ | |
public static function empty(): Calculator | |
{ | |
return new static([], []); | |
} | |
/** | |
* @param Item $item | |
*/ | |
public function scan(Item $item): void | |
{ | |
foreach ($this->items as $existingItem) { | |
if ($existingItem->equals($item)) { | |
$existingItem->setQuantity($existingItem->getQuantity() + $item->getQuantity()); | |
return; | |
} | |
} | |
if(array_key_exists($item->getCode(), $this->pricing)){ | |
$item->withPackPrice($this->pricing[$item->getCode()]); | |
} | |
$this->items[] = $item; | |
} | |
/** | |
* @return float | |
*/ | |
public function total(): float | |
{ | |
$total = 0; | |
foreach ($this->items as $item) { | |
$total += $item->getTotal(); | |
} | |
return $total / 100; | |
} | |
/** | |
* @param array $pricing | |
* | |
* @return Calculator | |
*/ | |
public function setPricing(array $pricing): Calculator | |
{ | |
$this->pricing = $pricing; | |
return $this; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace Src\PackItems; | |
final class Item | |
{ | |
/** | |
* @var int | |
*/ | |
private $price; | |
/** | |
* @var int | |
*/ | |
private $quantity; | |
/** | |
* @var array | |
*/ | |
private $packPrice; | |
/** | |
* @var string | |
*/ | |
private $code; | |
private function __construct(string $code, int $price, int $quantity, array $packPrice) | |
{ | |
$this->code = $code; | |
$this->price = $price; | |
$this->quantity = $quantity; | |
$this->packPrice = $packPrice; | |
} | |
/** | |
* @param string $code | |
* @param int $price | |
* | |
* @return Item | |
*/ | |
public static function fromBasic(string $code, int $price) | |
{ | |
return new static($code, $price, 1, []); | |
} | |
/** | |
* @return int | |
*/ | |
public function getQuantity(): int | |
{ | |
return $this->quantity; | |
} | |
/** | |
* @param Item $item | |
* | |
* @return bool | |
*/ | |
public function equals(Item $item): bool | |
{ | |
return $this->code === $item->getCode(); | |
} | |
/** | |
* @return float | |
*/ | |
public function getTotal(): float | |
{ | |
if (!count($this->packPrice)) { | |
return $this->quantity * $this->price; | |
} | |
$packs = array_keys($this->packPrice); | |
$minPack = min($packs); | |
if ($this->quantity < $minPack) { | |
return $this->quantity * $this->price; | |
} | |
$totalPrice = 0; | |
$quantity = $this->quantity; | |
foreach ($this->packPrice as $packQuantity => $packPrice) { | |
if ($quantity < $packQuantity) { | |
break; | |
} | |
$totalPrice += $packQuantity * $packPrice; | |
$quantity -= $packQuantity; | |
} | |
$totalPrice += $quantity * $this->price; | |
return $totalPrice; | |
} | |
/** | |
* @return string | |
*/ | |
public function getCode(): string | |
{ | |
return $this->code; | |
} | |
/** | |
* @param int $quantity | |
*/ | |
public function setQuantity(int $quantity): void | |
{ | |
$this->quantity = $quantity; | |
} | |
/** | |
* @param array $packPrice | |
* | |
* @return Item | |
*/ | |
public function withPackPrice(array $packPrice): Item | |
{ | |
$this->packPrice = $packPrice; | |
return $this; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace Tests\Unit; | |
use Src\PackItems\Calculator; | |
use Src\PackItems\Item; | |
use Tests\TestCase; | |
class PackItems extends TestCase | |
{ | |
public function testFirst(){ | |
$calculator = Calculator::empty() | |
->setPricing([ | |
'A' => [4 => 175], | |
'C' => [6 => 100] | |
]); | |
$items = [ | |
Item::fromBasic('A', 200), | |
Item::fromBasic('B', 1200), | |
Item::fromBasic('C', 125), | |
Item::fromBasic('D', 15), | |
Item::fromBasic('A', 200), | |
Item::fromBasic('B', 1200), | |
Item::fromBasic('A', 200), | |
Item::fromBasic('A', 200), | |
]; | |
foreach($items as $item){ | |
$calculator->scan($item); | |
} | |
$this->assertEquals(32.4, $calculator->total()); | |
} | |
public function testSecond(){ | |
$items = [ | |
Item::fromBasic('C', 125), | |
Item::fromBasic('C', 125), | |
Item::fromBasic('C', 125), | |
Item::fromBasic('C', 125), | |
Item::fromBasic('C', 125), | |
Item::fromBasic('C', 125), | |
Item::fromBasic('C', 125), | |
]; | |
$calculator = Calculator::empty() | |
->setPricing([ | |
'C' => [6 => 100] | |
]); | |
foreach($items as $item){ | |
$calculator->scan($item); | |
} | |
$this->assertEquals(7.25, $calculator->total()); | |
} | |
public function testThird(){ | |
$items = [ | |
Item::fromBasic('A', 200), | |
Item::fromBasic('B', 1200), | |
Item::fromBasic('C', 125), | |
Item::fromBasic('D', 15), | |
]; | |
$calculator = Calculator::empty() | |
->setPricing([ | |
'A' => [4 => 175], | |
'C' => [6 => 100] | |
]); | |
foreach($items as $item){ | |
$calculator->scan($item); | |
} | |
$this->assertEquals(15.4, $calculator->total()); | |
} | |
public function testFourth() | |
{ | |
$items = [ | |
Item::fromBasic('A', 200), | |
Item::fromBasic('A', 200), | |
Item::fromBasic('A', 200), | |
Item::fromBasic('A', 200), | |
Item::fromBasic('A', 200), | |
]; | |
$calculator = Calculator::empty() | |
->setPricing([ | |
'A' => [4 => 175] | |
]); | |
foreach($items as $item){ | |
$calculator->scan($item); | |
} | |
$this->assertEquals(((175*4) + 200) / 100, $calculator->total()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment