Here is a custom class I use to handle different types of orders in Laravel. This question includes the code regarding Order Type A. I want to know whether I can simplify the code. I have different Order Types with the same functions but different in behaviour. That's why I'm using an abstract class to extend all order types.
abstract class BaseOrder
{
abstract public function getOrder(Order $order);
abstract public function storeOrder(Request $request);
...
}
class OrderTypeA extends BaseOrder
{
private $type = 'A';
public function getOrder(Order $order)
{
return $order->load('items.product')
->makeHidden(['order_no', 'created_at', 'updated_at', 'created_by']);
}
public function storeOrder($request)
{
$returnedValues = DB::transaction(function () use ($request) {
$order = new Order;
$order->type = $this->type;
$order->from = $request->json('from');
$order->amount = $request->json('amount');
$order->status = 2;
$order->save();
foreach ($request->json('items') as $item) {
$order->items()->create([
'product_id' => $item['product_id'],
'quantity' => $item['quantity'],
'total' => $item['total'],
]);
}
return compact('order');
});
return $returnedValues['order']->load('items');
}
public function updateOrder($request)
{
$returnedValues = DB::transaction(function () use ($request) {
if ($request->id) {
$order = Order::findOrFail($request->id);
$order->amount = $request->json('amount');
$order->status = 1;
$order->save();
$order->items()->delete();
foreach ($request->json('items') as $item) {
$order->items()->create([
'product_id' => $item['product_id'],
'quantity' => $item['quantity'],
'total' => $item['total'],
]);
}
} else {
$order = new Order;
$order->type = $this->type;
$order->from = $request->json('from');
$order->to = null;
$order->amount = $request->json('amount');
$order->status = 1;
$order->save();
foreach ($request->json('items') as $item) {
$order->items()->create([
'product_id' => $item['product_id'],
'quantity' => $item['quantity'],
'total' => $item['total'],
]);
}
}
return compact('order');
});
return $returnedValues['order']->load('items');
}
public function generateOrder($customer)
{
$order = new stdClass();
$order->id = null;
$order->type = $this->type;
$order->from = $customer->id;
$order->to = null;
$order->status = 1;
$totalAmount = 0;
$items = [];
$stocks = Stock::where('type', 1)
->where('customer_id', $customer->id)
->whereRaw('stock <= reorder_level')
->get();
if (count($stocks) > 0) {
foreach ($stocks as $key => $stock) {
if ($stock->minimum_order_quantity != 0) {
$priceListItem = PriceList::where('product_id', $stock->product_id)->latest()->first();
$item = new stdClass;
$item->id = $key;
$item->product_id = $stock->product_id;
$item->product = Product::findOrFail($stock->product_id);
$item->order_id = null;
$item->quantity = (int) $stock->minimum_order_quantity;
$item->total = ((int) $stock->minimum_order_quantity * ((float) $priceListItem->price));
$item->is_checked = true;
$item->created_at = null;
$item->updated_at = null;
$totalAmount += $item->total;
$items[] = $item;
}
}
}
$order->amount = $totalAmount;
$order->items = $items;
return $order;
}
public function deleteOrder(Order $order)
{
if ($order->status == 'Draft') {
$order->forceDelete();
} else {
$order->delete();
}
return $order;
}
}