1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-20 16:31:33 +02:00
invoiceninja/app/Http/Controllers/InvoiceApiController.php

432 lines
14 KiB
PHP
Raw Normal View History

2015-03-17 02:30:56 +01:00
<?php namespace App\Http\Controllers;
2015-03-16 22:45:25 +01:00
2015-04-08 20:19:58 +02:00
use Auth;
2016-02-16 23:09:32 +01:00
use Illuminate\Support\Facades\Log;
2016-01-16 07:07:29 +01:00
use Illuminate\Support\Facades\Request;
2015-03-17 02:30:56 +01:00
use Utils;
2015-04-08 20:19:58 +02:00
use Response;
use Input;
use Validator;
2015-04-08 20:19:58 +02:00
use App\Models\Invoice;
use App\Models\Client;
2015-05-10 10:45:03 +02:00
use App\Models\Contact;
2015-04-08 20:19:58 +02:00
use App\Models\Product;
use App\Models\Invitation;
2015-05-10 10:45:03 +02:00
use App\Ninja\Repositories\ClientRepository;
2016-02-16 16:30:09 +01:00
use App\Ninja\Repositories\PaymentRepository;
use App\Ninja\Repositories\InvoiceRepository;
use App\Ninja\Mailers\ContactMailer as Mailer;
2015-11-27 13:55:28 +01:00
use App\Http\Controllers\BaseAPIController;
use App\Ninja\Transformers\InvoiceTransformer;
2016-05-01 21:30:39 +02:00
use App\Http\Requests\CreateInvoiceAPIRequest;
use App\Http\Requests\UpdateInvoiceAPIRequest;
2016-02-18 14:46:44 +01:00
use App\Services\InvoiceService;
2015-03-16 22:45:25 +01:00
2015-11-27 13:55:28 +01:00
class InvoiceApiController extends BaseAPIController
2015-03-16 22:45:25 +01:00
{
protected $invoiceRepo;
2016-02-18 14:46:44 +01:00
public function __construct(InvoiceService $invoiceService, InvoiceRepository $invoiceRepo, ClientRepository $clientRepo, PaymentRepository $paymentRepo, Mailer $mailer)
2015-03-16 22:45:25 +01:00
{
2016-03-02 15:36:46 +01:00
parent::__construct();
2015-11-27 13:55:28 +01:00
2015-03-16 22:45:25 +01:00
$this->invoiceRepo = $invoiceRepo;
2015-05-10 10:45:03 +02:00
$this->clientRepo = $clientRepo;
2016-02-16 16:30:09 +01:00
$this->paymentRepo = $paymentRepo;
2016-02-18 14:46:44 +01:00
$this->invoiceService = $invoiceService;
2015-03-16 22:45:25 +01:00
$this->mailer = $mailer;
}
2015-11-08 21:34:26 +01:00
/**
* @SWG\Get(
* path="/invoices",
* summary="List of invoices",
2015-11-08 22:53:13 +01:00
* tags={"invoice"},
2015-11-08 21:34:26 +01:00
* @SWG\Response(
* response=200,
* description="A list with invoices",
* @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/Invoice"))
* ),
* @SWG\Response(
* response="default",
* description="an ""unexpected"" error"
* )
* )
*/
2015-11-27 13:55:28 +01:00
public function index()
2015-03-16 22:45:25 +01:00
{
2016-01-15 23:22:22 +01:00
$paginator = Invoice::scope()->withTrashed();
$invoices = Invoice::scope()->withTrashed()
->with(array_merge(['invoice_items'], $this->getIncluded()));
2015-09-07 11:07:55 +02:00
2015-11-27 13:55:28 +01:00
if ($clientPublicId = Input::get('client_id')) {
$filter = function($query) use ($clientPublicId) {
2015-09-07 11:07:55 +02:00
$query->where('public_id', '=', $clientPublicId);
2015-11-27 13:55:28 +01:00
};
$invoices->whereHas('client', $filter);
$paginator->whereHas('client', $filter);
2015-09-07 11:07:55 +02:00
}
2015-11-27 13:55:28 +01:00
$invoices = $invoices->orderBy('created_at', 'desc')->paginate();
2015-04-13 09:54:51 +02:00
2015-11-27 13:55:28 +01:00
/*
2015-04-13 09:54:51 +02:00
// Add the first invitation link to the data
foreach ($invoices as $key => $invoice) {
foreach ($invoice->invitations as $subKey => $invitation) {
$invoices[$key]['link'] = $invitation->getLink();
}
unset($invoice['invitations']);
}
2015-11-27 13:55:28 +01:00
*/
$transformer = new InvoiceTransformer(Auth::user()->account, Input::get('serializer'));
$paginator = $paginator->paginate();
2015-03-16 22:45:25 +01:00
2015-11-27 13:55:28 +01:00
$data = $this->createCollection($invoices, $transformer, 'invoices', $paginator);
2015-03-16 22:45:25 +01:00
2015-11-27 13:55:28 +01:00
return $this->response($data);
2015-03-16 22:45:25 +01:00
}
2016-02-17 11:50:52 +01:00
/**
* @SWG\Get(
* path="/invoices/{invoice_id}",
* summary="Individual Invoice",
* tags={"invoice"},
* @SWG\Response(
* response=200,
* description="A single invoice",
* @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Invoice"))
* ),
* @SWG\Response(
* response="default",
* description="an ""unexpected"" error"
* )
* )
*/
2016-02-17 11:16:13 +01:00
public function show($publicId)
{
$invoice = Invoice::scope($publicId)->withTrashed()->first();
if(!$invoice)
return $this->errorResponse(['message'=>'Invoice does not exist!'], 404);
$transformer = new InvoiceTransformer(\Auth::user()->account, Input::get('serializer'));
$data = $this->createItem($invoice, $transformer, 'invoice');
return $this->response($data);
}
2015-11-08 22:53:13 +01:00
/**
* @SWG\Post(
* path="/invoices",
* tags={"invoice"},
* summary="Create an invoice",
* @SWG\Parameter(
* in="body",
* name="body",
* @SWG\Schema(ref="#/definitions/Invoice")
* ),
* @SWG\Response(
* response=200,
2015-11-08 22:57:28 +01:00
* description="New invoice",
2015-11-08 22:53:13 +01:00
* @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Invoice"))
* ),
* @SWG\Response(
* response="default",
* description="an ""unexpected"" error"
* )
* )
*/
2016-05-01 21:30:39 +02:00
public function store(CreateInvoiceAPIRequest $request)
2015-03-16 22:45:25 +01:00
{
$data = Input::all();
$error = null;
2015-10-28 20:22:07 +01:00
2015-05-10 10:45:03 +02:00
if (isset($data['email'])) {
$email = $data['email'];
$client = Client::scope()->whereHas('contacts', function($query) use ($email) {
$query->where('email', '=', $email);
2015-05-11 13:16:36 +02:00
})->first();
2016-03-02 14:36:42 +01:00
2015-05-11 13:16:36 +02:00
if (!$client) {
$validator = Validator::make(['email'=>$email], ['email' => 'email']);
if ($validator->fails()) {
2015-11-18 18:16:23 +01:00
$messages = $validator->messages();
return $messages->first();
}
$clientData = ['contact' => ['email' => $email]];
2016-02-16 16:30:09 +01:00
foreach ([
'name',
'address1',
'address2',
'city',
'state',
'postal_code',
'private_notes',
'currency_code',
2016-02-16 16:30:09 +01:00
] as $field) {
2015-05-10 10:45:03 +02:00
if (isset($data[$field])) {
$clientData[$field] = $data[$field];
}
}
2016-02-16 16:30:09 +01:00
foreach ([
'first_name',
'last_name',
'phone',
] as $field) {
2015-05-10 10:45:03 +02:00
if (isset($data[$field])) {
2016-02-16 16:30:09 +01:00
$clientData['contact'][$field] = $data[$field];
2015-05-10 10:45:03 +02:00
}
}
$client = $this->clientRepo->save($clientData);
2015-05-10 10:45:03 +02:00
}
} else if (isset($data['client_id'])) {
$client = Client::scope($data['client_id'])->firstOrFail();
2015-05-10 10:45:03 +02:00
}
$data = self::prepareData($data, $client);
$data['client_id'] = $client->id;
2016-02-18 14:46:44 +01:00
$invoice = $this->invoiceService->save($data);
2016-02-16 16:30:09 +01:00
$payment = false;
// Optionally create payment with invoice
if (isset($data['paid']) && $data['paid']) {
$payment = $this->paymentRepo->save([
'invoice_id' => $invoice->id,
'client_id' => $client->id,
'amount' => $data['paid']
]);
}
2015-10-22 20:48:12 +02:00
if (isset($data['email_invoice']) && $data['email_invoice']) {
2016-02-16 16:30:09 +01:00
if ($payment) {
$this->mailer->sendPaymentConfirmation($payment);
} else {
$this->mailer->sendInvoice($invoice);
}
}
2015-05-10 10:45:03 +02:00
$invoice = Invoice::scope($invoice->public_id)->with('client', 'invoice_items', 'invitations')->first();
$transformer = new InvoiceTransformer(\Auth::user()->account, Input::get('serializer'));
$data = $this->createItem($invoice, $transformer, 'invoice');
2015-07-02 22:21:29 +02:00
return $this->response($data);
2015-03-16 22:45:25 +01:00
}
private function prepareData($data, $client)
2015-03-16 22:45:25 +01:00
{
$account = Auth::user()->account;
$account->loadLocalizationSettings($client);
2016-03-02 14:36:42 +01:00
2015-03-16 22:45:25 +01:00
// set defaults for optional fields
$fields = [
'discount' => 0,
'is_amount_discount' => false,
'terms' => '',
'invoice_footer' => '',
'public_notes' => '',
'po_number' => '',
'invoice_design_id' => $account->invoice_design_id,
'invoice_items' => [],
'custom_value1' => 0,
'custom_value2' => 0,
'custom_taxes1' => false,
'custom_taxes2' => false,
2015-05-10 10:45:03 +02:00
'partial' => 0
2015-03-16 22:45:25 +01:00
];
2016-01-27 11:00:00 +01:00
if (!isset($data['invoice_status_id']) || $data['invoice_status_id'] == 0) {
$data['invoice_status_id'] = INVOICE_STATUS_DRAFT;
}
2015-03-16 22:45:25 +01:00
if (!isset($data['invoice_date'])) {
$fields['invoice_date_sql'] = date_create()->format('Y-m-d');
}
if (!isset($data['due_date'])) {
$fields['due_date_sql'] = false;
}
foreach ($fields as $key => $val) {
if (!isset($data[$key])) {
$data[$key] = $val;
}
}
// initialize the line items
if (isset($data['product_key']) || isset($data['cost']) || isset($data['notes']) || isset($data['qty'])) {
$data['invoice_items'] = [self::prepareItem($data)];
2015-10-13 09:11:44 +02:00
// make sure the tax isn't applied twice (for the invoice and the line item)
2016-03-31 11:29:01 +02:00
unset($data['invoice_items'][0]['tax_name1']);
unset($data['invoice_items'][0]['tax_rate1']);
unset($data['invoice_items'][0]['tax_name2']);
unset($data['invoice_items'][0]['tax_rate2']);
2015-03-16 22:45:25 +01:00
} else {
foreach ($data['invoice_items'] as $index => $item) {
$data['invoice_items'][$index] = self::prepareItem($item);
}
}
return $data;
}
private function prepareItem($item)
{
// if only the product key is set we'll load the cost and notes
2016-02-17 21:49:34 +01:00
if (!empty($item['product_key']) && empty($item['cost']) && empty($item['notes'])) {
$product = Product::findProductByKey($item['product_key']);
if ($product) {
if (empty($item['cost'])) {
$item['cost'] = $product->cost;
}
if (empty($item['notes'])) {
$item['notes'] = $product->notes;
}
}
}
2015-03-16 22:45:25 +01:00
$fields = [
'cost' => 0,
'product_key' => '',
'notes' => '',
'qty' => 1
];
foreach ($fields as $key => $val) {
if (!isset($item[$key])) {
$item[$key] = $val;
}
}
return $item;
}
2016-01-31 23:45:15 +01:00
public function emailInvoice()
2016-01-29 02:47:35 +01:00
{
$data = Input::all();
$error = null;
2016-02-16 22:57:06 +01:00
$invoice = Invoice::scope($data['id'])->withTrashed()->first();
2016-01-29 02:47:35 +01:00
2016-02-16 22:57:06 +01:00
if(!$invoice)
return $this->errorResponse(['message'=>'Invoice does not exist.'], 400);
2016-01-29 02:47:35 +01:00
2016-02-16 22:57:06 +01:00
2016-02-16 23:45:28 +01:00
$this->mailer->sendInvoice($invoice, false, false);
2016-02-16 23:28:00 +01:00
2016-02-16 23:38:23 +01:00
if($error) {
2016-02-16 22:57:06 +01:00
return $this->errorResponse(['message'=>'There was an error sending the invoice'], 400);
2016-01-29 02:47:35 +01:00
}
else {
$response = json_encode(RESULT_SUCCESS, JSON_PRETTY_PRINT);
}
$headers = Utils::getApiHeaders();
return Response::make($response, $error ? 400 : 200, $headers);
}
2016-01-06 05:01:52 +01:00
2016-01-16 07:07:29 +01:00
/**
* @SWG\Put(
* path="/invoices",
* tags={"invoice"},
* summary="Update an invoice",
* @SWG\Parameter(
* in="body",
* name="body",
* @SWG\Schema(ref="#/definitions/Invoice")
* ),
* @SWG\Response(
* response=200,
* description="Update invoice",
* @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Invoice"))
* ),
* @SWG\Response(
* response="default",
* description="an ""unexpected"" error"
* )
* )
*/
2016-05-01 21:30:39 +02:00
public function update(UpdateInvoiceAPIRequest $request, $publicId)
2016-01-06 05:01:52 +01:00
{
if ($request->action == ACTION_ARCHIVE) {
$invoice = Invoice::scope($publicId)->firstOrFail();
$this->invoiceRepo->archive($invoice);
2016-01-27 01:36:21 +01:00
2016-01-15 04:05:16 +01:00
$transformer = new InvoiceTransformer(\Auth::user()->account, Input::get('serializer'));
$data = $this->createItem($invoice, $transformer, 'invoice');
return $this->response($data);
}
else if ($request->action == ACTION_CONVERT) {
$quote = Invoice::scope($publicId)->firstOrFail();
$invoice = $this->invoiceRepo->cloneInvoice($quote, $quote->id);
$transformer = new InvoiceTransformer(\Auth::user()->account, Input::get('serializer'));
$data = $this->createItem($invoice, $transformer, 'invoice');
return $this->response($data);
}
2016-01-28 02:55:15 +01:00
else if ($request->action == ACTION_RESTORE) {
2016-01-28 03:31:19 +01:00
$invoice = Invoice::scope($publicId)->withTrashed()->firstOrFail();
$this->invoiceRepo->restore($invoice);
2016-01-28 02:55:15 +01:00
$transformer = new InvoiceTransformer(\Auth::user()->account, Input::get('serializer'));
$data = $this->createItem($invoice, $transformer, 'invoice');
return $this->response($data);
}
$data = $request->input();
$data['public_id'] = $publicId;
2016-02-18 14:46:44 +01:00
$this->invoiceService->save($data);
$invoice = Invoice::scope($publicId)->with('client', 'invoice_items', 'invitations')->firstOrFail();
$transformer = new InvoiceTransformer(\Auth::user()->account, Input::get('serializer'));
$data = $this->createItem($invoice, $transformer, 'invoice');
return $this->response($data);
2016-01-06 05:01:52 +01:00
}
2016-01-16 07:07:29 +01:00
/**
* @SWG\Delete(
* path="/invoices",
* tags={"invoice"},
* summary="Delete an invoice",
* @SWG\Parameter(
* in="body",
* name="body",
* @SWG\Schema(ref="#/definitions/Invoice")
* ),
* @SWG\Response(
* response=200,
* description="Delete invoice",
* @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Invoice"))
* ),
* @SWG\Response(
* response="default",
* description="an ""unexpected"" error"
* )
* )
*/
public function destroy($publicId)
{
$data['public_id'] = $publicId;
$invoice = Invoice::scope($publicId)->firstOrFail();
$this->invoiceRepo->delete($invoice);
$transformer = new InvoiceTransformer(\Auth::user()->account, Input::get('serializer'));
$data = $this->createItem($invoice, $transformer, 'invoice');
return $this->response($data);
}
2015-03-16 22:45:25 +01:00
}