mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-24 02:14:21 -04:00
Stubs for Recurring Expenses
This commit is contained in:
parent
3886925bb7
commit
a0f6afec0f
45
app/Factory/RecurringExpenseFactory.php
Normal file
45
app/Factory/RecurringExpenseFactory.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Factory;
|
||||
|
||||
use App\Models\RecurringExpense;
|
||||
|
||||
class RecurringExpenseFactory
|
||||
{
|
||||
public static function create(int $company_id, int $user_id) :RecurringExpense
|
||||
{
|
||||
$recurring_expense = new RecurringExpense();
|
||||
$recurring_expense->user_id = $user_id;
|
||||
$recurring_expense->company_id = $company_id;
|
||||
$recurring_expense->is_deleted = false;
|
||||
$recurring_expense->should_be_invoiced = false;
|
||||
$recurring_expense->tax_name1 = '';
|
||||
$recurring_expense->tax_rate1 = 0;
|
||||
$recurring_expense->tax_name2 = '';
|
||||
$recurring_expense->tax_rate2 = 0;
|
||||
$recurring_expense->tax_name3 = '';
|
||||
$recurring_expense->tax_rate3 = 0;
|
||||
$recurring_expense->date = null;
|
||||
$recurring_expense->payment_date = null;
|
||||
$recurring_expense->amount = 0;
|
||||
$recurring_expense->foreign_amount = 0;
|
||||
$recurring_expense->private_notes = '';
|
||||
$recurring_expense->public_notes = '';
|
||||
$recurring_expense->transaction_reference = '';
|
||||
$recurring_expense->custom_value1 = '';
|
||||
$recurring_expense->custom_value2 = '';
|
||||
$recurring_expense->custom_value3 = '';
|
||||
$recurring_expense->custom_value4 = '';
|
||||
|
||||
return $recurring_expense;
|
||||
}
|
||||
}
|
@ -38,11 +38,6 @@ class ExpenseFilters extends QueryFilters
|
||||
return $this->builder->where(function ($query) use ($filter) {
|
||||
$query->where('expenses.name', 'like', '%'.$filter.'%')
|
||||
->orWhere('expenses.id_number', 'like', '%'.$filter.'%')
|
||||
->orWhereHas('contacts', function ($query) use($filter){
|
||||
$query->where('expense_contacts.first_name', 'like', '%'.$filter.'%');
|
||||
$query->orWhere('expense_contacts.last_name', 'like', '%'.$filter.'%');
|
||||
$query->orWhere('expense_contacts.email', 'like', '%'.$filter.'%');
|
||||
})
|
||||
->orWhere('expenses.custom_value1', 'like', '%'.$filter.'%')
|
||||
->orWhere('expenses.custom_value2', 'like', '%'.$filter.'%')
|
||||
->orWhere('expenses.custom_value3', 'like', '%'.$filter.'%')
|
||||
|
148
app/Filters/RecurringExpenseFilters.php
Normal file
148
app/Filters/RecurringExpenseFilters.php
Normal file
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use App\Models\RecurringExpense;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
/**
|
||||
* RecurringExpenseFilters.
|
||||
*/
|
||||
class RecurringExpenseFilters extends QueryFilters
|
||||
{
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
public function filter(string $filter = '') : Builder
|
||||
{
|
||||
if (strlen($filter) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
return $this->builder->where(function ($query) use ($filter) {
|
||||
$query->where('recurring_expenses.name', 'like', '%'.$filter.'%')
|
||||
->orWhere('recurring_expenses.id_number', 'like', '%'.$filter.'%')
|
||||
->orWhere('recurring_expenses.custom_value1', 'like', '%'.$filter.'%')
|
||||
->orWhere('recurring_expenses.custom_value2', 'like', '%'.$filter.'%')
|
||||
->orWhere('recurring_expenses.custom_value3', 'like', '%'.$filter.'%')
|
||||
->orWhere('recurring_expenses.custom_value4', 'like', '%'.$filter.'%');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the list based on the status
|
||||
* archived, active, deleted.
|
||||
*
|
||||
* @param string filter
|
||||
* @return Builder
|
||||
*/
|
||||
public function status(string $filter = '') : Builder
|
||||
{
|
||||
if (strlen($filter) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
$table = 'expenses';
|
||||
$filters = explode(',', $filter);
|
||||
|
||||
return $this->builder->where(function ($query) use ($filters, $table) {
|
||||
$query->whereNull($table.'.id');
|
||||
|
||||
if (in_array(parent::STATUS_ACTIVE, $filters)) {
|
||||
$query->orWhereNull($table.'.deleted_at');
|
||||
}
|
||||
|
||||
if (in_array(parent::STATUS_ARCHIVED, $filters)) {
|
||||
$query->orWhere(function ($query) use ($table) {
|
||||
$query->whereNotNull($table.'.deleted_at');
|
||||
|
||||
if (! in_array($table, ['users'])) {
|
||||
$query->where($table.'.is_deleted', '=', 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (in_array(parent::STATUS_DELETED, $filters)) {
|
||||
$query->orWhere($table.'.is_deleted', '=', 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort) : Builder
|
||||
{
|
||||
$sort_col = explode('|', $sort);
|
||||
|
||||
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base query.
|
||||
*
|
||||
* @param int company_id
|
||||
* @param User $user
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
public function baseQuery(int $company_id, User $user) : Builder
|
||||
{
|
||||
$query = DB::table('recurring_expenses')
|
||||
->join('companies', 'companies.id', '=', 'recurring_expenses.company_id')
|
||||
->where('recurring_expenses.company_id', '=', $company_id)
|
||||
->select(
|
||||
DB::raw('COALESCE(recurring_expenses.country_id, companies.country_id) country_id'),
|
||||
'recurring_expenses.id',
|
||||
'recurring_expenses.private_notes',
|
||||
'recurring_expenses.custom_value1',
|
||||
'recurring_expenses.custom_value2',
|
||||
'recurring_expenses.custom_value3',
|
||||
'recurring_expenses.custom_value4',
|
||||
'recurring_expenses.created_at',
|
||||
'recurring_expenses.created_at as expense_created_at',
|
||||
'recurring_expenses.deleted_at',
|
||||
'recurring_expenses.is_deleted',
|
||||
'recurring_expenses.user_id',
|
||||
);
|
||||
|
||||
/*
|
||||
* If the user does not have permissions to view all invoices
|
||||
* limit the user to only the invoices they have created
|
||||
*/
|
||||
if (Gate::denies('view-list', RecurringExpense::class)) {
|
||||
$query->where('recurring_expenses.user_id', '=', $user->id);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the query by the users company ID.
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function entityFilter()
|
||||
{
|
||||
return $this->builder->company();
|
||||
}
|
||||
}
|
578
app/Http/Controllers/RecurringExpenseController.php
Normal file
578
app/Http/Controllers/RecurringExpenseController.php
Normal file
@ -0,0 +1,578 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Events\RecurringExpense\RecurringExpenseWasCreated;
|
||||
use App\Events\RecurringExpense\RecurringExpenseWasUpdated;
|
||||
use App\Factory\RecurringExpenseFactory;
|
||||
use App\Filters\RecurringExpenseFilters;
|
||||
use App\Http\Requests\RecurringExpense\CreateRecurringExpenseRequest;
|
||||
use App\Http\Requests\RecurringExpense\DestroyRecurringExpenseRequest;
|
||||
use App\Http\Requests\RecurringExpense\EditRecurringExpenseRequest;
|
||||
use App\Http\Requests\RecurringExpense\ShowRecurringExpenseRequest;
|
||||
use App\Http\Requests\RecurringExpense\StoreRecurringExpenseRequest;
|
||||
use App\Http\Requests\RecurringExpense\UpdateRecurringExpenseRequest;
|
||||
use App\Http\Requests\RecurringExpense\UploadRecurringExpenseRequest;
|
||||
use App\Models\Account;
|
||||
use App\Models\RecurringExpense;
|
||||
use App\Repositories\RecurringExpenseRepository;
|
||||
use App\Transformers\RecurringExpenseTransformer;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\BulkOptions;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Utils\Traits\SavesDocuments;
|
||||
use App\Utils\Traits\Uploadable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
/**
|
||||
* Class RecurringExpenseController.
|
||||
* @covers App\Http\Controllers\RecurringExpenseController
|
||||
*/
|
||||
class RecurringExpenseController extends BaseController
|
||||
{
|
||||
use MakesHash;
|
||||
use Uploadable;
|
||||
use BulkOptions;
|
||||
use SavesDocuments;
|
||||
|
||||
protected $entity_type = RecurringExpense::class;
|
||||
|
||||
protected $entity_transformer = RecurringExpenseTransformer::class;
|
||||
|
||||
/**
|
||||
* @var RecurringExpenseepository
|
||||
*/
|
||||
protected $recurring_expense_repo;
|
||||
|
||||
/**
|
||||
* RecurringExpenseController constructor.
|
||||
* @param RecurringExpenseRepository $recurring_expense_repo
|
||||
*/
|
||||
public function __construct(RecurringExpenseRepository $recurring_expense_repo)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->recurring_expense_repo = $recurring_expense_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/recurring_expenses",
|
||||
* operationId="getRecurringExpenses",
|
||||
* tags={"recurring_expenses"},
|
||||
* summary="Gets a list of recurring_expenses",
|
||||
* description="Lists recurring_expenses, search and filters allow fine grained lists to be generated.
|
||||
|
||||
Query parameters can be added to performed more fine grained filtering of the recurring_expenses, these are handled by the RecurringExpenseFilters class which defines the methods available",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Parameter(ref="#/components/parameters/index"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="A list of recurring_expenses",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/RecurringExpense"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
* @param RecurringExpenseFilters $filters
|
||||
* @return Response|mixed
|
||||
*/
|
||||
public function index(RecurringExpenseFilters $filters)
|
||||
{
|
||||
$recurring_expenses = RecurringExpense::filter($filters);
|
||||
|
||||
return $this->listResponse($recurring_expenses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param ShowRecurringExpenseRequest $request
|
||||
* @param RecurringExpense $recurring_expense
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/recurring_expenses/{id}",
|
||||
* operationId="showRecurringExpense",
|
||||
* tags={"recurring_expenses"},
|
||||
* summary="Shows a client",
|
||||
* description="Displays a client by id",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The RecurringExpense Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the recurring_expense object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/RecurringExpense"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function show(ShowRecurringExpenseRequest $request, RecurringExpense $recurring_expense)
|
||||
{
|
||||
return $this->itemResponse($recurring_expense);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param EditRecurringExpenseRequest $request
|
||||
* @param RecurringExpense $recurring_expense
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/recurring_expenses/{id}/edit",
|
||||
* operationId="editRecurringExpense",
|
||||
* tags={"recurring_expenses"},
|
||||
* summary="Shows a client for editting",
|
||||
* description="Displays a client by id",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The RecurringExpense Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the client object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/RecurringExpense"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function edit(EditRecurringExpenseRequest $request, RecurringExpense $recurring_expense)
|
||||
{
|
||||
return $this->itemResponse($recurring_expense);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param UpdateRecurringExpenseRequest $request
|
||||
* @param RecurringExpense $recurring_expense
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Put(
|
||||
* path="/api/v1/recurring_expenses/{id}",
|
||||
* operationId="updateRecurringExpense",
|
||||
* tags={"recurring_expenses"},
|
||||
* summary="Updates a client",
|
||||
* description="Handles the updating of a client by id",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The RecurringExpense Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the client object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/RecurringExpense"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function update(UpdateRecurringExpenseRequest $request, RecurringExpense $recurring_expense)
|
||||
{
|
||||
if ($request->entityIsDeleted($recurring_expense)) {
|
||||
return $request->disallowUpdate();
|
||||
}
|
||||
|
||||
$recurring_expense = $this->recurring_expense_repo->save($request->all(), $recurring_expense);
|
||||
|
||||
$this->uploadLogo($request->file('company_logo'), $recurring_expense->company, $recurring_expense);
|
||||
|
||||
event(new RecurringExpenseWasUpdated($recurring_expense, $recurring_expense->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
|
||||
return $this->itemResponse($recurring_expense->fresh());
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param CreateRecurringExpenseRequest $request
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/recurring_expenses/create",
|
||||
* operationId="getRecurringExpensesCreate",
|
||||
* tags={"recurring_expenses"},
|
||||
* summary="Gets a new blank client object",
|
||||
* description="Returns a blank object with default values",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="A blank client object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/RecurringExpense"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function create(CreateRecurringExpenseRequest $request)
|
||||
{
|
||||
$recurring_expense = RecurringExpenseFactory::create(auth()->user()->company()->id, auth()->user()->id);
|
||||
|
||||
return $this->itemResponse($recurring_expense);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param StoreRecurringExpenseRequest $request
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/recurring_expenses",
|
||||
* operationId="storeRecurringExpense",
|
||||
* tags={"recurring_expenses"},
|
||||
* summary="Adds a client",
|
||||
* description="Adds an client to a company",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the saved client object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/RecurringExpense"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function store(StoreRecurringExpenseRequest $request)
|
||||
{
|
||||
$recurring_expense = $this->recurring_expense_repo->save($request->all(), RecurringExpenseFactory::create(auth()->user()->company()->id, auth()->user()->id));
|
||||
|
||||
event(new RecurringExpenseWasCreated($recurring_expense, $recurring_expense->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
|
||||
return $this->itemResponse($recurring_expense);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param DestroyRecurringExpenseRequest $request
|
||||
* @param RecurringExpense $recurring_expense
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @throws \Exception
|
||||
* @OA\Delete(
|
||||
* path="/api/v1/recurring_expenses/{id}",
|
||||
* operationId="deleteRecurringExpense",
|
||||
* tags={"recurring_expenses"},
|
||||
* summary="Deletes a client",
|
||||
* description="Handles the deletion of a client by id",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The RecurringExpense Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns a HTTP status",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function destroy(DestroyRecurringExpenseRequest $request, RecurringExpense $recurring_expense)
|
||||
{
|
||||
$this->recurring_expense_repo->delete($recurring_expense);
|
||||
|
||||
return $this->itemResponse($recurring_expense->fresh());
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform bulk actions on the list view.
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/recurring_expenses/bulk",
|
||||
* operationId="bulkRecurringExpenses",
|
||||
* tags={"recurring_expenses"},
|
||||
* summary="Performs bulk actions on an array of recurring_expenses",
|
||||
* description="",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/index"),
|
||||
* @OA\RequestBody(
|
||||
* description="User credentials",
|
||||
* required=true,
|
||||
* @OA\MediaType(
|
||||
* mediaType="application/json",
|
||||
* @OA\Schema(
|
||||
* type="array",
|
||||
* @OA\Items(
|
||||
* type="integer",
|
||||
* description="Array of hashed IDs to be bulk 'actioned",
|
||||
* example="[0,1,2,3]",
|
||||
* ),
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="The RecurringExpense User response",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/RecurringExpense"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function bulk()
|
||||
{
|
||||
$action = request()->input('action');
|
||||
|
||||
$ids = request()->input('ids');
|
||||
$recurring_expenses = RecurringExpense::withTrashed()->find($this->transformKeys($ids));
|
||||
|
||||
$recurring_expenses->each(function ($recurring_expense, $key) use ($action) {
|
||||
if (auth()->user()->can('edit', $recurring_expense)) {
|
||||
$this->recurring_expense_repo->{$action}($recurring_expense);
|
||||
}
|
||||
});
|
||||
|
||||
return $this->listResponse(RecurringExpense::withTrashed()->whereIn('id', $this->transformKeys($ids)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a client statement.
|
||||
*
|
||||
* @return void [type] [description]
|
||||
*/
|
||||
public function statement()
|
||||
{
|
||||
//todo
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param UploadRecurringExpenseRequest $request
|
||||
* @param RecurringExpense $recurring_expense
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Put(
|
||||
* path="/api/v1/recurring_expenses/{id}/upload",
|
||||
* operationId="uploadRecurringExpense",
|
||||
* tags={"recurring_expense"},
|
||||
* summary="Uploads a document to a recurring_expense",
|
||||
* description="Handles the uploading of a document to a recurring_expense",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The RecurringExpense Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the RecurringExpense object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/RecurringExpense"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function upload(UploadRecurringExpenseRequest $request, RecurringExpense $recurring_expense)
|
||||
{
|
||||
|
||||
if(!$this->checkFeature(Account::FEATURE_DOCUMENTS))
|
||||
return $this->featureFailure();
|
||||
|
||||
if ($request->has('documents'))
|
||||
$this->saveDocuments($request->file('documents'), $recurring_expense);
|
||||
|
||||
return $this->itemResponse($recurring_expense->fresh());
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
|
||||
namespace App\Http\Requests\RecurringExpense;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\RecurringExpense;
|
||||
use App\Utils\Traits\BulkOptions;
|
||||
|
||||
class BulkRecurringExpenseRequest extends Request
|
||||
{
|
||||
use BulkOptions;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
if (! $this->has('action')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! in_array($this->action, $this->getBulkOptions(), true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return auth()->user()->can(auth()->user()->isAdmin(), RecurringExpense::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
$rules = $this->getGlobalRules();
|
||||
|
||||
/* We don't require IDs on bulk storing. */
|
||||
if ($this->action !== self::$STORE_METHOD) {
|
||||
$rules['ids'] = ['required'];
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\RecurringExpense;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\RecurringExpense;
|
||||
|
||||
class CreateRecurringExpenseRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('create', RecurringExpense::class);
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\RecurringExpense;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
|
||||
class DestroyRecurringExpenseRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('edit', $this->recurring_expense);
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\RecurringExpense;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
|
||||
class EditRecurringExpenseRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('edit', $this->recurring_expense);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\RecurringExpense;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
|
||||
class ShowRecurringExpenseRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('view', $this->recurring_expense);
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\RecurringExpense;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Http\ValidationRules\RecurringExpense\UniqueRecurringExpenseNumberRule;
|
||||
use App\Models\RecurringExpense;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class StoreRecurringExpenseRequest extends Request
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('create', RecurringExpense::class);
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
$rules = [];
|
||||
|
||||
if ($this->number)
|
||||
$rules['number'] = Rule::unique('recurring_expenses')->where('company_id', auth()->user()->company()->id);
|
||||
|
||||
if(!empty($this->client_id))
|
||||
$rules['client_id'] = 'bail|sometimes|exists:clients,id,company_id,'.auth()->user()->company()->id;
|
||||
|
||||
return $this->globalRules($rules);
|
||||
}
|
||||
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
$input = $this->decodePrimaryKeys($input);
|
||||
|
||||
if (array_key_exists('category_id', $input) && is_string($input['category_id'])) {
|
||||
$input['category_id'] = $this->decodePrimaryKey($input['category_id']);
|
||||
}
|
||||
|
||||
if (! array_key_exists('currency_id', $input) || strlen($input['currency_id']) == 0) {
|
||||
$input['currency_id'] = (string)auth()->user()->company()->settings->currency_id;
|
||||
}
|
||||
|
||||
if(array_key_exists('color', $input) && is_null($input['color']))
|
||||
$input['color'] = '';
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'unique' => ctrans('validation.unique', ['attribute' => 'email']),
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\RecurringExpense;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Utils\Traits\ChecksEntityStatus;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UpdateRecurringExpenseRequest extends Request
|
||||
{
|
||||
use MakesHash;
|
||||
use ChecksEntityStatus;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('edit', $this->recurring_expense);
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
/* Ensure we have a client name, and that all emails are unique*/
|
||||
|
||||
$rules['country_id'] = 'integer|nullable';
|
||||
|
||||
$rules['contacts.*.email'] = 'nullable|distinct';
|
||||
|
||||
if (isset($this->number)) {
|
||||
$rules['number'] = Rule::unique('recurring_expenses')->where('company_id', auth()->user()->company()->id)->ignore($this->recurring_expense->id);
|
||||
}
|
||||
|
||||
return $this->globalRules($rules);
|
||||
}
|
||||
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'unique' => ctrans('validation.unique', ['attribute' => 'email']),
|
||||
'email' => ctrans('validation.email', ['attribute' => 'email']),
|
||||
'name.required' => ctrans('validation.required', ['attribute' => 'name']),
|
||||
'required' => ctrans('validation.required', ['attribute' => 'email']),
|
||||
];
|
||||
}
|
||||
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
$input = $this->decodePrimaryKeys($input);
|
||||
|
||||
if (array_key_exists('category_id', $input) && is_string($input['category_id'])) {
|
||||
$input['category_id'] = $this->decodePrimaryKey($input['category_id']);
|
||||
}
|
||||
|
||||
if (array_key_exists('documents', $input)) {
|
||||
unset($input['documents']);
|
||||
}
|
||||
|
||||
if (! array_key_exists('currency_id', $input) || strlen($input['currency_id']) == 0) {
|
||||
$input['currency_id'] = (string)auth()->user()->company()->settings->currency_id;
|
||||
}
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\RecurringExpense;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
|
||||
class UploadRecurringExpenseRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('edit', $this->recurring_expense);
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
|
||||
$rules = [];
|
||||
|
||||
if($this->input('documents'))
|
||||
$rules['documents'] = 'file|mimes:html,csv,png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx|max:2000000';
|
||||
|
||||
return $rules;
|
||||
|
||||
}
|
||||
}
|
104
app/Models/RecurringExpense.php
Normal file
104
app/Models/RecurringExpense.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class RecurringExpense extends BaseModel
|
||||
{
|
||||
use SoftDeletes;
|
||||
use Filterable;
|
||||
|
||||
protected $fillable = [
|
||||
'client_id',
|
||||
'assigned_user_id',
|
||||
'vendor_id',
|
||||
'invoice_id',
|
||||
'currency_id',
|
||||
'date',
|
||||
'invoice_currency_id',
|
||||
'amount',
|
||||
'foreign_amount',
|
||||
'exchange_rate',
|
||||
'private_notes',
|
||||
'public_notes',
|
||||
'bank_id',
|
||||
'transaction_id',
|
||||
'category_id',
|
||||
'tax_rate1',
|
||||
'tax_name1',
|
||||
'tax_rate2',
|
||||
'tax_name2',
|
||||
'tax_rate3',
|
||||
'tax_name3',
|
||||
'payment_date',
|
||||
'payment_type_id',
|
||||
'project_id',
|
||||
'transaction_reference',
|
||||
'invoice_documents',
|
||||
'should_be_invoiced',
|
||||
'custom_value1',
|
||||
'custom_value2',
|
||||
'custom_value3',
|
||||
'custom_value4',
|
||||
'number',
|
||||
'tax_amount1',
|
||||
'tax_amount2',
|
||||
'tax_amount3',
|
||||
'uses_inclusive_taxes',
|
||||
'calculate_tax_by_amount',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'is_deleted' => 'boolean',
|
||||
'updated_at' => 'timestamp',
|
||||
'created_at' => 'timestamp',
|
||||
'deleted_at' => 'timestamp',
|
||||
];
|
||||
|
||||
protected $touches = [];
|
||||
|
||||
public function getEntityType()
|
||||
{
|
||||
return self::class;
|
||||
}
|
||||
|
||||
public function documents()
|
||||
{
|
||||
return $this->morphMany(Document::class, 'documentable');
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function assigned_user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'assigned_user_id', 'id');
|
||||
}
|
||||
|
||||
public function company()
|
||||
{
|
||||
return $this->belongsTo(Company::class);
|
||||
}
|
||||
|
||||
public function vendor()
|
||||
{
|
||||
return $this->belongsTo(Vendor::class);
|
||||
}
|
||||
|
||||
public function client()
|
||||
{
|
||||
return $this->belongsTo(Client::class);
|
||||
}
|
||||
}
|
31
app/Policies/RecurringExpensePolicy.php
Normal file
31
app/Policies/RecurringExpensePolicy.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
/**
|
||||
* Class RecurringExpensePolicy.
|
||||
*/
|
||||
class RecurringExpensePolicy extends EntityPolicy
|
||||
{
|
||||
/**
|
||||
* Checks if the user has create permissions.
|
||||
*
|
||||
* @param User $user
|
||||
* @return bool
|
||||
*/
|
||||
public function create(User $user) : bool
|
||||
{
|
||||
return $user->isAdmin() || $user->hasPermission('create_recurring_expense') || $user->hasPermission('create_all');
|
||||
}
|
||||
}
|
@ -12,7 +12,6 @@
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Models\Activity;
|
||||
use App\Models\Subscription;
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyGateway;
|
||||
@ -29,8 +28,10 @@ use App\Models\PaymentTerm;
|
||||
use App\Models\Product;
|
||||
use App\Models\Project;
|
||||
use App\Models\Quote;
|
||||
use App\Models\RecurringExpense;
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\Models\RecurringQuote;
|
||||
use App\Models\Subscription;
|
||||
use App\Models\Task;
|
||||
use App\Models\TaskStatus;
|
||||
use App\Models\TaxRate;
|
||||
@ -38,7 +39,6 @@ use App\Models\User;
|
||||
use App\Models\Vendor;
|
||||
use App\Models\Webhook;
|
||||
use App\Policies\ActivityPolicy;
|
||||
use App\Policies\SubscriptionPolicy;
|
||||
use App\Policies\ClientPolicy;
|
||||
use App\Policies\CompanyGatewayPolicy;
|
||||
use App\Policies\CompanyPolicy;
|
||||
@ -55,8 +55,10 @@ use App\Policies\PaymentTermPolicy;
|
||||
use App\Policies\ProductPolicy;
|
||||
use App\Policies\ProjectPolicy;
|
||||
use App\Policies\QuotePolicy;
|
||||
use App\Policies\RecurringExpensePolicy;
|
||||
use App\Policies\RecurringInvoicePolicy;
|
||||
use App\Policies\RecurringQuotePolicy;
|
||||
use App\Policies\SubscriptionPolicy;
|
||||
use App\Policies\TaskPolicy;
|
||||
use App\Policies\TaskStatusPolicy;
|
||||
use App\Policies\TaxRatePolicy;
|
||||
@ -92,6 +94,7 @@ class AuthServiceProvider extends ServiceProvider
|
||||
Product::class => ProductPolicy::class,
|
||||
Project::class => ProjectPolicy::class,
|
||||
Quote::class => QuotePolicy::class,
|
||||
RecurringExpense::class => RecurringExpensePolicy::class,
|
||||
RecurringInvoice::class => RecurringInvoicePolicy::class,
|
||||
RecurringQuote::class => RecurringQuotePolicy::class,
|
||||
Webhook::class => WebhookPolicy::class,
|
||||
|
60
app/Repositories/RecurringExpenseRepository.php
Normal file
60
app/Repositories/RecurringExpenseRepository.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Repositories;
|
||||
|
||||
use App\Factory\RecurringExpenseFactory;
|
||||
use App\Models\RecurringExpense;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
|
||||
/**
|
||||
* RecurringExpenseRepository.
|
||||
*/
|
||||
class RecurringExpenseRepository extends BaseRepository
|
||||
{
|
||||
use GeneratesCounter;
|
||||
|
||||
|
||||
/**
|
||||
* Saves the recurring_expense and its contacts.
|
||||
*
|
||||
* @param array $data The data
|
||||
* @param \App\Models\RecurringExpense $recurring_expense The recurring_expense
|
||||
*
|
||||
* @return \App\Models\RecurringExpense|Null recurring_expense Object
|
||||
*/
|
||||
public function save(array $data, RecurringExpense $recurring_expense) : ?RecurringExpense
|
||||
{
|
||||
$recurring_expense->fill($data);
|
||||
$recurring_expense->number = empty($recurring_expense->number) ? $this->getNextRecurringExpenseNumber($recurring_expense) : $recurring_expense->number;
|
||||
$recurring_expense->save();
|
||||
|
||||
if (array_key_exists('documents', $data)) {
|
||||
$this->saveDocuments($data['documents'], $recurring_expense);
|
||||
}
|
||||
|
||||
return $recurring_expense;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store recurring_expenses in bulk.
|
||||
*
|
||||
* @param array $recurring_expense
|
||||
* @return \App\Models\RecurringExpense|null
|
||||
*/
|
||||
public function create($recurring_expense): ?RecurringExpense
|
||||
{
|
||||
return $this->save(
|
||||
$recurring_expense,
|
||||
RecurringExpenseFactory::create(auth()->user()->company()->id, auth()->user()->id)
|
||||
);
|
||||
}
|
||||
}
|
101
app/Transformers/RecurringExpenseTransformer.php
Normal file
101
app/Transformers/RecurringExpenseTransformer.php
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Transformers;
|
||||
|
||||
use App\Models\Document;
|
||||
use App\Models\RecurringExpense;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* class RecurringExpenseTransformer.
|
||||
*/
|
||||
class RecurringExpenseTransformer extends EntityTransformer
|
||||
{
|
||||
use MakesHash;
|
||||
use SoftDeletes;
|
||||
|
||||
protected $defaultIncludes = [
|
||||
'documents',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $availableIncludes = [
|
||||
'documents',
|
||||
];
|
||||
|
||||
public function includeDocuments(RecurringExpense $recurring_expense)
|
||||
{
|
||||
$transformer = new DocumentTransformer($this->serializer);
|
||||
|
||||
return $this->includeCollection($recurring_expense->documents, $transformer, Document::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RecurringExpense $recurring_expense
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function transform(RecurringExpense $recurring_expense)
|
||||
{
|
||||
return [
|
||||
'id' => $this->encodePrimaryKey($recurring_expense->id),
|
||||
'user_id' => $this->encodePrimaryKey($recurring_expense->user_id),
|
||||
'assigned_user_id' => $this->encodePrimaryKey($recurring_expense->assigned_user_id),
|
||||
'vendor_id' => $this->encodePrimaryKey($recurring_expense->vendor_id),
|
||||
'invoice_id' => $this->encodePrimaryKey($recurring_expense->invoice_id),
|
||||
'client_id' => $this->encodePrimaryKey($recurring_expense->client_id),
|
||||
'bank_id' => (string) $recurring_expense->bank_id ?: '',
|
||||
'invoice_currency_id' => (string) $recurring_expense->invoice_currency_id ?: '',
|
||||
'recurring_expense_currency_id' => '', //todo remove redundant in 5.0.25
|
||||
'currency_id' => (string) $recurring_expense->currency_id ?: '',
|
||||
'category_id' => $this->encodePrimaryKey($recurring_expense->category_id),
|
||||
'payment_type_id' => (string) $recurring_expense->payment_type_id ?: '',
|
||||
'recurring_recurring_expense_id' => (string) $recurring_expense->recurring_recurring_expense_id ?: '',
|
||||
'is_deleted' => (bool) $recurring_expense->is_deleted,
|
||||
'should_be_invoiced' => (bool) $recurring_expense->should_be_invoiced,
|
||||
'invoice_documents' => (bool) $recurring_expense->invoice_documents,
|
||||
'amount' => (float) $recurring_expense->amount ?: 0,
|
||||
'foreign_amount' => (float) $recurring_expense->foreign_amount ?: 0,
|
||||
'exchange_rate' => (float) $recurring_expense->exchange_rate ?: 0,
|
||||
'tax_name1' => $recurring_expense->tax_name1 ? $recurring_expense->tax_name1 : '',
|
||||
'tax_rate1' => (float) $recurring_expense->tax_rate1,
|
||||
'tax_name2' => $recurring_expense->tax_name2 ? $recurring_expense->tax_name2 : '',
|
||||
'tax_rate2' => (float) $recurring_expense->tax_rate2,
|
||||
'tax_name3' => $recurring_expense->tax_name3 ? $recurring_expense->tax_name3 : '',
|
||||
'tax_rate3' => (float) $recurring_expense->tax_rate3,
|
||||
'private_notes' => (string) $recurring_expense->private_notes ?: '',
|
||||
'public_notes' => (string) $recurring_expense->public_notes ?: '',
|
||||
'transaction_reference' => (string) $recurring_expense->transaction_reference ?: '',
|
||||
'transaction_id' => (string) $recurring_expense->transaction_id ?: '',
|
||||
'date' => $recurring_expense->date ?: '',
|
||||
//'recurring_expense_date' => $recurring_expense->date ?: '',
|
||||
'number' => (string)$recurring_expense->number ?: '',
|
||||
'payment_date' => $recurring_expense->payment_date ?: '',
|
||||
'custom_value1' => $recurring_expense->custom_value1 ?: '',
|
||||
'custom_value2' => $recurring_expense->custom_value2 ?: '',
|
||||
'custom_value3' => $recurring_expense->custom_value3 ?: '',
|
||||
'custom_value4' => $recurring_expense->custom_value4 ?: '',
|
||||
'updated_at' => (int) $recurring_expense->updated_at,
|
||||
'archived_at' => (int) $recurring_expense->deleted_at,
|
||||
'created_at' => (int) $recurring_expense->created_at,
|
||||
'project_id' => $this->encodePrimaryKey($recurring_expense->project_id),
|
||||
'tax_amount1' => (float) $recurring_expense->tax_amount1,
|
||||
'tax_amount2' => (float) $recurring_expense->tax_amount2,
|
||||
'tax_amount3' => (float) $recurring_expense->tax_amount3,
|
||||
'uses_inclusive_taxes' => (bool) $recurring_expense->uses_inclusive_taxes,
|
||||
'calculate_tax_by_amount' => (bool) $recurring_expense->calculate_tax_by_amount,
|
||||
];
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Models\Project;
|
||||
use App\Models\Quote;
|
||||
use App\Models\RecurringExpense;
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\Models\Task;
|
||||
use App\Models\Timezone;
|
||||
@ -312,6 +313,27 @@ trait GeneratesCounter
|
||||
return $expense_number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next expense number.
|
||||
*
|
||||
* @param RecurringExpense $expense The expense
|
||||
* @return string The next expense number.
|
||||
*/
|
||||
public function getNextRecurringExpenseNumber(RecurringExpense $expense) :string
|
||||
{
|
||||
$this->resetCompanyCounters($expense->company);
|
||||
|
||||
$counter = $expense->company->settings->recurring_expense_number_counter;
|
||||
$setting_entity = $expense->company->settings->recurring_expense_number_counter;
|
||||
|
||||
$expense_number = $this->checkEntityNumber(RecurringExpense::class, $expense, $counter, $expense->company->settings->counter_padding, $expense->company->settings->recurring_expense_number_pattern);
|
||||
|
||||
$this->incrementCounter($expense->company, 'recurring_expense_number_counter');
|
||||
|
||||
return $expense_number;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines if it has shared counter.
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user