mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
expenses
This commit is contained in:
parent
d1bef24ede
commit
48ce3f64e6
23
app/Events/ExpenseWasArchived.php
Normal file
23
app/Events/ExpenseWasArchived.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php namespace App\Events;
|
||||
|
||||
use App\Events\Event;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ExpenseWasArchived extends Event {
|
||||
|
||||
use SerializesModels;
|
||||
|
||||
public $expense;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($espense)
|
||||
{
|
||||
$this->expense = $expense;
|
||||
}
|
||||
|
||||
}
|
22
app/Events/ExpenseWasCreated.php
Normal file
22
app/Events/ExpenseWasCreated.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php namespace App\Events;
|
||||
|
||||
use App\Events\Event;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ExpenseWasCreated extends Event {
|
||||
|
||||
use SerializesModels;
|
||||
|
||||
public $expense;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($expense)
|
||||
{
|
||||
$this->expense = $expense;
|
||||
}
|
||||
}
|
23
app/Events/ExpenseWasDeleted.php
Normal file
23
app/Events/ExpenseWasDeleted.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php namespace App\Events;
|
||||
|
||||
use App\Events\Event;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ExpenseWasDeleted extends Event {
|
||||
|
||||
use SerializesModels;
|
||||
|
||||
public $expense;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($expense)
|
||||
{
|
||||
$this->expense = $expense;
|
||||
}
|
||||
|
||||
}
|
23
app/Events/ExpenseWasRestored.php
Normal file
23
app/Events/ExpenseWasRestored.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php namespace App\Events;
|
||||
|
||||
use App\Events\Event;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ExpenseWasRestored extends Event {
|
||||
|
||||
use SerializesModels;
|
||||
|
||||
public $expense;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($expense)
|
||||
{
|
||||
$this->expense = $expense;
|
||||
}
|
||||
|
||||
}
|
131
app/Http/Controllers/ExpenseController.php
Normal file
131
app/Http/Controllers/ExpenseController.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php namespace App\Http\Controllers;
|
||||
|
||||
use Auth;
|
||||
use Datatable;
|
||||
use Utils;
|
||||
use View;
|
||||
use URL;
|
||||
use Validator;
|
||||
use Input;
|
||||
use Session;
|
||||
use Redirect;
|
||||
use Cache;
|
||||
use App\Models\Vendor;
|
||||
use App\Services\ExpenseService;
|
||||
use App\Ninja\Repositories\ExpenseRepository;
|
||||
use App\Http\Requests\CreateExpenseRequest;
|
||||
|
||||
class ExpenseController extends BaseController
|
||||
{
|
||||
protected $expenseRepo;
|
||||
protected $expenseService;
|
||||
|
||||
public function __construct(ExpenseRepository $expenseRepo, ExpenseService $expenseService)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->expenseRepo = $expenseRepo;
|
||||
$this->expenseService = $expenseService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return View::make('list', array(
|
||||
'entityType' => ENTITY_EXPENSE,
|
||||
'title' => trans('texts.expenses'),
|
||||
'sortCol' => '4',
|
||||
'columns' => Utils::trans([
|
||||
'checkbox',
|
||||
'vendor',
|
||||
'expense_amount',
|
||||
'expense_balance',
|
||||
'expense_date',
|
||||
'private_notes',
|
||||
''
|
||||
]),
|
||||
));
|
||||
}
|
||||
|
||||
public function getDatatable($vendorPublicId = null)
|
||||
{
|
||||
return $this->expenseService->getDatatable($vendorPublicId, Input::get('sSearch'));
|
||||
}
|
||||
|
||||
public function create($vendorPublicId = 0)
|
||||
{
|
||||
$vendor = Vendor::scope($vendorPublicId)->with('vendorcontacts')->firstOrFail();
|
||||
$data = array(
|
||||
'vendorPublicId' => Input::old('vendor') ? Input::old('vendor') : $vendorPublicId,
|
||||
'expense' => null,
|
||||
'method' => 'POST',
|
||||
'url' => 'expenses',
|
||||
'title' => trans('texts.new_expense'),
|
||||
'vendors' => Vendor::scope()->with('vendorcontacts')->orderBy('name')->get(),
|
||||
);
|
||||
|
||||
$data = array_merge($data, self::getViewModel());
|
||||
|
||||
return View::make('expenses.edit', $data);
|
||||
}
|
||||
|
||||
public function edit($publicId)
|
||||
{
|
||||
$expense = Expense::scope($publicId)->firstOrFail();
|
||||
$expense->expense_date = Utils::fromSqlDate($expense->expense_date);
|
||||
|
||||
$data = array(
|
||||
'vendor' => null,
|
||||
'expense' => $expense,
|
||||
'method' => 'PUT',
|
||||
'url' => 'expenses/'.$publicId,
|
||||
'title' => 'Edit Expense',
|
||||
'vendors' => Vendor::scope()->with('vendorcontacts')->orderBy('name')->get(), );
|
||||
|
||||
return View::make('expense.edit', $data);
|
||||
}
|
||||
|
||||
public function store(CreateExpenseRequest $request)
|
||||
{
|
||||
$expense = $this->expenseRepo->save($request->input());
|
||||
|
||||
Session::flash('message', trans('texts.created_expense'));
|
||||
|
||||
return redirect()->to('expenses');
|
||||
}
|
||||
|
||||
public function bulk()
|
||||
{
|
||||
$action = Input::get('action');
|
||||
$ids = Input::get('public_id') ? Input::get('public_id') : Input::get('ids');
|
||||
$count = $this->expenseService->bulk($ids, $action);
|
||||
|
||||
if ($count > 0) {
|
||||
$message = Utils::pluralize($action.'d_expense', $count);
|
||||
Session::flash('message', $message);
|
||||
}
|
||||
|
||||
return Redirect::to('expenses');
|
||||
}
|
||||
|
||||
private static function getViewModel()
|
||||
{
|
||||
return [
|
||||
'data' => Input::old('data'),
|
||||
'account' => Auth::user()->account,
|
||||
'sizes' => Cache::get('sizes'),
|
||||
'paymentTerms' => Cache::get('paymentTerms'),
|
||||
'industries' => Cache::get('industries'),
|
||||
'currencies' => Cache::get('currencies'),
|
||||
'languages' => Cache::get('languages'),
|
||||
'countries' => Cache::get('countries'),
|
||||
'customLabel1' => Auth::user()->account->custom_vendor_label1,
|
||||
'customLabel2' => Auth::user()->account->custom_vendor_label2,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
29
app/Http/Requests/CreateExpenseRequest.php
Normal file
29
app/Http/Requests/CreateExpenseRequest.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php namespace app\Http\Requests;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use Illuminate\Validation\Factory;
|
||||
|
||||
class CreateExpenseRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'amount' => 'required|positive',
|
||||
];
|
||||
}
|
||||
}
|
28
app/Http/Requests/UpdateExpenseRequest.php
Normal file
28
app/Http/Requests/UpdateExpenseRequest.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php namespace app\Http\Requests;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use Illuminate\Validation\Factory;
|
||||
use App\Models\Invoice;
|
||||
|
||||
class UpdatePaymentRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
@ -2,9 +2,8 @@
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use Illuminate\Validation\Factory;
|
||||
use App\Models\Invoice;
|
||||
|
||||
class UpdatePaymentRequest extends Request
|
||||
class UpdateExpenseRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
@ -23,6 +22,9 @@ class UpdatePaymentRequest extends Request
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [];
|
||||
return [
|
||||
'amount' => 'required|positive',
|
||||
];
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -189,6 +189,21 @@ Route::group(['middleware' => 'auth'], function() {
|
||||
Route::get('api/vendoractivities/{vendor_id?}', array('as'=>'api.vendoractivities', 'uses'=>'VendorActivityController@getDatatable'));
|
||||
Route::post('vendors/bulk', 'VendorController@bulk');
|
||||
|
||||
// Expense
|
||||
Route::get('expenses/{id}/edit', function() {
|
||||
return View::make('header');
|
||||
});
|
||||
|
||||
Route::resource('expenses', 'ExpenseController');
|
||||
Route::get('expenses/create/{vendor_id?}', 'ExpenseController@create');
|
||||
Route::get('api/expenses/{vendor_id?}', array('as'=>'api.expenses', 'uses'=>'ExpenseController@getDatatable'));
|
||||
|
||||
//Route::get('api/expenseactivities/{vendor_id?}', array('as'=>'api.expenseactivities', 'uses'=>'ExpenseActivityController@getDatatable'));
|
||||
//Route::post('vendors/bulk', 'VendorController@bulk');
|
||||
|
||||
|
||||
Route::post('expenses/bulk', 'ExpenseController@bulk');
|
||||
|
||||
});
|
||||
|
||||
// Route groups for API
|
||||
@ -252,6 +267,7 @@ if (!defined('CONTACT_EMAIL')) {
|
||||
define('ENV_STAGING', 'staging');
|
||||
|
||||
define('RECENTLY_VIEWED', 'RECENTLY_VIEWED');
|
||||
|
||||
define('ENTITY_CLIENT', 'client');
|
||||
define('ENTITY_CONTACT', 'contact');
|
||||
define('ENTITY_INVOICE', 'invoice');
|
||||
@ -346,6 +362,12 @@ if (!defined('CONTACT_EMAIL')) {
|
||||
define('ACTIVITY_TYPE_DELETE_VENDOR', 32);
|
||||
define('ACTIVITY_TYPE_RESTORE_VENDOR', 33);
|
||||
|
||||
// expenses
|
||||
define('ACTIVITY_TYPE_CREATE_EXPENSE', 34);
|
||||
define('ACTIVITY_TYPE_ARCHIVE_EXPENSE', 35);
|
||||
define('ACTIVITY_TYPE_DELETE_EXPENSE', 36);
|
||||
define('ACTIVITY_TYPE_RESTORE_EXPENSE', 37);
|
||||
|
||||
define('DEFAULT_INVOICE_NUMBER', '0001');
|
||||
define('RECENTLY_VIEWED_LIMIT', 8);
|
||||
define('LOGGED_ERROR_LIMIT', 100);
|
||||
@ -379,7 +401,6 @@ if (!defined('CONTACT_EMAIL')) {
|
||||
define('MAX_NUM_VENDORS_PRO', 20000);
|
||||
define('MAX_NUM_VENDORS_LEGACY', 500);
|
||||
|
||||
|
||||
define('INVOICE_STATUS_DRAFT', 1);
|
||||
define('INVOICE_STATUS_SENT', 2);
|
||||
define('INVOICE_STATUS_VIEWED', 3);
|
||||
|
16
app/Listeners/ExpenseListener.php
Normal file
16
app/Listeners/ExpenseListener.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php namespace app\Listeners;
|
||||
|
||||
use Carbon;
|
||||
use App\Models\Credit;
|
||||
use App\Events\PaymentWasDeleted;
|
||||
use App\Ninja\Repositories\ExpenseRepository;
|
||||
|
||||
class ExpenseListener
|
||||
{
|
||||
protected $expenseRepo;
|
||||
|
||||
public function __construct(ExpenseRepository $expenseRepo)
|
||||
{
|
||||
$this->expenseRepo = $expenseRepo;
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ use App\Events\CreditWasCreated;
|
||||
use App\Events\PaymentWasCreated;
|
||||
|
||||
use App\Events\VendorWasCreated;
|
||||
use App\Events\ExpenseWasCreated;
|
||||
|
||||
class SubscriptionListener
|
||||
{
|
||||
@ -51,4 +52,10 @@ class SubscriptionListener
|
||||
{
|
||||
$this->checkSubscriptions(ACTIVITY_TYPE_CREATE_VENDOR, $event->vendor);
|
||||
}
|
||||
|
||||
public function createdExpense(ExpenseWasCreated $event)
|
||||
{
|
||||
$this->checkSubscriptions(ACTIVITY_TYPE_CREATE_EXPENSE, $event->expense);
|
||||
}
|
||||
|
||||
}
|
||||
|
79
app/Models/Expense.php
Normal file
79
app/Models/Expense.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?php namespace App\Models;
|
||||
|
||||
use Utils;
|
||||
use DB;
|
||||
use Carbon;
|
||||
use Laracasts\Presenter\PresentableTrait;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use App\Events\ExpenseWasCreated;
|
||||
|
||||
class Expense extends EntityModel
|
||||
{
|
||||
use SoftDeletes;
|
||||
use PresentableTrait;
|
||||
|
||||
protected $dates = ['deleted_at'];
|
||||
protected $presenter = 'App\Ninja\Presenters\ExpensePresenter';
|
||||
|
||||
protected $fillable = [
|
||||
'vendor_id',
|
||||
];
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Account');
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('App\Models\User');
|
||||
}
|
||||
|
||||
public function vendor()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Vendor')->withTrashed();
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getEntityType()
|
||||
{
|
||||
return ENTITY_EXPENSE;
|
||||
}
|
||||
|
||||
public function apply($amount)
|
||||
{
|
||||
if ($amount > $this->balance) {
|
||||
$applied = $this->balance;
|
||||
$this->balance = 0;
|
||||
} else {
|
||||
$applied = $amount;
|
||||
$this->balance = $this->balance - $amount;
|
||||
}
|
||||
|
||||
$this->save();
|
||||
|
||||
return $applied;
|
||||
}
|
||||
}
|
||||
|
||||
Expense::creating(function ($expense) {
|
||||
$expense->setNullValues();
|
||||
});
|
||||
|
||||
Expense::created(function ($expense) {
|
||||
event(new ExpenseWasCreated($expense));
|
||||
});
|
||||
|
||||
Expense::updating(function ($expense) {
|
||||
$expense->setNullValues();
|
||||
});
|
||||
|
||||
Expense::updated(function ($expense) {
|
||||
event(new ExpenseWasUpdated($expense));
|
||||
});
|
||||
|
||||
|
||||
|
56
app/Models/ExpenseAcitvity.php
Normal file
56
app/Models/ExpenseAcitvity.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php namespace App\Models;
|
||||
|
||||
use Auth;
|
||||
use Eloquent;
|
||||
use Utils;
|
||||
use Session;
|
||||
use Request;
|
||||
use Carbon;
|
||||
|
||||
class ExpenseAcitvity extends Eloquent {
|
||||
|
||||
public $timestamps = true;
|
||||
|
||||
public function scopeScope($query)
|
||||
{
|
||||
return $query->whereAccountId(Auth::user()->account_id);
|
||||
}
|
||||
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Account');
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('App\Models\User')->withTrashed();
|
||||
}
|
||||
|
||||
public function vendor()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Vendor')->withTrashed();
|
||||
}
|
||||
|
||||
public function getMessage()
|
||||
{
|
||||
$activityTypeId = $this->activity_type_id;
|
||||
$account = $this->account;
|
||||
$vendor = $this->vendor;
|
||||
$user = $this->user;
|
||||
$contactId = $this->contact_id;
|
||||
$isSystem = $this->is_system;
|
||||
|
||||
if($vendor) {
|
||||
$route = $vendor->getRoute();
|
||||
|
||||
$data = [
|
||||
'vendor' => link_to($route, $vendor->getDisplayName()),
|
||||
'user' => $isSystem ? '<i>' . trans('texts.system') . '</i>' : $user->getDisplayName(),
|
||||
'vendorcontact' => $contactId ? $vendor->getDisplayName() : $user->getDisplayName(),
|
||||
];
|
||||
} else {
|
||||
return trans("texts.invalid_activity");
|
||||
}
|
||||
return trans("texts.activity_{$activityTypeId}", $data);
|
||||
}
|
||||
}
|
17
app/Ninja/Presenters/ExpensePresenter.php
Normal file
17
app/Ninja/Presenters/ExpensePresenter.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php namespace App\Ninja\Presenters;
|
||||
|
||||
use Utils;
|
||||
use Laracasts\Presenter\Presenter;
|
||||
|
||||
class ExpensePresenter extends Presenter {
|
||||
|
||||
public function vendor()
|
||||
{
|
||||
return $this->entity->vendor ? $this->entity->vendor->getDisplayName() : '';
|
||||
}
|
||||
|
||||
public function expense_date()
|
||||
{
|
||||
return Utils::fromSqlDate($this->entity->expense_date);
|
||||
}
|
||||
}
|
94
app/Ninja/Repositories/ExpenseRepository.php
Normal file
94
app/Ninja/Repositories/ExpenseRepository.php
Normal file
@ -0,0 +1,94 @@
|
||||
<?php namespace App\Ninja\Repositories;
|
||||
|
||||
use DB;
|
||||
use Utils;
|
||||
use App\Models\Expense;
|
||||
use App\Models\Vendor;
|
||||
use App\Ninja\Repositories\BaseRepository;
|
||||
|
||||
class ExpenseRepository extends BaseRepository
|
||||
{
|
||||
public function getClassName()
|
||||
{
|
||||
return 'App\Models\Expense';
|
||||
}
|
||||
|
||||
public function find($vendorPublicId = null, $filter = null)
|
||||
{
|
||||
$query = DB::table('expenses')
|
||||
->join('accounts', 'accounts.id', '=', 'expenses.account_id')
|
||||
->join('vendors', 'vendors.id', '=', 'expenses.vendor_id')
|
||||
->join('vendor_contacts', 'vendor_contacts.vendor_id', '=', 'vendors.id')
|
||||
->where('vendors.account_id', '=', \Auth::user()->account_id)
|
||||
->where('vendors.deleted_at', '=', null)
|
||||
->where('vendor_contacts.deleted_at', '=', null)
|
||||
->where('vendor_contacts.is_primary', '=', true)
|
||||
->select(
|
||||
DB::raw('COALESCE(vendors.currency_id, accounts.currency_id) currency_id'),
|
||||
DB::raw('COALESCE(vendors.country_id, accounts.country_id) country_id'),
|
||||
'expenses.public_id',
|
||||
'vendors.name as vendor_name',
|
||||
'vendors.public_id as vendor_public_id',
|
||||
'expenses.amount',
|
||||
'expenses.balance',
|
||||
'expenses.expense_date',
|
||||
'vendor_contacts.first_name',
|
||||
'vendor_contacts.last_name',
|
||||
'vendor_contacts.email',
|
||||
'expenses.private_notes',
|
||||
'expenses.deleted_at',
|
||||
'expenses.is_deleted'
|
||||
);
|
||||
|
||||
if ($vendorPublicId) {
|
||||
$query->where('vendors.public_id', '=', $vendorPublicId);
|
||||
}
|
||||
|
||||
if (!\Session::get('show_trash:expense')) {
|
||||
$query->where('expenses.deleted_at', '=', null);
|
||||
}
|
||||
|
||||
if ($filter) {
|
||||
$query->where(function ($query) use ($filter) {
|
||||
$query->where('vendors.name', 'like', '%'.$filter.'%');
|
||||
});
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function save($input)
|
||||
{
|
||||
$publicId = isset($input['public_id']) ? $input['public_id'] : false;
|
||||
|
||||
if ($publicId) {
|
||||
$expense = Expense::scope($publicId)->firstOrFail();
|
||||
} else {
|
||||
$expense = Expense::createNew();
|
||||
}
|
||||
|
||||
// First auto fille
|
||||
$expense->fill($input);
|
||||
|
||||
// We can have an expense without a vendor
|
||||
if(isset($input['vendor'])) {
|
||||
$expense->vendor_id = Vendor::getPrivateId($input['vendor']);
|
||||
}
|
||||
|
||||
$expense->expense_date = Utils::toSqlDate($input['expense_date']);
|
||||
$expense->amount = Utils::parseFloat($input['amount']);
|
||||
|
||||
if(isset($input['amountcur']))
|
||||
$expense->amountcur = Utils::parseFloat($input['amountcur']);
|
||||
|
||||
$expense->balance = Utils::parseFloat($input['amount']);
|
||||
$expense->private_notes = trim($input['private_notes']);
|
||||
|
||||
if(isset($input['exchange_rate']))
|
||||
$expense->exchange_rate = Utils::parseFloat($input['exchange_rate']);
|
||||
|
||||
$expense->save();
|
||||
|
||||
return $expense;
|
||||
}
|
||||
}
|
24
app/Ninja/Transformers/VendorContactTransformer.php
Normal file
24
app/Ninja/Transformers/VendorContactTransformer.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php namespace App\Ninja\Transformers;
|
||||
|
||||
use App\Models\Account;
|
||||
use App\Models\VendorContact;
|
||||
use League\Fractal;
|
||||
|
||||
class VendorContactTransformer extends EntityTransformer
|
||||
{
|
||||
public function transform(VendorContact $contact)
|
||||
{
|
||||
return [
|
||||
'id' => (int) $contact->public_id,
|
||||
'first_name' => $contact->first_name,
|
||||
'last_name' => $contact->last_name,
|
||||
'email' => $contact->email,
|
||||
'updated_at' => $this->getTimestamp($contact->updated_at),
|
||||
'archived_at' => $this->getTimestamp($contact->deleted_at),
|
||||
'is_primary' => (bool) $contact->is_primary,
|
||||
'phone' => $contact->phone,
|
||||
'last_login' => $contact->last_login,
|
||||
'account_key' => $this->account->account_key,
|
||||
];
|
||||
}
|
||||
}
|
91
app/Ninja/Transformers/VendorTransformer.php
Normal file
91
app/Ninja/Transformers/VendorTransformer.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php namespace App\Ninja\Transformers;
|
||||
|
||||
use App\Models\Account;
|
||||
use App\Models\Vendor;
|
||||
use App\Models\Contact;
|
||||
use League\Fractal;
|
||||
|
||||
/**
|
||||
* @SWG\Definition(definition="Vendor", @SWG\Xml(name="Vendor"))
|
||||
*/
|
||||
|
||||
class VendorTransformer extends EntityTransformer
|
||||
{
|
||||
/**
|
||||
* @SWG\Property(property="id", type="integer", example=1, readOnly=true)
|
||||
* @SWG\Property(property="balance", type="float", example=10, readOnly=true)
|
||||
* @SWG\Property(property="paid_to_date", type="float", example=10, readOnly=true)
|
||||
* @SWG\Property(property="user_id", type="integer", example=1)
|
||||
* @SWG\Property(property="account_key", type="string", example="123456")
|
||||
* @SWG\Property(property="updated_at", type="timestamp", example="")
|
||||
* @SWG\Property(property="archived_at", type="timestamp", example="1451160233")
|
||||
* @SWG\Property(property="address1", type="string", example="10 Main St.")
|
||||
* @SWG\Property(property="address2", type="string", example="1st Floor")
|
||||
* @SWG\Property(property="city", type="string", example="New York")
|
||||
* @SWG\Property(property="state", type="string", example="NY")
|
||||
* @SWG\Property(property="postal_code", type="string", example=10010)
|
||||
* @SWG\Property(property="country_id", type="integer", example=840)
|
||||
* @SWG\Property(property="work_phone", type="string", example="(212) 555-1212")
|
||||
* @SWG\Property(property="private_notes", type="string", example="Notes...")
|
||||
* @SWG\Property(property="last_login", type="date-time", example="2016-01-01 12:10:00")
|
||||
* @SWG\Property(property="website", type="string", example="http://www.example.com")
|
||||
* @SWG\Property(property="industry_id", type="integer", example=1)
|
||||
* @SWG\Property(property="size_id", type="integer", example=1)
|
||||
* @SWG\Property(property="is_deleted", type="boolean", example=false)
|
||||
* @SWG\Property(property="payment_terms", type="", example=30)
|
||||
* @SWG\Property(property="custom_value1", type="string", example="Value")
|
||||
* @SWG\Property(property="custom_value2", type="string", example="Value")
|
||||
* @SWG\Property(property="vat_number", type="string", example="123456")
|
||||
* @SWG\Property(property="id_number", type="string", example="123456")
|
||||
* @SWG\Property(property="language_id", type="integer", example=1)
|
||||
*/
|
||||
|
||||
protected $availableIncludes = [
|
||||
'contacts',
|
||||
'invoices',
|
||||
];
|
||||
|
||||
public function includeContacts(Vendor $vendor)
|
||||
{
|
||||
$transformer = new ContactTransformer($this->account, $this->serializer);
|
||||
return $this->includeCollection($vendor->contacts, $transformer, ENTITY_CONTACT);
|
||||
}
|
||||
|
||||
public function includeInvoices(Vendor $vendor)
|
||||
{
|
||||
$transformer = new InvoiceTransformer($this->account, $this->serializer);
|
||||
return $this->includeCollection($vendor->invoices, $transformer, ENTITY_INVOICE);
|
||||
}
|
||||
|
||||
public function transform(Vendor $vendor)
|
||||
{
|
||||
return [
|
||||
'id' => (int) $vendor->public_id,
|
||||
'name' => $vendor->name,
|
||||
'balance' => (float) $vendor->balance,
|
||||
'paid_to_date' => (float) $vendor->paid_to_date,
|
||||
'user_id' => (int) $vendor->user->public_id + 1,
|
||||
'account_key' => $this->account->account_key,
|
||||
'updated_at' => $this->getTimestamp($vendor->updated_at),
|
||||
'archived_at' => $this->getTimestamp($vendor->deleted_at),
|
||||
'address1' => $vendor->address1,
|
||||
'address2' => $vendor->address2,
|
||||
'city' => $vendor->city,
|
||||
'state' => $vendor->state,
|
||||
'postal_code' => $vendor->postal_code,
|
||||
'country_id' => (int) $vendor->country_id,
|
||||
'work_phone' => $vendor->work_phone,
|
||||
'private_notes' => $vendor->private_notes,
|
||||
'last_login' => $vendor->last_login,
|
||||
'website' => $vendor->website,
|
||||
'industry_id' => (int) $vendor->industry_id,
|
||||
'size_id' => (int) $vendor->size_id,
|
||||
'is_deleted' => (bool) $vendor->is_deleted,
|
||||
'payment_terms' => (int) $vendor->payment_terms,
|
||||
'vat_number' => $vendor->vat_number,
|
||||
'id_number' => $vendor->id_number,
|
||||
'language_id' => (int) $vendor->language_id,
|
||||
'currency_id' => (int) $vendor->currency_id
|
||||
];
|
||||
}
|
||||
}
|
@ -152,6 +152,21 @@ class EventServiceProvider extends ServiceProvider {
|
||||
'App\Listeners\VendorActivityListener@restoredVendor',
|
||||
],
|
||||
|
||||
// Expense events
|
||||
'App\Events\ExpenseWasCreated' => [
|
||||
'App\Listeners\ExpenseActivityListener@createdExpense',
|
||||
'App\Listeners\SubscriptionListener@createdExpense',
|
||||
],
|
||||
'App\Events\ExpenseWasArchived' => [
|
||||
'App\Listeners\ExpenseActivityListener@archivedExpense',
|
||||
],
|
||||
'App\Events\ExpenseWasDeleted' => [
|
||||
'App\Listeners\ExpenseActivityListener@deletedExpense',
|
||||
],
|
||||
'App\Events\ExpenseWasRestored' => [
|
||||
'App\Listeners\ExpenseActivityListener@restoredExpense',
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
/**
|
||||
|
84
app/Services/ExpenseService.php
Normal file
84
app/Services/ExpenseService.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php namespace App\Services;
|
||||
|
||||
use Utils;
|
||||
use URL;
|
||||
use App\Services\BaseService;
|
||||
use App\Ninja\Repositories\ExpenseRepository;
|
||||
|
||||
class ExpenseService extends BaseService
|
||||
{
|
||||
protected $expenseRepo;
|
||||
protected $datatableService;
|
||||
|
||||
public function __construct(ExpenseRepository $expenseRepo, DatatableService $datatableService)
|
||||
{
|
||||
$this->expenseRepo = $expenseRepo;
|
||||
$this->datatableService = $datatableService;
|
||||
}
|
||||
|
||||
protected function getRepo()
|
||||
{
|
||||
return $this->expenseRepo;
|
||||
}
|
||||
|
||||
public function save($data)
|
||||
{
|
||||
return $this->expenseRepo->save($data);
|
||||
}
|
||||
|
||||
public function getDatatable($vendorPublicId, $search)
|
||||
{
|
||||
$query = $this->expenseRepo->find($vendorPublicId, $search);
|
||||
|
||||
return $this->createDatatable(ENTITY_CREDIT, $query, !$vendorPublicId);
|
||||
}
|
||||
|
||||
protected function getDatatableColumns($entityType, $hideClient)
|
||||
{
|
||||
return [
|
||||
[
|
||||
'vendor_name',
|
||||
function ($model) {
|
||||
return $model->vendor_public_id ? link_to("vendors/{$model->vendor_public_id}", Utils::getVendorDisplayName($model)) : '';
|
||||
},
|
||||
! $hideClient
|
||||
],
|
||||
[
|
||||
'amount',
|
||||
function ($model) {
|
||||
return Utils::formatMoney($model->amount, $model->currency_id, $model->country_id) . '<span '.Utils::getEntityRowClass($model).'/>';
|
||||
}
|
||||
],
|
||||
[
|
||||
'balance',
|
||||
function ($model) {
|
||||
return Utils::formatMoney($model->balance, $model->currency_id, $model->country_id);
|
||||
}
|
||||
],
|
||||
[
|
||||
'expense_date',
|
||||
function ($model) {
|
||||
return Utils::fromSqlDate($model->expense_date);
|
||||
}
|
||||
],
|
||||
[
|
||||
'private_notes',
|
||||
function ($model) {
|
||||
return $model->private_notes;
|
||||
}
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
protected function getDatatableActions($entityType)
|
||||
{
|
||||
return [
|
||||
[
|
||||
trans('texts.apply_expense'),
|
||||
function ($model) {
|
||||
return URL::to("espense/create/{$model->vendor_public_id}") . '?paymentTypeId=1';
|
||||
}
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateExpensesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::dropIfExists('expenses');
|
||||
Schema::create('expenses', function(Blueprint $table)
|
||||
{
|
||||
$table->increments('id');
|
||||
$table->timestamps();
|
||||
|
||||
$table->unsignedInteger('account_id')->index();
|
||||
$table->unsignedInteger('vendor_id')->nullable();
|
||||
$table->unsignedInteger('user_id');
|
||||
|
||||
$table->softDeletes();
|
||||
|
||||
$table->boolean('is_deleted')->default(false);
|
||||
$table->decimal('amount', 13, 2);
|
||||
$table->decimal('amountcur', 13, 2);
|
||||
$table->decimal('exchange_rate', 13, 2);
|
||||
$table->decimal('balance', 13, 2);
|
||||
$table->date('expense_date')->nullable();
|
||||
$table->string('expense_number')->nullable();
|
||||
$table->text('private_notes');
|
||||
$table->integer('currency_id',false, true)->nullable();
|
||||
$table->boolean('is_invoiced')->default(false);
|
||||
$table->boolean('should_be_invoiced')->default(true);
|
||||
|
||||
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');;
|
||||
|
||||
$table->unsignedInteger('public_id')->index();
|
||||
$table->unique( array('account_id','public_id') );
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::drop('expenses');
|
||||
}
|
||||
}
|
@ -30298,6 +30298,17 @@ function getClientDisplayName(client)
|
||||
return '';
|
||||
}
|
||||
|
||||
function getVendorDisplayName(vendor)
|
||||
{
|
||||
var contact = vendor.contacts ? vendor.vendorcontacts[0] : false;
|
||||
if (vendor.name) {
|
||||
return vendor.name;
|
||||
} else if (contact) {
|
||||
return getContactDisplayName(contact);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function populateInvoiceComboboxes(clientId, invoiceId) {
|
||||
var clientMap = {};
|
||||
var invoiceMap = {};
|
||||
|
@ -893,6 +893,13 @@ return array(
|
||||
'activity_28' => ':user restored :credit credit',
|
||||
'activity_29' => ':contact approved quote :quote',
|
||||
'activity_30' => ':user created :vendor',
|
||||
'activity_31' => ':user created :vendor',
|
||||
'activity_32' => ':user created :vendor',
|
||||
'activity_33' => ':user created :vendor',
|
||||
'activity_34' => ':user created :vendor',
|
||||
'activity_35' => ':user created :vendor',
|
||||
'activity_36' => ':user created :vendor',
|
||||
'activity_37' => ':user created :vendor',
|
||||
|
||||
'payment' => 'Payment',
|
||||
'system' => 'System',
|
||||
@ -1018,4 +1025,9 @@ return array(
|
||||
'archive_vendor' => 'Archive vendor',
|
||||
'delete_vendor' => 'Delete vendor',
|
||||
'view_vendor' => 'View vendor',
|
||||
|
||||
// Expenses
|
||||
'expense_amount' => 'Expense amount',
|
||||
'expense_balance' => 'Expense balance',
|
||||
'expense_date' => 'Expense date',
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user