mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-24 02:14:21 -04:00
Expense and Vendors (#3226)
* add expenses, vendors and vendor_contacts along with factories and test data * padding out vendors, expenses * Minor fixes * Add Expense and Company TransformerS
This commit is contained in:
parent
27d06a2ae1
commit
84642bf035
@ -241,7 +241,6 @@ class CreateTestData extends Command
|
||||
'company_id' => $company->id
|
||||
]);
|
||||
|
||||
|
||||
factory(\App\Models\ClientContact::class, 1)->create([
|
||||
'user_id' => $user->id,
|
||||
'client_id' => $client->id,
|
||||
@ -262,9 +261,53 @@ class CreateTestData extends Command
|
||||
for ($x=0; $x<$y; $x++) {
|
||||
$this->createInvoice($client);
|
||||
$this->createQuote($client);
|
||||
$this->createExpense($client);
|
||||
$this->createVendor($client);
|
||||
}
|
||||
}
|
||||
|
||||
private function createExpense($client)
|
||||
{
|
||||
|
||||
factory(\App\Models\Expense::class, rand(10, 50))->create([
|
||||
'user_id' => $client->user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $client->company->id
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
private function createVendor($client)
|
||||
{
|
||||
|
||||
$vendor = factory(\App\Models\Vendor::class)->create([
|
||||
'user_id' => $client->user->id,
|
||||
'company_id' => $client->company->id
|
||||
]);
|
||||
|
||||
|
||||
factory(\App\Models\VendorContact::class, 1)->create([
|
||||
'user_id' => $client->user->id,
|
||||
'vendor_id' => $vendor->id,
|
||||
'company_id' => $client->company->id,
|
||||
'is_primary' => 1
|
||||
]);
|
||||
|
||||
factory(\App\Models\VendorContact::class, rand(1, 50))->create([
|
||||
'user_id' => $client->user->id,
|
||||
'vendor_id' => $vendor->id,
|
||||
'company_id' => $client->company->id,
|
||||
'is_primary' => 0
|
||||
]);
|
||||
|
||||
factory(\App\Models\Vendor::class, rand(10, 50))->create([
|
||||
'user_id' => $client->user->id,
|
||||
'company_id' => $client->company->id
|
||||
]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private function createInvoice($client)
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
namespace App\DataMapper;
|
||||
|
||||
use Parsedown;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
|
||||
class EmailTemplateDefaults
|
||||
{
|
||||
@ -23,7 +23,14 @@ class EmailTemplateDefaults
|
||||
|
||||
public static function emailInvoiceTemplate()
|
||||
{
|
||||
return Parsedown::instance()->line(self::transformText('invoice_message'));
|
||||
$converter = new CommonMarkConverter([
|
||||
'html_input' => 'strip',
|
||||
'allow_unsafe_links' => false,
|
||||
]);
|
||||
|
||||
return $converter->convertToHtml(self::transformText('invoice_message'));
|
||||
|
||||
//return Parsedown::instance()->line(self::transformText('invoice_message'));
|
||||
}
|
||||
|
||||
public static function emailQuoteSubject()
|
||||
@ -35,7 +42,13 @@ class EmailTemplateDefaults
|
||||
|
||||
public static function emailQuoteTemplate()
|
||||
{
|
||||
return Parsedown::instance()->line(self::transformText('quote_message'));
|
||||
$converter = new CommonMarkConverter([
|
||||
'html_input' => 'strip',
|
||||
'allow_unsafe_links' => false,
|
||||
]);
|
||||
|
||||
return $converter->convertToHtml(self::transformText('quote_message'));
|
||||
//return Parsedown::instance()->line(self::transformText('quote_message'));
|
||||
}
|
||||
|
||||
public static function emailPaymentSubject()
|
||||
@ -56,7 +69,7 @@ class EmailTemplateDefaults
|
||||
|
||||
public static function emailReminder1Template()
|
||||
{
|
||||
return Parsedown::instance()->line('First Email Reminder Text');
|
||||
// return Parsedown::instance()->line('First Email Reminder Text');
|
||||
}
|
||||
|
||||
public static function emailReminder2Subject()
|
||||
@ -67,7 +80,7 @@ class EmailTemplateDefaults
|
||||
|
||||
public static function emailReminder2Template()
|
||||
{
|
||||
return Parsedown::instance()->line('Second Email Reminder Text');
|
||||
// return Parsedown::instance()->line('Second Email Reminder Text');
|
||||
}
|
||||
|
||||
public static function emailReminder3Subject()
|
||||
@ -78,7 +91,7 @@ class EmailTemplateDefaults
|
||||
|
||||
public static function emailReminder3Template()
|
||||
{
|
||||
return Parsedown::instance()->line('Third Email Reminder Text');
|
||||
// return Parsedown::instance()->line('Third Email Reminder Text');
|
||||
}
|
||||
|
||||
public static function emailReminderEndlessSubject()
|
||||
|
39
app/Factory/ExpenseFactory.php
Normal file
39
app/Factory/ExpenseFactory.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Factory;
|
||||
|
||||
use App\DataMapper\ClientSettings;
|
||||
use App\DataMapper\CompanySettings;
|
||||
use App\Models\Expense;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class ExpenseFactory
|
||||
{
|
||||
public static function create(int $company_id, int $user_id) :Expense
|
||||
{
|
||||
$expense = new Expense();
|
||||
$expense->user_id = $user_id;
|
||||
$expense->company_id = $company_id;
|
||||
$expense->is_deleted = false;
|
||||
$expense->should_be_invoiced = false;
|
||||
$expense->tax_name1 = '';
|
||||
$expense->tax_rate1 = 0;
|
||||
$expense->tax_name2 = '';
|
||||
$expense->tax_rate2 = 0;
|
||||
$expense->tax_name3 = '';
|
||||
$expense->tax_rate3 = 0;
|
||||
$expense->expense_date = null;
|
||||
$expense->payment_date = null;
|
||||
|
||||
return $expense;
|
||||
}
|
||||
}
|
@ -40,6 +40,8 @@ class InvoiceFactory
|
||||
$invoice->tax_rate1 = 0;
|
||||
$invoice->tax_name2 = '';
|
||||
$invoice->tax_rate2 = 0;
|
||||
$invoice->tax_name3 = '';
|
||||
$invoice->tax_rate3 = 0;
|
||||
$invoice->custom_value1 = 0;
|
||||
$invoice->custom_value2 = 0;
|
||||
$invoice->custom_value3 = 0;
|
||||
|
28
app/Factory/VendorContactFactory.php
Normal file
28
app/Factory/VendorContactFactory.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Factory;
|
||||
|
||||
use App\Models\VendorContact;
|
||||
|
||||
class VendorContactFactory
|
||||
{
|
||||
public static function create(int $company_id, int $user_id) :VendorContact
|
||||
{
|
||||
$vendor_contact = new VendorContact;
|
||||
$vendor_contact->first_name = "";
|
||||
$vendor_contact->user_id = $user_id;
|
||||
$vendor_contact->company_id = $company_id;
|
||||
$vendor_contact->id = 0;
|
||||
|
||||
return $vendor_contact;
|
||||
}
|
||||
}
|
37
app/Factory/VendorFactory.php
Normal file
37
app/Factory/VendorFactory.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Factory;
|
||||
|
||||
use App\Models\Vendor;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class VendorFactory
|
||||
{
|
||||
public static function create(int $company_id, int $user_id) :Vendor
|
||||
{
|
||||
$vendor = new Vendor;
|
||||
$vendor->company_id = $company_id;
|
||||
$vendor->user_id = $user_id;
|
||||
$vendor->name = '';
|
||||
$vendor->website = '';
|
||||
$vendor->private_notes = '';
|
||||
$vendor->balance = 0;
|
||||
$vendor->paid_to_date = 0;
|
||||
$vendor->country_id = 4;
|
||||
$vendor->is_deleted = 0;
|
||||
|
||||
$vendor_contact = VendorContactFactory::create($company_id, $user_id);
|
||||
$vendor->contacts->add($vendor_contact);
|
||||
|
||||
return $vendor;
|
||||
}
|
||||
}
|
196
app/Filters/VendorFilters.php
Normal file
196
app/Filters/VendorFilters.php
Normal file
@ -0,0 +1,196 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use App\Models\Vendor;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
/**
|
||||
* VendorFilters
|
||||
*/
|
||||
class VendorFilters extends QueryFilters
|
||||
{
|
||||
|
||||
/**
|
||||
* Filter by balance
|
||||
*
|
||||
* @param string $balance
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function balance(string $balance): Builder
|
||||
{
|
||||
$parts = $this->split($balance);
|
||||
|
||||
return $this->builder->where('balance', $parts->operator, $parts->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter between balances
|
||||
*
|
||||
* @param string balance
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function between_balance(string $balance): Builder
|
||||
{
|
||||
$parts = explode(":", $balance);
|
||||
|
||||
return $this->builder->whereBetween('balance', [$parts[0], $parts[1]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter based on search text
|
||||
*
|
||||
* @param string query filter
|
||||
* @return Illuminate\Database\Query\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('vendors.name', 'like', '%'.$filter.'%')
|
||||
->orWhere('vendors.id_number', 'like', '%'.$filter.'%')
|
||||
->orWhere('vendor_contacts.first_name', 'like', '%'.$filter.'%')
|
||||
->orWhere('vendor_contacts.last_name', 'like', '%'.$filter.'%')
|
||||
->orWhere('vendor_contacts.email', 'like', '%'.$filter.'%')
|
||||
->orWhere('vendors.custom_value1', 'like', '%'.$filter.'%')
|
||||
->orWhere('vendors.custom_value2', 'like', '%'.$filter.'%')
|
||||
->orWhere('vendors.custom_value3', 'like', '%'.$filter.'%')
|
||||
->orWhere('vendors.custom_value4', 'like', '%'.$filter.'%');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the list based on the status
|
||||
* archived, active, deleted
|
||||
*
|
||||
* @param string filter
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function status(string $filter = '') : Builder
|
||||
{
|
||||
if (strlen($filter) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
$table = 'vendors';
|
||||
$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 Illuminate\Database\Query\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
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
* @deprecated
|
||||
*/
|
||||
public function baseQuery(int $company_id, User $user) : Builder
|
||||
{
|
||||
$query = DB::table('vendors')
|
||||
->join('companies', 'companies.id', '=', 'vendors.company_id')
|
||||
->join('vendor_contacts', 'vendor_contacts.vendor_id', '=', 'vendors.id')
|
||||
->where('vendors.company_id', '=', $company_id)
|
||||
->where('vendor_contacts.is_primary', '=', true)
|
||||
->where('vendor_contacts.deleted_at', '=', null)
|
||||
//->whereRaw('(vendors.name != "" or contacts.first_name != "" or contacts.last_name != "" or contacts.email != "")') // filter out buy now invoices
|
||||
->select(
|
||||
// DB::raw('COALESCE(vendors.currency_id, companies.currency_id) currency_id'),
|
||||
DB::raw('COALESCE(vendors.country_id, companies.country_id) country_id'),
|
||||
DB::raw("CONCAT(COALESCE(vendor_contacts.first_name, ''), ' ', COALESCE(vendor_contacts.last_name, '')) contact"),
|
||||
'vendors.id',
|
||||
'vendors.name',
|
||||
'vendors.private_notes',
|
||||
'vendor_contacts.first_name',
|
||||
'vendor_contacts.last_name',
|
||||
'vendors.custom_value1',
|
||||
'vendors.custom_value2',
|
||||
'vendors.custom_value3',
|
||||
'vendors.custom_value4',
|
||||
'vendors.balance',
|
||||
'vendors.last_login',
|
||||
'vendors.created_at',
|
||||
'vendors.created_at as vendor_created_at',
|
||||
'vendor_contacts.phone',
|
||||
'vendor_contacts.email',
|
||||
'vendors.deleted_at',
|
||||
'vendors.is_deleted',
|
||||
'vendors.user_id',
|
||||
'vendors.id_number',
|
||||
'vendors.settings'
|
||||
);
|
||||
|
||||
/**
|
||||
* 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', Vendor::class)) {
|
||||
$query->where('vendors.user_id', '=', $user->id);
|
||||
}
|
||||
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the query by the users company ID
|
||||
*
|
||||
* @param $company_id The company Id
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function entityFilter()
|
||||
{
|
||||
|
||||
//return $this->builder->whereCompanyId(auth()->user()->company()->id);
|
||||
return $this->builder->company();
|
||||
}
|
||||
}
|
@ -86,6 +86,8 @@ class BaseController extends Controller
|
||||
//'company.payments',
|
||||
'company.payments.paymentables',
|
||||
'company.quotes',
|
||||
'company.vendors',
|
||||
'company.expenses',
|
||||
];
|
||||
} else {
|
||||
$include = [
|
||||
|
510
app/Http/Controllers/ExpenseController.php
Normal file
510
app/Http/Controllers/ExpenseController.php
Normal file
@ -0,0 +1,510 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Filters\VendorFilters;
|
||||
use App\Jobs\Entity\ActionEntity;
|
||||
use App\Jobs\Util\ProcessBulk;
|
||||
use App\Jobs\Util\UploadAvatar;
|
||||
use App\Models\Country;
|
||||
use App\Models\Currency;
|
||||
use App\Models\Size;
|
||||
use App\Models\Vendor;
|
||||
use App\Repositories\BaseRepository;
|
||||
use App\Transformers\VendorTransformer;
|
||||
use App\Utils\Traits\BulkOptions;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Utils\Traits\Uploadable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class VendorController
|
||||
* @package App\Http\Controllers
|
||||
* @covers App\Http\Controllers\VendorController
|
||||
*/
|
||||
class VendorController extends BaseController
|
||||
{
|
||||
use MakesHash;
|
||||
use Uploadable;
|
||||
use BulkOptions;
|
||||
|
||||
protected $entity_type = Vendor::class;
|
||||
|
||||
protected $entity_transformer = VendorTransformer::class;
|
||||
|
||||
/**
|
||||
* @var Vendorepository
|
||||
*/
|
||||
protected $vendor_repo;
|
||||
|
||||
/**
|
||||
* VendorController constructor.
|
||||
* @param VendorRepository $vendorRepo
|
||||
*/
|
||||
public function __construct(VendorRepository $vendor_repo)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->vendor_repo = $vendor_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/vendors",
|
||||
* operationId="getVendors",
|
||||
* tags={"vendors"},
|
||||
* summary="Gets a list of vendors",
|
||||
* description="Lists vendors, search and filters allow fine grained lists to be generated.
|
||||
|
||||
Query parameters can be added to performed more fine grained filtering of the vendors, these are handled by the VendorFilters 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 vendors",
|
||||
* @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-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/Vendor"),
|
||||
* ),
|
||||
* @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 index(VendorFilters $filters)
|
||||
{
|
||||
$vendors = Vendor::filter($filters);
|
||||
|
||||
return $this->listResponse($vendors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/vendors/{id}",
|
||||
* operationId="showVendor",
|
||||
* tags={"vendors"},
|
||||
* 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 Vendor Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the vendor object",
|
||||
* @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-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/Vendor"),
|
||||
* ),
|
||||
* @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(ShowVendorRequest $request, Vendor $vendor)
|
||||
{
|
||||
return $this->itemResponse($vendor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/vendors/{id}/edit",
|
||||
* operationId="editVendor",
|
||||
* tags={"vendors"},
|
||||
* 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 Vendor 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-API-Version", ref="#/components/headers/X-API-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/Vendor"),
|
||||
* ),
|
||||
* @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(EditVendorRequest $request, Vendor $vendor)
|
||||
{
|
||||
return $this->itemResponse($vendor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param App\Models\Vendor $vendor
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Put(
|
||||
* path="/api/v1/vendors/{id}",
|
||||
* operationId="updateVendor",
|
||||
* tags={"vendors"},
|
||||
* 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 Vendor 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-API-Version", ref="#/components/headers/X-API-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/Vendor"),
|
||||
* ),
|
||||
* @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(UpdateVendorRequest $request, Vendor $vendor)
|
||||
{
|
||||
if($request->entityIsDeleted($vendor))
|
||||
return $request->disallowUpdate();
|
||||
|
||||
$vendor = $this->client_repo->save($request->all(), $vendor);
|
||||
|
||||
$this->uploadLogo($request->file('company_logo'), $vendor->company, $vendor);
|
||||
|
||||
return $this->itemResponse($vendor->fresh());
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/vendors/create",
|
||||
* operationId="getVendorsCreate",
|
||||
* tags={"vendors"},
|
||||
* 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-API-Version", ref="#/components/headers/X-API-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/Vendor"),
|
||||
* ),
|
||||
* @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(CreateVendorRequest $request)
|
||||
{
|
||||
$vendor = VendorFactory::create(auth()->user()->company()->id, auth()->user()->id);
|
||||
|
||||
return $this->itemResponse($vendor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/vendors",
|
||||
* operationId="storeVendor",
|
||||
* tags={"vendors"},
|
||||
* 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-API-Version", ref="#/components/headers/X-API-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/Vendor"),
|
||||
* ),
|
||||
* @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(StoreVendorRequest $request)
|
||||
{
|
||||
$vendor = $this->client_repo->save($request->all(), VendorFactory::create(auth()->user()->company()->id, auth()->user()->id));
|
||||
|
||||
$vendor->load('contacts', 'primary_contact');
|
||||
|
||||
$this->uploadLogo($request->file('company_logo'), $vendor->company, $vendor);
|
||||
|
||||
return $this->itemResponse($vendor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
* @OA\Delete(
|
||||
* path="/api/v1/vendors/{id}",
|
||||
* operationId="deleteVendor",
|
||||
* tags={"vendors"},
|
||||
* 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 Vendor 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-API-Version", ref="#/components/headers/X-API-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(DestroyVendorRequest $request, Vendor $vendor)
|
||||
{
|
||||
//may not need these destroy routes as we are using actions to 'archive/delete'
|
||||
$vendor->delete();
|
||||
|
||||
return response()->json([], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform bulk actions on the list view
|
||||
*
|
||||
* @param BulkVendorRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/vendors/bulk",
|
||||
* operationId="bulkVendors",
|
||||
* tags={"vendors"},
|
||||
* summary="Performs bulk actions on an array of vendors",
|
||||
* 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 Vendor User response",
|
||||
* @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-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/Vendor"),
|
||||
* ),
|
||||
* @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');
|
||||
$vendors = Vendor::withTrashed()->find($this->transformKeys($ids));
|
||||
|
||||
$vendors->each(function ($vendor, $key) use ($action) {
|
||||
if (auth()->user()->can('edit', $vendor)) {
|
||||
$this->client_repo->{$action}($vendor);
|
||||
}
|
||||
});
|
||||
|
||||
return $this->listResponse(Vendor::withTrashed()->whereIn('id', $this->transformKeys($ids)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a client statement
|
||||
*
|
||||
* @return [type] [description]
|
||||
*/
|
||||
public function statement()
|
||||
{
|
||||
//todo
|
||||
}
|
||||
}
|
@ -71,7 +71,7 @@ class SendingController extends Controller
|
||||
|
||||
$send_logs = false;
|
||||
|
||||
if($request->has('send_logs'));
|
||||
if($request->has('send_logs'))
|
||||
$send_logs = $request->input('send_logs');
|
||||
|
||||
Mail::to(config('ninja.contact.ninja_official_contact'))
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Parsedown;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
|
||||
class TemplateController extends BaseController
|
||||
{
|
||||
@ -106,9 +106,14 @@ class TemplateController extends BaseController
|
||||
$subject = request()->input('subject');
|
||||
$body = request()->input('body');
|
||||
|
||||
$converter = new CommonMarkConverter([
|
||||
'html_input' => 'strip',
|
||||
'allow_unsafe_links' => false,
|
||||
]);
|
||||
|
||||
$data = [
|
||||
'subject' => request()->input('subject'),
|
||||
'body' => Parsedown::instance()->text(request()->input('body')),
|
||||
'body' => $converter->convertToHtml(request()->input('body')),
|
||||
];
|
||||
|
||||
return response()->json($data, 200);
|
||||
|
509
app/Http/Controllers/VendorController.php
Normal file
509
app/Http/Controllers/VendorController.php
Normal file
@ -0,0 +1,509 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Filters\VendorFilters;
|
||||
use App\Jobs\Entity\ActionEntity;
|
||||
use App\Jobs\Util\ProcessBulk;
|
||||
use App\Jobs\Util\UploadAvatar;
|
||||
use App\Models\Country;
|
||||
use App\Models\Currency;
|
||||
use App\Models\Size;
|
||||
use App\Models\Vendor;
|
||||
use App\Repositories\BaseRepository;
|
||||
use App\Utils\Traits\BulkOptions;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Utils\Traits\Uploadable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class VendorController
|
||||
* @package App\Http\Controllers
|
||||
* @covers App\Http\Controllers\VendorController
|
||||
*/
|
||||
class VendorController extends BaseController
|
||||
{
|
||||
use MakesHash;
|
||||
use Uploadable;
|
||||
use BulkOptions;
|
||||
|
||||
protected $entity_type = Vendor::class;
|
||||
|
||||
protected $entity_transformer = VendorTransformer::class;
|
||||
|
||||
/**
|
||||
* @var Vendorepository
|
||||
*/
|
||||
protected $vendor_repo;
|
||||
|
||||
/**
|
||||
* VendorController constructor.
|
||||
* @param VendorRepository $vendorRepo
|
||||
*/
|
||||
public function __construct(VendorRepository $vendor_repo)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->vendor_repo = $vendor_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/vendors",
|
||||
* operationId="getVendors",
|
||||
* tags={"vendors"},
|
||||
* summary="Gets a list of vendors",
|
||||
* description="Lists vendors, search and filters allow fine grained lists to be generated.
|
||||
|
||||
Query parameters can be added to performed more fine grained filtering of the vendors, these are handled by the VendorFilters 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 vendors",
|
||||
* @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-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/Vendor"),
|
||||
* ),
|
||||
* @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 index(VendorFilters $filters)
|
||||
{
|
||||
$vendors = Vendor::filter($filters);
|
||||
|
||||
return $this->listResponse($vendors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/vendors/{id}",
|
||||
* operationId="showVendor",
|
||||
* tags={"vendors"},
|
||||
* 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 Vendor Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the vendor object",
|
||||
* @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-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/Vendor"),
|
||||
* ),
|
||||
* @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(ShowVendorRequest $request, Vendor $vendor)
|
||||
{
|
||||
return $this->itemResponse($vendor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/vendors/{id}/edit",
|
||||
* operationId="editVendor",
|
||||
* tags={"vendors"},
|
||||
* 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 Vendor 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-API-Version", ref="#/components/headers/X-API-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/Vendor"),
|
||||
* ),
|
||||
* @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(EditVendorRequest $request, Vendor $vendor)
|
||||
{
|
||||
return $this->itemResponse($vendor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param App\Models\Vendor $vendor
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Put(
|
||||
* path="/api/v1/vendors/{id}",
|
||||
* operationId="updateVendor",
|
||||
* tags={"vendors"},
|
||||
* 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 Vendor 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-API-Version", ref="#/components/headers/X-API-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/Vendor"),
|
||||
* ),
|
||||
* @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(UpdateVendorRequest $request, Vendor $vendor)
|
||||
{
|
||||
if($request->entityIsDeleted($vendor))
|
||||
return $request->disallowUpdate();
|
||||
|
||||
$vendor = $this->client_repo->save($request->all(), $vendor);
|
||||
|
||||
$this->uploadLogo($request->file('company_logo'), $vendor->company, $vendor);
|
||||
|
||||
return $this->itemResponse($vendor->fresh());
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/vendors/create",
|
||||
* operationId="getVendorsCreate",
|
||||
* tags={"vendors"},
|
||||
* 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-API-Version", ref="#/components/headers/X-API-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/Vendor"),
|
||||
* ),
|
||||
* @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(CreateVendorRequest $request)
|
||||
{
|
||||
$vendor = VendorFactory::create(auth()->user()->company()->id, auth()->user()->id);
|
||||
|
||||
return $this->itemResponse($vendor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/vendors",
|
||||
* operationId="storeVendor",
|
||||
* tags={"vendors"},
|
||||
* 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-API-Version", ref="#/components/headers/X-API-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/Vendor"),
|
||||
* ),
|
||||
* @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(StoreVendorRequest $request)
|
||||
{
|
||||
$vendor = $this->client_repo->save($request->all(), VendorFactory::create(auth()->user()->company()->id, auth()->user()->id));
|
||||
|
||||
$vendor->load('contacts', 'primary_contact');
|
||||
|
||||
$this->uploadLogo($request->file('company_logo'), $vendor->company, $vendor);
|
||||
|
||||
return $this->itemResponse($vendor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
* @OA\Delete(
|
||||
* path="/api/v1/vendors/{id}",
|
||||
* operationId="deleteVendor",
|
||||
* tags={"vendors"},
|
||||
* 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 Vendor 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-API-Version", ref="#/components/headers/X-API-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(DestroyVendorRequest $request, Vendor $vendor)
|
||||
{
|
||||
//may not need these destroy routes as we are using actions to 'archive/delete'
|
||||
$vendor->delete();
|
||||
|
||||
return response()->json([], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform bulk actions on the list view
|
||||
*
|
||||
* @param BulkVendorRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/vendors/bulk",
|
||||
* operationId="bulkVendors",
|
||||
* tags={"vendors"},
|
||||
* summary="Performs bulk actions on an array of vendors",
|
||||
* 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 Vendor User response",
|
||||
* @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-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/Vendor"),
|
||||
* ),
|
||||
* @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');
|
||||
$vendors = Vendor::withTrashed()->find($this->transformKeys($ids));
|
||||
|
||||
$vendors->each(function ($vendor, $key) use ($action) {
|
||||
if (auth()->user()->can('edit', $vendor)) {
|
||||
$this->client_repo->{$action}($vendor);
|
||||
}
|
||||
});
|
||||
|
||||
return $this->listResponse(Vendor::withTrashed()->whereIn('id', $this->transformKeys($ids)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a client statement
|
||||
*
|
||||
* @return [type] [description]
|
||||
*/
|
||||
public function statement()
|
||||
{
|
||||
//todo
|
||||
}
|
||||
}
|
47
app/Http/Requests/Vendor/BulkVendorRequest.php
vendored
Normal file
47
app/Http/Requests/Vendor/BulkVendorRequest.php
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Vendor;
|
||||
|
||||
use App\Utils\Traits\BulkOptions;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use App\Models\Vendor;
|
||||
|
||||
class BulkVendorRequest extends FormRequest
|
||||
{
|
||||
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(), Vendor::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;
|
||||
}
|
||||
}
|
29
app/Http/Requests/Vendor/CreateVendorRequest.php
vendored
Normal file
29
app/Http/Requests/Vendor/CreateVendorRequest.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\Vendor;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\Vendor;
|
||||
|
||||
class CreateVendorRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('create', Vendor::class);
|
||||
}
|
||||
}
|
29
app/Http/Requests/Vendor/DestroyVendorRequest.php
vendored
Normal file
29
app/Http/Requests/Vendor/DestroyVendorRequest.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\Vendor;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\Vendor;
|
||||
|
||||
class DestroyVendorRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('edit', $this->vendor);
|
||||
}
|
||||
}
|
39
app/Http/Requests/Vendor/EditVendorRequest.php
vendored
Normal file
39
app/Http/Requests/Vendor/EditVendorRequest.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\Vendor;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\Vendor;
|
||||
|
||||
class EditVendorRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('edit', $this->vendor);
|
||||
}
|
||||
|
||||
// public function prepareForValidation()
|
||||
// {
|
||||
// $input = $this->all();
|
||||
|
||||
// //$input['id'] = $this->encodePrimaryKey($input['id']);
|
||||
|
||||
// $this->replace($input);
|
||||
|
||||
// }
|
||||
}
|
29
app/Http/Requests/Vendor/ShowVendorRequest.php
vendored
Normal file
29
app/Http/Requests/Vendor/ShowVendorRequest.php
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\Vendor;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\Vendor;
|
||||
|
||||
class ShowVendorRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->can('view', $this->vendor);
|
||||
}
|
||||
}
|
79
app/Http/Requests/Vendor/StoreVendorRequest.php
vendored
Normal file
79
app/Http/Requests/Vendor/StoreVendorRequest.php
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\Vendor;
|
||||
|
||||
use App\DataMapper\VendorSettings;
|
||||
use App\Http\Requests\Request;
|
||||
use App\Http\ValidationRules\ValidVendorGroupSettingsRule;
|
||||
use App\Models\Vendor;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class StoreVendorRequest 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', Vendor::class);
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
|
||||
/* Ensure we have a client name, and that all emails are unique*/
|
||||
//$rules['name'] = 'required|min:1';
|
||||
$rules['id_number'] = 'unique:vendors,id_number,' . $this->id . ',id,company_id,' . $this->company_id;
|
||||
//$rules['settings'] = new ValidVendorGroupSettingsRule();
|
||||
$rules['contacts.*.email'] = 'nullable|distinct';
|
||||
|
||||
$contacts = request('contacts');
|
||||
|
||||
if (is_array($contacts)) {
|
||||
for ($i = 0; $i < count($contacts); $i++) {
|
||||
|
||||
//$rules['contacts.' . $i . '.email'] = 'nullable|email|distinct';
|
||||
}
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if (!isset($input['settings'])) {
|
||||
$input['settings'] = VendorSettings::defaults();
|
||||
}
|
||||
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'unique' => ctrans('validation.unique', ['attribute' => 'email']),
|
||||
//'required' => trans('validation.required', ['attribute' => 'email']),
|
||||
'contacts.*.email.required' => ctrans('validation.email', ['attribute' => 'email']),
|
||||
];
|
||||
}
|
||||
}
|
73
app/Http/Requests/Vendor/UpdateVendorRequest.php
vendored
Normal file
73
app/Http/Requests/Vendor/UpdateVendorRequest.php
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\Vendor;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Http\ValidationRules\IsDeletedRule;
|
||||
use App\Http\ValidationRules\ValidVendorGroupSettingsRule;
|
||||
use App\Utils\Traits\ChecksEntityStatus;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UpdateVendorRequest 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->vendor);
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
/* Ensure we have a client name, and that all emails are unique*/
|
||||
|
||||
$rules['country_id'] = 'integer|nullable';
|
||||
//$rules['id_number'] = 'unique:clients,id_number,,id,company_id,' . auth()->user()->company()->id;
|
||||
$rules['id_number'] = 'unique:clients,id_number,' . $this->id . ',id,company_id,' . $this->company_id;
|
||||
$rules['contacts.*.email'] = 'nullable|distinct';
|
||||
|
||||
$contacts = request('contacts');
|
||||
|
||||
if (is_array($contacts)) {
|
||||
// for ($i = 0; $i < count($contacts); $i++) {
|
||||
// // $rules['contacts.' . $i . '.email'] = 'nullable|email|unique:client_contacts,email,' . isset($contacts[$i]['id'].',company_id,'.$this->company_id);
|
||||
// //$rules['contacts.' . $i . '.email'] = 'nullable|email';
|
||||
// }
|
||||
}
|
||||
return $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();
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
}
|
@ -114,6 +114,14 @@ class Company extends BaseModel
|
||||
return $this->hasMany(Client::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function vendors()
|
||||
{
|
||||
return $this->hasMany(Vendor::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function activities()
|
||||
{
|
||||
return $this->hasMany(Activity::class);
|
||||
|
@ -13,26 +13,51 @@ namespace App\Models;
|
||||
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Expense extends BaseModel
|
||||
{
|
||||
use MakesHash;
|
||||
use SoftDeletes;
|
||||
|
||||
protected $guarded = [
|
||||
'id',
|
||||
protected $fillable = [
|
||||
'client_id',
|
||||
'vendor_id',
|
||||
'expense_currency_id',
|
||||
'expense_date',
|
||||
'invoice_currency_id',
|
||||
'amount',
|
||||
'foreign_amount',
|
||||
'exchange_rate',
|
||||
'private_notes',
|
||||
'public_notes',
|
||||
'bank_id',
|
||||
'transaction_id',
|
||||
'expense_category_id',
|
||||
'tax_rate1',
|
||||
'tax_name1',
|
||||
'tax_rate2',
|
||||
'tax_name2',
|
||||
'tax_rate3',
|
||||
'tax_name3',
|
||||
'payment_date',
|
||||
'payment_type_id',
|
||||
'transaction_reference',
|
||||
'invoice_documents',
|
||||
'should_be_invoiced',
|
||||
'custom_value1',
|
||||
'custom_value2',
|
||||
'custom_value3',
|
||||
'custom_value4',
|
||||
];
|
||||
|
||||
protected $appends = ['expense_id'];
|
||||
|
||||
public function getRouteKeyName()
|
||||
{
|
||||
return 'expense_id';
|
||||
}
|
||||
protected $casts = [
|
||||
'is_deleted' => 'boolean',
|
||||
'updated_at' => 'timestamp',
|
||||
'created_at' => 'timestamp',
|
||||
'deleted_at' => 'timestamp',
|
||||
];
|
||||
|
||||
public function getExpenseIdAttribute()
|
||||
{
|
||||
return $this->encodePrimaryKey($this->id);
|
||||
}
|
||||
|
||||
public function documents()
|
||||
{
|
||||
|
34
app/Models/ExpenseCategory.php
Normal file
34
app/Models/ExpenseCategory.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class ExpenseCategory extends BaseModel
|
||||
{
|
||||
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function expense()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Expense');
|
||||
}
|
||||
}
|
73
app/Models/Vendor.php
Normal file
73
app/Models/Vendor.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Vendor extends BaseModel
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'id_number',
|
||||
'vat_number',
|
||||
'work_phone',
|
||||
'address1',
|
||||
'address2',
|
||||
'city',
|
||||
'state',
|
||||
'postal_code',
|
||||
'country_id',
|
||||
'private_notes',
|
||||
'currency_id',
|
||||
'website',
|
||||
'transaction_name',
|
||||
'custom_value1',
|
||||
'custom_value2',
|
||||
'custom_value3',
|
||||
'custom_value4',
|
||||
];
|
||||
|
||||
|
||||
protected $casts = [
|
||||
'country_id' => 'string',
|
||||
'currency_id' => 'string',
|
||||
'is_deleted' => 'boolean',
|
||||
'updated_at' => 'timestamp',
|
||||
'created_at' => 'timestamp',
|
||||
'deleted_at' => 'timestamp',
|
||||
];
|
||||
|
||||
public function documents()
|
||||
{
|
||||
return $this->morphMany(Document::class, 'documentable');
|
||||
}
|
||||
|
||||
public function assigned_user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'assigned_user_id', 'id');
|
||||
}
|
||||
|
||||
public function contacts()
|
||||
{
|
||||
return $this->hasMany(VendorContact::class)->orderBy('is_primary', 'desc');
|
||||
}
|
||||
|
||||
public function activities()
|
||||
{
|
||||
return $this->hasMany(Activity::class);
|
||||
}
|
||||
}
|
||||
|
135
app/Models/VendorContact.php
Normal file
135
app/Models/VendorContact.php
Normal file
@ -0,0 +1,135 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\Language;
|
||||
use App\Models\User;
|
||||
use App\Notifications\ClientContactResetPassword as ResetPasswordNotification;
|
||||
use App\Notifications\ClientContactResetPassword;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Hashids\Hashids;
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Contracts\Translation\HasLocalePreference;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Laracasts\Presenter\PresentableTrait;
|
||||
|
||||
class VendorContact extends Authenticatable implements HasLocalePreference
|
||||
{
|
||||
use Notifiable;
|
||||
use MakesHash;
|
||||
use PresentableTrait;
|
||||
use SoftDeletes;
|
||||
|
||||
/* Used to authenticate a vendor */
|
||||
protected $guard = 'vendor';
|
||||
|
||||
/* Allow microtime timestamps */
|
||||
protected $dateFormat = 'Y-m-d H:i:s.u';
|
||||
|
||||
protected $dates = [
|
||||
'deleted_at'
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'hashed_id'
|
||||
];
|
||||
|
||||
protected $with = [
|
||||
'vendor',
|
||||
'company'
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'updated_at' => 'timestamp',
|
||||
'created_at' => 'timestamp',
|
||||
'deleted_at' => 'timestamp',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
'first_name',
|
||||
'last_name',
|
||||
'phone',
|
||||
'custom_value1',
|
||||
'custom_value2',
|
||||
'custom_value3',
|
||||
'custom_value4',
|
||||
'email',
|
||||
'is_primary',
|
||||
];
|
||||
|
||||
public function getHashedIdAttribute()
|
||||
{
|
||||
return $this->encodePrimaryKey($this->id);
|
||||
}
|
||||
|
||||
public function getContactIdAttribute()
|
||||
{
|
||||
return $this->encodePrimaryKey($this->id);
|
||||
}
|
||||
|
||||
public function vendor()
|
||||
{
|
||||
return $this->belongsTo(Vendor::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function primary_contact()
|
||||
{
|
||||
return $this->where('is_primary', true);
|
||||
}
|
||||
|
||||
public function company()
|
||||
{
|
||||
return $this->belongsTo(Company::class);
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function sendPasswordResetNotification($token)
|
||||
{
|
||||
$this->notify(new ClientContactResetPassword($token));
|
||||
}
|
||||
|
||||
public function preferredLocale()
|
||||
{
|
||||
$languages = Cache::get('languages');
|
||||
|
||||
return $languages->filter(function ($item) {
|
||||
return $item->id == $this->client->getSetting('language_id');
|
||||
})->first()->locale;
|
||||
|
||||
//$lang = Language::find($this->client->getSetting('language_id'));
|
||||
|
||||
//return $lang->locale;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the model for a bound value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return \Illuminate\Database\Eloquent\Model|null
|
||||
*/
|
||||
public function resolveRouteBinding($value)
|
||||
{
|
||||
return $this
|
||||
->withTrashed()
|
||||
->where('id', $this->decodePrimaryKey($value))->firstOrFail();
|
||||
}
|
||||
}
|
33
app/Policies/ExpensePolicy.php
Normal file
33
app/Policies/ExpensePolicy.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\Expense;
|
||||
use App\Models\User;
|
||||
|
||||
/**
|
||||
* Class ExpensePolicy
|
||||
* @package App\Policies
|
||||
*/
|
||||
class ExpensePolicy 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_expense') || $user->hasPermission('create_all');
|
||||
}
|
||||
}
|
33
app/Policies/VendorPolicy.php
Normal file
33
app/Policies/VendorPolicy.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\Vendor;
|
||||
use App\Models\User;
|
||||
|
||||
/**
|
||||
* Class VendorPolicy
|
||||
* @package App\Policies
|
||||
*/
|
||||
class VendorPolicy 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_vendor') || $user->hasPermission('create_all');
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ use App\Models\Activity;
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyGateway;
|
||||
use App\Models\Expense;
|
||||
use App\Models\GroupSetting;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
@ -24,10 +25,12 @@ use App\Models\RecurringInvoice;
|
||||
use App\Models\RecurringQuote;
|
||||
use App\Models\TaxRate;
|
||||
use App\Models\User;
|
||||
use App\Models\Vendor;
|
||||
use App\Policies\ActivityPolicy;
|
||||
use App\Policies\ClientPolicy;
|
||||
use App\Policies\CompanyGatewayPolicy;
|
||||
use App\Policies\CompanyPolicy;
|
||||
use App\Policies\ExpensePolicy;
|
||||
use App\Policies\GroupSettingPolicy;
|
||||
use App\Policies\InvoicePolicy;
|
||||
use App\Policies\PaymentPolicy;
|
||||
@ -37,6 +40,7 @@ use App\Policies\RecurringInvoicePolicy;
|
||||
use App\Policies\RecurringQuotePolicy;
|
||||
use App\Policies\TaxRatePolicy;
|
||||
use App\Policies\UserPolicy;
|
||||
use App\Policies\VendorPolicy;
|
||||
use Auth;
|
||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
@ -62,6 +66,8 @@ class AuthServiceProvider extends ServiceProvider
|
||||
GroupSetting::class => GroupSettingPolicy::class,
|
||||
CompanyGateway::class => CompanyGatewayPolicy::class,
|
||||
TaxRate::class => TaxRatePolicy::class,
|
||||
Vendor::class => VendorPolicy::class,
|
||||
Expense::class => ExpensePolicy::class,
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -72,7 +72,6 @@ class InvoiceRepository extends BaseRepository
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isset($data['invitations'])) {
|
||||
$invitations = collect($data['invitations']);
|
||||
|
||||
@ -81,7 +80,6 @@ class InvoiceRepository extends BaseRepository
|
||||
InvoiceInvitation::destroy($invitation);
|
||||
});
|
||||
|
||||
|
||||
foreach ($data['invitations'] as $invitation) {
|
||||
$inv = false;
|
||||
|
||||
@ -96,6 +94,7 @@ class InvoiceRepository extends BaseRepository
|
||||
$new_invitation->invoice_id = $invoice->id;
|
||||
$new_invitation->client_contact_id = $this->decodePrimaryKey($invitation['client_contact_id']);
|
||||
$new_invitation->save();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
76
app/Repositories/VendorContactRepository.php
Normal file
76
app/Repositories/VendorContactRepository.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Repositories;
|
||||
|
||||
use App\Models\Vendor;
|
||||
use App\Models\VendorContact;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* VendorContactRepository
|
||||
*/
|
||||
class VendorContactRepository extends BaseRepository
|
||||
{
|
||||
public function save($contacts, Vendor $vendor) : void
|
||||
{
|
||||
|
||||
/* Convert array to collection */
|
||||
$contacts = collect($contacts);
|
||||
|
||||
/* Get array of IDs which have been removed from the contacts array and soft delete each contact */
|
||||
collect($vendor->contacts->pluck('id'))->diff($contacts->pluck('id'))->each(function ($contact) {
|
||||
VendorContact::destroy($contact);
|
||||
});
|
||||
|
||||
$this->is_primary = true;
|
||||
/* Set first record to primary - always */
|
||||
$contacts = $contacts->sortByDesc('is_primary')->map(function ($contact) {
|
||||
$contact['is_primary'] = $this->is_primary;
|
||||
$this->is_primary = false;
|
||||
return $contact;
|
||||
});
|
||||
|
||||
//loop and update/create contacts
|
||||
$contacts->each(function ($contact) use ($vendor) {
|
||||
$update_contact = null;
|
||||
|
||||
if (isset($contact['id'])) {
|
||||
$update_contact = VendorContact::find($this->decodePrimaryKey($contact['id']));
|
||||
}
|
||||
|
||||
if (!$update_contact) {
|
||||
$update_contact = new VendorContact;
|
||||
$update_contact->vendor_id = $vendor->id;
|
||||
$update_contact->company_id = $vendor->company_id;
|
||||
$update_contact->user_id = $vendor->user_id;
|
||||
$update_contact->contact_key = Str::random(40);
|
||||
}
|
||||
|
||||
$update_contact->fill($contact);
|
||||
|
||||
$update_contact->save();
|
||||
});
|
||||
|
||||
|
||||
|
||||
//always made sure we have one blank contact to maintain state
|
||||
if ($contacts->count() == 0) {
|
||||
$new_contact = new VendorContact;
|
||||
$new_contact->vendor_id = $vendor->id;
|
||||
$new_contact->company_id = $vendor->company_id;
|
||||
$new_contact->user_id = $vendor->user_id;
|
||||
$new_contact->contact_key = Str::random(40);
|
||||
$new_contact->is_primary = true;
|
||||
$new_contact->save();
|
||||
}
|
||||
}
|
||||
}
|
95
app/Repositories/VendorRepository.php
Normal file
95
app/Repositories/VendorRepository.php
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Repositories;
|
||||
|
||||
use App\Factory\VendorFactory;
|
||||
use App\Models\Vendor;
|
||||
use App\Repositories\VSendorContactRepository;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* VendorRepository
|
||||
*/
|
||||
class VendorRepository extends BaseRepository
|
||||
{
|
||||
use GeneratesCounter;
|
||||
/**
|
||||
* @var vendorContactRepository
|
||||
*/
|
||||
protected $contact_repo;
|
||||
|
||||
/**
|
||||
* vendorController constructor.
|
||||
* @param vendorContactRepository $contact_repo
|
||||
*/
|
||||
public function __construct(VendorContactRepository $contact_repo)
|
||||
{
|
||||
$this->contact_repo = $contact_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the class name.
|
||||
*
|
||||
* @return string The class name.
|
||||
*/
|
||||
public function getClassName()
|
||||
{
|
||||
return Vendor::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the vendor and its contacts
|
||||
*
|
||||
* @param array $data The data
|
||||
* @param \App\Models\vendor $vendor The vendor
|
||||
*
|
||||
* @return vendor|\App\Models\vendor|null vendor Object
|
||||
*/
|
||||
public function save(array $data, Vendor $vendor) : ?Vendor
|
||||
{
|
||||
$vendor->fill($data);
|
||||
|
||||
$vendor->save();
|
||||
|
||||
if ($vendor->id_number == "" || !$vendor->id_number) {
|
||||
$vendor->id_number = $this->getNextVendorNumber($vendor);
|
||||
} //todo write tests for this and make sure that custom vendor numbers also works as expected from here
|
||||
|
||||
$vendor->save();
|
||||
|
||||
if (isset($data['contacts'])) {
|
||||
$contacts = $this->contact_repo->save($data['contacts'], $vendor);
|
||||
}
|
||||
|
||||
if (empty($data['name'])) {
|
||||
$data['name'] = $vendor->present()->name();
|
||||
}
|
||||
|
||||
|
||||
return $vendor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store vendors in bulk.
|
||||
*
|
||||
* @param array $vendor
|
||||
* @return vendor|null
|
||||
*/
|
||||
public function create($vendor): ?Vendor
|
||||
{
|
||||
return $this->save(
|
||||
$vendor,
|
||||
VendorFactory::create(auth()->user()->company()->id, auth()->user()->id)
|
||||
);
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyGateway;
|
||||
use App\Models\CompanyUser;
|
||||
use App\Models\Expense;
|
||||
use App\Models\GroupSetting;
|
||||
use App\Models\Payment;
|
||||
use App\Models\Product;
|
||||
@ -53,6 +54,7 @@ class CompanyTransformer extends EntityTransformer
|
||||
'timezone',
|
||||
'language',
|
||||
'expenses',
|
||||
'vendors',
|
||||
'payments',
|
||||
'company_user',
|
||||
'groups',
|
||||
@ -137,6 +139,20 @@ class CompanyTransformer extends EntityTransformer
|
||||
return $this->includeCollection($company->clients, $transformer, Client::class);
|
||||
}
|
||||
|
||||
public function includeExpenses(Company $company)
|
||||
{
|
||||
$transformer = new ExpenseTransformer($this->serializer);
|
||||
|
||||
return $this->includeCollection($company->expenses, $transformer, Expense::class);
|
||||
}
|
||||
|
||||
public function includeVendors(Company $company)
|
||||
{
|
||||
$transformer = new VendorTransformer($this->serializer);
|
||||
|
||||
return $this->includeCollection($company->vendors, $transformer, Vendor::class);
|
||||
}
|
||||
|
||||
public function includeGroups(Company $company)
|
||||
{
|
||||
$transformer = new GroupSettingTransformer($this->serializer);
|
||||
|
80
app/Transformers/ExpenseTransformer.php
Normal file
80
app/Transformers/ExpenseTransformer.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Transformers;
|
||||
|
||||
use App\Models\Expense;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
|
||||
/**
|
||||
* class ExpenseTransformer
|
||||
*/
|
||||
class ExpenseTransformer extends EntityTransformer
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
protected $defaultIncludes = [
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $availableIncludes = [
|
||||
|
||||
];
|
||||
|
||||
/**
|
||||
* @param Expense $expense
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function transform(Expense $expense)
|
||||
{
|
||||
return [
|
||||
'id' => $this->encodePrimaryKey($expense->id),
|
||||
'user_id' => $this->encodePrimaryKey($expense->user_id),
|
||||
'assigned_user_id' => $this->encodePrimaryKey($expense->assigned_user_id),
|
||||
'vendor_id' => $this->encodePrimaryKey($expense->vendor_id),
|
||||
'invoice_id' => $this->encodePrimaryKey($expense->invoice_id),
|
||||
'client_id' => $this->encodePrimaryKey($expense->client_id),
|
||||
'bank_id' => (string)$expense->bank_id ?: '',
|
||||
'invoice_currency_id' => (string)$expense->invoice_currency_id ?: '',
|
||||
'expense_currency_id' => (string)$expense->expense_currency_id ?: '',
|
||||
'invoice_category_id' => (string)$expense->invoice_category_id ?: '',
|
||||
'payment_type_id' => (string)$expense->payment_type_id ?: '',
|
||||
'recurring_expense_id' => (string)$expense->recurring_expense_id ?: '',
|
||||
'is_deleted' => (bool) $expense->is_deleted,
|
||||
'should_be_invoiced' => (bool) $expense->should_be_invoiced,
|
||||
'invoice_documents' => (bool) $expense->invoice_documents,
|
||||
'amount' => (float)$expense->amount ?: 0,
|
||||
'foreign_amount' => (float)$expense->foreign_amount ?: 0,
|
||||
'exchange_rate' => (float)$expense->exchange_rate ?: 0,
|
||||
'tax_name1' => $expense->tax_name1 ? $expense->tax_name1 : '',
|
||||
'tax_rate1' => (float) $expense->tax_rate1,
|
||||
'tax_name2' => $expense->tax_name2 ? $expense->tax_name2 : '',
|
||||
'tax_rate2' => (float) $expense->tax_rate2,
|
||||
'tax_name3' => $expense->tax_name3 ? $expense->tax_name3 : '',
|
||||
'tax_rate3' => (float) $expense->tax_rate3,
|
||||
'private_notes' => (string) $expense->private_notes ?: '',
|
||||
'public_notes' => (string) $expense->public_notes ?: '',
|
||||
'transaction_reference' => (string) $expense->transaction_reference ?: '',
|
||||
'transaction_id' => (string) $expense->transaction_id ?: '',
|
||||
'expense_date' => $expense->expense_date ?: '',
|
||||
'payment_date' => $expense->payment_date ?: '',
|
||||
'custom_value1' => $expense->custom_value1 ?: '',
|
||||
'custom_value2' => $expense->custom_value2 ?: '',
|
||||
'custom_value3' => $expense->custom_value3 ?: '',
|
||||
'custom_value4' => $expense->custom_value4 ?: '',
|
||||
'updated_at' => $expense->updated_at,
|
||||
'archived_at' => $expense->deleted_at,
|
||||
];
|
||||
}
|
||||
}
|
47
app/Transformers/VendorContactTransformer.php
Normal file
47
app/Transformers/VendorContactTransformer.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Transformers;
|
||||
|
||||
use App\Models\VendorContact;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
|
||||
/**
|
||||
* Class VendorContactTransformer.
|
||||
*
|
||||
*/
|
||||
class VendorContactTransformer extends EntityTransformer
|
||||
{
|
||||
use MakesHash;
|
||||
/**
|
||||
* @param ClientContact $vendor
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function transform(VendorContact $vendor)
|
||||
{
|
||||
return [
|
||||
'id' => $this->encodePrimaryKey($vendor->id),
|
||||
'first_name' => $vendor->first_name ?: '',
|
||||
'last_name' => $vendor->last_name ?: '',
|
||||
'email' => $vendor->email ?: '',
|
||||
'updated_at' => $vendor->updated_at,
|
||||
'archived_at' => $vendor->deleted_at,
|
||||
'is_primary' => (bool) $vendor->is_primary,
|
||||
'phone' => $vendor->phone ?: '',
|
||||
'custom_value1' => $vendor->custom_value1 ?: '',
|
||||
'custom_value2' => $vendor->custom_value2 ?: '',
|
||||
'custom_value3' => $vendor->custom_value3 ?: '',
|
||||
'custom_value4' => $vendor->custom_value4 ?: '',
|
||||
];
|
||||
}
|
||||
}
|
98
app/Transformers/VendorTransformer.php
Normal file
98
app/Transformers/VendorTransformer.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Transformers;
|
||||
|
||||
use App\Models\Activity;
|
||||
use App\Models\Vendor;
|
||||
use App\Models\VendorContact;
|
||||
use App\Models\VendorGatewayToken;
|
||||
use App\Transformers\ActivityTransformer;
|
||||
use App\Transformers\VendorGatewayTokenTransformer;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
|
||||
/**
|
||||
* class VendorTransformer
|
||||
*/
|
||||
class VendorTransformer extends EntityTransformer
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
protected $defaultIncludes = [
|
||||
'contacts',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $availableIncludes = [
|
||||
'activities',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @param Vendor $vendor
|
||||
*
|
||||
* @return \League\Fractal\Resource\Collection
|
||||
*/
|
||||
public function includeActivities(Vendor $vendor)
|
||||
{
|
||||
$transformer = new ActivityTransformer($this->serializer);
|
||||
|
||||
return $this->includeCollection($vendor->activities, $transformer, Activity::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Vendor $vendor
|
||||
*
|
||||
* @return \League\Fractal\Resource\Collection
|
||||
*/
|
||||
public function includeContacts(Vendor $vendor)
|
||||
{
|
||||
$transformer = new VendorContactTransformer($this->serializer);
|
||||
|
||||
return $this->includeCollection($vendor->contacts, $transformer, VendorContact::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Vendor $vendor
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function transform(Vendor $vendor)
|
||||
{
|
||||
return [
|
||||
'id' => $this->encodePrimaryKey($vendor->id),
|
||||
'user_id' => $this->encodePrimaryKey($vendor->user_id),
|
||||
'assigned_user_id' => $this->encodePrimaryKey($vendor->assigned_user_id),
|
||||
'name' => $vendor->name ?: '',
|
||||
'website' => $vendor->website ?: '',
|
||||
'private_notes' => $vendor->private_notes ?: '',
|
||||
'last_login' => (int)$vendor->last_login,
|
||||
'address1' => $vendor->address1 ?: '',
|
||||
'address2' => $vendor->address2 ?: '',
|
||||
'phone' => $vendor->phone ?: '',
|
||||
'city' => $vendor->city ?: '',
|
||||
'state' => $vendor->state ?: '',
|
||||
'postal_code' => $vendor->postal_code ?: '',
|
||||
'country_id' => (string)$vendor->country_id ?: '',
|
||||
'custom_value1' => $vendor->custom_value1 ?: '',
|
||||
'custom_value2' => $vendor->custom_value2 ?: '',
|
||||
'custom_value3' => $vendor->custom_value3 ?: '',
|
||||
'custom_value4' => $vendor->custom_value4 ?: '',
|
||||
'is_deleted' => (bool) $vendor->is_deleted,
|
||||
'vat_number' => $vendor->vat_number ?: '',
|
||||
'id_number' => $vendor->id_number ?: '',
|
||||
'updated_at' => $vendor->updated_at,
|
||||
'archived_at' => $vendor->deleted_at,
|
||||
];
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ namespace App\Utils\Traits;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Invoice;
|
||||
use Illuminate\Support\Carbon;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
use Parsedown;
|
||||
|
||||
/**
|
||||
@ -84,7 +85,14 @@ trait InvoiceEmailBuilder
|
||||
|
||||
//process markdown
|
||||
if ($is_markdown) {
|
||||
$data = Parsedown::instance()->line($data);
|
||||
//$data = Parsedown::instance()->line($data);
|
||||
|
||||
$converter = new CommonMarkConverter([
|
||||
'html_input' => 'strip',
|
||||
'allow_unsafe_links' => false,
|
||||
]);
|
||||
|
||||
$data = $converter->convertToHtml($data);
|
||||
}
|
||||
|
||||
return $data;
|
||||
|
22
database/factories/ExpenseFactory.php
Normal file
22
database/factories/ExpenseFactory.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
use App\DataMapper\ClientSettings;
|
||||
use App\DataMapper\CompanySettings;
|
||||
use App\Factory\InvoiceItemFactory;
|
||||
use Faker\Generator as Faker;
|
||||
|
||||
$factory->define(App\Models\Expense::class, function (Faker $faker) {
|
||||
return [
|
||||
'amount' => $faker->numberBetween(1,10),
|
||||
'custom_value1' => $faker->text(10),
|
||||
'custom_value2' => $faker->text(10),
|
||||
'custom_value3' => $faker->text(10),
|
||||
'custom_value4' => $faker->text(10),
|
||||
'exchange_rate' => $faker->randomFloat(2,0,1),
|
||||
'expense_date' => $faker->date(),
|
||||
'is_deleted' => false,
|
||||
'public_notes' => $faker->text(50),
|
||||
'private_notes' => $faker->text(50),
|
||||
'transaction_reference' => $faker->text(5),
|
||||
];
|
||||
});
|
24
database/factories/VendorContactFactory.php
Normal file
24
database/factories/VendorContactFactory.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
use Faker\Generator as Faker;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Model Factories
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This directory should contain each of the model factory definitions for
|
||||
| your application. Factories provide a convenient way to generate new
|
||||
| model instances for testing / seeding your application's database.
|
||||
|
|
||||
*/
|
||||
|
||||
$factory->define(App\Models\VendorContact::class, function (Faker $faker) {
|
||||
return [
|
||||
'first_name' => $faker->firstName,
|
||||
'last_name' => $faker->lastName,
|
||||
'phone' => $faker->phoneNumber,
|
||||
'email' => $faker->unique()->safeEmail,
|
||||
];
|
||||
|
||||
});
|
23
database/factories/VendorFactory.php
Normal file
23
database/factories/VendorFactory.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
use Faker\Generator as Faker;
|
||||
|
||||
$factory->define(App\Models\Vendor::class, function (Faker $faker) {
|
||||
return [
|
||||
'name' => $faker->name(),
|
||||
'website' => $faker->url,
|
||||
'private_notes' => $faker->text(200),
|
||||
'vat_number' => $faker->text(25),
|
||||
'id_number' => $faker->text(20),
|
||||
'custom_value1' => $faker->text(20),
|
||||
'custom_value2' => $faker->text(20),
|
||||
'custom_value3' => $faker->text(20),
|
||||
'custom_value4' => $faker->text(20),
|
||||
'address1' => $faker->buildingNumber,
|
||||
'address2' => $faker->streetAddress,
|
||||
'city' => $faker->city,
|
||||
'state' => $faker->state,
|
||||
'postal_code' => $faker->postcode,
|
||||
'country_id' => 4,
|
||||
];
|
||||
});
|
@ -1222,6 +1222,122 @@ class CreateUsersTable extends Migration
|
||||
$table->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
|
||||
|
||||
});
|
||||
|
||||
Schema::create('vendors', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->timestamps(6);
|
||||
$table->softDeletes();
|
||||
$table->unsignedInteger('user_id');
|
||||
$table->unsignedInteger('assigned_user_id');
|
||||
$table->unsignedInteger('company_id');
|
||||
$table->unsignedInteger('currency_id')->nullable();
|
||||
$table->string('name')->nullable();
|
||||
$table->string('address1');
|
||||
$table->string('address2');
|
||||
$table->string('city');
|
||||
$table->string('state');
|
||||
$table->string('postal_code');
|
||||
$table->unsignedInteger('country_id')->nullable();
|
||||
$table->string('work_phone');
|
||||
$table->text('private_notes');
|
||||
$table->string('website');
|
||||
$table->tinyInteger('is_deleted')->default(0);
|
||||
$table->string('vat_number')->nullable();
|
||||
$table->string('transaction_name')->nullable();
|
||||
$table->string('id_number')->nullable();
|
||||
|
||||
$table->string('custom_value1')->nullable();
|
||||
$table->string('custom_value2')->nullable();
|
||||
$table->string('custom_value3')->nullable();
|
||||
$table->string('custom_value4')->nullable();
|
||||
|
||||
|
||||
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
$table->foreign('country_id')->references('id')->on('countries');
|
||||
$table->foreign('currency_id')->references('id')->on('currencies');
|
||||
});
|
||||
|
||||
Schema::create('vendor_contacts', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->unsignedInteger('company_id');
|
||||
$table->unsignedInteger('user_id');
|
||||
$table->unsignedInteger('vendor_id')->index();
|
||||
$table->timestamps(6);
|
||||
$table->softDeletes();
|
||||
|
||||
$table->boolean('is_primary')->default(0);
|
||||
$table->string('first_name')->nullable();
|
||||
$table->string('last_name')->nullable();
|
||||
$table->string('email')->nullable();
|
||||
$table->string('phone')->nullable();
|
||||
|
||||
$table->string('custom_value1')->nullable();
|
||||
$table->string('custom_value2')->nullable();
|
||||
$table->string('custom_value3')->nullable();
|
||||
$table->string('custom_value4')->nullable();
|
||||
|
||||
$table->foreign('vendor_id')->references('id')->on('vendors')->onDelete('cascade');
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
|
||||
|
||||
});
|
||||
|
||||
Schema::create('expense_categories', function ($table) {
|
||||
$table->increments('id');
|
||||
$table->unsignedInteger('user_id');
|
||||
$table->unsignedInteger('company_id')->index();
|
||||
$table->timestamps(6);
|
||||
$table->softDeletes();
|
||||
$table->string('name')->nullable();
|
||||
});
|
||||
|
||||
Schema::create('expenses', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->timestamps(6);
|
||||
$table->softDeletes();
|
||||
|
||||
$table->unsignedInteger('company_id')->index();
|
||||
$table->unsignedInteger('vendor_id')->nullable();
|
||||
$table->unsignedInteger('user_id');
|
||||
$table->unsignedInteger('assigned_user_id');
|
||||
$table->unsignedInteger('invoice_id')->nullable();
|
||||
$table->unsignedInteger('client_id')->nullable();
|
||||
$table->unsignedInteger('bank_id')->nullable();
|
||||
$table->unsignedInteger('invoice_currency_id')->nullable(false);
|
||||
$table->unsignedInteger('expense_currency_id')->nullable(false);
|
||||
$table->unsignedInteger('invoice_category_id')->nullable();
|
||||
$table->unsignedInteger('payment_type_id')->nullable();
|
||||
$table->unsignedInteger('recurring_expense_id')->nullable();
|
||||
$table->boolean('is_deleted')->default(false);
|
||||
$table->decimal('amount', 13, 2);
|
||||
$table->decimal('foreign_amount', 13, 2);
|
||||
$table->decimal('exchange_rate', 13, 4);
|
||||
$table->string('tax_name1')->nullable();
|
||||
$table->decimal('tax_rate1', 13, 3)->default(0);
|
||||
$table->string('tax_name2')->nullable();
|
||||
$table->decimal('tax_rate2', 13, 3)->default(0);
|
||||
$table->string('tax_name3')->nullable();
|
||||
$table->decimal('tax_rate3', 13, 3)->default(0);
|
||||
$table->date('expense_date')->nullable();
|
||||
$table->date('payment_date')->nullable();
|
||||
$table->text('private_notes');
|
||||
$table->text('public_notes');
|
||||
$table->text('transaction_reference');
|
||||
$table->boolean('should_be_invoiced')->default(false);
|
||||
$table->boolean('invoice_documents')->default();
|
||||
$table->string('transaction_id')->nullable();
|
||||
|
||||
$table->string('custom_value1')->nullable();
|
||||
$table->string('custom_value2')->nullable();
|
||||
$table->string('custom_value3')->nullable();
|
||||
$table->string('custom_value4')->nullable();
|
||||
|
||||
// Relations
|
||||
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,6 +62,14 @@ Route::group(['middleware' => ['api_db','api_secret_check','token_auth','locale'
|
||||
|
||||
Route::post('recurring_quotes/bulk', 'RecurringQuoteController@bulk')->name('recurring_quotes.bulk');
|
||||
|
||||
Route::resource('expenses', 'ExpenseController'); // name = (expenses. index / create / show / update / destroy / edit
|
||||
|
||||
Route::post('expenses/bulk', 'ExpenseController@bulk')->name('expenses.bulk');
|
||||
|
||||
Route::resource('vendors', 'VendorController'); // name = (vendors. index / create / show / update / destroy / edit
|
||||
|
||||
Route::post('vendors/bulk', 'VendorController@bulk')->name('vendors.bulk');
|
||||
|
||||
Route::resource('client_statement', 'ClientStatementController@statement'); // name = (client_statement. index / create / show / update / destroy / edit
|
||||
|
||||
Route::resource('payments', 'PaymentController'); // name = (payments. index / create / show / update / destroy / edit
|
||||
@ -103,9 +111,7 @@ Route::group(['middleware' => ['api_db','api_secret_check','token_auth','locale'
|
||||
|
||||
Route::post('credits/bulk', 'CreditController@bulk')->name('credits.bulk');
|
||||
|
||||
Route::resource('expenses', 'ExpenseController'); // name = (expenses. index / create / show / update / destroy / edit
|
||||
|
||||
Route::post('expenses/bulk', 'ExpenseController@bulk')->name('expenses.bulk');
|
||||
|
||||
|
||||
Route::get('settings', 'SettingsController@index')->name('user.settings');
|
||||
|
@ -14,7 +14,6 @@ use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Parsedown;
|
||||
use Tests\MockAccountData;
|
||||
use Tests\TestCase;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user