Files
exchange/app/Http/Controllers/InvoiceController.php
T
2020-09-06 16:07:45 +08:00

311 lines
10 KiB
PHP

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\Routing\ResponseFactory;
use Illuminate\Support\MessageBag;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use App\Booking;
use App\Invoice;
use App\InvoiceDetails;
use App\InvoiceStatuses;
class InvoiceController extends Controller
{
public function show($id)
{
// validate $id is number
$invoice = Invoice::where('booking_id', $id)->first();
if (!$invoice) {
return response()->json(['message' => 'Invoice Not Found'], 404);
}
$lines = InvoiceDetails::where('invoice_id', $invoice['id'])->orderBy('order', 'asc')->get();
$status = InvoiceStatuses::where('invoice_id', $invoice['id'])->orderBy('created_at', 'asc')->get();
$invoice->lines = $lines;
$invoice->status = $status;
return response()->json($invoice, 200);
}
public function create(Request $request, $id)
{
$user = $request->user();
// validate $id
$validatedData = $request->validate([
'address' => 'required',
'buyer_company' => 'required',
'contact_no' => 'required',
'marking' => 'required',
'lines.*.order' => 'required|numeric',
'lines.*.stock_code' => 'required',
'lines.*.description' => 'required',
'lines.*.quantity' => 'required|numeric',
'lines.*.unit_price_rm' => 'required|numeric',
'lines.*.unit_price_rmb' => '',
'lines.*.total' => 'required|numeric',
]);
// booking_id belongs to user
$booking = Booking::where('id', $id)->first();
if (!$booking) {
return response()->json(['message' => 'Unable to find booking'], 403);
}
// user_id in booking does not match
if ($booking->user_id !== $user->id) {
return response()->json([
'message' => 'Booking does not belongs to you'
], 403);
}
// Amount match with total
$subtotalArray = array_map(
function ($line) { return $line['total']; },
$validatedData['lines']
);
$total = array_reduce($subtotalArray, function ($v1, $v2) {
return $v1 + $v2;
});
if ($total !== $booking->amount) {
return response()->json([
'message' => 'Booking amount expected is '.$booking->amount.'. Your Invoice amount is '.$total
], 400);
}
// Write to database if does not exist
$exist = Invoice::where('booking_id', $id)->first();
if ($exist) {
return response()
->json(['message' => 'Invoice exist. Cannot create duplicate invoice. Try edit.'], 400);
}
// Generate PO Number - po20200810-001(PO Format)
$dt = Carbon::now();
$po_number = 'po'.$dt->format('Ymmdd').'-'.$id;
$invoice = new Invoice;
$invoice->amount = $total;
$invoice->booking_id = (int)$id;
$invoice->buyer_company = $validatedData['buyer_company'];
$invoice->address = $validatedData['address'];
$invoice->contact_no = $validatedData['contact_no'];
$invoice->po_number = $po_number;
$invoice->save();
if (!$invoice) {
return response()
->json(['message' => 'Unable to Save Data'], 500);
}
// Insert invoice_id into lines
foreach( $validatedData['lines'] as $key => $line) {
$invoice_details = new InvoiceDetails;
$invoice_details->order = $line['order'];
$invoice_details->description = $line['description'];
$invoice_details->quantity = $line['quantity'];
$invoice_details->stock_code = $line['stock_code'];
$invoice_details->invoice_id = $invoice->id;
$invoice_details->unit_price_rmb = $line['unit_price_rmb'];
$invoice_details->unit_price_rm = $line['unit_price_rm'];
$invoice_details->total = $line['total'];
$invoice_details->save();
}
unset($line);
$invoice->lines = $invoice_details;
// Post status as pending
$status = new InvoiceStatuses;
$status->status = 'pending';
$status->comment = '';
$status->invoice_id = $invoice->id;
$status->save();
if($invoice_details) {
return $this->show($id);
} else {
return response(500);
}
}
public function edit(Request $request, $id)
{
$user = $request->user();
// validate $id
$validatedData = $request->validate([
'address' => 'required',
'buyer_company' => 'required',
'contact_no' => 'required',
'marking' => 'required',
'lines.*.order' => 'required|numeric',
'lines.*.stock_code' => 'required',
'lines.*.description' => 'required',
'lines.*.quantity' => 'required|numeric',
'lines.*.unit_price_rm' => 'required|numeric',
'lines.*.unit_price_rmb' => '',
'lines.*.total' => 'required|numeric',
]);
// booking_id belongs to user
$booking = Booking::where('id', $id)->first();
if (!$booking) {
return response()->json(['message' => 'Unable to find booking'], 403);
}
$invoice = Invoice::where('booking_id', $id)->first();
if (!$invoice) {
return response()->json(['message' => 'Invoice Not Found'], 404);
}
// role === 'member' && $booking->user_id !== user()->id && $currentstatus !== 'request_change')
if ($request->user()->role === 'member') {
if ($booking->user_id !== $request->user()->id) {
return response()->json([
'message' => 'Booking does not belongs to you'
], 403);
}
$currentstatus = InvoiceStatuses::where('invoice_id', $invoice['id'])->latest('created_at')->first()->status;
if ($currentstatus !== 'request_change') {
return response()->json(['message' => 'Submitted PO can only be changed when status is request_change'], 403);
}
}
// Amount match with total
$subtotalArray = array_map(
function ($line) { return $line['total']; },
$validatedData['lines']
);
$total = array_reduce($subtotalArray, function ($v1, $v2) {
return $v1 + $v2;
});
if ($total != $booking->amount) {
return response()->json([
'message' => 'Booking amount expected is '.$booking->amount.'. Your Invoice amount is '.$total
], 400);
}
// Generate PO Number - po20200810-001(PO Format)
$dt = Carbon::now();
$po_number = 'po'.$dt->format('Ymmdd').'-'.$id;
$invoice->amount = $total;
$invoice->booking_id = (int)$id;
$invoice->buyer_company = $validatedData['buyer_company'];
$invoice->address = $validatedData['address'];
$invoice->contact_no = $validatedData['contact_no'];
$invoice->po_number = $po_number;
$invoice->save();
if (!$invoice) {
return response()
->json(['message' => 'Unable to Save Data'], 500);
}
// Remove all invoice_details corresponding to invoice_id
$invoice_details = InvoiceDetails::where('invoice_id', $invoice->id);
$invoice_details->delete();
// Insert invoice_id into lines
foreach( $validatedData['lines'] as $key => $line) {
$invoice_details = new InvoiceDetails;
$invoice_details->order = $line['order'];
$invoice_details->description = $line['description'];
$invoice_details->quantity = $line['quantity'];
$invoice_details->stock_code = $line['stock_code'];
$invoice_details->invoice_id = $invoice->id;
$invoice_details->unit_price_rmb = $line['unit_price_rmb'];
$invoice_details->unit_price_rm = $line['unit_price_rm'];
$invoice_details->total = $line['total'];
$invoice_details->save();
}
unset($line);
// Post status as pending
$status = new InvoiceStatuses;
$status->status = 'pending';
if ($request->user()->role === 'admin') {
$status->comment = 'Edited by Admin.';
} else {
$status->comment = 'Edited by Member.';
}
$status->invoice_id = $invoice->id;
$status->save();
if($invoice_details) {
return $this->show($id);
} else {
return response(500);
}
}
public function postStatus(Request $request, $id)
{
// validate $id is integer
$validatedData = $request->validate([
'status' => ['required', Rule::in('request_change', 'approve')],
'comment' => Rule::requiredIf($request->status === 'request_change')
]);
// Save status to database
$status = new InvoiceStatuses;
$status->status = $validatedData['status'];
$status->comment = $validatedData['comment'];
$status->invoice_id = Invoice::where('booking_id', $id)->first()['id'];
$status->save();
if(!$status) {
return response()->json(['message' => 'Unable to Update Status'], 500);
}
// Change Status to 7 if approve
if ($validatedData['status'] === 'approve') {
$booking = Booking::find($id);
$booking->status = 7;
$booking->admin_status = 7;
$booking->save();
if(!$booking) {
return response()->json(['message' => 'Unable to Complete Booking. Please Approve Again'], 500);
}
}
// Response
return response()->json($status, 201);
}
public function getPO($id)
{
}
public function getDO($id)
{
}
public function getSupplierDO($id)
{
}
}