mirror of
https://github.com/crater-invoice/crater.git
synced 2025-10-27 11:41:09 -04:00
Merge branch 'expense-refactor' into 'master'
add customer in expense See merge request mohit.panjvani/crater-web!172
This commit is contained in:
@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Spatie\MediaLibrary\HasMedia\HasMedia;
|
||||
use Spatie\MediaLibrary\HasMedia\HasMediaTrait;
|
||||
use Crater\ExpenseCategory;
|
||||
use Crater\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
@ -16,6 +17,7 @@ class Expense extends Model implements HasMedia
|
||||
'expense_category_id',
|
||||
'amount',
|
||||
'company_id',
|
||||
'user_id',
|
||||
'expense_date',
|
||||
'notes',
|
||||
'attachment_receipt'
|
||||
@ -32,6 +34,11 @@ class Expense extends Model implements HasMedia
|
||||
return $this->belongsTo(ExpenseCategory::class, 'expense_category_id');
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function getFormattedExpenseDateAttribute($value)
|
||||
{
|
||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||
@ -81,6 +88,11 @@ class Expense extends Model implements HasMedia
|
||||
return $query->where('expenses.expense_category_id', $categoryId);
|
||||
}
|
||||
|
||||
public function scopeWhereUser($query, $user_id)
|
||||
{
|
||||
return $query->where('expenses.user_id', $user_id);
|
||||
}
|
||||
|
||||
public function scopeApplyFilters($query, array $filters)
|
||||
{
|
||||
$filters = collect($filters);
|
||||
@ -89,6 +101,10 @@ class Expense extends Model implements HasMedia
|
||||
$query->whereCategory($filters->get('expense_category_id'));
|
||||
}
|
||||
|
||||
if ($filters->get('user_id')) {
|
||||
$query->whereUser($filters->get('user_id'));
|
||||
}
|
||||
|
||||
if ($filters->get('from_date') && $filters->get('to_date')) {
|
||||
$start = Carbon::createFromFormat('d/m/Y', $filters->get('from_date'));
|
||||
$end = Carbon::createFromFormat('d/m/Y', $filters->get('to_date'));
|
||||
|
||||
@ -24,9 +24,11 @@ class ExpensesController extends Controller
|
||||
$limit = $request->has('limit') ? $request->limit : 10;
|
||||
|
||||
$expenses = Expense::with('category')
|
||||
->leftJoin('users', 'users.id', '=', 'expenses.user_id')
|
||||
->join('expense_categories', 'expense_categories.id', '=', 'expenses.expense_category_id')
|
||||
->applyFilters($request->only([
|
||||
'expense_category_id',
|
||||
'user_id',
|
||||
'search',
|
||||
'from_date',
|
||||
'to_date',
|
||||
@ -34,11 +36,16 @@ class ExpensesController extends Controller
|
||||
'orderBy'
|
||||
]))
|
||||
->whereCompany($request->header('company'))
|
||||
->select('expenses.*', 'expense_categories.name')
|
||||
->select('expenses.*', 'expense_categories.name', 'users.name as user_name')
|
||||
->paginate($limit);
|
||||
|
||||
$customers = User::customer()
|
||||
->whereCompany($request->header('company'))
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'expenses' => $expenses,
|
||||
'customers' => $customers,
|
||||
'currency' => Currency::findOrFail(
|
||||
CompanySetting::getSetting('currency', $request->header('company'))
|
||||
)
|
||||
@ -53,9 +60,13 @@ class ExpensesController extends Controller
|
||||
public function create(Request $request)
|
||||
{
|
||||
$categories = ExpenseCategory::whereCompany($request->header('company'))->get();
|
||||
$customers = User::customer()
|
||||
->whereCompany($request->header('company'))
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'categories' => $categories
|
||||
'categories' => $categories,
|
||||
'customers' => $customers
|
||||
]);
|
||||
}
|
||||
|
||||
@ -72,6 +83,7 @@ class ExpensesController extends Controller
|
||||
$expense = new Expense();
|
||||
$expense->notes = $request->notes;
|
||||
$expense->expense_category_id = $request->expense_category_id;
|
||||
$expense->user_id = $request->user_id;
|
||||
$expense->amount = $request->amount;
|
||||
$expense->company_id = $request->header('company');
|
||||
$expense->expense_date = $expense_date;
|
||||
@ -107,7 +119,9 @@ class ExpensesController extends Controller
|
||||
public function edit(Request $request,$id)
|
||||
{
|
||||
$categories = ExpenseCategory::whereCompany($request->header('company'))->get();
|
||||
$customers = User::where('role', 'customer')->whereCompany($request->header('company'))->get();
|
||||
$customers = User::customer()
|
||||
->whereCompany($request->header('company'))
|
||||
->get();
|
||||
$expense = Expense::with('category')->where('id', $id)->first();
|
||||
|
||||
return response()->json([
|
||||
@ -132,6 +146,7 @@ class ExpensesController extends Controller
|
||||
$expense->notes = $request->notes;
|
||||
$expense->expense_category_id = $request->expense_category_id;
|
||||
$expense->amount = $request->amount;
|
||||
$expense->user_id = $request->user_id;
|
||||
$expense->expense_date = $expense_date;
|
||||
$expense->save();
|
||||
|
||||
@ -205,7 +220,7 @@ class ExpensesController extends Controller
|
||||
* Retrive details of an expense receipt from storage.
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
*/
|
||||
public function showReceipt($id)
|
||||
{
|
||||
$expense = Expense::find($id);
|
||||
@ -239,7 +254,7 @@ class ExpensesController extends Controller
|
||||
* @param int $id
|
||||
* @param strig $hash
|
||||
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse | \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
*/
|
||||
public function downloadReceipt($id, $hash)
|
||||
{
|
||||
$company = Company::where('unique_hash', $hash)->first();
|
||||
|
||||
@ -9,6 +9,7 @@ use carbon\carbon;
|
||||
use Crater\MemberLoan;
|
||||
use Crater\Address;
|
||||
use Crater\Payment;
|
||||
use Crater\Expense;
|
||||
use Crater\Company;
|
||||
use Crater\Notifications\MailResetPasswordNotification;
|
||||
use Spatie\MediaLibrary\HasMedia\HasMedia;
|
||||
@ -105,6 +106,11 @@ class User extends Authenticatable implements HasMedia
|
||||
return $this->hasMany(Address::class);
|
||||
}
|
||||
|
||||
public function expenses()
|
||||
{
|
||||
return $this->hasMany(Expense::class);
|
||||
}
|
||||
|
||||
public function billingAddress()
|
||||
{
|
||||
return $this->hasOne(Address::class)->where('type', Address::BILLING_TYPE);
|
||||
|
||||
@ -23,6 +23,8 @@ class CreateExpensesTable extends Migration
|
||||
$table->foreign('expense_category_id')->references('id')->on('expense_categories')->onDelete('cascade');
|
||||
$table->integer('company_id')->unsigned()->nullable();
|
||||
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
|
||||
$table->integer('user_id')->unsigned()->nullable();
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
@ -412,6 +412,8 @@
|
||||
"title": "النفقات",
|
||||
"expenses_list": "قائمة النفقات",
|
||||
"expense_title": "Title",
|
||||
"select_a_customer": "حدد عميلاً",
|
||||
"customer": "العميل",
|
||||
"contact": "تواصل",
|
||||
"category": "الفئة",
|
||||
"from_date": "من تاريخ",
|
||||
|
||||
@ -201,6 +201,7 @@
|
||||
"action": "Aktion",
|
||||
"add_expense": "Aufwendung hinzufügen",
|
||||
"add_new_expense": "Neue Aufwendung hinzufügen",
|
||||
"select_a_customer": "Wählen Sie einen Kunden aus",
|
||||
"amount": "Summe",
|
||||
"categories": {
|
||||
"actions": "Aktionen",
|
||||
@ -215,6 +216,7 @@
|
||||
"title": "Titel"
|
||||
},
|
||||
"category": "Kategorie",
|
||||
"customer": "Kunden",
|
||||
"category_id": "Kategorie-Id",
|
||||
"confirm_delete": "Sie können diese Ausgabe nicht wiederherstellen. | Sie können diese Ausgaben nicht wiederherstellen.",
|
||||
"contact": "Kontakt",
|
||||
|
||||
@ -426,7 +426,9 @@
|
||||
"expenses": {
|
||||
"title": "Expenses",
|
||||
"expenses_list": "Expenses List",
|
||||
"select_a_customer": "Select a customer",
|
||||
"expense_title": "Title",
|
||||
"customer": "Customer",
|
||||
"contact": "Contact",
|
||||
"category": "Category",
|
||||
"from_date": "From Date",
|
||||
|
||||
@ -412,6 +412,8 @@
|
||||
"expenses_list": "Lista de gastos",
|
||||
"expense_title": "Título",
|
||||
"contact": "Contacto",
|
||||
"customer": "Cliente",
|
||||
"select_a_customer": "Selecciona un cliente",
|
||||
"category": "Categoría",
|
||||
"from_date": "Desde la fecha",
|
||||
"to_date": "Hasta la fecha",
|
||||
|
||||
@ -410,6 +410,8 @@
|
||||
"expenses_list": "Liste des dépenses",
|
||||
"expense_title": "Titre",
|
||||
"contact": "Contact",
|
||||
"customer": "Client Client",
|
||||
"select_a_customer": "Sélectionnez un client",
|
||||
"category": "Catégorie",
|
||||
"from_date": "A partir de la date",
|
||||
"to_date": "À ce jour",
|
||||
|
||||
@ -414,6 +414,7 @@
|
||||
"expense_title": "Título",
|
||||
"contact": "Contato",
|
||||
"category": "Categoria",
|
||||
"customer": "Cliente",
|
||||
"from_date": "A partir da Data",
|
||||
"to_date": "Até a Data",
|
||||
"expense_date": "Data",
|
||||
|
||||
@ -102,6 +102,19 @@
|
||||
<span v-if="!$v.formData.amount.minValue" class="text-danger">{{ $t('validation.price_minvalue') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-sm-6">
|
||||
<label class="form-label">{{ $t('expenses.customer') }}</label>
|
||||
<base-select
|
||||
ref="baseSelect"
|
||||
v-model="customer"
|
||||
:options="customerList"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:placeholder="$t('customers.select_a_customer')"
|
||||
label="name"
|
||||
track-by="id"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group col-sm-6">
|
||||
<label for="description">{{ $t('expenses.note') }}</label>
|
||||
<base-text-area
|
||||
@ -169,7 +182,8 @@ export default {
|
||||
expense_category_id: null,
|
||||
expense_date: new Date(),
|
||||
amount: null,
|
||||
notes: ''
|
||||
notes: '',
|
||||
user_id: null
|
||||
},
|
||||
money: {
|
||||
decimal: '.',
|
||||
@ -185,7 +199,9 @@ export default {
|
||||
passData: [],
|
||||
contacts: [],
|
||||
previewReceipt: null,
|
||||
fileSendUrl: '/api/expenses'
|
||||
fileSendUrl: '/api/expenses',
|
||||
customer: null,
|
||||
customerList: []
|
||||
}
|
||||
},
|
||||
validations: {
|
||||
@ -297,6 +313,8 @@ export default {
|
||||
},
|
||||
async fetchInitialData () {
|
||||
this.fetchCategories()
|
||||
let fetchData = await this.fetchCreateExpense()
|
||||
this.customerList = fetchData.data.customers
|
||||
if (this.isEdit) {
|
||||
let response = await this.fetchExpense(this.$route.params.id)
|
||||
this.category = response.data.expense.category
|
||||
@ -304,6 +322,9 @@ export default {
|
||||
this.formData.expense_date = moment(this.formData.expense_date).toString()
|
||||
this.formData.amount = (response.data.expense.amount)
|
||||
this.fileSendUrl = `/api/expenses/${this.$route.params.id}`
|
||||
if (response.data.expense.user_id) {
|
||||
this.customer = this.customerList.find(customer => customer.id === response.data.expense.user_id)
|
||||
}
|
||||
}
|
||||
},
|
||||
async sendData () {
|
||||
@ -319,9 +340,10 @@ export default {
|
||||
data.append('attachment_receipt', this.file)
|
||||
}
|
||||
data.append('expense_category_id', this.formData.expense_category_id)
|
||||
data.append('expense_date', moment(this.formData.expense_date).format('DD/MM/YYYY'))
|
||||
data.append('expense_date', moment(this.formData.expense_date).format('DD/MM/YYYY'))
|
||||
data.append('amount', (this.formData.amount))
|
||||
data.append('notes', this.formData.notes ? this.formData.notes : '')
|
||||
data.append('user_id', this.customer ? this.customer.id : '')
|
||||
|
||||
if (this.isEdit) {
|
||||
this.isLoading = true
|
||||
|
||||
@ -43,7 +43,19 @@
|
||||
<transition name="fade">
|
||||
<div v-show="showFilters" class="filter-section">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-3">
|
||||
<label>{{ $t('expenses.customer') }}</label>
|
||||
<base-select
|
||||
v-model="filters.user"
|
||||
:options="customers"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
:placeholder="$t('expenses.select_a_customer')"
|
||||
label="name"
|
||||
@click="filter = ! filter"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label>{{ $t('expenses.category') }}</label>
|
||||
<base-select
|
||||
v-model="filters.category"
|
||||
@ -55,7 +67,7 @@
|
||||
@click="filter = ! filter"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-3">
|
||||
<label>{{ $t('expenses.from_date') }}</label>
|
||||
<base-date-picker
|
||||
v-model="filters.from_date"
|
||||
@ -63,7 +75,7 @@
|
||||
calendar-button-icon="calendar"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="col-md-3">
|
||||
<label>{{ $t('expenses.to_date') }}</label>
|
||||
<base-date-picker
|
||||
v-model="filters.to_date"
|
||||
@ -161,6 +173,11 @@
|
||||
sort-as="name"
|
||||
show="category.name"
|
||||
/>
|
||||
<table-column
|
||||
:label="$t('expenses.customer')"
|
||||
sort-as="user_name"
|
||||
show="user_name"
|
||||
/>
|
||||
<table-column
|
||||
:label="$t('expenses.date')"
|
||||
sort-as="expense_date"
|
||||
@ -237,10 +254,12 @@ export default {
|
||||
showFilters: false,
|
||||
filtersApplied: false,
|
||||
isRequestOngoing: true,
|
||||
customers: [],
|
||||
filters: {
|
||||
category: null,
|
||||
from_date: '',
|
||||
to_date: ''
|
||||
to_date: '',
|
||||
user: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -308,6 +327,7 @@ export default {
|
||||
]),
|
||||
async fetchData ({ page, filter, sort }) {
|
||||
let data = {
|
||||
user_id: this.filters.user ? this.filters.user.id : null,
|
||||
expense_category_id: this.filters.category !== null ? this.filters.category.id : '',
|
||||
from_date: this.filters.from_date === '' ? this.filters.from_date : moment(this.filters.from_date).format('DD/MM/YYYY'),
|
||||
to_date: this.filters.to_date === '' ? this.filters.to_date : moment(this.filters.to_date).format('DD/MM/YYYY'),
|
||||
@ -318,6 +338,7 @@ export default {
|
||||
|
||||
this.isRequestOngoing = true
|
||||
let response = await this.fetchExpenses(data)
|
||||
this.customers = response.data.customers
|
||||
this.isRequestOngoing = false
|
||||
|
||||
return {
|
||||
@ -340,7 +361,8 @@ export default {
|
||||
this.filters = {
|
||||
category: null,
|
||||
from_date: '',
|
||||
to_date: ''
|
||||
to_date: '',
|
||||
user: null
|
||||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
|
||||
Reference in New Issue
Block a user