mirror of
https://github.com/InvoiceShelf/InvoiceShelf.git
synced 2026-09-05 23:01:07 +00:00
chore(money,taxation): remove legacy-era money and taxation sources
This commit is contained in:
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Money\Http\Controllers;
|
||||
|
||||
use App\Domains\Money\Application\CurrencyService;
|
||||
use App\Domains\Money\Http\Resources\CurrencyResource;
|
||||
use App\Platform\Http\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
|
||||
class CurrenciesController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly CurrencyService $currencyService,
|
||||
) {}
|
||||
|
||||
public function __invoke(Request $request): AnonymousResourceCollection
|
||||
{
|
||||
$currencies = $this->currencyService->getAllWithCommonFirst();
|
||||
|
||||
return CurrencyResource::collection($currencies);
|
||||
}
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Money\Http\Controllers;
|
||||
|
||||
use App\Domains\Accounts\Models\CompanySetting;
|
||||
use App\Domains\Money\Application\ExchangeRateProviderService;
|
||||
use App\Domains\Money\Contracts\ExchangeRateBackfill;
|
||||
use App\Domains\Money\ExchangeRates\ExchangeRateException;
|
||||
use App\Domains\Money\Http\Requests\BulkExchangeRateRequest;
|
||||
use App\Domains\Money\Http\Requests\ExchangeRateProviderRequest;
|
||||
use App\Domains\Money\Http\Resources\ExchangeRateProviderResource;
|
||||
use App\Domains\Money\Models\Currency;
|
||||
use App\Domains\Money\Models\ExchangeRateLog;
|
||||
use App\Domains\Money\Models\ExchangeRateProvider;
|
||||
use App\Platform\Http\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class ExchangeRateProviderController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ExchangeRateProviderService $exchangeRateProviderService,
|
||||
private readonly ExchangeRateBackfill $exchangeRateBackfill,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('viewAny', ExchangeRateProvider::class);
|
||||
|
||||
$limit = $request->has('limit') ? $request->limit : 5;
|
||||
|
||||
$exchangeRateProviders = ExchangeRateProvider::whereCompany()->paginate($limit);
|
||||
|
||||
return ExchangeRateProviderResource::collection($exchangeRateProviders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function store(ExchangeRateProviderRequest $request)
|
||||
{
|
||||
$this->authorize('create', ExchangeRateProvider::class);
|
||||
|
||||
$payload = $request->getExchangeRateProviderPayload();
|
||||
$query = $this->exchangeRateProviderService->checkActiveCurrencies($payload['currencies'] ?? []);
|
||||
|
||||
if (count($query) !== 0) {
|
||||
return respondJson('currency_used', 'Currency used.');
|
||||
}
|
||||
|
||||
try {
|
||||
$this->exchangeRateProviderService->validateProvider($payload);
|
||||
$exchangeRateProvider = $this->exchangeRateProviderService->create($payload);
|
||||
|
||||
return new ExchangeRateProviderResource($exchangeRateProvider);
|
||||
} catch (ExchangeRateException $exception) {
|
||||
return respondJson($exception->errorKey, $exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function show(ExchangeRateProvider $exchangeRateProvider)
|
||||
{
|
||||
$this->authorize('view', $exchangeRateProvider);
|
||||
|
||||
return new ExchangeRateProviderResource($exchangeRateProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function update(ExchangeRateProviderRequest $request, ExchangeRateProvider $exchangeRateProvider)
|
||||
{
|
||||
$this->authorize('update', $exchangeRateProvider);
|
||||
|
||||
$payload = $request->getExchangeRateProviderPayload();
|
||||
$query = $this->exchangeRateProviderService->checkUpdateActiveCurrencies(
|
||||
$exchangeRateProvider,
|
||||
$payload['currencies'] ?? [],
|
||||
);
|
||||
|
||||
if (count($query) !== 0) {
|
||||
return respondJson('currency_used', 'Currency used.');
|
||||
}
|
||||
|
||||
try {
|
||||
$this->exchangeRateProviderService->validateProvider($payload);
|
||||
$this->exchangeRateProviderService->update($exchangeRateProvider, $payload);
|
||||
|
||||
return new ExchangeRateProviderResource($exchangeRateProvider);
|
||||
} catch (ExchangeRateException $exception) {
|
||||
return respondJson($exception->errorKey, $exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function destroy(ExchangeRateProvider $exchangeRateProvider)
|
||||
{
|
||||
$this->authorize('delete', $exchangeRateProvider);
|
||||
|
||||
if ($exchangeRateProvider->active == true) {
|
||||
return respondJson('provider_active', 'Provider Active.');
|
||||
}
|
||||
|
||||
$exchangeRateProvider->delete();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function activeProvider(Request $request, Currency $currency)
|
||||
{
|
||||
$query = ExchangeRateProvider::whereCompany()->whereJsonContains('currencies', $currency->code)
|
||||
->where('active', true)
|
||||
->get();
|
||||
|
||||
if (count($query) !== 0) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'provider_active',
|
||||
], 200);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => 'no_active_provider',
|
||||
], 200);
|
||||
}
|
||||
|
||||
public function getRate(Request $request, Currency $currency)
|
||||
{
|
||||
$settings = CompanySetting::getSettings(['currency'], $request->header('company'));
|
||||
$baseCurrency = Currency::findOrFail($settings['currency']);
|
||||
|
||||
$query = ExchangeRateProvider::whereJsonContains('currencies', $currency->code)
|
||||
->where('active', true)
|
||||
->get()
|
||||
->toArray();
|
||||
|
||||
$exchangeRate = ExchangeRateLog::where('base_currency_id', $currency->id)
|
||||
->where('currency_id', $baseCurrency->id)
|
||||
->orderBy('created_at', 'desc')
|
||||
->value('exchange_rate');
|
||||
|
||||
if ($query) {
|
||||
$filter = Arr::only($query[0], ['key', 'driver', 'driver_config']);
|
||||
try {
|
||||
$exchangeRate = $this->exchangeRateProviderService->getExchangeRate(
|
||||
$filter['driver'],
|
||||
$filter['key'],
|
||||
$filter['driver_config'] ?? [],
|
||||
$currency->code,
|
||||
$baseCurrency->code,
|
||||
);
|
||||
|
||||
return response()->json(['exchangeRate' => $exchangeRate]);
|
||||
} catch (ExchangeRateException) {
|
||||
// Fall back to the latest stored rate below, matching the
|
||||
// existing API behavior when a live provider is unavailable.
|
||||
}
|
||||
}
|
||||
if ($exchangeRate) {
|
||||
return response()->json([
|
||||
'exchangeRate' => [$exchangeRate],
|
||||
], 200);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => 'no_exchange_rate_available',
|
||||
], 200);
|
||||
}
|
||||
|
||||
public function supportedCurrencies(Request $request)
|
||||
{
|
||||
$this->authorize('viewAny', ExchangeRateProvider::class);
|
||||
|
||||
try {
|
||||
$currencies = $this->exchangeRateProviderService->getSupportedCurrencies(
|
||||
$request->driver,
|
||||
$request->key,
|
||||
$request->driver_config ?? [],
|
||||
);
|
||||
|
||||
return response()->json(['supportedCurrencies' => $currencies]);
|
||||
} catch (ExchangeRateException $exception) {
|
||||
return respondJson($exception->errorKey, $exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function usedCurrencies(Request $request)
|
||||
{
|
||||
$this->authorize('viewAny', ExchangeRateProvider::class);
|
||||
|
||||
$providerId = $request->provider_id;
|
||||
|
||||
$activeExchangeRateProviders = ExchangeRateProvider::where('active', true)
|
||||
->whereCompany()
|
||||
->when($providerId, function ($query) use ($providerId) {
|
||||
return $query->where('id', '<>', $providerId);
|
||||
})
|
||||
->pluck('currencies');
|
||||
$activeExchangeRateProvider = [];
|
||||
|
||||
foreach ($activeExchangeRateProviders as $data) {
|
||||
if (is_array($data)) {
|
||||
for ($limit = 0; $limit < count($data); $limit++) {
|
||||
$activeExchangeRateProvider[] = $data[$limit];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$allExchangeRateProviders = ExchangeRateProvider::whereCompany()->pluck('currencies');
|
||||
$allExchangeRateProvider = [];
|
||||
|
||||
foreach ($allExchangeRateProviders as $data) {
|
||||
if (is_array($data)) {
|
||||
for ($limit = 0; $limit < count($data); $limit++) {
|
||||
$allExchangeRateProvider[] = $data[$limit];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'allUsedCurrencies' => $allExchangeRateProvider ? $allExchangeRateProvider : [],
|
||||
'activeUsedCurrencies' => $activeExchangeRateProvider ? $activeExchangeRateProvider : [],
|
||||
]);
|
||||
}
|
||||
|
||||
public function usedCurrenciesWithoutRate(Request $request)
|
||||
{
|
||||
return response()->json([
|
||||
'currencies' => Currency::whereIn(
|
||||
'id',
|
||||
$this->exchangeRateBackfill->currencyIdsMissingRates(),
|
||||
)->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function bulkUpdate(BulkExchangeRateRequest $request)
|
||||
{
|
||||
if ($this->exchangeRateBackfill->apply(
|
||||
(int) $request->header('company'),
|
||||
$request->validated('currencies'),
|
||||
)) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Money\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class BulkExchangeRateRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'currencies' => [
|
||||
'required',
|
||||
],
|
||||
'currencies.*.id' => [
|
||||
'required',
|
||||
'numeric',
|
||||
],
|
||||
'currencies.*.exchange_rate' => [
|
||||
'required',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Money\Http\Requests;
|
||||
|
||||
use App\Rules\PublicHttpUrl;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class ExchangeRateProviderRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'driver' => [
|
||||
'required',
|
||||
],
|
||||
'key' => [
|
||||
'required',
|
||||
],
|
||||
'currencies' => [
|
||||
'nullable',
|
||||
],
|
||||
'currencies.*' => [
|
||||
'nullable',
|
||||
],
|
||||
'driver_config' => [
|
||||
'nullable',
|
||||
],
|
||||
// Only the CurrencyConverter "DEDICATED" plan reads a custom URL from
|
||||
// driver_config; guard it against SSRF (private/reserved targets).
|
||||
'driver_config.url' => [
|
||||
'nullable',
|
||||
'string',
|
||||
'url',
|
||||
new PublicHttpUrl,
|
||||
],
|
||||
'active' => [
|
||||
'nullable',
|
||||
'boolean',
|
||||
],
|
||||
];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
public function getExchangeRateProviderPayload()
|
||||
{
|
||||
return collect($this->validated())
|
||||
->merge([
|
||||
'company_id' => $this->header('company'),
|
||||
])
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Money\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class CurrencyResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param Request $request
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'code' => $this->code,
|
||||
'symbol' => $this->symbol,
|
||||
'precision' => $this->precision,
|
||||
'thousand_separator' => $this->thousand_separator,
|
||||
'decimal_separator' => $this->decimal_separator,
|
||||
'swap_currency_symbol' => $this->swap_currency_symbol,
|
||||
'exchange_rate' => $this->exchange_rate,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Money\Http\Resources\CustomerPortal;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class CurrencyResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param Request $request
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'code' => $this->code,
|
||||
'symbol' => $this->symbol,
|
||||
'precision' => $this->precision,
|
||||
'thousand_separator' => $this->thousand_separator,
|
||||
'decimal_separator' => $this->decimal_separator,
|
||||
'swap_currency_symbol' => $this->swap_currency_symbol,
|
||||
'exchange_rate' => $this->exchange_rate,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Money\Http\Resources;
|
||||
|
||||
use App\Domains\Accounts\Http\Resources\CompanyResource;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class ExchangeRateProviderResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param Request $request
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'key' => $this->key,
|
||||
'driver' => $this->driver,
|
||||
'currencies' => $this->currencies,
|
||||
'driver_config' => $this->driver_config,
|
||||
'company_id' => $this->company_id,
|
||||
'active' => $this->active,
|
||||
'company' => $this->when($this->company()->exists(), function () {
|
||||
return new CompanyResource($this->company);
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Money\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Currency extends Model
|
||||
{
|
||||
protected $table = 'currencies';
|
||||
|
||||
use HasFactory;
|
||||
|
||||
public const COMMON_CURRENCY_CODES = [
|
||||
'USD', 'EUR', 'GBP', 'JPY', 'CAD',
|
||||
'AUD', 'CHF', 'CNY', 'INR', 'BRL',
|
||||
];
|
||||
|
||||
protected $guarded = [
|
||||
'id',
|
||||
];
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Money\Models;
|
||||
|
||||
use App\Domains\Accounts\Models\Company;
|
||||
use App\Domains\Accounts\Models\CompanySetting;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class ExchangeRateLog extends Model
|
||||
{
|
||||
protected $table = 'exchange_rate_logs';
|
||||
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [
|
||||
'id',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'exchange_rate' => 'float',
|
||||
];
|
||||
}
|
||||
|
||||
public function currency(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Currency::class);
|
||||
}
|
||||
|
||||
public function company(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Company::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an exchange rate log entry from a document model (invoice, estimate, etc.)
|
||||
* using its exchange rate, currency, and the company's default currency setting.
|
||||
*/
|
||||
public static function addExchangeRateLog(mixed $model): self
|
||||
{
|
||||
$data = [
|
||||
'exchange_rate' => $model->exchange_rate,
|
||||
'company_id' => $model->company_id,
|
||||
'base_currency_id' => $model->currency_id,
|
||||
'currency_id' => CompanySetting::getSetting('currency', $model->company_id),
|
||||
];
|
||||
|
||||
return self::create($data);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Money\Models;
|
||||
|
||||
use App\Domains\Accounts\Models\Company;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class ExchangeRateProvider extends Model
|
||||
{
|
||||
protected $table = 'exchange_rate_providers';
|
||||
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [
|
||||
'id',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'currencies' => 'array',
|
||||
'driver_config' => 'array',
|
||||
'active' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
public function company(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Company::class);
|
||||
}
|
||||
|
||||
public function setCurrenciesAttribute($value)
|
||||
{
|
||||
$this->attributes['currencies'] = json_encode($value);
|
||||
}
|
||||
|
||||
public function setDriverConfigAttribute($value)
|
||||
{
|
||||
$this->attributes['driver_config'] = json_encode($value);
|
||||
}
|
||||
|
||||
public function scopeWhereCompany($query)
|
||||
{
|
||||
$query->where('exchange_rate_providers.company_id', request()->header('company'));
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Money\Policies;
|
||||
|
||||
use App\Domains\Accounts\Models\User;
|
||||
use App\Domains\Money\Models\ExchangeRateProvider;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
use Illuminate\Auth\Access\Response;
|
||||
use Silber\Bouncer\BouncerFacade;
|
||||
|
||||
class ExchangeRateProviderPolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*
|
||||
* @return Response|bool
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
if (BouncerFacade::can('view-exchange-rate-provider', ExchangeRateProvider::class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*
|
||||
* @return Response|bool
|
||||
*/
|
||||
public function view(User $user, ExchangeRateProvider $exchangeRateProvider): bool
|
||||
{
|
||||
if (BouncerFacade::can('view-exchange-rate-provider', $exchangeRateProvider) && $user->hasCompany($exchangeRateProvider->company_id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*
|
||||
* @return Response|bool
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
if (BouncerFacade::can('create-exchange-rate-provider', ExchangeRateProvider::class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*
|
||||
* @return Response|bool
|
||||
*/
|
||||
public function update(User $user, ExchangeRateProvider $exchangeRateProvider): bool
|
||||
{
|
||||
if (BouncerFacade::can('edit-exchange-rate-provider', $exchangeRateProvider) && $user->hasCompany($exchangeRateProvider->company_id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*
|
||||
* @return Response|bool
|
||||
*/
|
||||
public function delete(User $user, ExchangeRateProvider $exchangeRateProvider): bool
|
||||
{
|
||||
if (BouncerFacade::can('delete-exchange-rate-provider', $exchangeRateProvider) && $user->hasCompany($exchangeRateProvider->company_id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore the model.
|
||||
*
|
||||
* @return Response|bool
|
||||
*/
|
||||
public function restore(User $user, ExchangeRateProvider $exchangeRateProvider): bool
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete the model.
|
||||
*
|
||||
* @return Response|bool
|
||||
*/
|
||||
public function forceDelete(User $user, ExchangeRateProvider $exchangeRateProvider): bool
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Taxation\Http\Controllers;
|
||||
|
||||
use App\Domains\Taxation\Http\Requests\TaxTypeRequest;
|
||||
use App\Domains\Taxation\Http\Resources\TaxTypeResource;
|
||||
use App\Domains\Taxation\Models\TaxType;
|
||||
use App\Platform\Http\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
class TaxTypesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('viewAny', TaxType::class);
|
||||
|
||||
$limit = $request->has('limit') ? $request->limit : 5;
|
||||
|
||||
$taxTypes = TaxType::applyFilters($request->all())
|
||||
->where('type', TaxType::TYPE_GENERAL)
|
||||
->whereCompany()
|
||||
->latest()
|
||||
->paginateData($limit);
|
||||
|
||||
return TaxTypeResource::collection($taxTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function store(TaxTypeRequest $request)
|
||||
{
|
||||
$this->authorize('create', TaxType::class);
|
||||
|
||||
$taxType = TaxType::create($request->getTaxTypePayload());
|
||||
|
||||
return new TaxTypeResource($taxType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function show(TaxType $taxType)
|
||||
{
|
||||
$this->authorize('view', $taxType);
|
||||
|
||||
return new TaxTypeResource($taxType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function update(TaxTypeRequest $request, TaxType $taxType)
|
||||
{
|
||||
$this->authorize('update', $taxType);
|
||||
|
||||
$taxType->update($request->getTaxTypePayload());
|
||||
|
||||
return new TaxTypeResource($taxType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function destroy(TaxType $taxType)
|
||||
{
|
||||
$this->authorize('delete', $taxType);
|
||||
|
||||
if ($taxType->taxes() && $taxType->taxes()->count() > 0) {
|
||||
return respondJson('taxes_attached', 'Taxes Attached.');
|
||||
}
|
||||
|
||||
$taxType->delete();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Taxation\Http\Resources\CustomerPortal;
|
||||
|
||||
use App\Domains\Money\Http\Resources\CustomerPortal\CurrencyResource;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class TaxResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param Request $request
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'tax_type_id' => $this->tax_type_id,
|
||||
'invoice_id' => $this->invoice_id,
|
||||
'estimate_id' => $this->estimate_id,
|
||||
'invoice_item_id' => $this->invoice_item_id,
|
||||
'estimate_item_id' => $this->estimate_item_id,
|
||||
'item_id' => $this->item_id,
|
||||
'company_id' => $this->company_id,
|
||||
'name' => $this->name,
|
||||
'amount' => $this->amount,
|
||||
'percent' => $this->percent,
|
||||
'compound_tax' => $this->compound_tax,
|
||||
'base_amount' => $this->base_amount,
|
||||
'currency_id' => $this->currency_id,
|
||||
'recurring_invoice_id' => $this->recurring_invoice_id,
|
||||
'tax_type' => $this->when($this->taxType()->exists(), function () {
|
||||
return new TaxTypeResource($this->taxType);
|
||||
}),
|
||||
'currency' => $this->when($this->currency()->exists(), function () {
|
||||
return new CurrencyResource($this->currency);
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Taxation\Http\Resources\CustomerPortal;
|
||||
|
||||
use App\Domains\Accounts\Http\Resources\CustomerPortal\CompanyResource;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class TaxTypeResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param Request $request
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'percent' => $this->percent,
|
||||
'transaction_type' => $this->transaction_type,
|
||||
'compound_tax' => $this->compound_tax,
|
||||
'collective_tax' => $this->collective_tax,
|
||||
'description' => $this->description,
|
||||
'company_id' => $this->company_id,
|
||||
'company' => $this->when($this->company()->exists(), function () {
|
||||
return new CompanyResource($this->company);
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Taxation\Http\Resources;
|
||||
|
||||
use App\Domains\Money\Http\Resources\CurrencyResource;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class TaxResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param Request $request
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'tax_type_id' => $this->tax_type_id,
|
||||
'invoice_id' => $this->invoice_id,
|
||||
'estimate_id' => $this->estimate_id,
|
||||
'invoice_item_id' => $this->invoice_item_id,
|
||||
'estimate_item_id' => $this->estimate_item_id,
|
||||
'expense_id' => $this->expense_id,
|
||||
'item_id' => $this->item_id,
|
||||
'company_id' => $this->company_id,
|
||||
'name' => $this->name,
|
||||
'amount' => $this->amount,
|
||||
'percent' => $this->percent,
|
||||
'calculation_type' => $this->calculation_type,
|
||||
'fixed_amount' => $this->fixed_amount,
|
||||
'compound_tax' => $this->compound_tax,
|
||||
'base_amount' => $this->base_amount,
|
||||
'currency_id' => $this->currency_id,
|
||||
'type' => $this->taxType->type,
|
||||
'recurring_invoice_id' => $this->recurring_invoice_id,
|
||||
'tax_type' => $this->when($this->taxType()->exists(), function () {
|
||||
return new TaxTypeResource($this->taxType);
|
||||
}),
|
||||
'currency' => $this->when($this->currency()->exists(), function () {
|
||||
return new CurrencyResource($this->currency);
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Taxation\Http\Resources;
|
||||
|
||||
use App\Domains\Accounts\Http\Resources\CompanyResource;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class TaxTypeResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param Request $request
|
||||
*/
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'percent' => $this->percent,
|
||||
'fixed_amount' => $this->fixed_amount,
|
||||
'calculation_type' => $this->calculation_type,
|
||||
'type' => $this->type,
|
||||
'transaction_type' => $this->transaction_type,
|
||||
'compound_tax' => $this->compound_tax,
|
||||
'collective_tax' => $this->collective_tax,
|
||||
'description' => $this->description,
|
||||
'company_id' => $this->company_id,
|
||||
'company' => $this->when($this->company()->exists(), function () {
|
||||
return new CompanyResource($this->company);
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Taxation\Models;
|
||||
|
||||
use App\Domains\Catalog\Models\Item;
|
||||
use App\Domains\Money\Models\Currency;
|
||||
use App\Domains\Purchases\Models\Expense;
|
||||
use App\Domains\Sales\Models\Estimate;
|
||||
use App\Domains\Sales\Models\EstimateItem;
|
||||
use App\Domains\Sales\Models\Invoice;
|
||||
use App\Domains\Sales\Models\InvoiceItem;
|
||||
use App\Domains\Sales\Models\RecurringInvoice;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class Tax extends Model
|
||||
{
|
||||
protected $table = 'taxes';
|
||||
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [
|
||||
'id',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'amount' => 'integer',
|
||||
'percent' => 'float',
|
||||
'fixed_amount' => 'integer',
|
||||
'compound_tax' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
public function taxType(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(TaxType::class);
|
||||
}
|
||||
|
||||
public function invoice(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Invoice::class);
|
||||
}
|
||||
|
||||
public function recurringInvoice(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(RecurringInvoice::class);
|
||||
}
|
||||
|
||||
public function estimate(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Estimate::class);
|
||||
}
|
||||
|
||||
public function currency(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Currency::class);
|
||||
}
|
||||
|
||||
public function invoiceItem(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(InvoiceItem::class);
|
||||
}
|
||||
|
||||
public function expense(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Expense::class);
|
||||
}
|
||||
|
||||
public function estimateItem(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(EstimateItem::class);
|
||||
}
|
||||
|
||||
public function item(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Item::class);
|
||||
}
|
||||
|
||||
public function scopeWhereCompany(Builder $query, int $company_id): void
|
||||
{
|
||||
$query->where('company_id', $company_id);
|
||||
}
|
||||
|
||||
public function scopeTaxAttributes(Builder $query): void
|
||||
{
|
||||
$query->select(
|
||||
DB::raw('sum(base_amount) as total_tax_amount, tax_type_id')
|
||||
)->groupBy('tax_type_id');
|
||||
}
|
||||
|
||||
public function scopeInvoicesBetween(Builder $query, Carbon $start, Carbon $end): void
|
||||
{
|
||||
$query->where(function (Builder $query) use ($start, $end) {
|
||||
$query->whereHas('invoice', function (Builder $query) use ($start, $end) {
|
||||
$query->where('paid_status', Invoice::STATUS_PAID)
|
||||
->whereBetween(
|
||||
'invoice_date',
|
||||
[$start->format('Y-m-d'), $end->format('Y-m-d')]
|
||||
);
|
||||
})->orWhereHas('invoiceItem.invoice', function (Builder $query) use ($start, $end) {
|
||||
$query->where('paid_status', Invoice::STATUS_PAID)
|
||||
->whereBetween(
|
||||
'invoice_date',
|
||||
[$start->format('Y-m-d'), $end->format('Y-m-d')]
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public function scopeWhereInvoicesFilters(Builder $query, array $filters): void
|
||||
{
|
||||
$filters = collect($filters);
|
||||
|
||||
if ($filters->get('from_date') && $filters->get('to_date')) {
|
||||
$start = Carbon::createFromFormat('Y-m-d', $filters->get('from_date'));
|
||||
$end = Carbon::createFromFormat('Y-m-d', $filters->get('to_date'));
|
||||
|
||||
$query->invoicesBetween($start, $end);
|
||||
}
|
||||
}
|
||||
|
||||
public function scopeExpensesBetween(Builder $query, Carbon $start, Carbon $end): void
|
||||
{
|
||||
$query->whereHas('expense', function (Builder $query) use ($start, $end) {
|
||||
$query->whereBetween(
|
||||
'expense_date',
|
||||
[$start->format('Y-m-d'), $end->format('Y-m-d')]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
public function scopeWhereExpensesFilters(Builder $query, array $filters): void
|
||||
{
|
||||
$filters = collect($filters);
|
||||
|
||||
if ($filters->get('from_date') && $filters->get('to_date')) {
|
||||
$start = Carbon::createFromFormat('Y-m-d', $filters->get('from_date'));
|
||||
$end = Carbon::createFromFormat('Y-m-d', $filters->get('to_date'));
|
||||
|
||||
$query->expensesBetween($start, $end);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Taxation\Models;
|
||||
|
||||
use App\Domains\Accounts\Models\Company;
|
||||
use App\Support\SafeOrderBy;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class TaxType extends Model
|
||||
{
|
||||
protected $table = 'tax_types';
|
||||
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [
|
||||
'id',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'percent' => 'float',
|
||||
'fixed_amount' => 'integer',
|
||||
'compound_tax' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
public const TYPE_GENERAL = 'GENERAL';
|
||||
|
||||
public const TYPE_MODULE = 'MODULE';
|
||||
|
||||
public const TRANSACTION_TYPE_SALES = 'sales';
|
||||
|
||||
public const TRANSACTION_TYPE_PURCHASES = 'purchases';
|
||||
|
||||
public function taxes(): HasMany
|
||||
{
|
||||
return $this->hasMany(Tax::class);
|
||||
}
|
||||
|
||||
public function company(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Company::class);
|
||||
}
|
||||
|
||||
public function scopeWhereCompany(Builder $query): void
|
||||
{
|
||||
$query->where('company_id', request()->header('company'));
|
||||
}
|
||||
|
||||
public function scopeWhereTaxType(Builder $query, int $tax_type_id): void
|
||||
{
|
||||
$query->orWhere('id', $tax_type_id);
|
||||
}
|
||||
|
||||
public function scopeWhereTransactionType(Builder $query, string $transaction_type): void
|
||||
{
|
||||
$query->where('transaction_type', $transaction_type);
|
||||
}
|
||||
|
||||
public function scopeApplyFilters(Builder $query, array $filters): void
|
||||
{
|
||||
$filters = collect($filters);
|
||||
|
||||
if ($filters->get('tax_type_id')) {
|
||||
$query->whereTaxType($filters->get('tax_type_id'));
|
||||
}
|
||||
|
||||
if ($filters->get('company_id')) {
|
||||
$query->whereCompany($filters->get('company_id'));
|
||||
}
|
||||
|
||||
if ($filters->get('transaction_type')) {
|
||||
$query->whereTransactionType($filters->get('transaction_type'));
|
||||
}
|
||||
|
||||
if ($filters->get('search')) {
|
||||
$query->whereSearch($filters->get('search'));
|
||||
}
|
||||
|
||||
if ($filters->get('orderByField') || $filters->get('orderBy')) {
|
||||
$field = $filters->get('orderByField') ? $filters->get('orderByField') : 'payment_number';
|
||||
$orderBy = $filters->get('orderBy') ? $filters->get('orderBy') : 'asc';
|
||||
$query->whereOrder($field, $orderBy);
|
||||
}
|
||||
}
|
||||
|
||||
public function scopeWhereOrder(Builder $query, string $orderByField, string $orderBy): void
|
||||
{
|
||||
SafeOrderBy::apply($query, $orderByField, $orderBy);
|
||||
}
|
||||
|
||||
public function scopeWhereSearch(Builder $query, string $search): void
|
||||
{
|
||||
$query->where('name', 'LIKE', '%'.$search.'%');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|LengthAwarePaginator
|
||||
*/
|
||||
public function scopePaginateData(Builder $query, string $limit)
|
||||
{
|
||||
if ($limit == 'all') {
|
||||
return $query->get();
|
||||
}
|
||||
|
||||
return $query->paginate($limit);
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Taxation\Policies;
|
||||
|
||||
use App\Domains\Accounts\Models\User;
|
||||
use App\Domains\Taxation\Models\TaxType;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
use Silber\Bouncer\BouncerFacade;
|
||||
|
||||
class TaxTypePolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
if (BouncerFacade::can('view-tax-type', TaxType::class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function view(User $user, TaxType $taxType): bool
|
||||
{
|
||||
if (BouncerFacade::can('view-tax-type', $taxType) && $user->hasCompany($taxType->company_id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
if (BouncerFacade::can('create-tax-type', TaxType::class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function update(User $user, TaxType $taxType): bool
|
||||
{
|
||||
if (BouncerFacade::can('edit-tax-type', $taxType) && $user->hasCompany($taxType->company_id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function delete(User $user, TaxType $taxType): bool
|
||||
{
|
||||
if (BouncerFacade::can('delete-tax-type', $taxType) && $user->hasCompany($taxType->company_id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore the model.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function restore(User $user, TaxType $taxType): bool
|
||||
{
|
||||
if (BouncerFacade::can('delete-tax-type', $taxType) && $user->hasCompany($taxType->company_id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete the model.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function forceDelete(User $user, TaxType $taxType): bool
|
||||
{
|
||||
if (BouncerFacade::can('delete-tax-type', $taxType) && $user->hasCompany($taxType->company_id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user