mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-24 02:14:21 -04:00
Merge branch 'v5-stable' into patch-4
This commit is contained in:
commit
5d5cc1eec2
@ -57,7 +57,6 @@ DELETE_PDF_DAYS=60
|
||||
DELETE_BACKUP_DAYS=60
|
||||
|
||||
COMPOSER_AUTH='{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}'
|
||||
SENTRY_LARAVEL_DSN=https://39389664f3f14969b4c43dadda00a40b@sentry2.invoicing.co/5
|
||||
|
||||
GOOGLE_PLAY_PACKAGE_NAME=
|
||||
APPSTORE_PASSWORD=
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,6 +4,7 @@
|
||||
/public/react
|
||||
/storage/*.key
|
||||
/storage/debugbar
|
||||
/storage/*
|
||||
/vendor
|
||||
/.idea
|
||||
/.vscode
|
||||
|
62
README.md
62
README.md
@ -3,7 +3,6 @@
|
||||
</p>
|
||||
|
||||

|
||||

|
||||
[](https://www.codacy.com/gh/turbo124/invoiceninja/dashboard?utm_source=github.com&utm_medium=referral&utm_content=turbo124/invoiceninja&utm_campaign=Badge_Grade)
|
||||
<a href="https://cla-assistant.io/invoiceninja/invoiceninja"><img src="https://cla-assistant.io/readme/badge/invoiceninja/invoiceninja" alt="CLA assistant" /></a>
|
||||
|
||||
@ -19,18 +18,33 @@ Just make sure to add the `invoice-ninja` tag to your question.
|
||||
|
||||
Version 5 of Invoice Ninja is here! We've taken the best parts of version 4 and bolted on all of the most requested features to produce a invoicing application like no other.
|
||||
|
||||
The new interface has a lot more functionality so it isn't a carbon copy of v4, but once you get used to the new layout and functionality we are sure you will love it!
|
||||
All Pro and Enterprise features from the hosted app are included in the open-code. We offer a $30 per year white-label license to remove the Invoice Ninja branding from client facing parts of the app.
|
||||
|
||||
## Referral Program
|
||||
* Earn 50% of Pro & Enterprise Plans up to 4 years - [Learn more](https://www.invoiceninja.com/referral-program/)
|
||||
* [Videos](https://www.youtube.com/@appinvoiceninja)
|
||||
* [API Documentation](https://app.swaggerhub.com/apis/invoiceninja/invoiceninja)
|
||||
* [APP Documentation](https://invoiceninja.github.io/)
|
||||
* [Support Forum](https://forum.invoiceninja.com)
|
||||
* [StackOverflow](https://stackoverflow.com/tags/invoice-ninja/)
|
||||
|
||||
## Mobile Apps
|
||||
* [iPhone](https://apps.apple.com/app/id1503970375?platform=iphone)
|
||||
* [Android](https://play.google.com/store/apps/details?id=com.invoiceninja.app)
|
||||
|
||||
## Desktop Apps
|
||||
* [macOS](https://apps.apple.com/app/id1503970375?platform=mac)
|
||||
* [Windows](https://microsoft.com/en-us/p/invoice-ninja/9n3f2bbcfdr6)
|
||||
* [Linux](https://snapcraft.io/invoiceninja)
|
||||
|
||||
|
||||
## Installation Options
|
||||
* [Docker File](https://hub.docker.com/r/invoiceninja/invoiceninja/)
|
||||
* [Cloudron](https://cloudron.io/store/com.invoiceninja.cloudronapp.html)
|
||||
* [Softaculous](https://www.softaculous.com/apps/ecommerce/Invoice_Ninja)
|
||||
|
||||
## Recommended Providers
|
||||
* [Stripe](https://stripe.com/)
|
||||
* [Postmark](https://postmarkapp.com/)
|
||||
|
||||
## Development
|
||||
* [API Documentation](https://app.swaggerhub.com/apis/invoiceninja/invoiceninja)
|
||||
* [APP Documentation](https://invoiceninja.github.io/)
|
||||
|
||||
## Quick Start
|
||||
|
||||
@ -68,43 +82,11 @@ user: user@example.com
|
||||
pass: password
|
||||
```
|
||||
|
||||
## Contribution guide.
|
||||
|
||||
Code Style to follow [PSR-2](https://www.php-fig.org/psr/psr-2/) standards.
|
||||
|
||||
All methods names to be in CamelCase
|
||||
|
||||
All variables names to be in snake_case
|
||||
|
||||
Where practical code should be strongly typed, ie your methods must return a type ie
|
||||
|
||||
`public function doThis() : void`
|
||||
|
||||
PHP >= 7.3 allows the return type Nullable so there should be no circumstance a type cannot be return by using the following:
|
||||
|
||||
`public function doThat() ?:string`
|
||||
|
||||
To improve chances of PRs being merged please include tests to ensure your code works well and integrates with the rest of the project.
|
||||
|
||||
## Documentation
|
||||
|
||||
API documentation is hosted using Swagger and can be found [HERE](https://app.swaggerhub.com/apis/invoiceninja/invoiceninja)
|
||||
|
||||
Installation, Configuration and Troubleshooting documentation can be found [HERE] (https://invoiceninja.github.io)
|
||||
|
||||
## Credits
|
||||
* [Hillel Coren](https://hillelcoren.com/)
|
||||
* [David Bomba](https://github.com/turbo124)
|
||||
* [All contributors](https://github.com/invoiceninja/invoiceninja/graphs/contributors)
|
||||
|
||||
**Special thanks to:**
|
||||
* [Holger Lösken](https://github.com/codedge) - [codedge](http://codedge.de)
|
||||
* [Samuel Laulhau](https://github.com/lalop) - [Lalop](http://lalop.co/)
|
||||
* [Alexander Vanderveen](https://blog.technicallycomputers.ca/) - [Technically Computers](https://www.technicallycomputers.ca/)
|
||||
* [Efthymios Sarmpanis](https://github.com/esarbanis)
|
||||
* [Gianfranco Gasbarri](https://github.com/gincos)
|
||||
* [Clemens Mol](https://github.com/clemensmol)
|
||||
* [Benjamin Beganović](https://github.com/beganovich)
|
||||
* [All contributors](https://github.com/invoiceninja/invoiceninja/graphs/contributors)
|
||||
|
||||
## Security
|
||||
|
||||
|
@ -1 +1 @@
|
||||
5.5.25
|
||||
5.5.47
|
@ -13,7 +13,9 @@ namespace App\Console\Commands;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Backup;
|
||||
use App\Models\Company;
|
||||
use App\Models\Design;
|
||||
use App\Models\Document;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use stdClass;
|
||||
@ -25,14 +27,14 @@ class BackupUpdate extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'ninja:backup-update';
|
||||
protected $signature = 'ninja:backup-files {--disk=}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Shift backups from DB to storage';
|
||||
protected $description = 'Shift files between object storage locations';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
@ -74,17 +76,52 @@ class BackupUpdate extends Command
|
||||
{
|
||||
set_time_limit(0);
|
||||
|
||||
Backup::whereHas('activity')->whereRaw('html_backup IS NOT NULL')->cursor()->each(function ($backup) {
|
||||
if (strlen($backup->html_backup) > 1 && $backup->activity->invoice->exists()) {
|
||||
$client = $backup->activity->invoice->client;
|
||||
$backup->storeRemotely($backup->html_backup, $client);
|
||||
} elseif (strlen($backup->html_backup) > 1 && $backup->activity->quote->exists()) {
|
||||
$client = $backup->activity->quote->client;
|
||||
$backup->storeRemotely($backup->html_backup, $client);
|
||||
} elseif (strlen($backup->html_backup) > 1 && $backup->activity->credit->exists()) {
|
||||
$client = $backup->activity->credit->client;
|
||||
$backup->storeRemotely($backup->html_backup, $client);
|
||||
}
|
||||
});
|
||||
//logos
|
||||
Company::cursor()
|
||||
->each(function ($company){
|
||||
|
||||
$company_logo = $company->present()->logo();
|
||||
|
||||
if($company_logo == 'https://invoicing.co/images/new_logo.png')
|
||||
return;
|
||||
|
||||
$logo = @file_get_contents($company_logo);
|
||||
|
||||
if($logo){
|
||||
|
||||
$path = str_replace("https://objects.invoicing.co/", "", $company->present()->logo());
|
||||
$path = str_replace("https://v5-at-backup.us-southeast-1.linodeobjects.com/", "", $path);
|
||||
|
||||
Storage::disk($this->option('disk'))->put($path, $logo);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
//documents
|
||||
Document::cursor()
|
||||
->each(function ($document){
|
||||
|
||||
$doc_bin = $document->getFile();
|
||||
|
||||
if($doc_bin)
|
||||
Storage::disk($this->option('disk'))->put($document->url, $doc_bin);
|
||||
|
||||
});
|
||||
|
||||
|
||||
//backups
|
||||
Backup::cursor()
|
||||
->each(function ($backup){
|
||||
|
||||
$backup_bin = Storage::disk('s3')->get($backup->filename);
|
||||
|
||||
if($backup_bin)
|
||||
Storage::disk($this->option('disk'))->put($backup->filename, $backup_bin);
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -703,13 +703,32 @@ class CheckData extends Command
|
||||
->count();
|
||||
|
||||
if($count == 0){
|
||||
$this->logMessage("# {$client->id} # {$client->name} {$client->balance} is invalid should be 0");
|
||||
|
||||
//factor in over payments to the client balance
|
||||
$over_payment = Payment::where('client_id', $client->id)
|
||||
->where('is_deleted', 0)
|
||||
->whereIn('status_id', [1,4])
|
||||
->selectRaw('sum(amount - applied) as p')
|
||||
->pluck('p')
|
||||
->first();
|
||||
|
||||
if($this->option('client_balance')){
|
||||
$over_payment = $over_payment*-1;
|
||||
|
||||
if(floatval($over_payment) == floatval($client->balance)){
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
$this->logMessage("# {$client->id} # {$client->name} {$client->balance} is invalid should be {$over_payment}");
|
||||
|
||||
}
|
||||
|
||||
|
||||
if($this->option('client_balance') && (floatval($over_payment) != floatval($client->balance) )){
|
||||
|
||||
$this->logMessage("# {$client->id} " . $client->present()->name().' - '.$client->number." Fixing {$client->balance} to 0");
|
||||
|
||||
$client->balance = 0;
|
||||
$client->balance = $over_payment;
|
||||
$client->save();
|
||||
|
||||
}
|
||||
@ -1029,6 +1048,29 @@ class CheckData extends Command
|
||||
|
||||
$this->logMessage("Fixing - {$ninja_portal_url}");
|
||||
}
|
||||
else{
|
||||
|
||||
$c = Client::on('db-ninja-01')->where("company_id", config('ninja.ninja_default_company_id'))->where('custom_value2', $cu->account->key)->first();
|
||||
|
||||
if($c)
|
||||
{
|
||||
|
||||
$cc = $c->contacts()->first();
|
||||
|
||||
if($cc)
|
||||
{
|
||||
$ninja_portal_url = "https://invoiceninja.invoicing.co/client/ninja/{$cc->contact_key}/{$cu->account->key}";
|
||||
|
||||
$cu->ninja_portal_url = $ninja_portal_url;
|
||||
$cu->save();
|
||||
|
||||
$this->logMessage("Fixing - {$ninja_portal_url}");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
@ -25,6 +25,9 @@ use App\Helpers\Invoice\InvoiceSum;
|
||||
use App\Jobs\Company\CreateCompanyTaskStatuses;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Account;
|
||||
use App\Models\BankIntegration;
|
||||
use App\Models\BankTransaction;
|
||||
use App\Models\BankTransactionRule;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Company;
|
||||
@ -47,6 +50,7 @@ use App\Utils\Ninja;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Carbon\Carbon;
|
||||
use Database\Factories\BankTransactionRuleFactory;
|
||||
use Faker\Factory;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
@ -87,7 +91,7 @@ class CreateSingleAccount extends Command
|
||||
MultiDB::setDb($this->option('database'));
|
||||
|
||||
$this->info(date('r').' Create Single Sample Account...');
|
||||
$this->count = 1;
|
||||
$this->count = 5;
|
||||
$this->gateway = $this->argument('gateway');
|
||||
|
||||
$this->info('Warming up cache');
|
||||
@ -179,6 +183,23 @@ class CreateSingleAccount extends Command
|
||||
'rate' => 5
|
||||
]);
|
||||
|
||||
$bi = BankIntegration::factory()->create([
|
||||
'account_id' => $account->id,
|
||||
'company_id' => $company->id,
|
||||
'user_id' => $user->id,
|
||||
]);
|
||||
|
||||
BankTransaction::factory()->count(50)->create([
|
||||
'bank_integration_id' => $bi->id,
|
||||
'user_id' => $user->id,
|
||||
'company_id' => $company->id,
|
||||
]);
|
||||
|
||||
$btr = BankTransactionRule::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'company_id' => $company->id,
|
||||
'applies_to' => (bool)rand(0,1) ? 'CREDIT' : 'DEBIT',
|
||||
]);
|
||||
|
||||
$this->info('Creating '.$this->count.' clients');
|
||||
|
||||
@ -358,7 +379,7 @@ class CreateSingleAccount extends Command
|
||||
|
||||
private function createExpense($client)
|
||||
{
|
||||
Expense::factory()->count(rand(1, 2))->create([
|
||||
Expense::factory()->count(rand(1, 20))->create([
|
||||
'user_id' => $client->user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $client->company->id,
|
||||
@ -590,7 +611,6 @@ class CreateSingleAccount extends Command
|
||||
$cached_tables = config('ninja.cached_tables');
|
||||
|
||||
foreach ($cached_tables as $name => $class) {
|
||||
if (! Cache::has($name)) {
|
||||
// check that the table exists in case the migration is pending
|
||||
if (! Schema::hasTable((new $class())->getTable())) {
|
||||
continue;
|
||||
@ -608,7 +628,6 @@ class CreateSingleAccount extends Command
|
||||
if ($tableData->count()) {
|
||||
Cache::forever($name, $tableData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -437,7 +437,7 @@ class CreateTestData extends Command
|
||||
'company_id' => $client->company->id,
|
||||
]);
|
||||
|
||||
Document::factory()->count(50)->create([
|
||||
Document::factory()->count(5)->create([
|
||||
'user_id' => $client->user->id,
|
||||
'company_id' => $client->company_id,
|
||||
'documentable_type' => Vendor::class,
|
||||
|
@ -22,6 +22,8 @@ use App\Jobs\Company\CreateCompanyTaskStatuses;
|
||||
use App\Jobs\Ninja\CompanySizeCheck;
|
||||
use App\Jobs\Util\VersionCheck;
|
||||
use App\Models\Account;
|
||||
use App\Models\BankIntegration;
|
||||
use App\Models\BankTransaction;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Company;
|
||||
@ -39,6 +41,7 @@ use App\Models\Vendor;
|
||||
use App\Models\VendorContact;
|
||||
use App\Repositories\InvoiceRepository;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\AppSetup;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Carbon\Carbon;
|
||||
@ -51,7 +54,7 @@ use Illuminate\Support\Str;
|
||||
|
||||
class DemoMode extends Command
|
||||
{
|
||||
use MakesHash, GeneratesCounter;
|
||||
use MakesHash, GeneratesCounter, AppSetup;
|
||||
|
||||
protected $signature = 'ninja:demo-mode';
|
||||
|
||||
@ -81,34 +84,14 @@ class DemoMode extends Command
|
||||
|
||||
$cached_tables = config('ninja.cached_tables');
|
||||
|
||||
foreach ($cached_tables as $name => $class) {
|
||||
if (! Cache::has($name)) {
|
||||
// check that the table exists in case the migration is pending
|
||||
if (! Schema::hasTable((new $class())->getTable())) {
|
||||
continue;
|
||||
}
|
||||
if ($name == 'payment_terms') {
|
||||
$orderBy = 'num_days';
|
||||
} elseif ($name == 'fonts') {
|
||||
$orderBy = 'sort_order';
|
||||
} elseif (in_array($name, ['currencies', 'industries', 'languages', 'countries', 'banks'])) {
|
||||
$orderBy = 'name';
|
||||
} else {
|
||||
$orderBy = 'id';
|
||||
}
|
||||
$tableData = $class::orderBy($orderBy)->get();
|
||||
if ($tableData->count()) {
|
||||
Cache::forever($name, $tableData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->info('Migrating');
|
||||
Artisan::call('migrate:fresh --force');
|
||||
|
||||
$this->info('Seeding');
|
||||
Artisan::call('db:seed --force');
|
||||
|
||||
$this->buildCache(true);
|
||||
|
||||
$this->info('Seeding Random Data');
|
||||
$this->createSmallAccount();
|
||||
|
||||
@ -223,6 +206,18 @@ class DemoMode extends Command
|
||||
'company_id' => $company->id,
|
||||
]);
|
||||
|
||||
$bi = BankIntegration::factory()->create([
|
||||
'account_id' => $account->id,
|
||||
'company_id' => $company->id,
|
||||
'user_id' => $user->id,
|
||||
]);
|
||||
|
||||
BankTransaction::factory()->count(50)->create([
|
||||
'bank_integration_id' => $bi->id,
|
||||
'user_id' => $user->id,
|
||||
'company_id' => $company->id,
|
||||
]);
|
||||
|
||||
$this->info('Creating '.$this->count.' clients');
|
||||
|
||||
for ($x = 0; $x < $this->count; $x++) {
|
||||
|
@ -103,8 +103,9 @@ class MobileLocalization extends Command
|
||||
$data = substr($data, $start, $end - $start - 5);
|
||||
|
||||
$data = str_replace("\n", '', $data);
|
||||
$data = str_replace('"', "\'", $data);
|
||||
$data = str_replace("\'", "\#", $data);
|
||||
$data = str_replace("'", '"', $data);
|
||||
$data = str_replace("\#", "'", $data);
|
||||
|
||||
return json_decode('{'.rtrim($data, ',').'}');
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ class S3Cleanup extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (! Ninja::isHosted()) {
|
||||
if (!Ninja::isHosted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ use App\Utils\Traits\MakesReminders;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\App;
|
||||
|
||||
//@deprecated 27-11-2022 - only ever should be used for testing
|
||||
class SendRemindersCron extends Command
|
||||
{
|
||||
use MakesReminders, MakesDates;
|
||||
@ -175,7 +176,7 @@ class SendRemindersCron extends Command
|
||||
/**Refresh Invoice values*/
|
||||
$invoice->calc()->getInvoice()->save();
|
||||
$invoice->fresh();
|
||||
$invoice->service()->deletePdf();
|
||||
$invoice->service()->deletePdf()->save();
|
||||
|
||||
/* Refresh the client here to ensure the balance is fresh */
|
||||
$client = $invoice->client;
|
||||
|
@ -89,14 +89,14 @@ class TranslationsExport extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
Storage::makeDirectory(storage_path('lang'));
|
||||
Storage::disk('local')->makeDirectory('lang');
|
||||
|
||||
foreach ($this->langs as $lang) {
|
||||
Storage::makeDirectory(storage_path("lang/{$lang}"));
|
||||
Storage::disk('local')->makeDirectory("lang/{$lang}");
|
||||
|
||||
$translations = Lang::getLoader()->load($lang, 'texts');
|
||||
|
||||
Storage::put(storage_path("lang/{$lang}/{$lang}.json"), json_encode(Arr::dot($translations), JSON_UNESCAPED_UNICODE));
|
||||
Storage::disk('local')->put("lang/{$lang}/{$lang}.json", json_encode(Arr::dot($translations), JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,10 +17,12 @@ use App\Jobs\Cron\RecurringInvoicesCron;
|
||||
use App\Jobs\Cron\SubscriptionCron;
|
||||
use App\Jobs\Ledger\LedgerBalanceUpdate;
|
||||
use App\Jobs\Ninja\AdjustEmailQuota;
|
||||
use App\Jobs\Ninja\BankTransactionSync;
|
||||
use App\Jobs\Ninja\CompanySizeCheck;
|
||||
use App\Jobs\Ninja\QueueSize;
|
||||
use App\Jobs\Ninja\SystemMaintenance;
|
||||
use App\Jobs\Ninja\TaskScheduler;
|
||||
use App\Jobs\Quote\QuoteCheckExpired;
|
||||
use App\Jobs\Util\DiskCleanup;
|
||||
use App\Jobs\Util\ReminderJob;
|
||||
use App\Jobs\Util\SchedulerCheck;
|
||||
@ -42,55 +44,81 @@ class Kernel extends ConsoleKernel
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
/* Check for the latest version of Invoice Ninja */
|
||||
$schedule->job(new VersionCheck)->daily();
|
||||
|
||||
$schedule->job(new DiskCleanup)->daily()->withoutOverlapping();
|
||||
/* Checks and cleans redundant files */
|
||||
$schedule->job(new DiskCleanup)->dailyAt('02:10')->withoutOverlapping()->name('disk-cleanup-job')->onOneServer();
|
||||
|
||||
$schedule->job(new ReminderJob)->hourly()->withoutOverlapping();
|
||||
/* Send reminders */
|
||||
$schedule->job(new ReminderJob)->hourly()->withoutOverlapping()->name('reminder-job')->onOneServer();
|
||||
|
||||
$schedule->job(new QueueSize)->everyFiveMinutes()->withoutOverlapping();
|
||||
/* Returns the number of jobs in the queue */
|
||||
$schedule->job(new QueueSize)->everyFiveMinutes()->withoutOverlapping()->name('queue-size-job')->onOneServer();
|
||||
|
||||
$schedule->job(new CompanySizeCheck)->daily()->withoutOverlapping();
|
||||
/* Checks for large companies and marked them as is_large */
|
||||
$schedule->job(new CompanySizeCheck)->dailyAt('23:20')->withoutOverlapping()->name('company-size-job')->onOneServer();
|
||||
|
||||
$schedule->job(new UpdateExchangeRates)->daily()->withoutOverlapping();
|
||||
/* Pulls in the latest exchange rates */
|
||||
$schedule->job(new UpdateExchangeRates)->dailyAt('23:30')->withoutOverlapping()->name('exchange-rate-job')->onOneServer();
|
||||
|
||||
$schedule->job(new SubscriptionCron)->daily()->withoutOverlapping();
|
||||
/* Runs cleanup code for subscriptions */
|
||||
$schedule->job(new SubscriptionCron)->dailyAt('00:01')->withoutOverlapping()->name('subscription-job')->onOneServer();
|
||||
|
||||
$schedule->job(new RecurringInvoicesCron)->hourly()->withoutOverlapping();
|
||||
/* Sends recurring invoices*/
|
||||
$schedule->job(new RecurringInvoicesCron)->hourly()->withoutOverlapping()->name('recurring-invoice-job')->onOneServer();
|
||||
|
||||
$schedule->job(new RecurringExpensesCron)->dailyAt('00:10')->withoutOverlapping();
|
||||
/* Sends recurring invoices*/
|
||||
$schedule->job(new RecurringExpensesCron)->dailyAt('00:10')->withoutOverlapping()->name('recurring-expense-job')->onOneServer();
|
||||
|
||||
$schedule->job(new AutoBillCron)->dailyAt('06:00')->withoutOverlapping();
|
||||
/* Fires notifications for expired Quotes */
|
||||
$schedule->job(new QuoteCheckExpired)->dailyAt('05:10')->withoutOverlapping()->name('quote-expired-job')->onOneServer();
|
||||
|
||||
$schedule->job(new SchedulerCheck)->daily()->withoutOverlapping();
|
||||
/* Performs auto billing */
|
||||
$schedule->job(new AutoBillCron)->dailyAt('06:20')->withoutOverlapping()->name('auto-bill-job')->onOneServer();
|
||||
|
||||
$schedule->job(new TaskScheduler())->daily()->withoutOverlapping();
|
||||
/* Checks the status of the scheduler */
|
||||
$schedule->job(new SchedulerCheck)->dailyAt('01:10')->withoutOverlapping();
|
||||
|
||||
$schedule->job(new SystemMaintenance)->weekly()->withoutOverlapping();
|
||||
/* Checks for scheduled tasks */
|
||||
$schedule->job(new TaskScheduler())->dailyAt('06:50')->withoutOverlapping()->name('task-scheduler-job')->onOneServer();
|
||||
|
||||
/* Performs system maintenance such as pruning the backup table */
|
||||
$schedule->job(new SystemMaintenance)->sundays()->at('02:30')->withoutOverlapping()->name('system-maintenance-job')->onOneServer();
|
||||
|
||||
/* Pulls in bank transactions from third party services */
|
||||
$schedule->job(new BankTransactionSync)->dailyAt('04:10')->withoutOverlapping()->name('bank-trans-sync-job')->onOneServer();
|
||||
|
||||
if (Ninja::isSelfHost()) {
|
||||
|
||||
$schedule->call(function () {
|
||||
Account::whereNotNull('id')->update(['is_scheduler_running' => true]);
|
||||
})->everyFiveMinutes();
|
||||
|
||||
}
|
||||
|
||||
/* Run hosted specific jobs */
|
||||
if (Ninja::isHosted()) {
|
||||
|
||||
$schedule->job(new AdjustEmailQuota)->dailyAt('23:30')->withoutOverlapping();
|
||||
|
||||
$schedule->job(new SendFailedEmails)->daily()->withoutOverlapping();
|
||||
//not used @deprecate
|
||||
// $schedule->job(new SendFailedEmails)->daily()->withoutOverlapping();
|
||||
|
||||
$schedule->command('ninja:check-data --database=db-ninja-01')->daily('02:00')->withoutOverlapping();
|
||||
$schedule->command('ninja:check-data --database=db-ninja-01')->dailyAt('02:10')->withoutOverlapping()->name('check-data-db-1-job')->onOneServer();
|
||||
|
||||
$schedule->command('ninja:check-data --database=db-ninja-02')->dailyAt('02:05')->withoutOverlapping();
|
||||
$schedule->command('ninja:check-data --database=db-ninja-02')->dailyAt('02:20')->withoutOverlapping()->name('check-data-db-2-job')->onOneServer();
|
||||
|
||||
$schedule->command('ninja:s3-cleanup')->dailyAt('23:15')->withoutOverlapping()->name('s3-cleanup-job')->onOneServer();
|
||||
|
||||
$schedule->command('ninja:s3-cleanup')->dailyAt('23:15')->withoutOverlapping();
|
||||
}
|
||||
|
||||
if (config('queue.default') == 'database' && Ninja::isSelfHost() && config('ninja.internal_queue_enabled') && ! config('ninja.is_docker')) {
|
||||
|
||||
$schedule->command('queue:work database --stop-when-empty --memory=256')->everyMinute()->withoutOverlapping();
|
||||
|
||||
$schedule->command('queue:restart')->everyFiveMinutes()->withoutOverlapping();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
80
app/DataMapper/Analytics/AccountSignup.php
Normal file
80
app/DataMapper/Analytics/AccountSignup.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\DataMapper\Analytics;
|
||||
|
||||
use Turbo124\Beacon\ExampleMetric\GenericMixedMetric;
|
||||
|
||||
class AccountSignup extends GenericMixedMetric
|
||||
{
|
||||
/**
|
||||
* The type of Sample.
|
||||
*
|
||||
* Monotonically incrementing counter
|
||||
*
|
||||
* - counter
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'mixed_metric';
|
||||
|
||||
/**
|
||||
* The name of the counter.
|
||||
* @var string
|
||||
*/
|
||||
public $name = 'account.signup';
|
||||
|
||||
/**
|
||||
* The datetime of the counter measurement.
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
/**
|
||||
* The Class failure name
|
||||
* set to 0.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $string_metric5 = 'plan';
|
||||
|
||||
/**
|
||||
* The exception string
|
||||
* set to 0.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $string_metric6 = 'term';
|
||||
|
||||
/**
|
||||
* The counter
|
||||
* set to 1.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $int_metric1 = 1;
|
||||
|
||||
/**
|
||||
* Company Key
|
||||
* @var string
|
||||
*/
|
||||
public $string_metric7 = 'key';
|
||||
|
||||
public function __construct($string_metric5, $string_metric6, $string_metric7)
|
||||
{
|
||||
$this->string_metric5 = $string_metric5 ?: 'free';
|
||||
$this->string_metric6 = $string_metric6 ?: 'year';
|
||||
$this->string_metric7 = $string_metric7;
|
||||
}
|
||||
}
|
50
app/DataMapper/Analytics/BankAccountsCreated.php
Normal file
50
app/DataMapper/Analytics/BankAccountsCreated.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\DataMapper\Analytics;
|
||||
|
||||
use Turbo124\Beacon\ExampleMetric\GenericMixedMetric;
|
||||
|
||||
class BankAccountsCreated extends GenericMixedMetric
|
||||
{
|
||||
/**
|
||||
* The type of Sample.
|
||||
*
|
||||
* Monotonically incrementing counter
|
||||
*
|
||||
* - counter
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'mixed_metric';
|
||||
|
||||
/**
|
||||
* The name of the counter.
|
||||
* @var string
|
||||
*/
|
||||
public $name = 'bank_accounts.created';
|
||||
|
||||
/**
|
||||
* The datetime of the counter measurement.
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
public $int_metric1 = 0;
|
||||
|
||||
public function __construct($int_metric1)
|
||||
{
|
||||
$this->int_metric1 = $int_metric1;
|
||||
}
|
||||
}
|
@ -44,6 +44,8 @@ class InvoiceItem
|
||||
public $line_total = 0;
|
||||
|
||||
public $gross_line_total = 0;
|
||||
|
||||
public $tax_amount = 0;
|
||||
|
||||
public $date = '';
|
||||
|
||||
@ -75,6 +77,7 @@ class InvoiceItem
|
||||
'sort_id' => 'string',
|
||||
'line_total' => 'float',
|
||||
'gross_line_total' => 'float',
|
||||
'tax_amount' => 'float',
|
||||
'date' => 'string',
|
||||
'custom_value1' => 'string',
|
||||
'custom_value2' => 'string',
|
||||
|
@ -21,6 +21,7 @@ use Illuminate\Auth\Access\AuthorizationException;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException;
|
||||
use Illuminate\Database\Eloquent\RelationNotFoundException;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Illuminate\Http\Exceptions\ThrottleRequestsException;
|
||||
use Illuminate\Http\Request;
|
||||
@ -31,6 +32,7 @@ use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use PDOException;
|
||||
use Sentry\Laravel\Integration;
|
||||
use Sentry\State\Scope;
|
||||
use Swift_TransportException;
|
||||
use Symfony\Component\Console\Exception\CommandNotFoundException;
|
||||
@ -83,7 +85,7 @@ class Handler extends ExceptionHandler
|
||||
}
|
||||
|
||||
if (Ninja::isHosted() && ! ($exception instanceof ValidationException)) {
|
||||
app('sentry')->configureScope(function (Scope $scope): void {
|
||||
Integration::configureScope(function (Scope $scope): void {
|
||||
$name = 'hosted@invoiceninja.com';
|
||||
|
||||
if (auth()->guard('contact') && auth()->guard('contact')->user()) {
|
||||
@ -103,9 +105,9 @@ class Handler extends ExceptionHandler
|
||||
]);
|
||||
});
|
||||
|
||||
app('sentry')->captureException($exception);
|
||||
Integration::captureUnhandledException($exception);
|
||||
} elseif (app()->bound('sentry') && $this->shouldReport($exception)) {
|
||||
app('sentry')->configureScope(function (Scope $scope): void {
|
||||
Integration::configureScope(function (Scope $scope): void {
|
||||
if (auth()->guard('contact') && auth()->guard('contact')->user() && auth()->guard('contact')->user()->company->account->report_errors) {
|
||||
$scope->setUser([
|
||||
'id' => auth()->guard('contact')->user()->company->account->key,
|
||||
@ -122,7 +124,7 @@ class Handler extends ExceptionHandler
|
||||
});
|
||||
|
||||
if ($this->validException($exception)) {
|
||||
app('sentry')->captureException($exception);
|
||||
Integration::captureUnhandledException($exception);
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,7 +183,7 @@ class Handler extends ExceptionHandler
|
||||
} elseif ($exception instanceof FatalThrowableError && $request->expectsJson()) {
|
||||
return response()->json(['message'=>'Fatal error'], 500);
|
||||
} elseif ($exception instanceof AuthorizationException) {
|
||||
return response()->json(['message'=>'You are not authorized to view or perform this action'], 401);
|
||||
return response()->json(['message'=> $exception->getMessage()], 401);
|
||||
} elseif ($exception instanceof TokenMismatchException) {
|
||||
return redirect()
|
||||
->back()
|
||||
@ -197,14 +199,21 @@ class Handler extends ExceptionHandler
|
||||
// nlog($exception->validator->getMessageBag());
|
||||
return response()->json(['message' => 'The given data was invalid.', 'errors' => $exception->validator->getMessageBag()], 422);
|
||||
} elseif ($exception instanceof RelationNotFoundException && $request->expectsJson()) {
|
||||
return response()->json(['message' => $exception->getMessage()], 400);
|
||||
return response()->json(['message' => "Relation `{$exception->relation}` is not a valid include."], 400);
|
||||
} elseif ($exception instanceof GenericPaymentDriverFailure && $request->expectsJson()) {
|
||||
return response()->json(['message' => $exception->getMessage()], 400);
|
||||
} elseif ($exception instanceof GenericPaymentDriverFailure) {
|
||||
return response()->json(['message' => $exception->getMessage()], 400);
|
||||
} elseif ($exception instanceof StripeConnectFailure) {
|
||||
return response()->json(['message' => $exception->getMessage()], 400);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// elseif ($exception instanceof QueryException) {
|
||||
// return response()->json(['message' => 'We had a problem executing this query. Please retry.'], 500);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
return parent::render($request, $exception);
|
||||
}
|
||||
|
41
app/Exceptions/YodleeApiException.php
Normal file
41
app/Exceptions/YodleeApiException.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
class YodleeApiException extends Exception
|
||||
{
|
||||
/**
|
||||
* Report the exception.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function report()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the exception into an HTTP response.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function render($request)
|
||||
{
|
||||
|
||||
// $msg = 'Unable to refund the transaction';
|
||||
$msg = ctrans('texts.error');
|
||||
|
||||
if ($this->getMessage() && strlen($this->getMessage()) >= 1) {
|
||||
$msg = $this->getMessage();
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'message' => $msg,
|
||||
], 400);
|
||||
}
|
||||
}
|
@ -76,6 +76,7 @@ class ClientExport extends BaseExport
|
||||
'contact_custom_value3' => 'contact.custom_value3',
|
||||
'contact_custom_value4' => 'contact.custom_value4',
|
||||
'email' => 'contact.email',
|
||||
'status' => 'status'
|
||||
];
|
||||
|
||||
private array $decorate_keys = [
|
||||
@ -173,6 +174,19 @@ class ClientExport extends BaseExport
|
||||
$entity['industry_id'] = $client->industry ? ctrans("texts.industry_{$client->industry->name}") : '';
|
||||
}
|
||||
|
||||
$entity['status'] = $this->calculateStatus($client);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
private function calculateStatus($client)
|
||||
{
|
||||
if($client->is_deleted)
|
||||
return ctrans('texts.deleted');
|
||||
|
||||
if($client->deleted_at)
|
||||
return ctrans('texts.arcvived');
|
||||
|
||||
return ctrans('texts.active');
|
||||
}
|
||||
}
|
||||
|
@ -88,6 +88,7 @@ class InvoiceItemExport extends BaseExport
|
||||
private array $decorate_keys = [
|
||||
'client',
|
||||
'currency_id',
|
||||
'status'
|
||||
];
|
||||
|
||||
public function __construct(Company $company, array $input)
|
||||
@ -116,6 +117,7 @@ class InvoiceItemExport extends BaseExport
|
||||
$this->csv->insertOne($this->buildHeader());
|
||||
|
||||
$query = Invoice::query()
|
||||
->withTrashed()
|
||||
->with('client')->where('company_id', $this->company->id)
|
||||
->where('is_deleted',0);
|
||||
|
||||
@ -206,10 +208,10 @@ class InvoiceItemExport extends BaseExport
|
||||
if(in_array('currency_id', $this->input['report_keys']))
|
||||
$entity['currency'] = $invoice->client->currency() ? $invoice->client->currency()->code : $invoice->company->currency()->code;
|
||||
|
||||
if(in_array('client_id', $this->input['report_keys']))
|
||||
// if(in_array('client_id', $this->input['report_keys']))
|
||||
$entity['client'] = $invoice->client->present()->name();
|
||||
|
||||
if(in_array('status_id', $this->input['report_keys']))
|
||||
// if(in_array('status_id', $this->input['report_keys']))
|
||||
$entity['status'] = $invoice->stringStatus($invoice->status_id);
|
||||
|
||||
return $entity;
|
||||
|
@ -89,7 +89,10 @@ class PaymentExport extends BaseExport
|
||||
//insert the header
|
||||
$this->csv->insertOne($this->buildHeader());
|
||||
|
||||
$query = Payment::query()->where('company_id', $this->company->id)->where('is_deleted', 0);
|
||||
$query = Payment::query()
|
||||
->withTrashed()
|
||||
->where('company_id', $this->company->id)
|
||||
->where('is_deleted', 0);
|
||||
|
||||
$query = $this->addDateRange($query);
|
||||
|
||||
|
@ -82,7 +82,10 @@ class ProductExport extends BaseExport
|
||||
//insert the header
|
||||
$this->csv->insertOne($this->buildHeader());
|
||||
|
||||
$query = Product::query()->where('company_id', $this->company->id)->where('is_deleted', 0);
|
||||
$query = Product::query()
|
||||
->withTrashed()
|
||||
->where('company_id', $this->company->id)
|
||||
->where('is_deleted', 0);
|
||||
|
||||
$query = $this->addDateRange($query);
|
||||
|
||||
|
@ -99,6 +99,7 @@ class QuoteExport extends BaseExport
|
||||
$this->csv->insertOne($this->buildHeader());
|
||||
|
||||
$query = Quote::query()
|
||||
->withTrashed()
|
||||
->with('client')
|
||||
->where('company_id', $this->company->id)
|
||||
->where('is_deleted', 0);
|
||||
|
@ -116,6 +116,7 @@ class QuoteItemExport extends BaseExport
|
||||
$this->csv->insertOne($this->buildHeader());
|
||||
|
||||
$query = Quote::query()
|
||||
->withTrashed()
|
||||
->with('client')->where('company_id', $this->company->id)
|
||||
->where('is_deleted', 0);
|
||||
|
||||
|
@ -54,6 +54,7 @@ class RecurringInvoiceExport extends BaseExport
|
||||
'po_number' => 'po_number',
|
||||
'private_notes' => 'private_notes',
|
||||
'public_notes' => 'public_notes',
|
||||
'next_send_date' => 'next_send_date',
|
||||
'status' => 'status_id',
|
||||
'tax_name1' => 'tax_name1',
|
||||
'tax_name2' => 'tax_name2',
|
||||
@ -66,6 +67,7 @@ class RecurringInvoiceExport extends BaseExport
|
||||
'currency' => 'currency_id',
|
||||
'vendor' => 'vendor_id',
|
||||
'project' => 'project_id',
|
||||
'frequency' => 'frequency_id'
|
||||
];
|
||||
|
||||
private array $decorate_keys = [
|
||||
@ -162,6 +164,8 @@ class RecurringInvoiceExport extends BaseExport
|
||||
$entity['vendor'] = $invoice->vendor ? $invoice->vendor->name : '';
|
||||
}
|
||||
|
||||
$entity['frequency'] = $invoice->frequencyForKey($invoice->frequency_id);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,10 @@ class TaskExport extends BaseExport
|
||||
//insert the header
|
||||
$this->csv->insertOne($this->buildHeader());
|
||||
|
||||
$query = Task::query()->where('company_id', $this->company->id)->where('is_deleted', 0);
|
||||
$query = Task::query()
|
||||
->withTrashed()
|
||||
->where('company_id', $this->company->id)
|
||||
->where('is_deleted', 0);
|
||||
|
||||
$query = $this->addDateRange($query);
|
||||
|
||||
|
37
app/Factory/BankIntegrationFactory.php
Normal file
37
app/Factory/BankIntegrationFactory.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Factory;
|
||||
|
||||
use App\Models\BankIntegration;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class BankIntegrationFactory
|
||||
{
|
||||
public static function create(int $company_id, int $user_id, int $account_id) :BankIntegration
|
||||
{
|
||||
$bank_integration = new BankIntegration;
|
||||
$bank_integration->account_id = $account_id;
|
||||
$bank_integration->user_id = $user_id;
|
||||
$bank_integration->company_id = $company_id;
|
||||
|
||||
$bank_integration->provider_name = '';
|
||||
$bank_integration->bank_account_id = '';
|
||||
$bank_integration->bank_account_name = '';
|
||||
$bank_integration->bank_account_number = '';
|
||||
$bank_integration->bank_account_status = '';
|
||||
$bank_integration->bank_account_type = '';
|
||||
$bank_integration->balance = 0;
|
||||
$bank_integration->currency = '';
|
||||
|
||||
return $bank_integration;
|
||||
}
|
||||
}
|
35
app/Factory/BankTransactionFactory.php
Normal file
35
app/Factory/BankTransactionFactory.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Factory;
|
||||
|
||||
use App\Models\BankTransaction;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class BankTransactionFactory
|
||||
{
|
||||
public static function create(int $company_id, int $user_id) :BankTransaction
|
||||
{
|
||||
$bank_transaction = new BankTransaction;
|
||||
$bank_transaction->user_id = $user_id;
|
||||
$bank_transaction->company_id = $company_id;
|
||||
|
||||
$bank_transaction->amount = 0;
|
||||
$bank_transaction->currency_id = 1;
|
||||
$bank_transaction->account_type = '';
|
||||
$bank_transaction->category_type = '';
|
||||
$bank_transaction->date = now()->format('Y-m-d');
|
||||
$bank_transaction->description = '';
|
||||
$bank_transaction->status_id = 1;
|
||||
|
||||
return $bank_transaction;
|
||||
}
|
||||
}
|
30
app/Factory/BankTransactionRuleFactory.php
Normal file
30
app/Factory/BankTransactionRuleFactory.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Factory;
|
||||
|
||||
use App\Models\BankTransactionRule;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class BankTransactionRuleFactory
|
||||
{
|
||||
public static function create(int $company_id, int $user_id) :BankTransactionRule
|
||||
{
|
||||
$bank_transaction_rule = new BankTransactionRule;
|
||||
$bank_transaction_rule->user_id = $user_id;
|
||||
$bank_transaction_rule->company_id = $company_id;
|
||||
|
||||
$bank_transaction_rule->name = '';
|
||||
$bank_transaction_rule->rules = [];
|
||||
|
||||
return $bank_transaction_rule;
|
||||
}
|
||||
}
|
@ -29,6 +29,7 @@ class RecurringInvoiceFactory
|
||||
$invoice->private_notes = '';
|
||||
$invoice->date = null;
|
||||
$invoice->due_date = null;
|
||||
$invoice->due_date_days = 'terms';
|
||||
$invoice->partial_due_date = null;
|
||||
$invoice->is_deleted = false;
|
||||
$invoice->line_items = json_encode([]);
|
||||
|
@ -25,9 +25,9 @@ class RecurringInvoiceToInvoiceFactory
|
||||
$invoice->discount = $recurring_invoice->discount;
|
||||
$invoice->is_amount_discount = $recurring_invoice->is_amount_discount;
|
||||
$invoice->po_number = $recurring_invoice->po_number;
|
||||
$invoice->footer = self::tranformObject($recurring_invoice->footer, $client);
|
||||
$invoice->terms = self::tranformObject($recurring_invoice->terms, $client);
|
||||
$invoice->public_notes = self::tranformObject($recurring_invoice->public_notes, $client);
|
||||
$invoice->footer = $recurring_invoice->footer ? self::tranformObject($recurring_invoice->footer, $client) : null;
|
||||
$invoice->terms = $recurring_invoice->terms ? self::tranformObject($recurring_invoice->terms, $client) : null;
|
||||
$invoice->public_notes = $recurring_invoice->public_notes ? self::tranformObject($recurring_invoice->public_notes, $client) : null;
|
||||
$invoice->private_notes = $recurring_invoice->private_notes;
|
||||
$invoice->is_deleted = $recurring_invoice->is_deleted;
|
||||
$invoice->line_items = self::transformItems($recurring_invoice, $client);
|
||||
|
133
app/Filters/BankIntegrationFilters.php
Normal file
133
app/Filters/BankIntegrationFilters.php
Normal file
@ -0,0 +1,133 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use App\Models\BankIntegration;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
/**
|
||||
* BankIntegrationFilters.
|
||||
*/
|
||||
class BankIntegrationFilters extends QueryFilters
|
||||
{
|
||||
/**
|
||||
* Filter by name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return Builder
|
||||
*/
|
||||
public function name(string $name = ''): Builder
|
||||
{
|
||||
if(strlen($name) >=1)
|
||||
return $this->builder->where('bank_account_name', 'like', '%'.$name.'%');
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
public function filter(string $filter = '') : Builder
|
||||
{
|
||||
if (strlen($filter) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
return $this->builder->where(function ($query) use ($filter) {
|
||||
$query->where('bank_integrations.bank_account_name', 'like', '%'.$filter.'%');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the list based on the status
|
||||
* archived, active, deleted.
|
||||
*
|
||||
* @param string filter
|
||||
* @return Builder
|
||||
*/
|
||||
public function status(string $filter = '') : Builder
|
||||
{
|
||||
if (strlen($filter) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
$table = 'bank_integrations';
|
||||
$filters = explode(',', $filter);
|
||||
|
||||
return $this->builder->where(function ($query) use ($filters, $table) {
|
||||
$query->whereNull($table.'.id');
|
||||
|
||||
if (in_array(parent::STATUS_ACTIVE, $filters)) {
|
||||
$query->orWhereNull($table.'.deleted_at');
|
||||
}
|
||||
|
||||
if (in_array(parent::STATUS_ARCHIVED, $filters)) {
|
||||
$query->orWhere(function ($query) use ($table) {
|
||||
$query->whereNotNull($table.'.deleted_at');
|
||||
|
||||
if (! in_array($table, ['users'])) {
|
||||
$query->where($table.'.is_deleted', '=', 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (in_array(parent::STATUS_DELETED, $filters)) {
|
||||
$query->orWhere($table.'.is_deleted', '=', 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort) : Builder
|
||||
{
|
||||
$sort_col = explode('|', $sort);
|
||||
|
||||
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base query.
|
||||
*
|
||||
* @param int company_id
|
||||
* @param User $user
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
public function baseQuery(int $company_id, User $user) : Builder
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the query by the users company ID.
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function entityFilter()
|
||||
{
|
||||
//return $this->builder->whereCompanyId(auth()->user()->company()->id);
|
||||
return $this->builder->company();
|
||||
}
|
||||
}
|
197
app/Filters/BankTransactionFilters.php
Normal file
197
app/Filters/BankTransactionFilters.php
Normal file
@ -0,0 +1,197 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use App\Models\BankTransaction;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
/**
|
||||
* BankTransactionFilters.
|
||||
*/
|
||||
class BankTransactionFilters extends QueryFilters
|
||||
{
|
||||
/**
|
||||
* Filter by name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return Builder
|
||||
*/
|
||||
public function name(string $name = ''): Builder
|
||||
{
|
||||
if(strlen($name) >=1)
|
||||
return $this->builder->where('bank_account_name', 'like', '%'.$name.'%');
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
public function filter(string $filter = '') : Builder
|
||||
{
|
||||
if (strlen($filter) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
return $this->builder->where(function ($query) use ($filter) {
|
||||
$query->where('bank_transactions.description', 'like', '%'.$filter.'%');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filter based on client status.
|
||||
*
|
||||
* Statuses we need to handle
|
||||
* - all
|
||||
* - unmatched
|
||||
* - matched
|
||||
* - converted
|
||||
* - deposits
|
||||
* - withdrawals
|
||||
*
|
||||
* @return Builder
|
||||
*/
|
||||
public function client_status(string $value = '') :Builder
|
||||
{
|
||||
if (strlen($value) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
$status_parameters = explode(',', $value);
|
||||
|
||||
if (in_array('all', $status_parameters)) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
if (in_array('unmatched', $status_parameters)) {
|
||||
$this->builder->where('status_id', BankTransaction::STATUS_UNMATCHED);
|
||||
}
|
||||
|
||||
if (in_array('matched', $status_parameters)) {
|
||||
$this->builder->where('status_id', BankTransaction::STATUS_MATCHED);
|
||||
}
|
||||
|
||||
if (in_array('converted', $status_parameters)) {
|
||||
$this->builder->where('status_id', BankTransaction::STATUS_CONVERTED);
|
||||
}
|
||||
|
||||
if (in_array('deposits', $status_parameters)) {
|
||||
$this->builder->where('base_type', 'CREDIT');
|
||||
}
|
||||
|
||||
if (in_array('withdrawals', $status_parameters)) {
|
||||
$this->builder->where('base_type', 'DEBIT');
|
||||
}
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the list based on the status
|
||||
* archived, active, deleted.
|
||||
*
|
||||
* @param string filter
|
||||
* @return Builder
|
||||
*/
|
||||
public function status(string $filter = '') : Builder
|
||||
{
|
||||
if (strlen($filter) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
$table = 'bank_transactions';
|
||||
$filters = explode(',', $filter);
|
||||
|
||||
return $this->builder->where(function ($query) use ($filters, $table) {
|
||||
$query->whereNull($table.'.id');
|
||||
|
||||
if (in_array(parent::STATUS_ACTIVE, $filters)) {
|
||||
$query->orWhereNull($table.'.deleted_at');
|
||||
}
|
||||
|
||||
if (in_array(parent::STATUS_ARCHIVED, $filters)) {
|
||||
$query->orWhere(function ($query) use ($table) {
|
||||
$query->whereNotNull($table.'.deleted_at');
|
||||
|
||||
if (! in_array($table, ['users'])) {
|
||||
$query->where($table.'.is_deleted', '=', 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (in_array(parent::STATUS_DELETED, $filters)) {
|
||||
$query->orWhere($table.'.is_deleted', '=', 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort) : Builder
|
||||
{
|
||||
$sort_col = explode('|', $sort);
|
||||
|
||||
if(!is_array($sort_col))
|
||||
return $this->builder;
|
||||
|
||||
if($sort_col[0] == 'deposit')
|
||||
return $this->builder->where('base_type', 'CREDIT')->orderBy('amount', $sort_col[1]);
|
||||
|
||||
if($sort_col[0] == 'withdrawal')
|
||||
return $this->builder->where('base_type', 'DEBIT')->orderBy('amount', $sort_col[1]);
|
||||
|
||||
if($sort_col[0] == 'status')
|
||||
$sort_col[0] = 'status_id';
|
||||
|
||||
if(in_array($sort_col[0],['invoices','expense']))
|
||||
return $this->builder;
|
||||
|
||||
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base query.
|
||||
*
|
||||
* @param int company_id
|
||||
* @param User $user
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
public function baseQuery(int $company_id, User $user) : Builder
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the query by the users company ID.
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function entityFilter()
|
||||
{
|
||||
//return $this->builder->whereCompanyId(auth()->user()->company()->id);
|
||||
return $this->builder->company();
|
||||
}
|
||||
}
|
133
app/Filters/BankTransactionRuleFilters.php
Normal file
133
app/Filters/BankTransactionRuleFilters.php
Normal file
@ -0,0 +1,133 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use App\Models\BankTransactionRule;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
/**
|
||||
* BankTransactionRuleilters.
|
||||
*/
|
||||
class BankTransactionRuleFilters extends QueryFilters
|
||||
{
|
||||
/**
|
||||
* Filter by name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return Builder
|
||||
*/
|
||||
public function name(string $name = ''): Builder
|
||||
{
|
||||
if(strlen($name) >=1)
|
||||
return $this->builder->where('name', 'like', '%'.$name.'%');
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
* @param string query filter
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
public function filter(string $filter = '') : Builder
|
||||
{
|
||||
if (strlen($filter) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
return $this->builder->where(function ($query) use ($filter) {
|
||||
$query->where('bank_transaction_rules.name', 'like', '%'.$filter.'%');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the list based on the status
|
||||
* archived, active, deleted.
|
||||
*
|
||||
* @param string filter
|
||||
* @return Builder
|
||||
*/
|
||||
public function status(string $filter = '') : Builder
|
||||
{
|
||||
if (strlen($filter) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
$table = 'bank_transaction_rules';
|
||||
$filters = explode(',', $filter);
|
||||
|
||||
return $this->builder->where(function ($query) use ($filters, $table) {
|
||||
$query->whereNull($table.'.id');
|
||||
|
||||
if (in_array(parent::STATUS_ACTIVE, $filters)) {
|
||||
$query->orWhereNull($table.'.deleted_at');
|
||||
}
|
||||
|
||||
if (in_array(parent::STATUS_ARCHIVED, $filters)) {
|
||||
$query->orWhere(function ($query) use ($table) {
|
||||
$query->whereNotNull($table.'.deleted_at');
|
||||
|
||||
if (! in_array($table, ['users'])) {
|
||||
$query->where($table.'.is_deleted', '=', 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (in_array(parent::STATUS_DELETED, $filters)) {
|
||||
$query->orWhere($table.'.is_deleted', '=', 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
* @param string sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort) : Builder
|
||||
{
|
||||
$sort_col = explode('|', $sort);
|
||||
|
||||
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base query.
|
||||
*
|
||||
* @param int company_id
|
||||
* @param User $user
|
||||
* @return Builder
|
||||
* @deprecated
|
||||
*/
|
||||
public function baseQuery(int $company_id, User $user) : Builder
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the query by the users company ID.
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function entityFilter()
|
||||
{
|
||||
//return $this->builder->whereCompanyId(auth()->user()->company()->id);
|
||||
return $this->builder->company();
|
||||
}
|
||||
}
|
@ -28,7 +28,7 @@ class ClientFilters extends QueryFilters
|
||||
* @param string $name
|
||||
* @return Builder
|
||||
*/
|
||||
public function name(string $name): Builder
|
||||
public function name(string $name = ''): Builder
|
||||
{
|
||||
if(strlen($name) >=1)
|
||||
return $this->builder->where('name', 'like', '%'.$name.'%');
|
||||
|
@ -136,6 +136,6 @@ class DesignFilters extends QueryFilters
|
||||
public function entityFilter()
|
||||
{
|
||||
//return $this->builder->whereCompanyId(auth()->user()->company()->id);
|
||||
return $this->builder->whereCompanyId(auth()->user()->company()->id)->orWhere('company_id', null);
|
||||
return $this->builder->where('company_id', auth()->user()->company()->id)->orWhere('company_id', null)->orderBy('id','asc');
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
@ -54,6 +55,15 @@ class DocumentFilters extends QueryFilters
|
||||
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
||||
}
|
||||
|
||||
|
||||
public function company_documents($value = 'false')
|
||||
{
|
||||
if($value == 'true')
|
||||
return $this->builder->where('documentable_type', Company::class);
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base query.
|
||||
*
|
||||
|
@ -44,6 +44,55 @@ class ExpenseFilters extends QueryFilters
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter based on client status.
|
||||
*
|
||||
* Statuses we need to handle
|
||||
* - all
|
||||
* - logged
|
||||
* - pending
|
||||
* - invoiced
|
||||
* - paid
|
||||
* - unpaid
|
||||
*
|
||||
* @return Builder
|
||||
*/
|
||||
public function client_status(string $value = '') :Builder
|
||||
{
|
||||
if (strlen($value) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
$status_parameters = explode(',', $value);
|
||||
|
||||
if (in_array('all', $status_parameters)) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
if (in_array('logged', $status_parameters)) {
|
||||
$this->builder->where('amount', '>', 0);
|
||||
}
|
||||
|
||||
if (in_array('pending', $status_parameters)) {
|
||||
$this->builder->whereNull('invoice_id')->whereNotNull('payment_date');
|
||||
}
|
||||
|
||||
if (in_array('invoiced', $status_parameters)) {
|
||||
$this->builder->whereNotNull('invoice_id');
|
||||
}
|
||||
|
||||
if (in_array('paid', $status_parameters)) {
|
||||
$this->builder->whereNotNull('payment_date');
|
||||
}
|
||||
|
||||
if (in_array('unpaid', $status_parameters)) {
|
||||
$this->builder->whereNull('payment_date');
|
||||
}
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filters the list based on the status
|
||||
* archived, active, deleted.
|
||||
|
@ -56,8 +56,6 @@ class InvoiceFilters extends QueryFilters
|
||||
if (in_array('unpaid', $status_parameters)) {
|
||||
$this->builder->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]);
|
||||
}
|
||||
//->where('due_date', '>', Carbon::now())
|
||||
//->orWhere('partial_due_date', '>', Carbon::now());
|
||||
|
||||
if (in_array('overdue', $status_parameters)) {
|
||||
$this->builder->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
||||
@ -167,7 +165,7 @@ class InvoiceFilters extends QueryFilters
|
||||
->orderBy('due_date', 'ASC');
|
||||
}
|
||||
|
||||
public function payable(string $client_id)
|
||||
public function payable(string $client_id = '')
|
||||
{
|
||||
if (strlen($client_id) == 0) {
|
||||
return $this->builder;
|
||||
@ -185,7 +183,7 @@ class InvoiceFilters extends QueryFilters
|
||||
* @param string sort formatted as column|asc
|
||||
* @return Builder
|
||||
*/
|
||||
public function sort(string $sort) : Builder
|
||||
public function sort(string $sort = '') : Builder
|
||||
{
|
||||
$sort_col = explode('|', $sort);
|
||||
|
||||
|
@ -102,6 +102,9 @@ class ProductFilters extends QueryFilters
|
||||
{
|
||||
$sort_col = explode('|', $sort);
|
||||
|
||||
if(!is_array($sort_col))
|
||||
return $this->builder;
|
||||
|
||||
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
||||
}
|
||||
|
||||
|
@ -17,19 +17,20 @@ use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class PurchaseOrderFilters extends QueryFilters
|
||||
{
|
||||
|
||||
/**
|
||||
* Filter based on client status.
|
||||
*
|
||||
* Statuses we need to handle
|
||||
* - all
|
||||
* - paid
|
||||
* - unpaid
|
||||
* - overdue
|
||||
* - reversed
|
||||
* - draft
|
||||
* - sent
|
||||
* - accepted
|
||||
* - cancelled
|
||||
*
|
||||
* @return Builder
|
||||
*/
|
||||
public function credit_status(string $value = '') :Builder
|
||||
public function client_status(string $value = '') :Builder
|
||||
{
|
||||
if (strlen($value) == 0) {
|
||||
return $this->builder;
|
||||
@ -45,16 +46,17 @@ class PurchaseOrderFilters extends QueryFilters
|
||||
$this->builder->where('status_id', PurchaseOrder::STATUS_DRAFT);
|
||||
}
|
||||
|
||||
if (in_array('partial', $status_parameters)) {
|
||||
$this->builder->where('status_id', PurchaseOrder::STATUS_PARTIAL);
|
||||
if (in_array('sent', $status_parameters)) {
|
||||
$this->builder->where('status_id', PurchaseOrder::STATUS_SENT);
|
||||
}
|
||||
|
||||
if (in_array('applied', $status_parameters)) {
|
||||
$this->builder->where('status_id', PurchaseOrder::STATUS_APPLIED);
|
||||
if (in_array('accepted', $status_parameters)) {
|
||||
$this->builder->where('status_id', PurchaseOrder::STATUS_ACCEPTED);
|
||||
}
|
||||
|
||||
//->where('due_date', '>', Carbon::now())
|
||||
//->orWhere('partial_due_date', '>', Carbon::now());
|
||||
if (in_array('cancelled', $status_parameters)) {
|
||||
$this->builder->where('status_id', PurchaseOrder::STATUS_CANCELLED);
|
||||
}
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ abstract class QueryFilters
|
||||
public function clientFilter()
|
||||
{
|
||||
if (auth()->guard('contact')->user()) {
|
||||
return $this->builder->whereClientId(auth()->guard('contact')->user()->client->id);
|
||||
return $this->builder->where('client_id', auth()->guard('contact')->user()->client->id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,6 +179,15 @@ abstract class QueryFilters
|
||||
|
||||
$created_at = date('Y-m-d H:i:s', $value);
|
||||
|
||||
if(is_string($created_at)){
|
||||
|
||||
$created_at = strtotime(str_replace("/","-",$created_at));
|
||||
|
||||
if(!$created_at)
|
||||
return $this->builder;
|
||||
|
||||
}
|
||||
|
||||
return $this->builder->where('created_at', '>=', $created_at);
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use App\Models\Quote;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
@ -33,13 +34,59 @@ class QuoteFilters extends QueryFilters
|
||||
}
|
||||
|
||||
return $this->builder->where(function ($query) use ($filter) {
|
||||
$query->where('quotes.custom_value1', 'like', '%'.$filter.'%')
|
||||
->orWhere('quotes.custom_value2', 'like', '%'.$filter.'%')
|
||||
->orWhere('quotes.custom_value3', 'like', '%'.$filter.'%')
|
||||
->orWhere('quotes.custom_value4', 'like', '%'.$filter.'%');
|
||||
$query->where('quotes.number', 'like', '%'.$filter.'%')
|
||||
->orwhere('quotes.custom_value1', 'like', '%'.$filter.'%')
|
||||
->orWhere('quotes.custom_value2', 'like', '%'.$filter.'%')
|
||||
->orWhere('quotes.custom_value3', 'like', '%'.$filter.'%')
|
||||
->orWhere('quotes.custom_value4', 'like', '%'.$filter.'%');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter based on client status.
|
||||
*
|
||||
* Statuses we need to handle
|
||||
* - all
|
||||
* - active
|
||||
* - paused
|
||||
* - completed
|
||||
*
|
||||
* @param string client_status The invoice status as seen by the client
|
||||
* @return Builder
|
||||
*/
|
||||
public function client_status(string $value = '') :Builder
|
||||
{
|
||||
if (strlen($value) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
$status_parameters = explode(',', $value);
|
||||
|
||||
if (in_array('all', $status_parameters)) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
if (in_array('draft', $status_parameters)) {
|
||||
$this->builder->where('status_id', Quote::STATUS_DRAFT);
|
||||
}
|
||||
|
||||
if (in_array('sent', $status_parameters)) {
|
||||
$this->builder->where('status_id', Quote::STATUS_SENT);
|
||||
}
|
||||
|
||||
if (in_array('approved', $status_parameters)) {
|
||||
$this->builder->where('status_id', Quote::STATUS_APPROVED);
|
||||
}
|
||||
|
||||
if (in_array('expired', $status_parameters)) {
|
||||
$this->builder->where('status_id', Quote::STATUS_SENT)
|
||||
->where('due_date', '<=', now()->toDateString());
|
||||
}
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filters the list based on the status
|
||||
* archived, active, deleted.
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
@ -40,6 +41,46 @@ class RecurringInvoiceFilters extends QueryFilters
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter based on client status.
|
||||
*
|
||||
* Statuses we need to handle
|
||||
* - all
|
||||
* - active
|
||||
* - paused
|
||||
* - completed
|
||||
*
|
||||
* @param string client_status The invoice status as seen by the client
|
||||
* @return Builder
|
||||
*/
|
||||
public function client_status(string $value = '') :Builder
|
||||
{
|
||||
if (strlen($value) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
$status_parameters = explode(',', $value);
|
||||
|
||||
if (in_array('all', $status_parameters)) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
if (in_array('active', $status_parameters)) {
|
||||
$this->builder->where('status_id', RecurringInvoice::STATUS_ACTIVE);
|
||||
}
|
||||
|
||||
if (in_array('paused', $status_parameters)) {
|
||||
$this->builder->where('status_id', RecurringInvoice::STATUS_PAUSED);
|
||||
}
|
||||
|
||||
if (in_array('completed', $status_parameters)) {
|
||||
$this->builder->where('status_id', RecurringInvoice::STATUS_COMPLETED);
|
||||
}
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filters the list based on the status
|
||||
* archived, active, deleted.
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace App\Filters;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
/**
|
||||
@ -19,6 +20,8 @@ use Illuminate\Database\Eloquent\Builder;
|
||||
*/
|
||||
class TaskFilters extends QueryFilters
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
@ -41,6 +44,37 @@ class TaskFilters extends QueryFilters
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filter based on client status.
|
||||
*
|
||||
* Statuses we need to handle
|
||||
* - all
|
||||
* - invoiced
|
||||
*
|
||||
* @param string client_status The invoice status as seen by the client
|
||||
* @return Builder
|
||||
*/
|
||||
public function client_status(string $value = '') :Builder
|
||||
{
|
||||
if (strlen($value) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
$status_parameters = explode(',', $value);
|
||||
|
||||
if (in_array('all', $status_parameters)) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
if (in_array('invoiced', $status_parameters)) {
|
||||
$this->builder->whereNotNull('invoice_id');
|
||||
}
|
||||
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filters the list based on the status
|
||||
* archived, active, deleted.
|
||||
@ -80,6 +114,16 @@ class TaskFilters extends QueryFilters
|
||||
});
|
||||
}
|
||||
|
||||
public function project_tasks($project)
|
||||
{
|
||||
|
||||
if (strlen($project) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
return $this->builder->where('project_id', $this->decodePrimaryKey($project));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the list based on $sort.
|
||||
*
|
||||
|
17
app/Helpers/Bank/AccountTransformerInterface.php
Normal file
17
app/Helpers/Bank/AccountTransformerInterface.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Helpers\Bank;
|
||||
|
||||
interface AccountTransformerInterface
|
||||
{
|
||||
public function transform($accounts);
|
||||
}
|
17
app/Helpers/Bank/BankExpenseInterface.php
Normal file
17
app/Helpers/Bank/BankExpenseInterface.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Helpers\Bank;
|
||||
|
||||
interface BankExpenseInterface
|
||||
{
|
||||
|
||||
}
|
17
app/Helpers/Bank/BankRevenueInterface.php
Normal file
17
app/Helpers/Bank/BankRevenueInterface.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Helpers\Bank;
|
||||
|
||||
interface BankRevenueInterface
|
||||
{
|
||||
public function transform($transaction);
|
||||
}
|
104
app/Helpers/Bank/Yodlee/Transformer/AccountTransformer.php
Normal file
104
app/Helpers/Bank/Yodlee/Transformer/AccountTransformer.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Helpers\Bank\Yodlee\Transformer;
|
||||
|
||||
use App\Helpers\Bank\AccountTransformerInterface;
|
||||
|
||||
/**
|
||||
[0] => stdClass Object
|
||||
(
|
||||
[CONTAINER] => bank
|
||||
[providerAccountId] => 11308693
|
||||
[accountName] => My CD - 8878
|
||||
[accountStatus] => ACTIVE
|
||||
[accountNumber] => xxxx8878
|
||||
[aggregationSource] => USER
|
||||
[isAsset] => 1
|
||||
[balance] => stdClass Object
|
||||
(
|
||||
[currency] => USD
|
||||
[amount] => 49778.07
|
||||
)
|
||||
|
||||
[id] => 12331861
|
||||
[includeInNetWorth] => 1
|
||||
[providerId] => 18769
|
||||
[providerName] => Dag Site Captcha
|
||||
[isManual] =>
|
||||
[currentBalance] => stdClass Object
|
||||
(
|
||||
[currency] => USD
|
||||
[amount] => 49778.07
|
||||
)
|
||||
|
||||
[accountType] => CD
|
||||
[displayedName] => LORETTA
|
||||
[createdDate] => 2022-07-28T06:55:33Z
|
||||
[lastUpdated] => 2022-07-28T06:56:09Z
|
||||
[dataset] => Array
|
||||
(
|
||||
[0] => stdClass Object
|
||||
(
|
||||
[name] => BASIC_AGG_DATA
|
||||
[additionalStatus] => AVAILABLE_DATA_RETRIEVED
|
||||
[updateEligibility] => ALLOW_UPDATE
|
||||
[lastUpdated] => 2022-07-28T06:55:50Z
|
||||
[lastUpdateAttempt] => 2022-07-28T06:55:50Z
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
)
|
||||
)
|
||||
*/
|
||||
|
||||
|
||||
class AccountTransformer implements AccountTransformerInterface
|
||||
{
|
||||
|
||||
public function transform($yodlee_account)
|
||||
{
|
||||
|
||||
$data = [];
|
||||
|
||||
if(!property_exists($yodlee_account, 'account'))
|
||||
return $data;
|
||||
|
||||
foreach($yodlee_account->account as $account)
|
||||
{
|
||||
$data[] = $this->transformAccount($account);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function transformAccount($account)
|
||||
{
|
||||
|
||||
return [
|
||||
'id' => $account->id,
|
||||
'account_type' => $account->CONTAINER,
|
||||
// 'account_name' => $account->accountName,
|
||||
'account_name' => property_exists($account, 'accountName') ? $account->accountName : $account->nickname,
|
||||
'account_status' => $account->accountStatus,
|
||||
'account_number' => property_exists($account, 'accountNumber') ? '**** ' . substr($account?->accountNumber, -7) : '',
|
||||
'provider_account_id' => $account->providerAccountId,
|
||||
'provider_id' => $account->providerId,
|
||||
'provider_name' => $account->providerName,
|
||||
'nickname' => property_exists($account, 'nickname') ? $account->nickname : '',
|
||||
'current_balance' => property_exists($account, 'currentBalance') ? $account->currentBalance->amount : 0,
|
||||
'account_currency' => property_exists($account, 'currency') ? $account->currentBalance->currency : '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
80
app/Helpers/Bank/Yodlee/Transformer/ExpenseTransformer.php
Normal file
80
app/Helpers/Bank/Yodlee/Transformer/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) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Helpers\Bank\Yodlee\Transformer;
|
||||
|
||||
/**
|
||||
"date": "string",
|
||||
"sourceId": "string",
|
||||
"symbol": "string",
|
||||
"cusipNumber": "string",
|
||||
"highLevelCategoryId": 0,
|
||||
"detailCategoryId": 0,
|
||||
"description": {},
|
||||
"memo": "string",
|
||||
"settleDate": "string",
|
||||
"type": "string",
|
||||
"intermediary": [],
|
||||
"baseType": "CREDIT",
|
||||
"categorySource": "SYSTEM",
|
||||
"principal": {},
|
||||
"lastUpdated": "string",
|
||||
"interest": {},
|
||||
"price": {},
|
||||
"commission": {},
|
||||
"id": 0,
|
||||
"merchantType": "string",
|
||||
"amount": {
|
||||
"amount": 0,
|
||||
"convertedAmount": 0,
|
||||
"currency": "USD",
|
||||
"convertedCurrency": "USD"
|
||||
},
|
||||
"checkNumber": "string",
|
||||
"isPhysical": true,
|
||||
"quantity": 0,
|
||||
"valoren": "string",
|
||||
"isManual": true,
|
||||
"merchant": {
|
||||
"website": "string",
|
||||
"address": {},
|
||||
"contact": {},
|
||||
"categoryLabel": [],
|
||||
"coordinates": {},
|
||||
"name": "string",
|
||||
"id": "string",
|
||||
"source": "YODLEE",
|
||||
"logoURL": "string"
|
||||
},
|
||||
"sedol": "string",
|
||||
"transactionDate": "string",
|
||||
"categoryType": "TRANSFER",
|
||||
"accountId": 0,
|
||||
"createdDate": "string",
|
||||
"sourceType": "AGGREGATED",
|
||||
"CONTAINER": "bank",
|
||||
"postDate": "string",
|
||||
"parentCategoryId": 0,
|
||||
"subType": "OVERDRAFT_CHARGE",
|
||||
"category": "string",
|
||||
"runningBalance": {},
|
||||
"categoryId": 0,
|
||||
"holdingDescription": "string",
|
||||
"isin": "string",
|
||||
"status": "POSTED"
|
||||
*/
|
||||
|
||||
class ExpenseTransformer
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
187
app/Helpers/Bank/Yodlee/Transformer/IncomeTransformer.php
Normal file
187
app/Helpers/Bank/Yodlee/Transformer/IncomeTransformer.php
Normal file
@ -0,0 +1,187 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Helpers\Bank\Yodlee\Transformer;
|
||||
|
||||
use App\Helpers\Bank\BankRevenueInterface;
|
||||
use App\Utils\Traits\AppSetup;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
/**
|
||||
"date": "string",
|
||||
"sourceId": "string",
|
||||
"symbol": "string",
|
||||
"cusipNumber": "string",
|
||||
"highLevelCategoryId": 0,
|
||||
"detailCategoryId": 0,
|
||||
"description": {},
|
||||
"memo": "string",
|
||||
"settleDate": "string",
|
||||
"type": "string",
|
||||
"intermediary": [],
|
||||
"baseType": "CREDIT",
|
||||
"categorySource": "SYSTEM",
|
||||
"principal": {},
|
||||
"lastUpdated": "string",
|
||||
"interest": {},
|
||||
"price": {},
|
||||
"commission": {},
|
||||
"id": 0,
|
||||
"merchantType": "string",
|
||||
"amount": {
|
||||
"amount": 0,
|
||||
"convertedAmount": 0,
|
||||
"currency": "USD",
|
||||
"convertedCurrency": "USD"
|
||||
},
|
||||
"checkNumber": "string",
|
||||
"isPhysical": true,
|
||||
"quantity": 0,
|
||||
"valoren": "string",
|
||||
"isManual": true,
|
||||
"merchant": {
|
||||
"website": "string",
|
||||
"address": {},
|
||||
"contact": {},
|
||||
"categoryLabel": [],
|
||||
"coordinates": {},
|
||||
"name": "string",
|
||||
"id": "string",
|
||||
"source": "YODLEE",
|
||||
"logoURL": "string"
|
||||
},
|
||||
"sedol": "string",
|
||||
"transactionDate": "string",
|
||||
"categoryType": "TRANSFER",
|
||||
"accountId": 0,
|
||||
"createdDate": "string",
|
||||
"sourceType": "AGGREGATED",
|
||||
"CONTAINER": "bank",
|
||||
"postDate": "string",
|
||||
"parentCategoryId": 0,
|
||||
"subType": "OVERDRAFT_CHARGE",
|
||||
"category": "string",
|
||||
"runningBalance": {},
|
||||
"categoryId": 0,
|
||||
"holdingDescription": "string",
|
||||
"isin": "string",
|
||||
"status": "POSTED"
|
||||
|
||||
(
|
||||
[CONTAINER] => bank
|
||||
[id] => 103953585
|
||||
[amount] => stdClass Object
|
||||
(
|
||||
[amount] => 480.66
|
||||
[currency] => USD
|
||||
)
|
||||
|
||||
[categoryType] => UNCATEGORIZE
|
||||
[categoryId] => 1
|
||||
[category] => Uncategorized
|
||||
[categorySource] => SYSTEM
|
||||
[highLevelCategoryId] => 10000017
|
||||
[createdDate] => 2022-08-04T21:50:17Z
|
||||
[lastUpdated] => 2022-08-04T21:50:17Z
|
||||
[description] => stdClass Object
|
||||
(
|
||||
[original] => CHEROKEE NATION TAX TA TAHLEQUAH OK
|
||||
)
|
||||
|
||||
[isManual] =>
|
||||
[sourceType] => AGGREGATED
|
||||
[date] => 2022-08-03
|
||||
[transactionDate] => 2022-08-03
|
||||
[postDate] => 2022-08-03
|
||||
[status] => POSTED
|
||||
[accountId] => 12331794
|
||||
[runningBalance] => stdClass Object
|
||||
(
|
||||
[amount] => 480.66
|
||||
[currency] => USD
|
||||
)
|
||||
|
||||
[checkNumber] => 998
|
||||
)
|
||||
*/
|
||||
|
||||
class IncomeTransformer implements BankRevenueInterface
|
||||
{
|
||||
use AppSetup;
|
||||
|
||||
public function transform($transaction)
|
||||
{
|
||||
|
||||
$data = [];
|
||||
|
||||
if(!property_exists($transaction, 'transaction'))
|
||||
return $data;
|
||||
|
||||
foreach($transaction->transaction as $transaction)
|
||||
{
|
||||
$data[] = $this->transformTransaction($transaction);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function transformTransaction($transaction)
|
||||
{
|
||||
|
||||
return [
|
||||
'transaction_id' => $transaction->id,
|
||||
'amount' => $transaction->amount->amount,
|
||||
'currency_id' => $this->convertCurrency($transaction->amount->currency),
|
||||
'account_type' => $transaction->CONTAINER,
|
||||
'category_id' => $transaction->highLevelCategoryId,
|
||||
'category_type' => $transaction->categoryType,
|
||||
'date' => $transaction->date,
|
||||
'bank_account_id' => $transaction->accountId,
|
||||
'description' => $transaction->description->original,
|
||||
'base_type' => property_exists($transaction, 'baseType') ? $transaction->baseType : $this->calculateBaseType($transaction),
|
||||
];
|
||||
}
|
||||
|
||||
private function calculateBaseType($transaction)
|
||||
{
|
||||
//CREDIT / DEBIT
|
||||
|
||||
if(property_exists($transaction, 'highLevelCategoryId') && $transaction->highLevelCategoryId == 10000012)
|
||||
return 'CREDIT';
|
||||
|
||||
return 'DEBIT';
|
||||
|
||||
}
|
||||
|
||||
private function convertCurrency(string $code)
|
||||
{
|
||||
|
||||
$currencies = Cache::get('currencies');
|
||||
|
||||
if (! $currencies) {
|
||||
$this->buildCache(true);
|
||||
}
|
||||
|
||||
$currency = $currencies->filter(function ($item) use($code){
|
||||
return $item->code == $code;
|
||||
})->first();
|
||||
|
||||
if($currency)
|
||||
return $currency->id;
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
298
app/Helpers/Bank/Yodlee/Yodlee.php
Normal file
298
app/Helpers/Bank/Yodlee/Yodlee.php
Normal file
@ -0,0 +1,298 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Helpers\Bank\Yodlee;
|
||||
|
||||
use App\Exceptions\YodleeApiException;
|
||||
use App\Helpers\Bank\Yodlee\Transformer\AccountTransformer;
|
||||
use App\Helpers\Bank\Yodlee\Transformer\IncomeTransformer;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class Yodlee
|
||||
{
|
||||
|
||||
public bool $test_mode = false;
|
||||
|
||||
private string $api_endpoint = 'https://production.api.yodlee.com/ysl';
|
||||
|
||||
private string $dev_api_endpoint = 'https://sandbox.api.yodlee.com/ysl';
|
||||
|
||||
private string $test_api_endpoint = 'https://development.api.yodlee.com/ysl';
|
||||
|
||||
public string $dev_fast_track_url = 'https://fl4.sandbox.yodlee.com/authenticate/restserver/fastlink';
|
||||
|
||||
public string $test_fast_track_url = 'https://fl4.preprod.yodlee.com/authenticate/USDevexPreProd3-449/fastlink?channelAppName=usdevexpreprod3';
|
||||
|
||||
public string $production_track_url = 'https://fl4.prod.yodlee.com/authenticate/USDevexProd3-331/fastlink?channelAppName=usdevexprod3';
|
||||
|
||||
protected string $client_id;
|
||||
|
||||
protected string $client_secret;
|
||||
|
||||
protected string $admin_name;
|
||||
|
||||
protected ?string $bank_account_id;
|
||||
|
||||
public function __construct(?string $bank_account_id = null)
|
||||
{
|
||||
|
||||
$this->bank_account_id = $bank_account_id;
|
||||
|
||||
$this->client_id = config('ninja.yodlee.client_id');
|
||||
|
||||
$this->client_secret = config('ninja.yodlee.client_secret');
|
||||
|
||||
$this->admin_name = config('ninja.yodlee.admin_name');
|
||||
|
||||
$this->test_mode = config('ninja.yodlee.test_mode');
|
||||
|
||||
config('ninja.yodlee.dev_mode') ? $this->setDevUrl() : null;
|
||||
|
||||
}
|
||||
|
||||
public function getFastTrackUrl()
|
||||
{
|
||||
if(config('ninja.yodlee.dev_mode'))
|
||||
return $this->dev_fast_track_url;
|
||||
|
||||
return $this->test_mode ? $this->test_fast_track_url : $this->production_track_url;
|
||||
}
|
||||
|
||||
public function setTestMode()
|
||||
{
|
||||
$this->test_mode = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDevUrl()
|
||||
{
|
||||
$this->test_api_endpoint = $this->dev_api_endpoint;
|
||||
|
||||
$this->api_endpoint = $this->dev_api_endpoint;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEndpoint()
|
||||
{
|
||||
return $this->test_mode ? $this->test_api_endpoint : $this->api_endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we do not pass in a user
|
||||
* we pass in the admin username instead
|
||||
*/
|
||||
public function getAccessToken($is_admin = false)
|
||||
{
|
||||
if($is_admin)
|
||||
$user = $this->admin_name;
|
||||
else
|
||||
$user = $this->bank_account_id ?: $this->admin_name;
|
||||
|
||||
$response = $this->bankFormRequest('/auth/token', 'post', [], ['loginName' => $user]);
|
||||
|
||||
return $response->token->accessToken;
|
||||
}
|
||||
|
||||
|
||||
public function createUser($company)
|
||||
{
|
||||
|
||||
$token = $this->getAccessToken(true);
|
||||
|
||||
$user['user'] = [
|
||||
'loginName' => Str::uuid(),
|
||||
];
|
||||
|
||||
/*
|
||||
{
|
||||
"user": {
|
||||
"preferences": {
|
||||
"dateFormat": "string",
|
||||
"timeZone": "string",
|
||||
"currency": "USD",
|
||||
"locale": "en_US"
|
||||
},
|
||||
"address": {
|
||||
"zip": "string",
|
||||
"country": "string",
|
||||
"address3": "string",
|
||||
"address2": "string",
|
||||
"city": "string",
|
||||
"address1": "string",
|
||||
"state": "string"
|
||||
},
|
||||
"loginName": "string",
|
||||
"name": {
|
||||
"middle": "string",
|
||||
"last": "string",
|
||||
"fullName": "string",
|
||||
"first": "string"
|
||||
},
|
||||
"email": "string",
|
||||
"segmentName": "string"
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
$response = Http::withHeaders($this->getHeaders(["Authorization" => "Bearer {$token}"]))->post($this->getEndpoint(). "/user/register", $user);
|
||||
|
||||
if($response->successful())
|
||||
return $response->object();
|
||||
|
||||
if($response->failed())
|
||||
throw new YodleeApiException($response->body());
|
||||
|
||||
}
|
||||
|
||||
public function getAccounts($params = [])
|
||||
{
|
||||
|
||||
$token = $this->getAccessToken();
|
||||
|
||||
$response = Http::withHeaders($this->getHeaders(["Authorization" => "Bearer {$token}"]))->get($this->getEndpoint(). "/accounts", $params);
|
||||
|
||||
if($response->successful()){
|
||||
|
||||
$at = new AccountTransformer();
|
||||
return $at->transform($response->object());
|
||||
|
||||
}
|
||||
|
||||
if($response->failed())
|
||||
throw new YodleeApiException($response->body());
|
||||
|
||||
}
|
||||
|
||||
public function getAccount($account_id)
|
||||
{
|
||||
|
||||
$token = $this->getAccessToken();
|
||||
|
||||
$response = Http::withHeaders($this->getHeaders(["Authorization" => "Bearer {$token}"]))->get($this->getEndpoint(). "/accounts/{$account_id}", []);
|
||||
|
||||
if($response->successful())
|
||||
return true;
|
||||
|
||||
if($response->failed())
|
||||
return false;
|
||||
}
|
||||
|
||||
public function deleteAccount($account_id)
|
||||
{
|
||||
|
||||
$token = $this->getAccessToken();
|
||||
|
||||
$response = Http::withHeaders($this->getHeaders(["Authorization" => "Bearer {$token}"]))->delete($this->getEndpoint(). "/accounts/{$account_id}", []);
|
||||
|
||||
if($response->successful()){
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
if($response->failed())
|
||||
throw new YodleeApiException($response->body());
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function getTransactions($params = [])
|
||||
{
|
||||
$token = $this->getAccessToken();
|
||||
|
||||
$response = Http::withHeaders($this->getHeaders(["Authorization" => "Bearer {$token}"]))->get($this->getEndpoint(). "/transactions", $params);
|
||||
|
||||
if($response->successful()){
|
||||
// return $response->object();
|
||||
$it = new IncomeTransformer();
|
||||
return $it->transform($response->object());
|
||||
|
||||
}
|
||||
|
||||
if($response->failed())
|
||||
throw new YodleeApiException($response->body());
|
||||
|
||||
}
|
||||
|
||||
public function getTransactionCount($params = [])
|
||||
{
|
||||
$token = $this->getAccessToken();
|
||||
|
||||
$response = Http::withHeaders($this->getHeaders(["Authorization" => "Bearer {$token}"]))->get($this->getEndpoint(). "/transactions/count", $params);
|
||||
|
||||
if($response->successful()){
|
||||
|
||||
return $response->object();
|
||||
|
||||
}
|
||||
|
||||
if($response->failed())
|
||||
throw new YodleeApiException($response->body());
|
||||
|
||||
}
|
||||
|
||||
public function getTransactionCategories($params = [])
|
||||
{
|
||||
$token = $this->getAccessToken();
|
||||
|
||||
$response = Http::withHeaders($this->getHeaders(["Authorization" => "Bearer {$token}"]))->get($this->getEndpoint(). "/transactions/categories", $params);
|
||||
|
||||
if($response->successful())
|
||||
return $response->object();
|
||||
|
||||
if($response->failed())
|
||||
throw new YodleeApiException($response->body());
|
||||
|
||||
}
|
||||
|
||||
private function bankFormRequest(string $uri, string $verb, array $data, array $headers)
|
||||
{
|
||||
|
||||
$response = Http::withHeaders($this->getFormHeaders($headers))->asForm()->{$verb}($this->getEndpoint() . $uri, $this->buildBody());
|
||||
|
||||
if($response->successful())
|
||||
return $response->object();
|
||||
|
||||
if($response->failed())
|
||||
throw new YodleeApiException($response->body());
|
||||
|
||||
}
|
||||
|
||||
private function getHeaders($data = [])
|
||||
{
|
||||
return array_merge($data, [
|
||||
'Api-Version' => '1.1',
|
||||
'ContentType' => 'application/json'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
private function getFormHeaders($data = [])
|
||||
{
|
||||
return array_merge($data, [
|
||||
'Api-Version' => '1.1',
|
||||
]);
|
||||
}
|
||||
|
||||
private function buildBody()
|
||||
{
|
||||
|
||||
return [
|
||||
'clientId' => $this->client_id,
|
||||
'secret' => $this->client_secret,
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
}
|
99
app/Helpers/Epc/EpcQrGenerator.php
Normal file
99
app/Helpers/Epc/EpcQrGenerator.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Helpers\Epc;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\Invoice;
|
||||
use App\Utils\Ninja;
|
||||
use BaconQrCode\Renderer\ImageRenderer;
|
||||
use BaconQrCode\Renderer\Image\SvgImageBackEnd;
|
||||
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
|
||||
use BaconQrCode\Writer;
|
||||
|
||||
/**
|
||||
* EpcQrGenerator.
|
||||
*/
|
||||
class EpcQrGenerator
|
||||
{
|
||||
|
||||
private array $sepa = [
|
||||
'serviceTag' => 'BCD',
|
||||
'version' => 2,
|
||||
'characterSet' => 1,
|
||||
'identification' => 'SCT',
|
||||
'bic' => '',
|
||||
'purpose' => '',
|
||||
|
||||
];
|
||||
|
||||
public function __construct(protected Company $company, protected Invoice $invoice, protected float $amount){}
|
||||
|
||||
public function getQrCode()
|
||||
{
|
||||
|
||||
$renderer = new ImageRenderer(
|
||||
new RendererStyle(200),
|
||||
new SvgImageBackEnd()
|
||||
);
|
||||
$writer = new Writer($renderer);
|
||||
|
||||
$this->validateFields();
|
||||
|
||||
try {
|
||||
$qr = $writer->writeString($this->encodeMessage(), 'utf-8');
|
||||
}
|
||||
catch(\Throwable $e){
|
||||
return '';
|
||||
}
|
||||
catch(\Exception $e){
|
||||
return '';
|
||||
}
|
||||
return "<svg viewBox='0 0 200 200' width='200' height='200' x='0' y='0' xmlns='http://www.w3.org/2000/svg'>
|
||||
<rect x='0' y='0' width='100%'' height='100%' />{$qr}</svg>";
|
||||
|
||||
}
|
||||
|
||||
public function encodeMessage()
|
||||
{
|
||||
|
||||
return rtrim(implode("\n", array(
|
||||
$this->sepa['serviceTag'],
|
||||
sprintf('%03d', $this->sepa['version']),
|
||||
$this->sepa['characterSet'],
|
||||
$this->sepa['identification'],
|
||||
isset($this->company?->custom_fields?->company2) ? $this->company->settings->custom_value2 : '',
|
||||
$this->company->present()->name(),
|
||||
isset($this->company?->custom_fields?->company1) ? $this->company->settings->custom_value1 : '',
|
||||
$this->formatMoney($this->amount),
|
||||
$this->sepa['purpose'],
|
||||
substr($this->invoice->number,0,34),
|
||||
'',
|
||||
''
|
||||
)), "\n");
|
||||
|
||||
}
|
||||
|
||||
private function validateFields()
|
||||
{
|
||||
|
||||
if(Ninja::isSelfHost() && isset($this->company?->custom_fields?->company2))
|
||||
nlog('The BIC field is not present and _may_ be a required fields for EPC QR codes');
|
||||
|
||||
if(Ninja::isSelfHost() && isset($this->company?->custom_fields?->company1))
|
||||
nlog('The IBAN field is required');
|
||||
|
||||
}
|
||||
|
||||
private function formatMoney($value) {
|
||||
return sprintf('EUR%s', number_format($value, 2, '.', ''));
|
||||
}
|
||||
}
|
@ -40,4 +40,7 @@ function nlog($output, $context = []): void
|
||||
} else {
|
||||
\Illuminate\Support\Facades\Log::channel('invoiceninja')->info($output, $context);
|
||||
}
|
||||
|
||||
$output = null;
|
||||
$context = null;
|
||||
}
|
@ -30,6 +30,8 @@ class InvoiceItemSum
|
||||
|
||||
private $gross_line_total;
|
||||
|
||||
private $tax_amount;
|
||||
|
||||
private $currency;
|
||||
|
||||
private $total_taxes;
|
||||
@ -111,14 +113,10 @@ class InvoiceItemSum
|
||||
$this->setLineTotal($this->getLineTotal() - $this->formatValue($this->item->discount, $this->currency->precision));
|
||||
} else {
|
||||
|
||||
/*Test 16-08-2021*/
|
||||
$discount = ($this->item->line_total * ($this->item->discount / 100));
|
||||
|
||||
$this->setLineTotal($this->formatValue(($this->getLineTotal() - $discount), $this->currency->precision));
|
||||
/*Test 16-08-2021*/
|
||||
|
||||
//replaces the following
|
||||
|
||||
// $this->setLineTotal($this->getLineTotal() - $this->formatValue(round($this->item->line_total * ($this->item->discount / 100), 2), $this->currency->precision));
|
||||
}
|
||||
|
||||
$this->item->is_amount_discount = $this->invoice->is_amount_discount;
|
||||
@ -160,6 +158,8 @@ class InvoiceItemSum
|
||||
|
||||
$this->item->gross_line_total = $this->getLineTotal() + $item_tax;
|
||||
|
||||
$this->item->tax_amount = $item_tax;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,8 @@ class InvoiceItemSumInclusive
|
||||
|
||||
private $tax_collection;
|
||||
|
||||
private $tax_amount;
|
||||
|
||||
public function __construct($invoice)
|
||||
{
|
||||
$this->tax_collection = collect([]);
|
||||
@ -144,6 +146,8 @@ class InvoiceItemSumInclusive
|
||||
$this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total);
|
||||
}
|
||||
|
||||
$this->item->tax_amount = $this->formatValue($item_tax, $this->currency->precision);
|
||||
|
||||
$this->setTotalTaxes($this->formatValue($item_tax, $this->currency->precision));
|
||||
|
||||
return $this;
|
||||
|
@ -19,7 +19,7 @@ use Sprain\SwissQrBill as QrBill;
|
||||
/**
|
||||
* SwissQrGenerator.
|
||||
*/
|
||||
class SwissQrGenerator
|
||||
class SwissQrGenerator
|
||||
{
|
||||
|
||||
protected Company $company;
|
||||
@ -33,7 +33,7 @@ class SwissQrGenerator
|
||||
$this->company = $company;
|
||||
|
||||
$this->invoice = $invoice;
|
||||
|
||||
|
||||
$this->client = $invoice->client;
|
||||
}
|
||||
|
||||
@ -87,10 +87,10 @@ class SwissQrGenerator
|
||||
$qrBill->setUltimateDebtor(
|
||||
QrBill\DataGroup\Element\StructuredAddress::createWithStreet(
|
||||
substr($this->client->present()->name(), 0 , 70),
|
||||
$this->client->address1 ? substr($this->client->address1, 0 , 70) : '',
|
||||
$this->client->address2 ? substr($this->client->address2, 0 , 16) : '',
|
||||
$this->client->postal_code ? substr($this->client->postal_code, 0, 16) : '',
|
||||
$this->client->city ? substr($this->client->postal_code, 0, 35) : '',
|
||||
$this->client->address1 ? substr($this->client->address1, 0 , 70) : '_',
|
||||
$this->client->address2 ? substr($this->client->address2, 0 , 16) : '_',
|
||||
$this->client->postal_code ? substr($this->client->postal_code, 0, 16) : '_',
|
||||
$this->client->city ? substr($this->client->city, 0, 35) : '_',
|
||||
'CH'
|
||||
));
|
||||
|
||||
@ -104,15 +104,43 @@ class SwissQrGenerator
|
||||
|
||||
// Add payment reference
|
||||
// This is what you will need to identify incoming payments.
|
||||
|
||||
if(stripos($this->invoice->number, "Live") === 0)
|
||||
{
|
||||
// we're currently in preview status. Let's give a dummy reference for now
|
||||
$invoice_number = "123456789";
|
||||
}
|
||||
else
|
||||
{
|
||||
$tempInvoiceNumber = $this->invoice->number;
|
||||
$tempInvoiceNumber = preg_replace('/[^A-Za-z0-9]/', '', $tempInvoiceNumber);
|
||||
$tempInvoiceNumber = substr($tempInvoiceNumber, 1);
|
||||
|
||||
$calcInvoiceNumber = "";
|
||||
$array = str_split($tempInvoiceNumber);
|
||||
foreach($array as $char)
|
||||
{
|
||||
if (is_numeric($char))
|
||||
{
|
||||
//
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($char)
|
||||
{
|
||||
$char = strtolower($char);
|
||||
$char = ord($char) - 96;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
$calcInvoiceNumber .= $char;
|
||||
}
|
||||
|
||||
$invoice_number = $calcInvoiceNumber;
|
||||
|
||||
if(stripos($this->invoice->number, "Live-") === 0)
|
||||
{
|
||||
// we're currently in preview status. Let's give a dummy reference for now
|
||||
$invoice_number = "123456789";
|
||||
}
|
||||
else
|
||||
{
|
||||
$invoice_number = $this->invoice->number;
|
||||
}
|
||||
|
||||
if(strlen($this->company->present()->besr_id()) > 1)
|
||||
@ -141,7 +169,7 @@ class SwissQrGenerator
|
||||
// Optionally, add some human-readable information about what the bill is for.
|
||||
$qrBill->setAdditionalInformation(
|
||||
QrBill\DataGroup\Element\AdditionalInformation::create(
|
||||
$this->invoice->public_notes ?: ''
|
||||
$this->invoice->public_notes ? substr($this->invoice->public_notes, 0, 139) : ctrans('texts.invoice_number_placeholder', ['invoice' => $this->invoice->number])
|
||||
)
|
||||
);
|
||||
|
||||
@ -149,7 +177,7 @@ class SwissQrGenerator
|
||||
// Now get the QR code image and save it as a file.
|
||||
try {
|
||||
|
||||
$output = new QrBill\PaymentPart\Output\HtmlOutput\HtmlOutput($qrBill, 'en');
|
||||
$output = new QrBill\PaymentPart\Output\HtmlOutput\HtmlOutput($qrBill, $this->client->locale() ?: 'en');
|
||||
|
||||
$html = $output
|
||||
->setPrintable(false)
|
||||
@ -173,4 +201,4 @@ class SwissQrGenerator
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -108,6 +108,10 @@ class ActivityController extends BaseController
|
||||
'credit' => $activity->credit ? $activity->credit : '',
|
||||
'task' => $activity->task ? $activity->task : '',
|
||||
'vendor' => $activity->vendor ? $activity->vendor : '',
|
||||
'vendor_contact' => $activity->vendor_contact ? $activity->vendor_contact : '',
|
||||
'purchase_order' => $activity->purchase_order ? $activity->purchase_order : '',
|
||||
'subscription' => $activity->subscription ? $activity->subscription : '',
|
||||
'vendor_contact' => $activity->vendor_contact ? $activity->vendor_contact : '',
|
||||
];
|
||||
|
||||
return array_merge($arr, $activity->toArray());
|
||||
@ -180,9 +184,7 @@ class ActivityController extends BaseController
|
||||
} else {
|
||||
$html_backup = file_get_contents(Storage::disk(config('filesystems.default'))->path($backup->filename));
|
||||
}
|
||||
} elseif ($backup && $backup->html_backup) { //db
|
||||
$html_backup = $backup->html_backup;
|
||||
} elseif (! $backup || ! $backup->html_backup) { //failed
|
||||
} else { //failed
|
||||
return response()->json(['message'=> ctrans('texts.no_backup_exists'), 'errors' => new stdClass], 404);
|
||||
}
|
||||
|
||||
|
@ -592,7 +592,10 @@ class LoginController extends BaseController
|
||||
|
||||
$google = new Google();
|
||||
|
||||
$user = $google->getTokenResponse(request()->input('id_token'));
|
||||
if(request()->has('id_token'))
|
||||
$user = $google->getTokenResponse(request()->input('id_token'));
|
||||
else
|
||||
return response()->json(['message' => 'Illegal request'], 403);
|
||||
|
||||
if (is_array($user)) {
|
||||
$query = [
|
||||
|
305
app/Http/Controllers/Bank/YodleeController.php
Normal file
305
app/Http/Controllers/Bank/YodleeController.php
Normal file
@ -0,0 +1,305 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Bank;
|
||||
|
||||
use App\Helpers\Bank\Yodlee\Yodlee;
|
||||
use App\Http\Controllers\BaseController;
|
||||
use App\Http\Requests\Yodlee\YodleeAuthRequest;
|
||||
use App\Jobs\Bank\ProcessBankTransactions;
|
||||
use App\Models\BankIntegration;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class YodleeController extends BaseController
|
||||
{
|
||||
|
||||
public function auth(YodleeAuthRequest $request)
|
||||
{
|
||||
|
||||
// create a user at this point
|
||||
// use the one time token here to pull in the actual user
|
||||
// store the user_account_id on the accounts table
|
||||
|
||||
$yodlee = new Yodlee();
|
||||
|
||||
$company = $request->getCompany();
|
||||
|
||||
|
||||
//ensure user is enterprise!!
|
||||
|
||||
if($company->account->bank_integration_account_id){
|
||||
|
||||
$flow = 'edit';
|
||||
|
||||
$token = $company->account->bank_integration_account_id;
|
||||
|
||||
}
|
||||
else{
|
||||
|
||||
$flow = 'add';
|
||||
|
||||
$response = $yodlee->createUser($company);
|
||||
|
||||
$token = $response->user->loginName;
|
||||
|
||||
$company->account->bank_integration_account_id = $token;
|
||||
|
||||
$company->push();
|
||||
|
||||
}
|
||||
|
||||
$yodlee = new Yodlee($token);
|
||||
|
||||
if($request->has('window_closed') && $request->input("window_closed") == "true")
|
||||
$this->getAccounts($company, $token);
|
||||
|
||||
$data = [
|
||||
'access_token' => $yodlee->getAccessToken(),
|
||||
'fasttrack_url' => $yodlee->getFastTrackUrl(),
|
||||
'config_name' => config('ninja.yodlee.config_name'),
|
||||
'flow' => $flow,
|
||||
'company' => $company,
|
||||
'account' => $company->account,
|
||||
'completed' => $request->has('window_closed') ? true : false,
|
||||
];
|
||||
|
||||
return view('bank.yodlee.auth', $data);
|
||||
|
||||
}
|
||||
|
||||
private function getAccounts($company, $token)
|
||||
{
|
||||
$yodlee = new Yodlee($token);
|
||||
|
||||
$accounts = $yodlee->getAccounts();
|
||||
|
||||
foreach($accounts as $account)
|
||||
{
|
||||
|
||||
if(!BankIntegration::where('bank_account_id', $account['id'])->where('company_id', $company->id)->exists())
|
||||
{
|
||||
$bank_integration = new BankIntegration();
|
||||
$bank_integration->company_id = $company->id;
|
||||
$bank_integration->account_id = $company->account_id;
|
||||
$bank_integration->user_id = $company->owner()->id;
|
||||
$bank_integration->bank_account_id = $account['id'];
|
||||
$bank_integration->bank_account_type = $account['account_type'];
|
||||
$bank_integration->bank_account_name = $account['account_name'];
|
||||
$bank_integration->bank_account_status = $account['account_status'];
|
||||
$bank_integration->bank_account_number = $account['account_number'];
|
||||
$bank_integration->provider_id = $account['provider_id'];
|
||||
$bank_integration->provider_name = $account['provider_name'];
|
||||
$bank_integration->nickname = $account['nickname'];
|
||||
$bank_integration->balance = $account['current_balance'];
|
||||
$bank_integration->currency = $account['account_currency'];
|
||||
$bank_integration->from_date = now()->subYear();
|
||||
|
||||
$bank_integration->save();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
$company->account->bank_integrations->each(function ($bank_integration) use ($company){
|
||||
|
||||
ProcessBankTransactions::dispatch($company->account->bank_integration_account_id, $bank_integration);
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process Yodlee Refresh Webhook.
|
||||
*
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/yodlee/refresh",
|
||||
* operationId="yodleeRefreshWebhook",
|
||||
* tags={"yodlee"},
|
||||
* summary="Processing webhooks from Yodlee",
|
||||
* description="Notifies the system when a data point can be refreshed",
|
||||
* @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="",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/Credit"),
|
||||
* ),
|
||||
* @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"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
|
||||
/*
|
||||
{
|
||||
"event":{
|
||||
"info":"REFRESH.PROCESS_COMPLETED",
|
||||
"loginName":"fri21",
|
||||
"data":{
|
||||
"providerAccount":[
|
||||
{
|
||||
"id":10995860,
|
||||
"providerId":16441,
|
||||
"isManual":false,
|
||||
"createdDate":"2017-12-22T05:47:35Z",
|
||||
"aggregationSource":"USER",
|
||||
"status":"SUCCESS",
|
||||
"requestId":"NSyMGo+R4dktywIu3hBIkc3PgWA=",
|
||||
"dataset":[
|
||||
{
|
||||
"name":"BASIC_AGG_DATA",
|
||||
"additionalStatus":"AVAILABLE_DATA_RETRIEVED",
|
||||
"updateEligibility":"ALLOW_UPDATE",
|
||||
"lastUpdated":"2017-12-22T05:48:16Z",
|
||||
"lastUpdateAttempt":"2017-12-22T05:48:16Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}*/
|
||||
public function refreshWebhook(Request $request)
|
||||
{
|
||||
//we should ignore this one
|
||||
nlog("yodlee refresh");
|
||||
nlog($request->all());
|
||||
|
||||
return response()->json(['message' => 'Success'], 200);
|
||||
|
||||
//
|
||||
|
||||
// return response()->json(['message' => 'Unauthorized'], 403);
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
"event":{
|
||||
"notificationId":"63c73475-4db5-49ef-8553-8303337ca7c3",
|
||||
"info":"LATEST_BALANCE_UPDATES",
|
||||
"loginName":"user1",
|
||||
"data":{
|
||||
"providerAccountId":658552,
|
||||
"latestBalanceEvent":[
|
||||
{
|
||||
"accountId":12345,
|
||||
"status":"SUCCESS"
|
||||
},
|
||||
{
|
||||
"accountId":12346,
|
||||
"status":"FAILED"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
public function balanceWebhook(Request $request)
|
||||
{
|
||||
|
||||
nlog("yodlee refresh");
|
||||
nlog($request->all());
|
||||
|
||||
return response()->json(['message' => 'Success'], 200);
|
||||
|
||||
//
|
||||
|
||||
// return response()->json(['message' => 'Unauthorized'], 403);
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
"event":{
|
||||
"data":[
|
||||
{
|
||||
"autoRefresh":{
|
||||
"additionalStatus":"SCHEDULED",
|
||||
"status":"ENABLED"
|
||||
},
|
||||
"accountIds":[
|
||||
1112645899,
|
||||
1112645898
|
||||
],
|
||||
"loginName":"YSL1555332811628",
|
||||
"providerAccountId":11381459
|
||||
}
|
||||
],
|
||||
"notificationTime":"2019-06-14T04:49:39Z",
|
||||
"notificationId":"4e672150-156048777",
|
||||
"info":"AUTO_REFRESH_UPDATES"
|
||||
}
|
||||
}
|
||||
*/
|
||||
public function refreshUpdatesWebhook(Request $request)
|
||||
{
|
||||
//notifies a user if there are problems with yodlee accessing the data
|
||||
nlog("update refresh");
|
||||
nlog($request->all());
|
||||
|
||||
return response()->json(['message' => 'Success'], 200);
|
||||
|
||||
//
|
||||
|
||||
// return response()->json(['message' => 'Unauthorized'], 403);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
"event": {
|
||||
"notificationId": "64b7ed1a-1530523285",
|
||||
"info": "DATA_UPDATES.USER_DATA",
|
||||
"data": {
|
||||
"userCount": 1,
|
||||
"fromDate": "2017-11-10T10:18:44Z",
|
||||
"toDate": "2017-11-10T11:18:43Z",
|
||||
"userData": [{
|
||||
"user": {
|
||||
"loginName": "YSL1484052178554"
|
||||
},
|
||||
"links": [{
|
||||
"methodType": "GET",
|
||||
"rel": "getUserData",
|
||||
"href": "dataExtracts/userData?fromDate=2017-11-10T10:18:44Z&toDate=2017-11-10T11:18:43Z&loginName=YSL1484052178554"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
*/
|
||||
public function dataUpdatesWebhook(Request $request)
|
||||
{
|
||||
//this is the main hook we use for notifications
|
||||
|
||||
nlog("data refresh");
|
||||
nlog($request->all());
|
||||
|
||||
return response()->json(['message' => 'Success'], 200);
|
||||
|
||||
//
|
||||
|
||||
// return response()->json(['message' => 'Unauthorized'], 403);
|
||||
}
|
||||
|
||||
}
|
697
app/Http/Controllers/BankIntegrationController.php
Normal file
697
app/Http/Controllers/BankIntegrationController.php
Normal file
@ -0,0 +1,697 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Factory\BankIntegrationFactory;
|
||||
use App\Filters\BankIntegrationFilters;
|
||||
use App\Helpers\Bank\Yodlee\Yodlee;
|
||||
use App\Http\Requests\BankIntegration\AdminBankIntegrationRequest;
|
||||
use App\Http\Requests\BankIntegration\CreateBankIntegrationRequest;
|
||||
use App\Http\Requests\BankIntegration\DestroyBankIntegrationRequest;
|
||||
use App\Http\Requests\BankIntegration\EditBankIntegrationRequest;
|
||||
use App\Http\Requests\BankIntegration\ShowBankIntegrationRequest;
|
||||
use App\Http\Requests\BankIntegration\StoreBankIntegrationRequest;
|
||||
use App\Http\Requests\BankIntegration\UpdateBankIntegrationRequest;
|
||||
use App\Jobs\Bank\ProcessBankTransactions;
|
||||
use App\Models\BankIntegration;
|
||||
use App\Repositories\BankIntegrationRepository;
|
||||
use App\Services\Bank\BankMatchingService;
|
||||
use App\Transformers\BankIntegrationTransformer;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class BankIntegrationController extends BaseController
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
protected $entity_type = BankIntegration::class;
|
||||
|
||||
protected $entity_transformer = BankIntegrationTransformer::class;
|
||||
|
||||
protected $bank_integration_repo;
|
||||
|
||||
public function __construct(BankIntegrationRepository $bank_integration_repo)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->bank_integration_repo = $bank_integration_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/bank_integrations",
|
||||
* operationId="getBankIntegrations",
|
||||
* tags={"bank_integrations"},
|
||||
* summary="Gets a list of bank_integrations",
|
||||
* description="Lists all bank integrations",
|
||||
* @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\Parameter(
|
||||
* name="rows",
|
||||
* in="query",
|
||||
* description="The number of bank integrations to return",
|
||||
* example="50",
|
||||
* required=false,
|
||||
* @OA\Schema(
|
||||
* type="number",
|
||||
* format="integer",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="A list of bank integrations",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankIntegration"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
* @param Request $request
|
||||
* @return Response|mixed
|
||||
*/
|
||||
public function index(BankIntegrationFilters $filters)
|
||||
{
|
||||
|
||||
$bank_integrations = BankIntegration::filter($filters);
|
||||
|
||||
return $this->listResponse($bank_integrations);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param ShowBankIntegrationRequest $request
|
||||
* @param BankIntegration $bank_integration
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/bank_integrations/{id}",
|
||||
* operationId="showBankIntegration",
|
||||
* tags={"bank_integrations"},
|
||||
* summary="Shows a bank_integration",
|
||||
* description="Displays a bank_integration 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 BankIntegration Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the bank_integration object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankIntegration"),
|
||||
* ),
|
||||
* @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(ShowBankIntegrationRequest $request, BankIntegration $bank_integration)
|
||||
{
|
||||
return $this->itemResponse($bank_integration);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param EditBankIntegrationRequest $request
|
||||
* @param BankIntegration $bank_integration
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/bank_integrations/{id}/edit",
|
||||
* operationId="editBankIntegration",
|
||||
* tags={"bank_integrations"},
|
||||
* summary="Shows a bank_integration for editing",
|
||||
* description="Displays a bank_integration 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 BankIntegration Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the bank_integration object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankIntegration"),
|
||||
* ),
|
||||
* @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(EditBankIntegrationRequest $request, BankIntegration $bank_integration)
|
||||
{
|
||||
return $this->itemResponse($bank_integration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param UpdateBankIntegrationRequest $request
|
||||
* @param BankIntegration $bank_integration
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Put(
|
||||
* path="/api/v1/bank_integrations/{id}",
|
||||
* operationId="updateBankIntegration",
|
||||
* tags={"bank_integrations"},
|
||||
* summary="Updates a bank_integration",
|
||||
* description="Handles the updating of a bank_integration 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 BankIntegration Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the bank_integration object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankIntegration"),
|
||||
* ),
|
||||
* @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(UpdateBankIntegrationRequest $request, BankIntegration $bank_integration)
|
||||
{
|
||||
|
||||
//stubs for updating the model
|
||||
$bank_integration = $this->bank_integration_repo->save($request->all(), $bank_integration);
|
||||
|
||||
return $this->itemResponse($bank_integration->fresh());
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param CreateBankIntegrationRequest $request
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/bank_integrations/create",
|
||||
* operationId="getBankIntegrationsCreate",
|
||||
* tags={"bank_integrations"},
|
||||
* summary="Gets a new blank bank_integration 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 bank_integration object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankIntegration"),
|
||||
* ),
|
||||
* @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(CreateBankIntegrationRequest $request)
|
||||
{
|
||||
$bank_integration = BankIntegrationFactory::create(auth()->user()->company()->id, auth()->user()->id, auth()->user()->account_id);
|
||||
|
||||
return $this->itemResponse($bank_integration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param StoreBankIntegrationRequest $request
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/bank_integrations",
|
||||
* operationId="storeBankIntegration",
|
||||
* tags={"bank_integrations"},
|
||||
* summary="Adds a bank_integration",
|
||||
* description="Adds an bank_integration 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 bank_integration object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankIntegration"),
|
||||
* ),
|
||||
* @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(StoreBankIntegrationRequest $request)
|
||||
{
|
||||
//stub to store the model
|
||||
$bank_integration = $this->bank_integration_repo->save($request->all(), BankIntegrationFactory::create(auth()->user()->company()->id, auth()->user()->id, auth()->user()->account_id));
|
||||
|
||||
return $this->itemResponse($bank_integration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param DestroyBankIntegrationRequest $request
|
||||
* @param BankIntegration $bank_integration
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @throws \Exception
|
||||
* @OA\Delete(
|
||||
* path="/api/v1/bank_integrations/{id}",
|
||||
* operationId="deleteBankIntegration",
|
||||
* tags={"bank_integrations"},
|
||||
* summary="Deletes a bank_integration",
|
||||
* description="Handles the deletion of a bank_integration 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 BankIntegration Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns a HTTP status",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function destroy(DestroyBankIntegrationRequest $request, BankIntegration $bank_integration)
|
||||
{
|
||||
$this->bank_integration_repo->delete($bank_integration);
|
||||
|
||||
return $this->itemResponse($bank_integration->fresh());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform bulk actions on the list view.
|
||||
*
|
||||
* @return Collection
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/bank_integrations/bulk",
|
||||
* operationId="bulkBankIntegrations",
|
||||
* tags={"bank_integrations"},
|
||||
* summary="Performs bulk actions on an array of bank_integrations",
|
||||
* 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="Action paramters",
|
||||
* 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 Bulk Action response",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\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');
|
||||
|
||||
if(!in_array($action, ['archive', 'restore', 'delete']))
|
||||
return response()->json(['message' => 'Unsupported action.'], 400);
|
||||
|
||||
$ids = request()->input('ids');
|
||||
|
||||
$bank_integrations = BankIntegration::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
|
||||
|
||||
$bank_integrations->each(function ($bank_integration, $key) use ($action) {
|
||||
if (auth()->user()->can('edit', $bank_integration)) {
|
||||
$this->bank_integration_repo->{$action}($bank_integration);
|
||||
}
|
||||
});
|
||||
|
||||
/* Need to understand which permission are required for the given bulk action ie. view / edit */
|
||||
|
||||
return $this->listResponse(BankIntegration::withTrashed()->whereIn('id', $this->transformKeys($ids))->company());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the remote list of accounts stored on the third party provider.
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/bank_integrations/refresh_accounts",
|
||||
* operationId="getRefreshAccounts",
|
||||
* tags={"bank_integrations"},
|
||||
* summary="Gets the list of accounts from the remote server",
|
||||
* description="Adds an bank_integration 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 bank_integration object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankIntegration"),
|
||||
* ),
|
||||
* @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 refreshAccounts(AdminBankIntegrationRequest $request)
|
||||
{
|
||||
// As yodlee is the first integration we don't need to perform switches yet, however
|
||||
// if we add additional providers we can reuse this class
|
||||
|
||||
$bank_account_id = auth()->user()->account->bank_integration_account_id;
|
||||
|
||||
if(!$bank_account_id)
|
||||
return response()->json(['message' => 'Not yet authenticated with Bank Integration service'], 400);
|
||||
|
||||
$yodlee = new Yodlee($bank_account_id);
|
||||
|
||||
$accounts = $yodlee->getAccounts();
|
||||
|
||||
foreach($accounts as $account)
|
||||
{
|
||||
|
||||
if(!BankIntegration::where('bank_account_id', $account['id'])->where('company_id', auth()->user()->company()->id)->exists())
|
||||
{
|
||||
$bank_integration = new BankIntegration();
|
||||
$bank_integration->company_id = auth()->user()->company()->id;
|
||||
$bank_integration->account_id = auth()->user()->account_id;
|
||||
$bank_integration->user_id = auth()->user()->id;
|
||||
$bank_integration->bank_account_id = $account['id'];
|
||||
$bank_integration->bank_account_type = $account['account_type'];
|
||||
$bank_integration->bank_account_name = $account['account_name'];
|
||||
$bank_integration->bank_account_status = $account['account_status'];
|
||||
$bank_integration->bank_account_number = $account['account_number'];
|
||||
$bank_integration->provider_id = $account['provider_id'];
|
||||
$bank_integration->provider_name = $account['provider_name'];
|
||||
$bank_integration->nickname = $account['nickname'];
|
||||
$bank_integration->balance = $account['current_balance'];
|
||||
$bank_integration->currency = $account['account_currency'];
|
||||
|
||||
$bank_integration->save();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$account = auth()->user()->account;
|
||||
|
||||
if(Cache::get("throttle_polling:{$account->key}"))
|
||||
return response()->json(BankIntegration::query()->company(), 200);
|
||||
|
||||
$account->bank_integrations->each(function ($bank_integration) use ($account){
|
||||
|
||||
ProcessBankTransactions::dispatch($account->bank_integration_account_id, $bank_integration);
|
||||
|
||||
});
|
||||
|
||||
Cache::put("throttle_polling:{$account->key}", true, 300);
|
||||
|
||||
return response()->json(BankIntegration::query()->company(), 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the remote list of accounts stored on the third party provider
|
||||
* and update our local cache.
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/bank_integrations/remove_account/account_id",
|
||||
* operationId="getRemoveAccount",
|
||||
* tags={"bank_integrations"},
|
||||
* summary="Removes an account from the integration",
|
||||
* description="Removes an account from the integration",
|
||||
* @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 bank_integration object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankIntegration"),
|
||||
* ),
|
||||
* @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 removeAccount(AdminBankIntegrationRequest $request, $acc_id)
|
||||
{
|
||||
|
||||
$bank_account_id = auth()->user()->account->bank_integration_account_id;
|
||||
|
||||
if(!$bank_account_id)
|
||||
return response()->json(['message' => 'Not yet authenticated with Bank Integration service'], 400);
|
||||
|
||||
$bi = BankIntegration::withTrashed()->where('bank_account_id', $acc_id)->where('company_id', auth()->user()->company()->id)->firstOrFail();
|
||||
|
||||
$yodlee = new Yodlee($bank_account_id);
|
||||
$res = $yodlee->deleteAccount($acc_id);
|
||||
|
||||
$this->bank_integration_repo->delete($bi);
|
||||
|
||||
return $this->itemResponse($bi->fresh());
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the remote list of accounts stored on the third party provider
|
||||
* and update our local cache.
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/bank_integrations/get_transactions/account_id",
|
||||
* operationId="getAccountTransactions",
|
||||
* tags={"bank_integrations"},
|
||||
* summary="Retrieve transactions for a account",
|
||||
* description="Retrieve transactions for a account",
|
||||
* @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="Retrieve transactions for a account",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankIntegration"),
|
||||
* ),
|
||||
* @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 getTransactions(AdminBankIntegrationRequest $request)
|
||||
{
|
||||
|
||||
auth()->user()->account->bank_integrations->each(function ($bank_integration) {
|
||||
|
||||
ProcessBankTransactions::dispatchSync(auth()->user()->account->bank_integration_account_id, $bank_integration);
|
||||
|
||||
});
|
||||
|
||||
return response()->json(['message' => 'Fetching transactions....'], 200);
|
||||
|
||||
}
|
||||
}
|
577
app/Http/Controllers/BankTransactionController.php
Normal file
577
app/Http/Controllers/BankTransactionController.php
Normal file
@ -0,0 +1,577 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Factory\BankTransactionFactory;
|
||||
use App\Filters\BankTransactionFilters;
|
||||
use App\Helpers\Bank\Yodlee\Yodlee;
|
||||
use App\Http\Requests\BankTransaction\AdminBankTransactionRequest;
|
||||
use App\Http\Requests\BankTransaction\CreateBankTransactionRequest;
|
||||
use App\Http\Requests\BankTransaction\DestroyBankTransactionRequest;
|
||||
use App\Http\Requests\BankTransaction\EditBankTransactionRequest;
|
||||
use App\Http\Requests\BankTransaction\ImportBankTransactionsRequest;
|
||||
use App\Http\Requests\BankTransaction\MatchBankTransactionRequest;
|
||||
use App\Http\Requests\BankTransaction\ShowBankTransactionRequest;
|
||||
use App\Http\Requests\BankTransaction\StoreBankTransactionRequest;
|
||||
use App\Http\Requests\BankTransaction\UpdateBankTransactionRequest;
|
||||
use App\Http\Requests\Import\PreImportRequest;
|
||||
use App\Jobs\Bank\MatchBankTransactions;
|
||||
use App\Models\BankTransaction;
|
||||
use App\Repositories\BankTransactionRepository;
|
||||
use App\Services\Bank\BankMatchingService;
|
||||
use App\Transformers\BankTransactionTransformer;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class BankTransactionController extends BaseController
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
protected $entity_type = BankTransaction::class;
|
||||
|
||||
protected $entity_transformer = BankTransactionTransformer::class;
|
||||
|
||||
protected $bank_transaction_repo;
|
||||
|
||||
public function __construct(BankTransactionRepository $bank_transaction_repo)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->bank_transaction_repo = $bank_transaction_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/bank_transactions",
|
||||
* operationId="getBankTransactions",
|
||||
* tags={"bank_transactions"},
|
||||
* summary="Gets a list of bank_transactions",
|
||||
* description="Lists all bank integrations",
|
||||
* @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\Parameter(
|
||||
* name="rows",
|
||||
* in="query",
|
||||
* description="The number of bank integrations to return",
|
||||
* example="50",
|
||||
* required=false,
|
||||
* @OA\Schema(
|
||||
* type="number",
|
||||
* format="integer",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="A list of bank integrations",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankTransaction"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
* @param BankTransactionFilters $filter
|
||||
* @return Response|mixed
|
||||
*/
|
||||
public function index(BankTransactionFilters $filters)
|
||||
{
|
||||
|
||||
$bank_transactions = BankTransaction::filter($filters);
|
||||
|
||||
return $this->listResponse($bank_transactions);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param ShowBankTransactionRequest $request
|
||||
* @param BankTransaction $bank_transaction
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/bank_transactions/{id}",
|
||||
* operationId="showBankTransaction",
|
||||
* tags={"bank_transactions"},
|
||||
* summary="Shows a bank_transaction",
|
||||
* description="Displays a bank_transaction 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 BankTransaction Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the bank_transaction object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankTransaction"),
|
||||
* ),
|
||||
* @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(ShowBankTransactionRequest $request, BankTransaction $bank_transaction)
|
||||
{
|
||||
return $this->itemResponse($bank_transaction);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param EditBankTransactionRequest $request
|
||||
* @param BankTransaction $bank_transaction
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/bank_transactions/{id}/edit",
|
||||
* operationId="editBankTransaction",
|
||||
* tags={"bank_transactions"},
|
||||
* summary="Shows a bank_transaction for editing",
|
||||
* description="Displays a bank_transaction 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 BankTransaction Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the bank_transaction object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankTransaction"),
|
||||
* ),
|
||||
* @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(EditBankTransactionRequest $request, BankTransaction $bank_transaction)
|
||||
{
|
||||
return $this->itemResponse($bank_transaction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param UpdateBankTransactionRequest $request
|
||||
* @param BankTransaction $bank_transaction
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Put(
|
||||
* path="/api/v1/bank_transactions/{id}",
|
||||
* operationId="updateBankTransaction",
|
||||
* tags={"bank_transactions"},
|
||||
* summary="Updates a bank_transaction",
|
||||
* description="Handles the updating of a bank_transaction 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 BankTransaction Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the bank_transaction object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankTransaction"),
|
||||
* ),
|
||||
* @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(UpdateBankTransactionRequest $request, BankTransaction $bank_transaction)
|
||||
{
|
||||
|
||||
//stubs for updating the model
|
||||
$bank_transaction = $this->bank_transaction_repo->save($request->all(), $bank_transaction);
|
||||
|
||||
return $this->itemResponse($bank_transaction->fresh());
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param CreateBankTransactionRequest $request
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/bank_transactions/create",
|
||||
* operationId="getBankTransactionsCreate",
|
||||
* tags={"bank_transactions"},
|
||||
* summary="Gets a new blank bank_transaction 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 bank_transaction object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankTransaction"),
|
||||
* ),
|
||||
* @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(CreateBankTransactionRequest $request)
|
||||
{
|
||||
$bank_transaction = BankTransactionFactory::create(auth()->user()->company()->id, auth()->user()->id, auth()->user()->account_id);
|
||||
|
||||
return $this->itemResponse($bank_transaction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param StoreBankTransactionRequest $request
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/bank_transactions",
|
||||
* operationId="storeBankTransaction",
|
||||
* tags={"bank_transactions"},
|
||||
* summary="Adds a bank_transaction",
|
||||
* description="Adds an bank_transaction 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 bank_transaction object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankTransaction"),
|
||||
* ),
|
||||
* @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(StoreBankTransactionRequest $request)
|
||||
{
|
||||
//stub to store the model
|
||||
$bank_transaction = $this->bank_transaction_repo->save($request->all(), BankTransactionFactory::create(auth()->user()->company()->id, auth()->user()->id, auth()->user()->account_id));
|
||||
|
||||
return $this->itemResponse($bank_transaction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param DestroyBankTransactionRequest $request
|
||||
* @param BankTransaction $bank_transaction
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @throws \Exception
|
||||
* @OA\Delete(
|
||||
* path="/api/v1/bank_transactions/{id}",
|
||||
* operationId="deleteBankTransaction",
|
||||
* tags={"bank_transactions"},
|
||||
* summary="Deletes a bank_transaction",
|
||||
* description="Handles the deletion of a bank_transaction 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 BankTransaction Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns a HTTP status",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function destroy(DestroyBankTransactionRequest $request, BankTransaction $bank_transaction)
|
||||
{
|
||||
$this->bank_transaction_repo->delete($bank_transaction);
|
||||
|
||||
return $this->itemResponse($bank_transaction->fresh());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform bulk actions on the list view.
|
||||
*
|
||||
* @return Collection
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/bank_transations/bulk",
|
||||
* operationId="bulkBankTransactions",
|
||||
* tags={"bank_transactions"},
|
||||
* summary="Performs bulk actions on an array of bank_transations",
|
||||
* 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="Action paramters",
|
||||
* 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 Bulk Action response",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\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');
|
||||
|
||||
if(!in_array($action, ['archive', 'restore', 'delete', 'convert_matched']))
|
||||
return response()->json(['message' => 'Unsupported action.'], 400);
|
||||
|
||||
$ids = request()->input('ids');
|
||||
|
||||
$bank_transactions = BankTransaction::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
|
||||
|
||||
if($action == 'convert_matched') //catch this action
|
||||
{
|
||||
if(auth()->user()->isAdmin())
|
||||
{
|
||||
$this->bank_transaction_repo->convert_matched($bank_transactions);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
||||
$bank_transactions->each(function ($bank_transaction, $key) use ($action) {
|
||||
if (auth()->user()->can('edit', $bank_transaction)) {
|
||||
$this->bank_transaction_repo->{$action}($bank_transaction);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/* Need to understand which permission are required for the given bulk action ie. view / edit */
|
||||
|
||||
return $this->listResponse(BankTransaction::withTrashed()->whereIn('id', $this->transformKeys($ids))->company());
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform bulk actions on the list view.
|
||||
*
|
||||
* @return Collection
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/bank_transations/match",
|
||||
* operationId="matchBankTransactions",
|
||||
* tags={"bank_transactions"},
|
||||
* summary="Performs match actions on an array of bank_transactions",
|
||||
* 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="Action paramters",
|
||||
* 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 Bulk Action response",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\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 match(MatchBankTransactionRequest $request)
|
||||
{
|
||||
|
||||
// MatchBankTransactions::dispatch(auth()->user()->company()->id, auth()->user()->company()->db, $request->all());
|
||||
|
||||
$bts = (new MatchBankTransactions(auth()->user()->company()->id, auth()->user()->company()->db, $request->all()))->handle();
|
||||
|
||||
return $this->listResponse($bts);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
505
app/Http/Controllers/BankTransactionRuleController.php
Normal file
505
app/Http/Controllers/BankTransactionRuleController.php
Normal file
@ -0,0 +1,505 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Factory\BankTransactionFactory;
|
||||
use App\Factory\BankTransactionRuleFactory;
|
||||
use App\Filters\BankTransactionFilters;
|
||||
use App\Filters\BankTransactionRuleFilters;
|
||||
use App\Helpers\Bank\Yodlee\Yodlee;
|
||||
use App\Http\Requests\BankTransactionRule\CreateBankTransactionRuleRequest;
|
||||
use App\Http\Requests\BankTransactionRule\DestroyBankTransactionRuleRequest;
|
||||
use App\Http\Requests\BankTransactionRule\EditBankTransactionRuleRequest;
|
||||
use App\Http\Requests\BankTransactionRule\ShowBankTransactionRuleRequest;
|
||||
use App\Http\Requests\BankTransactionRule\StoreBankTransactionRuleRequest;
|
||||
use App\Http\Requests\BankTransactionRule\UpdateBankTransactionRuleRequest;
|
||||
use App\Http\Requests\BankTransaction\AdminBankTransactionRuleRequest;
|
||||
use App\Http\Requests\Import\PreImportRequest;
|
||||
use App\Jobs\Bank\MatchBankTransactionRules;
|
||||
use App\Models\BankTransaction;
|
||||
use App\Models\BankTransactionRule;
|
||||
use App\Repositories\BankTransactionRepository;
|
||||
use App\Repositories\BankTransactionRuleRepository;
|
||||
use App\Services\Bank\BankMatchingService;
|
||||
use App\Transformers\BankTransactionRuleTransformer;
|
||||
use App\Transformers\BankTransactionTransformer;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class BankTransactionRuleController extends BaseController
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
protected $entity_type = BankTransactionRule::class;
|
||||
|
||||
protected $entity_transformer = BankTransactionRuleTransformer::class;
|
||||
|
||||
protected $bank_transaction_repo;
|
||||
|
||||
public function __construct(BankTransactionRuleRepository $bank_transaction_repo)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->bank_transaction_repo = $bank_transaction_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/bank_transaction_rules",
|
||||
* operationId="getBankTransactionRules",
|
||||
* tags={"bank_transaction_rules"},
|
||||
* summary="Gets a list of bank_transaction_rules",
|
||||
* description="Lists all bank transaction rules",
|
||||
* @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\Parameter(
|
||||
* name="rows",
|
||||
* in="query",
|
||||
* description="The number of bank integrations to return",
|
||||
* example="50",
|
||||
* required=false,
|
||||
* @OA\Schema(
|
||||
* type="number",
|
||||
* format="integer",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="A list of bank integrations",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankTransactionRule"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
* @param BankTransactionFilters $filter
|
||||
* @return Response|mixed
|
||||
*/
|
||||
public function index(BankTransactionRuleFilters $filters)
|
||||
{
|
||||
|
||||
$bank_transaction_rules = BankTransactionRule::filter($filters);
|
||||
|
||||
return $this->listResponse($bank_transaction_rules);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param ShowBankTransactionRuleRequest $request
|
||||
* @param BankTransactionRule $bank_transaction_rule
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/bank_transaction_rules/{id}",
|
||||
* operationId="showBankTransactionRule",
|
||||
* tags={"bank_transaction_rules"},
|
||||
* summary="Shows a bank_transaction",
|
||||
* description="Displays a bank_transaction 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 Bank Transaction RuleHashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the bank_transaction rule object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankTransactionRule"),
|
||||
* ),
|
||||
* @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(ShowBankTransactionRuleRequest $request, BankTransactionRule $bank_transaction_rule)
|
||||
{
|
||||
return $this->itemResponse($bank_transaction_rule);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param EditBankTransactionRuleRequest $request
|
||||
* @param BankTransactionRule $bank_transaction_rule
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/bank_transaction_rules/{id}/edit",
|
||||
* operationId="editBankTransactionRule",
|
||||
* tags={"bank_transaction_rules"},
|
||||
* summary="Shows a bank_transaction for editing",
|
||||
* description="Displays a bank_transaction 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 Bank Transaction Rule Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the bank_transaction rule object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankTransactionRule"),
|
||||
* ),
|
||||
* @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(EditBankTransactionRuleRequest $request, BankTransactionRule $bank_transaction_rule)
|
||||
{
|
||||
return $this->itemResponse($bank_transaction_rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param UpdateBankTransactionRuleRequest $request
|
||||
* @param BankTransactionRule $bank_transaction_rule
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Put(
|
||||
* path="/api/v1/bank_transaction_rules/{id}",
|
||||
* operationId="updateBankTransactionRule",
|
||||
* tags={"bank_transaction_rules"},
|
||||
* summary="Updates a bank_transaction Rule",
|
||||
* description="Handles the updating of a bank_transaction rule 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 Bank Transaction Rule Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the bank_transaction rule object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankTransactionRule"),
|
||||
* ),
|
||||
* @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(UpdateBankTransactionRuleRequest $request, BankTransactionRule $bank_transaction_rule)
|
||||
{
|
||||
|
||||
//stubs for updating the model
|
||||
$bank_transaction = $this->bank_transaction_repo->save($request->all(), $bank_transaction_rule);
|
||||
|
||||
return $this->itemResponse($bank_transaction_rule->fresh());
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param CreateBankTransactionRuleRequest $request
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/bank_transaction_rules/create",
|
||||
* operationId="getBankTransactionRulesCreate",
|
||||
* tags={"bank_transaction_rules"},
|
||||
* summary="Gets a new blank bank_transaction rule 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 bank_transaction rule object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankTransactionRule"),
|
||||
* ),
|
||||
* @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(CreateBankTransactionRuleRequest $request)
|
||||
{
|
||||
$bank_transaction_rule = BankTransactionRuleFactory::create(auth()->user()->company()->id, auth()->user()->id, auth()->user()->account_id);
|
||||
|
||||
return $this->itemResponse($bank_transaction_rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param StoreBankTransactionRuleRequest $request
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/bank_transaction_rules",
|
||||
* operationId="storeBankTransaction",
|
||||
* tags={"bank_transaction_rules"},
|
||||
* summary="Adds a bank_transaction rule",
|
||||
* description="Adds an bank_transaction 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 bank_transaction rule object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/BankTransactionRule"),
|
||||
* ),
|
||||
* @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(StoreBankTransactionRuleRequest $request)
|
||||
{
|
||||
//stub to store the model
|
||||
$bank_transaction_rule = $this->bank_transaction_repo->save($request->all(), BankTransactionRuleFactory::create(auth()->user()->company()->id, auth()->user()->id, auth()->user()->account_id));
|
||||
|
||||
return $this->itemResponse($bank_transaction_rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param DestroyBankTransactionRuleRequest $request
|
||||
* @param BankTransactionRule $bank_transaction_rule
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @throws \Exception
|
||||
* @OA\Delete(
|
||||
* path="/api/v1/bank_transaction_rules/{id}",
|
||||
* operationId="deleteBankTransactionRule",
|
||||
* tags={"bank_transaction_rules"},
|
||||
* summary="Deletes a bank_transaction rule",
|
||||
* description="Handles the deletion of a bank_transaction rule 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 Bank Transaction Rule Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns a HTTP status",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function destroy(DestroyBankTransactionRuleRequest $request, BankTransactionRule $bank_transaction_rule)
|
||||
{
|
||||
$this->bank_transaction_repo->delete($bank_transaction_rule);
|
||||
|
||||
return $this->itemResponse($bank_transaction_rule->fresh());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform bulk actions on the list view.
|
||||
*
|
||||
* @return Collection
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/bank_transation_rules/bulk",
|
||||
* operationId="bulkBankTransactionRules",
|
||||
* tags={"bank_transaction_rules"},
|
||||
* summary="Performs bulk actions on an array of bank_transation rules",
|
||||
* 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="Action paramters",
|
||||
* 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 Bulk Action response",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\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');
|
||||
|
||||
if(!in_array($action, ['archive', 'restore', 'delete']))
|
||||
return response()->json(['message' => 'Unsupported action.'], 400);
|
||||
|
||||
$ids = request()->input('ids');
|
||||
|
||||
$bank_transaction_rules = BankTransactionRule::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
|
||||
|
||||
$bank_transaction_rules->each(function ($bank_transaction_rule, $key) use ($action) {
|
||||
if (auth()->user()->can('edit', $bank_transaction_rule)) {
|
||||
$this->bank_transaction_repo->{$action}($bank_transaction_rule);
|
||||
}
|
||||
});
|
||||
|
||||
/* Need to understand which permission are required for the given bulk action ie. view / edit */
|
||||
|
||||
return $this->listResponse(BankTransactionRule::withTrashed()->whereIn('id', $this->transformKeys($ids))->company());
|
||||
}
|
||||
|
||||
}
|
@ -12,6 +12,7 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Account;
|
||||
use App\Models\BankTransaction;
|
||||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use App\Transformers\ArraySerializer;
|
||||
@ -105,6 +106,9 @@ class BaseController extends Controller
|
||||
'company.vendors.documents',
|
||||
'company.webhooks',
|
||||
'company.system_logs',
|
||||
'company.bank_integrations',
|
||||
'company.bank_transactions',
|
||||
'company.bank_transaction_rules',
|
||||
];
|
||||
|
||||
private $mini_load = [
|
||||
@ -122,6 +126,8 @@ class BaseController extends Controller
|
||||
'company.designs.company',
|
||||
'company.expense_categories',
|
||||
'company.subscriptions',
|
||||
'company.bank_integrations',
|
||||
'company.bank_transaction_rules',
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
@ -438,11 +444,33 @@ class BaseController extends Controller
|
||||
$query->where('subscriptions.user_id', $user->id);
|
||||
}
|
||||
},
|
||||
'company.bank_integrations'=> function ($query) use ($updated_at, $user) {
|
||||
$query->whereNotNull('updated_at');
|
||||
|
||||
if (! $user->isAdmin()) {
|
||||
$query->where('bank_integrations.user_id', $user->id);
|
||||
}
|
||||
},
|
||||
'company.bank_transactions'=> function ($query) use ($updated_at, $user) {
|
||||
$query->where('updated_at', '>=', $updated_at);
|
||||
|
||||
if (! $user->isAdmin()) {
|
||||
$query->where('bank_transactions.user_id', $user->id);
|
||||
}
|
||||
},
|
||||
'company.bank_transaction_rules'=> function ($query) use ($updated_at, $user) {
|
||||
$query->where('updated_at', '>=', $updated_at);
|
||||
|
||||
if (! $user->isAdmin()) {
|
||||
$query->where('bank_transaction_rules.user_id', $user->id);
|
||||
}
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
if ($query instanceof Builder) {
|
||||
$limit = request()->input('per_page', 20);
|
||||
//27-10-2022 - enforce unsigned integer
|
||||
$limit = $this->resolveQueryLimit();
|
||||
|
||||
$paginator = $query->paginate($limit);
|
||||
$query = $paginator->getCollection();
|
||||
@ -455,6 +483,14 @@ class BaseController extends Controller
|
||||
return $this->response($this->manager->createData($resource)->toArray());
|
||||
}
|
||||
|
||||
private function resolveQueryLimit()
|
||||
{
|
||||
if(request()->has('per_page'))
|
||||
return abs((int)request()->input('per_page', 20));
|
||||
|
||||
return 20;
|
||||
}
|
||||
|
||||
protected function miniLoadResponse($query)
|
||||
{
|
||||
$user = auth()->user();
|
||||
@ -497,11 +533,23 @@ class BaseController extends Controller
|
||||
$query->where('activities.user_id', $user->id);
|
||||
}
|
||||
},
|
||||
'company.bank_integrations'=> function ($query) use ($created_at, $user) {
|
||||
|
||||
if (! $user->isAdmin()) {
|
||||
$query->where('bank_integrations.user_id', $user->id);
|
||||
}
|
||||
},
|
||||
'company.bank_transaction_rules'=> function ($query) use ($user) {
|
||||
|
||||
if (! $user->isAdmin()) {
|
||||
$query->where('bank_transaction_rules.user_id', $user->id);
|
||||
}
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
if ($query instanceof Builder) {
|
||||
$limit = request()->input('per_page', 20);
|
||||
$limit = $this->resolveQueryLimit();
|
||||
|
||||
$paginator = $query->paginate($limit);
|
||||
$query = $paginator->getCollection();
|
||||
@ -741,11 +789,25 @@ class BaseController extends Controller
|
||||
|
||||
}
|
||||
},
|
||||
'company.bank_integrations'=> function ($query) use ($created_at, $user) {
|
||||
$query->where('created_at', '>=', $created_at);
|
||||
|
||||
if (! $user->isAdmin()) {
|
||||
$query->where('bank_integrations.user_id', $user->id);
|
||||
}
|
||||
},
|
||||
'company.bank_transactions'=> function ($query) use ($created_at, $user) {
|
||||
$query->where('created_at', '>=', $created_at);
|
||||
|
||||
if (! $user->isAdmin()) {
|
||||
$query->where('bank_transactions.user_id', $user->id);
|
||||
}
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
if ($query instanceof Builder) {
|
||||
$limit = request()->input('per_page', 20);
|
||||
$limit = $this->resolveQueryLimit();
|
||||
|
||||
$paginator = $query->paginate($limit);
|
||||
$query = $paginator->getCollection();
|
||||
@ -773,8 +835,19 @@ class BaseController extends Controller
|
||||
// 10-01-2022 need to ensure we snake case properly here to ensure permissions work as expected
|
||||
// 28-03-2022 this is definitely correct here, do not append _ to the view, it resolved correctly when snake cased
|
||||
if (auth()->user() && ! auth()->user()->hasPermission('view'.lcfirst(class_basename(Str::snake($this->entity_type))))) {
|
||||
//03-09-2022
|
||||
$query->where('user_id', '=', auth()->user()->id)->orWhere('assigned_user_id', auth()->user()->id);
|
||||
//06-10-2022 - some entities do not have assigned_user_id - this becomes an issue when we have a large company and low permission users
|
||||
if(lcfirst(class_basename(Str::snake($this->entity_type))) == 'user')
|
||||
$query->where('id', auth()->user()->id);
|
||||
elseif($this->entity_type == BankTransaction::class){ //table without assigned_user_id
|
||||
$query->where('user_id', '=', auth()->user()->id);
|
||||
}
|
||||
elseif(in_array(lcfirst(class_basename(Str::snake($this->entity_type))),['design','group_setting','payment_term'])){
|
||||
//need to pass these back regardless
|
||||
nlog($this->entity_type);
|
||||
}
|
||||
else
|
||||
$query->where('user_id', '=', auth()->user()->id)->orWhere('assigned_user_id', auth()->user()->id);
|
||||
|
||||
}
|
||||
|
||||
if (request()->has('updated_at') && request()->input('updated_at') > 0) {
|
||||
@ -786,7 +859,7 @@ class BaseController extends Controller
|
||||
}
|
||||
|
||||
if ($query instanceof Builder) {
|
||||
$limit = request()->input('per_page', 20);
|
||||
$limit = $this->resolveQueryLimit();
|
||||
$paginator = $query->paginate($limit);
|
||||
$query = $paginator->getCollection();
|
||||
$resource = new Collection($query, $transformer, $this->entity_type);
|
||||
|
@ -640,7 +640,14 @@ class ClientController extends BaseController
|
||||
{
|
||||
//delete all documents
|
||||
$client->documents->each(function ($document) {
|
||||
Storage::disk(config('filesystems.default'))->delete($document->url);
|
||||
|
||||
try{
|
||||
Storage::disk(config('filesystems.default'))->delete($document->url);
|
||||
}
|
||||
catch(\Exception $e){
|
||||
nlog($e->getMessage());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
//force delete the client
|
||||
@ -662,7 +669,7 @@ class ClientController extends BaseController
|
||||
*
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/clients/{id}/{mergaeble_client_hashed_id}/merge",
|
||||
* path="/api/v1/clients/{id}/{mergeable_client_hashed_id}/merge",
|
||||
* operationId="mergeClient",
|
||||
* tags={"clients"},
|
||||
* summary="Merges two clients",
|
||||
@ -683,7 +690,7 @@ class ClientController extends BaseController
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="mergeable_client_hashedid",
|
||||
* name="mergeable_client_hashed_id",
|
||||
* in="path",
|
||||
* description="The Mergeable Client Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
|
@ -56,8 +56,6 @@ class InvoiceController extends Controller
|
||||
{
|
||||
set_time_limit(0);
|
||||
|
||||
// $invoice->service()->removeUnpaidGatewayFees()->save();
|
||||
|
||||
$invitation = $invoice->invitations()->where('client_contact_id', auth()->guard('contact')->user()->id)->first();
|
||||
|
||||
if ($invitation && auth()->guard('contact') && ! session()->get('is_silent') && ! $invitation->viewed_date) {
|
||||
|
@ -41,6 +41,25 @@ class SubscriptionPurchaseController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
public function upgrade(Subscription $subscription, Request $request)
|
||||
{
|
||||
/* Make sure the contact is logged into the correct company for this subscription */
|
||||
if (auth()->guard('contact')->user() && auth()->guard('contact')->user()->company_id != $subscription->company_id) {
|
||||
auth()->guard('contact')->logout();
|
||||
$request->session()->invalidate();
|
||||
}
|
||||
|
||||
if ($request->has('locale')) {
|
||||
$this->setLocale($request->query('locale'));
|
||||
}
|
||||
|
||||
return view('billing-portal.purchasev2', [
|
||||
'subscription' => $subscription,
|
||||
'hash' => Str::uuid()->toString(),
|
||||
'request_data' => $request->all(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set locale for incoming request.
|
||||
*
|
||||
@ -56,4 +75,7 @@ class SubscriptionPurchaseController extends Controller
|
||||
App::setLocale($record->locale);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -164,7 +164,8 @@ class CompanyController extends BaseController
|
||||
*/
|
||||
public function create(CreateCompanyRequest $request)
|
||||
{
|
||||
$company = CompanyFactory::create(auth()->user()->company()->account->id);
|
||||
$cf = new \App\Factory\CompanyFactory;
|
||||
$company = $cf->create(auth()->user()->company()->account->id);
|
||||
|
||||
return $this->itemResponse($company);
|
||||
}
|
||||
|
@ -110,6 +110,9 @@ class ConnectedAccountController extends BaseController
|
||||
|
||||
$email = $user->getMail() ?: $user->getUserPrincipalName();
|
||||
|
||||
nlog("microsoft");
|
||||
nlog($email);
|
||||
|
||||
if(auth()->user()->email != $email && MultiDB::checkUserEmailExists($email))
|
||||
return response()->json(['message' => ctrans('texts.email_already_register')], 400);
|
||||
|
||||
|
@ -33,6 +33,7 @@ use App\Models\Client;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Invoice;
|
||||
use App\Repositories\CreditRepository;
|
||||
use App\Services\PdfMaker\PdfMerge;
|
||||
use App\Transformers\CreditTransformer;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\TempFile;
|
||||
@ -534,6 +535,20 @@ class CreditController extends BaseController
|
||||
return response()->json(['message' => ctrans('texts.sent_message')], 200);
|
||||
}
|
||||
|
||||
if($action == 'bulk_print' && auth()->user()->can('view', $credits->first())){
|
||||
|
||||
$paths = $credits->map(function ($credit){
|
||||
return $credit->service()->getCreditPdf($credit->invitations->first());
|
||||
});
|
||||
|
||||
$merge = (new PdfMerge($paths->toArray()))->run();
|
||||
|
||||
return response()->streamDownload(function () use ($merge) {
|
||||
echo ($merge);
|
||||
}, 'print.pdf', ['Content-Type' => 'application/pdf']);
|
||||
|
||||
}
|
||||
|
||||
$credits->each(function ($credit, $key) use ($action) {
|
||||
if (auth()->user()->can('edit', $credit)) {
|
||||
$this->performAction($credit, $action, true);
|
||||
|
@ -131,22 +131,22 @@ class EmailController extends BaseController
|
||||
if(Ninja::isHosted() && !$entity_obj->company->account->account_sms_verified)
|
||||
return response(['message' => 'Please verify your account to send emails.'], 400);
|
||||
|
||||
nlog($entity);
|
||||
|
||||
if($entity == 'purchaseOrder' || $entity == 'purchase_order' || $template == 'purchase_order' || $entity == 'App\Models\PurchaseOrder'){
|
||||
return $this->sendPurchaseOrder($entity_obj, $data, $template);
|
||||
}
|
||||
|
||||
$entity_obj->invitations->each(function ($invitation) use ($data, $entity_string, $entity_obj, $template) {
|
||||
|
||||
if (! $invitation->contact->trashed() && $invitation->contact->email) {
|
||||
$entity_obj->service()->markSent()->save();
|
||||
|
||||
EmailEntity::dispatch($invitation->fresh(), $invitation->company, $template, $data);
|
||||
EmailEntity::dispatch($invitation->fresh(), $invitation->company, $template, $data)->delay(now()->addSeconds(2));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$entity_obj = $entity_obj->fresh();
|
||||
$entity_obj->last_sent_date = now();
|
||||
|
||||
$entity_obj->save();
|
||||
|
||||
/*Only notify the admin ONCE, not once per contact/invite*/
|
||||
@ -194,7 +194,7 @@ class EmailController extends BaseController
|
||||
|
||||
$data['template'] = $template;
|
||||
|
||||
PurchaseOrderEmail::dispatch($entity_obj, $entity_obj->company, $data);
|
||||
PurchaseOrderEmail::dispatch($entity_obj, $entity_obj->company, $data)->delay(now()->addSeconds(2));
|
||||
|
||||
return $this->itemResponse($entity_obj);
|
||||
|
||||
|
@ -126,7 +126,7 @@ class ImportController extends Controller
|
||||
|
||||
private function getEntityMap($entity_type)
|
||||
{
|
||||
return sprintf('App\\Import\\Definitions\%sMap', ucfirst($entity_type));
|
||||
return sprintf('App\\Import\\Definitions\%sMap', ucfirst(Str::camel($entity_type)));
|
||||
}
|
||||
|
||||
private function getCsvData($csvfile)
|
||||
@ -136,6 +136,8 @@ class ImportController extends Controller
|
||||
}
|
||||
|
||||
$csv = Reader::createFromString($csvfile);
|
||||
$csvdelimiter = self::detectDelimiter($csvfile);
|
||||
$csv->setDelimiter($csvdelimiter);
|
||||
$stmt = new Statement();
|
||||
$data = iterator_to_array($stmt->process($csv));
|
||||
|
||||
@ -156,4 +158,17 @@ class ImportController extends Controller
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function detectDelimiter($csvfile)
|
||||
{
|
||||
$delimiters = array(',', '.', ';');
|
||||
$bestDelimiter = false;
|
||||
$count = 0;
|
||||
foreach ($delimiters as $delimiter)
|
||||
if (substr_count($csvfile, $delimiter) > $count) {
|
||||
$count = substr_count($csvfile, $delimiter);
|
||||
$bestDelimiter = $delimiter;
|
||||
}
|
||||
return $bestDelimiter;
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ use App\Factory\CloneInvoiceToQuoteFactory;
|
||||
use App\Factory\InvoiceFactory;
|
||||
use App\Filters\InvoiceFilters;
|
||||
use App\Http\Requests\Invoice\ActionInvoiceRequest;
|
||||
use App\Http\Requests\Invoice\BulkInvoiceRequest;
|
||||
use App\Http\Requests\Invoice\CreateInvoiceRequest;
|
||||
use App\Http\Requests\Invoice\DestroyInvoiceRequest;
|
||||
use App\Http\Requests\Invoice\EditInvoiceRequest;
|
||||
@ -27,6 +28,7 @@ use App\Http\Requests\Invoice\StoreInvoiceRequest;
|
||||
use App\Http\Requests\Invoice\UpdateInvoiceRequest;
|
||||
use App\Http\Requests\Invoice\UpdateReminderRequest;
|
||||
use App\Http\Requests\Invoice\UploadInvoiceRequest;
|
||||
use App\Jobs\Cron\AutoBill;
|
||||
use App\Jobs\Entity\EmailEntity;
|
||||
use App\Jobs\Invoice\BulkInvoiceJob;
|
||||
use App\Jobs\Invoice\StoreInvoice;
|
||||
@ -40,6 +42,7 @@ use App\Models\Invoice;
|
||||
use App\Models\Quote;
|
||||
use App\Models\TransactionEvent;
|
||||
use App\Repositories\InvoiceRepository;
|
||||
use App\Services\PdfMaker\PdfMerge;
|
||||
use App\Transformers\InvoiceTransformer;
|
||||
use App\Transformers\QuoteTransformer;
|
||||
use App\Utils\Ninja;
|
||||
@ -237,7 +240,7 @@ class InvoiceController extends BaseController
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::INVOICE_UPDATED, $transaction, $invoice->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::INVOICE_UPDATED, $transaction, $invoice->company->db);
|
||||
|
||||
return $this->itemResponse($invoice);
|
||||
}
|
||||
@ -425,15 +428,15 @@ class InvoiceController extends BaseController
|
||||
|
||||
event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
|
||||
$transaction = [
|
||||
'invoice' => $invoice->transaction_event(),
|
||||
'payment' => [],
|
||||
'client' => $invoice->client->transaction_event(),
|
||||
'credit' => [],
|
||||
'metadata' => [],
|
||||
];
|
||||
// $transaction = [
|
||||
// 'invoice' => $invoice->transaction_event(),
|
||||
// 'payment' => [],
|
||||
// 'client' => $invoice->client->transaction_event(),
|
||||
// 'credit' => [],
|
||||
// 'metadata' => [],
|
||||
// ];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::INVOICE_UPDATED, $transaction, $invoice->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::INVOICE_UPDATED, $transaction, $invoice->company->db);
|
||||
|
||||
return $this->itemResponse($invoice);
|
||||
}
|
||||
@ -545,11 +548,11 @@ class InvoiceController extends BaseController
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function bulk()
|
||||
public function bulk(BulkInvoiceRequest $request)
|
||||
{
|
||||
$action = request()->input('action');
|
||||
$action = $request->input('action');
|
||||
|
||||
$ids = request()->input('ids');
|
||||
$ids = $request->input('ids');
|
||||
|
||||
if(Ninja::isHosted() && (stripos($action, 'email') !== false) && !auth()->user()->company()->account->account_sms_verified)
|
||||
return response(['message' => 'Please verify your account to send emails.'], 400);
|
||||
@ -588,6 +591,20 @@ class InvoiceController extends BaseController
|
||||
|
||||
}
|
||||
|
||||
if($action == 'bulk_print' && auth()->user()->can('view', $invoices->first())){
|
||||
|
||||
$paths = $invoices->map(function ($invoice){
|
||||
return $invoice->service()->getInvoicePdf();
|
||||
});
|
||||
|
||||
$merge = (new PdfMerge($paths->toArray()))->run();
|
||||
|
||||
return response()->streamDownload(function () use ($merge) {
|
||||
echo ($merge);
|
||||
}, 'print.pdf', ['Content-Type' => 'application/pdf']);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the other actions to the switch
|
||||
*/
|
||||
@ -680,11 +697,14 @@ class InvoiceController extends BaseController
|
||||
{
|
||||
/*If we are using bulk actions, we don't want to return anything */
|
||||
switch ($action) {
|
||||
case 'auto_bill':
|
||||
AutoBill::dispatch($invoice->id, $invoice->company->db);
|
||||
return $this->itemResponse($invoice);
|
||||
|
||||
case 'clone_to_invoice':
|
||||
$invoice = CloneInvoiceFactory::create($invoice, auth()->user()->id);
|
||||
|
||||
return $this->itemResponse($invoice);
|
||||
break;
|
||||
|
||||
case 'clone_to_quote':
|
||||
$quote = CloneInvoiceToQuoteFactory::create($invoice, auth()->user()->id);
|
||||
|
||||
@ -751,7 +771,7 @@ class InvoiceController extends BaseController
|
||||
}
|
||||
break;
|
||||
case 'cancel':
|
||||
$invoice = $invoice->service()->handleCancellation()->deletePdf()->touchPdf()->save();
|
||||
$invoice = $invoice->service()->handleCancellation()->touchPdf()->save();
|
||||
|
||||
if (! $bulk) {
|
||||
$this->itemResponse($invoice);
|
||||
@ -761,7 +781,7 @@ class InvoiceController extends BaseController
|
||||
case 'email':
|
||||
//check query parameter for email_type and set the template else use calculateTemplate
|
||||
|
||||
if (request()->has('email_type') && property_exists($invoice->company->settings, request()->input('email_type'))) {
|
||||
if (request()->has('email_type') && in_array(request()->input('email_type'), ['reminder1', 'reminder2', 'reminder3', 'reminder_endless', 'custom1', 'custom2', 'custom3'])) {
|
||||
$this->reminder_template = $invoice->client->getSetting(request()->input('email_type'));
|
||||
} else {
|
||||
$this->reminder_template = $invoice->calculateTemplate('invoice');
|
||||
|
@ -181,7 +181,10 @@ class MigrationController extends BaseController
|
||||
$company->tasks()->forceDelete();
|
||||
$company->vendors()->forceDelete();
|
||||
$company->expenses()->forceDelete();
|
||||
$company->purchase_orders()->forceDelete();
|
||||
$company->bank_transaction_rules()->forceDelete();
|
||||
$company->bank_transactions()->forceDelete();
|
||||
// $company->bank_integrations()->forceDelete();
|
||||
|
||||
$company->all_activities()->forceDelete();
|
||||
|
||||
$settings = $company->settings;
|
||||
|
@ -3,20 +3,21 @@
|
||||
* @OA\Schema(
|
||||
* schema="Activity",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="______"),
|
||||
* @OA\Property(property="activity_type_id", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="client_id", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="company_id", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="user_id", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="invoice_id", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="payment_id", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="credit_id", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="updated_at", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="expense_id", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="is_system", type="boolean", example=true, description="______"),
|
||||
* @OA\Property(property="contact_id", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="task_id", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="notes", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="ip", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="The id field of the activity"),
|
||||
* @OA\Property(property="activity_type_id", type="string", example="Opnel5aKBz", description="The activity type id"),
|
||||
* @OA\Property(property="client_id", type="string", example="Opnel5aKBz", description="The client hashed id"),
|
||||
* @OA\Property(property="company_id", type="string", example="Opnel5aKBz", description="The company hashed id"),
|
||||
* @OA\Property(property="user_id", type="string", example="Opnel5aKBz", description="The user hashed id"),
|
||||
* @OA\Property(property="invoice_id", type="string", example="Opnel5aKBz", description="The invoice hashed id"),
|
||||
* @OA\Property(property="payment_id", type="string", example="Opnel5aKBz", description="The payment hashed id"),
|
||||
* @OA\Property(property="credit_id", type="string", example="Opnel5aKBz", description="The credit hashed id"),
|
||||
* @OA\Property(property="updated_at", type="integer", example="343421434", description="Unixtimestamp the last time the record was updated"),
|
||||
* @OA\Property(property="expense_id", type="string", example="Opnel5aKBz", description="The expense hashed id"),
|
||||
* @OA\Property(property="is_system", type="boolean", example=true, description="Defines is the activity was performed by the system"),
|
||||
* @OA\Property(property="contact_id", type="string", example="Opnel5aKBz", description="The contact hashed id"),
|
||||
* @OA\Property(property="task_id", type="string", example="Opnel5aKBz", description="The task hashed id"),
|
||||
* @OA\Property(property="notes", type="string", example="Opnel5aKBz", description="Activity Notes"),
|
||||
* @OA\Property(property="token_id", type="string", example="Opnel5aKBz", description="The hashed ID of the token who performed the action"),
|
||||
* @OA\Property(property="ip", type="string", example="192.168.1.252", description="The IP Address of the user who performed the action"),
|
||||
* )
|
||||
*/
|
||||
|
10
app/Http/Controllers/OpenAPI/BTRulesSchema.php
Normal file
10
app/Http/Controllers/OpenAPI/BTRulesSchema.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* schema="BTRules",
|
||||
* type="object",
|
||||
* @OA\Property(property="data_key", type="string", example="description,amount", description="The key to search"),
|
||||
* @OA\Property(property="operator", type="string", example=">", description="The operator flag of the search"),
|
||||
* @OA\Property(property="value", type="string" ,example="bob", description="The value to search for"),
|
||||
* )
|
||||
*/
|
18
app/Http/Controllers/OpenAPI/BankIntegration.php
Normal file
18
app/Http/Controllers/OpenAPI/BankIntegration.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* schema="BankIntegration",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="AS3df3A", description="The bank integration hashed id"),
|
||||
* @OA\Property(property="company_id", type="string", example="AS3df3A", description="The company hashed id"),
|
||||
* @OA\Property(property="user_id", type="string", example="AS3df3A", description="The user hashed id"),
|
||||
* @OA\Property(property="provider_bank_name", type="string", example="Chase Bank", description="The providers bank name"),
|
||||
* @OA\Property(property="bank_account_id", type="integer", example="1233434", description="The bank account id"),
|
||||
* @OA\Property(property="bank_account_name", type="string", example="My Checking Acc", description="The name of the account"),
|
||||
* @OA\Property(property="bank_account_number", type="string", example="111 234 2332", description="The account number"),
|
||||
* @OA\Property(property="bank_account_status", type="string", example="ACTIVE", description="The status of the bank account"),
|
||||
* @OA\Property(property="bank_account_type", type="string", example="CREDITCARD", description="The type of account"),
|
||||
* @OA\Property(property="balance", type="number", example="1000000", description="The current bank balance if available"),
|
||||
* @OA\Property(property="currency", type="string", example="USD", description="iso_3166_3 code"),
|
||||
* )
|
||||
*/
|
20
app/Http/Controllers/OpenAPI/BankTransaction.php
Normal file
20
app/Http/Controllers/OpenAPI/BankTransaction.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* schema="BankTransaction",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="AS3df3A", description="The bank integration hashed id"),
|
||||
* @OA\Property(property="company_id", type="string", example="AS3df3A", description="The company hashed id"),
|
||||
* @OA\Property(property="user_id", type="string", example="AS3df3A", description="The user hashed id"),
|
||||
* @OA\Property(property="transaction_id", type="integer", example=343434, description="The id of the transaction rule"),
|
||||
* @OA\Property(property="amount", type="number", example=10.00, description="The transaction amount"),
|
||||
* @OA\Property(property="currency_id", type="string", example="1", description="The currency ID of the currency"),
|
||||
* @OA\Property(property="account_type", type="string", example="creditCard", description="The account type"),
|
||||
* @OA\Property(property="description", type="string", example="Potato purchases for kevin", description="The description of the transaction"),
|
||||
* @OA\Property(property="category_id", type="integer", example=1, description="The category id"),
|
||||
* @OA\Property(property="category_type", type="string", example="Expenses", description="The category description"),
|
||||
* @OA\Property(property="base_type", type="string", example="CREDIT", description="Either CREDIT or DEBIT"),
|
||||
* @OA\Property(property="date", type="string", example="2022-09-01", description="The date of the transaction"),
|
||||
* @OA\Property(property="bank_account_id", type="integer", example="1", description="The ID number of the bank account"),
|
||||
* )
|
||||
*/
|
25
app/Http/Controllers/OpenAPI/BankTransactionRule.php
Normal file
25
app/Http/Controllers/OpenAPI/BankTransactionRule.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* schema="BankTransactionRule",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="AS3df3A", description="The bank transaction rules hashed id"),
|
||||
* @OA\Property(property="company_id", type="string", example="AS3df3A", description="The company hashed id"),
|
||||
* @OA\Property(property="user_id", type="string", example="AS3df3A", description="The user hashed id"),
|
||||
* @OA\Property(property="name", type="string", example="Rule 1", description="The name of the transaction"),
|
||||
* @OA\Property(
|
||||
* property="rules",
|
||||
* type="array",
|
||||
* description="A mapped collection of the sub rules for the BankTransactionRule",
|
||||
* @OA\Items(
|
||||
* ref="#/components/schemas/BTRules",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Property(property="auto_convert", type="boolean", example=true, description="Flags whether the rule converts the transaction automatically"),
|
||||
* @OA\Property(property="matches_on_all", type="boolean", example=true, description="Flags whether all subrules are required for the match"),
|
||||
* @OA\Property(property="applies_to", type="string", example="CREDIT", description="Flags whether the rule applies to a CREDIT or DEBIT"),
|
||||
* @OA\Property(property="client_id", type="string", example="AS3df3A", description="The client hashed id"),
|
||||
* @OA\Property(property="vendor_id", type="string", example="AS3df3A", description="The vendor hashed id"),
|
||||
* @OA\Property(property="category_id", type="string", example="AS3df3A", description="The category hashed id"),
|
||||
* )
|
||||
*/
|
@ -3,29 +3,28 @@
|
||||
* @OA\Schema(
|
||||
* schema="ClientContact",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="_________"),
|
||||
* @OA\Property(property="user_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="company_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="client_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="first_name", type="string", example="", description="________"),
|
||||
* @OA\Property(property="last_name", type="string", example="", description="________"),
|
||||
* @OA\Property(property="phone", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value1", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value2", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value3", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value4", type="string", example="", description="________"),
|
||||
* @OA\Property(property="email", type="string", example="", description="________"),
|
||||
* @OA\Property(property="accepted_terms_version", type="string", example="", description="________"),
|
||||
* @OA\Property(property="password", type="string", example="", description="________"),
|
||||
* @OA\Property(property="confirmation-code", type="string", example="", description="________"),
|
||||
* @OA\Property(property="token", type="string", example="", description="________"),
|
||||
* @OA\Property(property="is_primary", type="boolean", example=true, description="________"),
|
||||
* @OA\Property(property="confirmed", type="boolean", example=true, description="________"),
|
||||
* @OA\Property(property="is_locked", type="boolean", example=true, description="________"),
|
||||
* @OA\Property(property="send_email", type="boolean", example=true, description="________"),
|
||||
* @OA\Property(property="failed_logins", type="number", format="integer", example="3", description="________"),
|
||||
* @OA\Property(property="email_verified_at", type="number", format="integer", example="134341234234", description="________"),
|
||||
* @OA\Property(property="paid_to_date", type="number", format="float", example="10.00", description="________"),
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="The hashed if of the contact"),
|
||||
* @OA\Property(property="user_id", type="string", example="Opnel5aKBz", description="The hashed id of the user who created the contact"),
|
||||
* @OA\Property(property="company_id", type="string", example="Opnel5aKBz", description="The hashed id of the company"),
|
||||
* @OA\Property(property="client_id", type="string", example="Opnel5aKBz", description="The hashed id of the client"),
|
||||
* @OA\Property(property="first_name", type="string", example="John", description="The first name of the contact"),
|
||||
* @OA\Property(property="last_name", type="string", example="Doe", description="The last name of the contact"),
|
||||
* @OA\Property(property="phone", type="string", example="555-152-4524", description="The phone number of the contact"),
|
||||
* @OA\Property(property="custom_value1", type="string", example="", description="A Custom field value"),
|
||||
* @OA\Property(property="custom_value2", type="string", example="", description="A Custom field value"),
|
||||
* @OA\Property(property="custom_value3", type="string", example="", description="A Custom field value"),
|
||||
* @OA\Property(property="custom_value4", type="string", example="", description="A Custom field value"),
|
||||
* @OA\Property(property="email", type="string", example="", description="The email of the contact"),
|
||||
* @OA\Property(property="accepted_terms_version", type="string", example="A long set of ToS", description="The terms of service which the contact has accpeted"),
|
||||
* @OA\Property(property="password", type="string", example="*****", description="The hashed password of the contact"),
|
||||
* @OA\Property(property="confirmation-code", type="string", example="333-sdjkh34gbasd", description="The confirmation code used to authenticate the contacts email address"),
|
||||
* @OA\Property(property="token", type="string", example="333-sdjkh34gbasd", description="A uuid based token."),
|
||||
* @OA\Property(property="is_primary", type="boolean", example=true, description="Defines is this contact is the primary contact for the client"),
|
||||
* @OA\Property(property="confirmed", type="boolean", example=true, description="Boolean value confirms the user has confirmed their account."),
|
||||
* @OA\Property(property="is_locked", type="boolean", example=true, description="Boolean value defines if the contact has been locked out."),
|
||||
* @OA\Property(property="send_email", type="boolean", example=true, description="Boolean value determines is this contact should receive emails"),
|
||||
* @OA\Property(property="failed_logins", type="number", format="integer", example="3", description="The number of failed logins the contact has had"),
|
||||
* @OA\Property(property="email_verified_at", type="number", format="integer", example="134341234234", description="The date which the contact confirmed their email"),
|
||||
* @OA\Property(property="last_login", type="number", format="integer", example="134341234234", description="Timestamp"),
|
||||
* @OA\Property(property="created_at", type="number", format="integer", example="134341234234", description="Timestamp"),
|
||||
* @OA\Property(property="updated_at", type="number", format="integer", example="134341234234", description="Timestamp"),
|
||||
|
@ -3,13 +3,13 @@
|
||||
* @OA\Schema(
|
||||
* schema="ClientGatewayToken",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="______"),
|
||||
* @OA\Property(property="company_id", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="client_id", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="token", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="routing_number", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="company_gateway_id", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="is_default", type="boolean", example="true", description="______"),
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="The hashed id of the client gateway token"),
|
||||
* @OA\Property(property="company_id", type="string", example="2", description="The hashed id of the company"),
|
||||
* @OA\Property(property="client_id", type="string", example="2", description="The hashed_id of the client"),
|
||||
* @OA\Property(property="token", type="string", example="2", description="The payment token"),
|
||||
* @OA\Property(property="routing_number", type="string", example="2", description="THe bank account routing number"),
|
||||
* @OA\Property(property="company_gateway_id", type="string", example="2", description="The hashed id of the company gateway"),
|
||||
* @OA\Property(property="is_default", type="boolean", example="true", description="Flag determining if the token is the default payment method"),
|
||||
*
|
||||
* )
|
||||
*/
|
||||
|
@ -3,9 +3,9 @@
|
||||
* @OA\Schema(
|
||||
* schema="Client",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="_________"),
|
||||
* @OA\Property(property="user_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="company_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="The hashed id of the client"),
|
||||
* @OA\Property(property="user_id", type="string", example="", description="The hashed id of the user"),
|
||||
* @OA\Property(property="company_id", type="string", example="", description="The hashed id of the company"),
|
||||
* @OA\Property(
|
||||
* property="contacts",
|
||||
* type="array",
|
||||
@ -13,35 +13,35 @@
|
||||
* ref="#/components/schemas/ClientContact",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Property(property="name", type="string", example="", description="________"),
|
||||
* @OA\Property(property="website", type="string", example="", description="________"),
|
||||
* @OA\Property(property="private_notes", type="string", example="", description="________"),
|
||||
* @OA\Property(property="client_hash", type="string", example="", description="________"),
|
||||
* @OA\Property(property="industry_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="size_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="address1", type="string", example="", description="________"),
|
||||
* @OA\Property(property="address2", type="string", example="", description="________"),
|
||||
* @OA\Property(property="city", type="string", example="", description="________"),
|
||||
* @OA\Property(property="state", type="string", example="", description="________"),
|
||||
* @OA\Property(property="postal_code", type="string", example="", description="________"),
|
||||
* @OA\Property(property="name", type="string", example="Jims housekeeping", description="The client name"),
|
||||
* @OA\Property(property="website", type="string", example="www.jims.com", description="The client website"),
|
||||
* @OA\Property(property="private_notes", type="string", example="These are very private notes", description="Private notes on the client"),
|
||||
* @OA\Property(property="client_hash", type="string", example="asdfkjhk342hjhbfdvmnfb1", description="The client hash"),
|
||||
* @OA\Property(property="industry_id", type="number", example="5", description="The industry id of the client"),
|
||||
* @OA\Property(property="size_id", type="number", example="2", description="The size id of the client"),
|
||||
* @OA\Property(property="address1", type="string", example="", description="Address line 1"),
|
||||
* @OA\Property(property="address2", type="string", example="", description="Address line 2"),
|
||||
* @OA\Property(property="city", type="string", example="Beverley Hills", description="City"),
|
||||
* @OA\Property(property="state", type="string", example="Californnia", description="State/Locality"),
|
||||
* @OA\Property(property="postal_code", type="string", example="90210", description="Zip / Postal code"),
|
||||
* @OA\Property(property="phone", type="string", example="555-3434-3434", description="The client phone number"),
|
||||
* @OA\Property(property="country_id", type="number", format="integer", example="1", description="________"),
|
||||
* @OA\Property(property="custom_value1", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value2", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value3", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value4", type="string", example="", description="________"),
|
||||
* @OA\Property(property="vat_number", type="string", example="", description="________"),
|
||||
* @OA\Property(property="id_number", type="string", example="", description="________"),
|
||||
* @OA\Property(property="number", type="string", example="", description="________"),
|
||||
* @OA\Property(property="shipping_address1", type="string", example="", description="________"),
|
||||
* @OA\Property(property="shipping_address2", type="string", example="", description="________"),
|
||||
* @OA\Property(property="shipping_city", type="string", example="", description="________"),
|
||||
* @OA\Property(property="shipping_state", type="string", example="", description="________"),
|
||||
* @OA\Property(property="shipping_postal_code", type="string", example="", description="________"),
|
||||
* @OA\Property(property="shipping_country_id", type="number", format="integer", example="", description="________"),
|
||||
* @OA\Property(property="is_deleted", type="boolean", example=true, description="________"),
|
||||
* @OA\Property(property="balance", type="number", format="float", example="10.00", description="________"),
|
||||
* @OA\Property(property="paid_to_date", type="number", format="float", example="10.00", description="________"),
|
||||
* @OA\Property(property="country_id", type="number", format="integer", example="1", description="The client country id"),
|
||||
* @OA\Property(property="custom_value1", type="string", example="Something custom", description="A custom value"),
|
||||
* @OA\Property(property="custom_value2", type="string", example="2002-01-01", description="A custom value"),
|
||||
* @OA\Property(property="custom_value3", type="string", example="Something custom", description="A custom value"),
|
||||
* @OA\Property(property="custom_value4", type="string", example="Something custom", description="A custom value"),
|
||||
* @OA\Property(property="vat_number", type="string", example="VAT123", description="The client VAT number"),
|
||||
* @OA\Property(property="id_number", type="string", example="CLIENT_ID_NUMBER", description=" The client id number"),
|
||||
* @OA\Property(property="number", type="string", example="", description="The client number - assigned by the system typically"),
|
||||
* @OA\Property(property="shipping_address1", type="string", example="5 Wallaby Way", description="The shipping address line 1"),
|
||||
* @OA\Property(property="shipping_address2", type="string", example="Suite 5", description="The shipping address line 2"),
|
||||
* @OA\Property(property="shipping_city", type="string", example="Perth", description="The shipping city"),
|
||||
* @OA\Property(property="shipping_state", type="string", example="Western Australia", description="The shipping state"),
|
||||
* @OA\Property(property="shipping_postal_code", type="string", example="6110", description="The shipping postal code"),
|
||||
* @OA\Property(property="shipping_country_id", type="number", format="integer", example="4", description="The shipping country id"),
|
||||
* @OA\Property(property="is_deleted", type="boolean", example=true, description="Boolean flagged determining if the client has been deleted"),
|
||||
* @OA\Property(property="balance", type="number", format="float", example="10.00", description="The client balance"),
|
||||
* @OA\Property(property="paid_to_date", type="number", format="float", example="10.00", description="The amount the client has paid to date."),
|
||||
* @OA\Property(property="credit_balance", type="number", format="float", example="10.00", description="An amount which is available to the client for future use."),
|
||||
* @OA\Property(property="last_login", type="number", format="integer", example="134341234234", description="Timestamp"),
|
||||
* @OA\Property(property="created_at", type="number", format="integer", example="134341234234", description="Timestamp"),
|
||||
|
@ -3,14 +3,14 @@
|
||||
* @OA\Schema(
|
||||
* schema="CompanyGateway",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="______"),
|
||||
* @OA\Property(property="company_id", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="gateway_key", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="The hashed id of the company gateway"),
|
||||
* @OA\Property(property="company_id", type="string", example="2", description="The company hashed id"),
|
||||
* @OA\Property(property="gateway_key", type="string", example="2", description="The gateway key (hash)"),
|
||||
* @OA\Property(property="accepted_credit_cards", type="integer", example="32", description="Bitmask representation of cards"),
|
||||
* @OA\Property(property="require_billing_address", type="boolean", example=true, description="______"),
|
||||
* @OA\Property(property="require_shipping_address", type="boolean", example=true, description="______"),
|
||||
* @OA\Property(property="require_billing_address", type="boolean", example=true, description="Determines if the the billing address is required prior to payment."),
|
||||
* @OA\Property(property="require_shipping_address", type="boolean", example=true, description="Determines if the the billing address is required prior to payment."),
|
||||
* @OA\Property(property="config", type="string", example="dfadsfdsafsafd", description="The configuration map for the gateway"),
|
||||
* @OA\Property(property="update_details", type="boolean", example=true, description="______"),
|
||||
* @OA\Property(property="update_details", type="boolean", example=true, description="Determines if the client details should be updated."),
|
||||
* @OA\Property(
|
||||
* property="fees_and_limits",
|
||||
* type="array",
|
||||
|
@ -17,9 +17,9 @@
|
||||
* @OA\Property(property="update_products", type="boolean", example=true, description="Toggles updating a product description which description changes"),
|
||||
* @OA\Property(property="show_product_details", type="boolean", example=true, description="Toggles showing a product description which description changes"),
|
||||
* @OA\Property(property="custom_fields", type="object", description="Custom fields map"),
|
||||
* @OA\Property(property="enable_product_cost", type="boolean", example=true, description="______________"),
|
||||
* @OA\Property(property="enable_product_quantity", type="boolean", example=true, description="______________"),
|
||||
* @OA\Property(property="default_quantity", type="boolean", example=true, description="______________"),
|
||||
* @OA\Property(property="enable_product_cost", type="boolean", example=true, description="Show/Hide the product cost field in the UI"),
|
||||
* @OA\Property(property="enable_product_quantity", type="boolean", example=true, description="Show/hide the product quantity field (used in the UI to show the default quantity)"),
|
||||
* @OA\Property(property="default_quantity", type="boolean", example=true, description="Enable/Disable whether to use a default quantity"),
|
||||
* @OA\Property(property="custom_surcharge_taxes1", type="boolean", example=true, description="Toggles charging taxes on custom surcharge amounts"),
|
||||
* @OA\Property(property="custom_surcharge_taxes2", type="boolean", example=true, description="Toggles charging taxes on custom surcharge amounts"),
|
||||
* @OA\Property(property="custom_surcharge_taxes3", type="boolean", example=true, description="Toggles charging taxes on custom surcharge amounts"),
|
||||
|
@ -4,20 +4,20 @@
|
||||
* schema="CompanySettings",
|
||||
* type="object",
|
||||
* @OA\Property(property="timezone_id", type="string", example="15", description="The timezone id"),
|
||||
* @OA\Property(property="date_format_id", type="string", example="15", description="____________"),
|
||||
* @OA\Property(property="military_time", type="boolean", example=true, description="____________"),
|
||||
* @OA\Property(property="language_id", type="string", example="1", description="____________"),
|
||||
* @OA\Property(property="show_currency_code", type="boolean", example=true, description="____________"),
|
||||
* @OA\Property(property="date_format_id", type="string", example="15", description="The date format id"),
|
||||
* @OA\Property(property="military_time", type="boolean", example=true, description="Toggles 12/24 hour time"),
|
||||
* @OA\Property(property="language_id", type="string", example="1", description="The language id"),
|
||||
* @OA\Property(property="show_currency_code", type="boolean", example=true, description="Toggles whether the currency symbol or code is shown"),
|
||||
* @OA\Property(property="currency_id", type="string", example=true, description="The default currency id"),
|
||||
* @OA\Property(property="payment_terms", type="integer", example="1", description="-1 sets no payment term, 0 sets payment due immediately, positive integers indicates payment terms in days"),
|
||||
* @OA\Property(property="company_gateway_ids", type="string", example="1,2,3,4", description="A commad separate list of available gateways"),
|
||||
* @OA\Property(property="custom_value1", type="string", example="Custom Label", description="____________"),
|
||||
* @OA\Property(property="custom_value2", type="string", example="Custom Label", description="____________"),
|
||||
* @OA\Property(property="custom_value3", type="string", example="Custom Label", description="____________"),
|
||||
* @OA\Property(property="custom_value4", type="string", example="Custom Label", description="____________"),
|
||||
* @OA\Property(property="default_task_rate", type="number", format="float", example="10.00", description="____________"),
|
||||
* @OA\Property(property="send_reminders", type="boolean", example=true, description="____________"),
|
||||
* @OA\Property(property="enable_client_portal_tasks", type="boolean", example=true, description="____________"),
|
||||
* @OA\Property(property="custom_value1", type="string", example="Custom Label", description="A Custom Label"),
|
||||
* @OA\Property(property="custom_value2", type="string", example="Custom Label", description="A Custom Label"),
|
||||
* @OA\Property(property="custom_value3", type="string", example="Custom Label", description="A Custom Label"),
|
||||
* @OA\Property(property="custom_value4", type="string", example="Custom Label", description="A Custom Label"),
|
||||
* @OA\Property(property="default_task_rate", type="number", format="float", example="10.00", description="The default task rate"),
|
||||
* @OA\Property(property="send_reminders", type="boolean", example=true, description="Toggles whether reminders are sent"),
|
||||
* @OA\Property(property="enable_client_portal_tasks", type="boolean", example=true, description="Show/hide the tasks panel in the client portal"),
|
||||
* @OA\Property(property="email_style", type="string", example="light", description="options include plain,light,dark,custom"),
|
||||
* @OA\Property(property="reply_to_email", type="string", example="email@gmail.com", description="The reply to email address"),
|
||||
* @OA\Property(property="bcc_email", type="string", example="email@gmail.com, contact@gmail.com", description="A comma separate list of BCC emails"),
|
||||
@ -26,35 +26,35 @@
|
||||
* @OA\Property(property="email_style_custom", type="string", example="<HTML></HTML>", description="The custom template"),
|
||||
* @OA\Property(property="counter_number_applied", type="string", example="when_sent", description="enum when the invoice number counter is set, ie when_saved, when_sent, when_paid"),
|
||||
* @OA\Property(property="quote_number_applied", type="string", example="when_sent", description="enum when the quote number counter is set, ie when_saved, when_sent"),
|
||||
* @OA\Property(property="custom_message_dashboard", type="string", example="Please pay invoices immediately", description="____________"),
|
||||
* @OA\Property(property="custom_message_unpaid_invoice", type="string", example="Please pay invoices immediately", description="____________"),
|
||||
* @OA\Property(property="custom_message_paid_invoice", type="string", example="Thanks for paying this invoice!", description="____________"),
|
||||
* @OA\Property(property="custom_message_unapproved_quote", type="string", example="Please approve quote", description="____________"),
|
||||
* @OA\Property(property="lock_invoices", type="boolean", example=true, description="____________"),
|
||||
* @OA\Property(property="auto_archive_invoice", type="boolean", example=true, description="____________"),
|
||||
* @OA\Property(property="auto_archive_quote", type="boolean", example=true, description="____________"),
|
||||
* @OA\Property(property="auto_convert_quote", type="boolean", example=true, description="____________"),
|
||||
* @OA\Property(property="inclusive_taxes", type="boolean", example=true, description="____________"),
|
||||
* @OA\Property(property="custom_message_dashboard", type="string", example="Please pay invoices immediately", description="A custom message which is displayed on the dashboard"),
|
||||
* @OA\Property(property="custom_message_unpaid_invoice", type="string", example="Please pay invoices immediately", description="A custom message which is displayed in the client portal when a client is viewing a unpaid invoice."),
|
||||
* @OA\Property(property="custom_message_paid_invoice", type="string", example="Thanks for paying this invoice!", description="A custom message which is displayed in the client portal when a client is viewing a paid invoice."),
|
||||
* @OA\Property(property="custom_message_unapproved_quote", type="string", example="Please approve quote", description="A custom message which is displayed in the client portal when a client is viewing a unapproved quote."),
|
||||
* @OA\Property(property="lock_invoices", type="boolean", example=true, description="Toggles whether invoices are locked once sent and cannot be modified further"),
|
||||
* @OA\Property(property="auto_archive_invoice", type="boolean", example=true, description="Toggles whether a invoice is archived immediately following payment"),
|
||||
* @OA\Property(property="auto_archive_quote", type="boolean", example=true, description="Toggles whether a quote is archived after being converted to a invoice"),
|
||||
* @OA\Property(property="auto_convert_quote", type="boolean", example=true, description="Toggles whether a quote is converted to a invoice when approved"),
|
||||
* @OA\Property(property="inclusive_taxes", type="boolean", example=true, description="Boolean flag determining whether inclusive or exclusive taxes are used"),
|
||||
* @OA\Property(property="translations", type="object", example="", description="JSON payload of customized translations"),
|
||||
* @OA\Property(property="task_number_pattern", type="string", example="{$year}-{$counter}", description="Allows customisation of the task number pattern"),
|
||||
* @OA\Property(property="task_number_counter", type="integer", example="1", description="____________"),
|
||||
* @OA\Property(property="task_number_counter", type="integer", example="1", description="The incrementing counter for tasks"),
|
||||
* @OA\Property(property="reminder_send_time", type="integer", example="32400", description="Time from UTC +0 when the email will be sent to the client"),
|
||||
* @OA\Property(property="expense_number_pattern", type="string", example="{$year}-{$counter}", description="Allows customisation of the expense number pattern"),
|
||||
* @OA\Property(property="expense_number_counter", type="integer", example="1", description="____________"),
|
||||
* @OA\Property(property="expense_number_counter", type="integer", example="1", description="The incrementing counter for expenses"),
|
||||
* @OA\Property(property="vendor_number_pattern", type="string", example="{$year}-{$counter}", description="Allows customisation of the vendor number pattern"),
|
||||
* @OA\Property(property="vendor_number_counter", type="integer", example="1", description="____________"),
|
||||
* @OA\Property(property="vendor_number_counter", type="integer", example="1", description="The incrementing counter for vendors"),
|
||||
* @OA\Property(property="ticket_number_pattern", type="string", example="{$year}-{$counter}", description="Allows customisation of the ticket number pattern"),
|
||||
* @OA\Property(property="ticket_number_counter", type="integer", example="1", description="____________"),
|
||||
* @OA\Property(property="ticket_number_counter", type="integer", example="1", description="The incrementing counter for tickets"),
|
||||
* @OA\Property(property="payment_number_pattern", type="string", example="{$year}-{$counter}", description="Allows customisation of the payment number pattern"),
|
||||
* @OA\Property(property="payment_number_counter", type="integer", example="1", description="____________"),
|
||||
* @OA\Property(property="payment_number_counter", type="integer", example="1", description="The incrementing counter for payments"),
|
||||
* @OA\Property(property="invoice_number_pattern", type="string", example="{$year}-{$counter}", description="Allows customisation of the invoice number pattern"),
|
||||
* @OA\Property(property="invoice_number_counter", type="integer", example="1", description="____________"),
|
||||
* @OA\Property(property="invoice_number_counter", type="integer", example="1", description="The incrementing counter for invoices"),
|
||||
* @OA\Property(property="quote_number_pattern", type="string", example="{$year}-{$counter}", description="Allows customisation of the quote number pattern"),
|
||||
* @OA\Property(property="quote_number_counter", type="integer", example="1", description="____________"),
|
||||
* @OA\Property(property="quote_number_counter", type="integer", example="1", description="The incrementing counter for quotes"),
|
||||
* @OA\Property(property="client_number_pattern", type="string", example="{$year}-{$counter}", description="Allows customisation of the client number pattern"),
|
||||
* @OA\Property(property="client_number_counter", type="integer", example="1", description="____________"),
|
||||
* @OA\Property(property="client_number_counter", type="integer", example="1", description="The incrementing counter for clients"),
|
||||
* @OA\Property(property="credit_number_pattern", type="string", example="{$year}-{$counter}", description="Allows customisation of the credit number pattern"),
|
||||
* @OA\Property(property="credit_number_counter", type="integer", example="1", description="____________"),
|
||||
* @OA\Property(property="credit_number_counter", type="integer", example="1", description="The incrementing counter for credits"),
|
||||
* @OA\Property(property="recurring_invoice_number_prefix", type="string", example="R", description="This string is prepended to the recurring invoice number"),
|
||||
* @OA\Property(property="reset_counter_frequency_id", type="integer", example="1", description="CONSTANT which is used to apply the frequency which the counters are reset"),
|
||||
* @OA\Property(property="reset_counter_date", type="string", example="2019-01-01", description="The explicit date which is used to reset counters"),
|
||||
@ -103,52 +103,52 @@
|
||||
* @OA\Property(property="name", type="string", example="Acme Co", description="The company name"),
|
||||
* @OA\Property(property="company_logo", type="object", example="logo.png", description="The company logo file"),
|
||||
* @OA\Property(property="website", type="string", example="www.acme.com", description="The company website URL"),
|
||||
* @OA\Property(property="address1", type="string", example="Suite 888", description="____________"),
|
||||
* @OA\Property(property="address2", type="string", example="5 Jimbo Way", description="____________"),
|
||||
* @OA\Property(property="city", type="string", example="Sydney", description="____________"),
|
||||
* @OA\Property(property="state", type="string", example="Florisa", description="____________"),
|
||||
* @OA\Property(property="postal_code", type="string", example="90210", description="____________"),
|
||||
* @OA\Property(property="phone", type="string", example="555-213-3948", description="____________"),
|
||||
* @OA\Property(property="email", type="string", example="joe@acme.co", description="____________"),
|
||||
* @OA\Property(property="address1", type="string", example="Suite 888", description="The company address line 1"),
|
||||
* @OA\Property(property="address2", type="string", example="5 Jimbo Way", description="The company address line 2"),
|
||||
* @OA\Property(property="city", type="string", example="Sydney", description="The company city"),
|
||||
* @OA\Property(property="state", type="string", example="Florisa", description="The company state"),
|
||||
* @OA\Property(property="postal_code", type="string", example="90210", description="The company zip/postal code"),
|
||||
* @OA\Property(property="phone", type="string", example="555-213-3948", description="The company phone"),
|
||||
* @OA\Property(property="email", type="string", example="joe@acme.co", description="The company email"),
|
||||
* @OA\Property(property="country_id", type="string", example="1", description="The country ID"),
|
||||
* @OA\Property(property="vat_number", type="string", example="32 120 377 720", description="____________"),
|
||||
* @OA\Property(property="vat_number", type="string", example="32 120 377 720", description="The company VAT/TAX ID number"),
|
||||
* @OA\Property(property="page_size", type="string", example="A4", description="The default page size"),
|
||||
* @OA\Property(property="font_size", type="number", example="9", description="The font size"),
|
||||
* @OA\Property(property="primary_font", type="string", example="roboto", description="The primary font"),
|
||||
* @OA\Property(property="secondary_font", type="string", example="roboto", description="The secondary font"),
|
||||
* @OA\Property(property="hide_paid_to_date", type="boolean", example=false, description="____________"),
|
||||
* @OA\Property(property="embed_documents", type="boolean", example=false, description="____________"),
|
||||
* @OA\Property(property="all_pages_header", type="boolean", example=false, description="____________"),
|
||||
* @OA\Property(property="all_pages_footer", type="boolean", example=false, description="____________"),
|
||||
* @OA\Property(property="document_email_attachment", type="boolean", example=false, description="____________"),
|
||||
* @OA\Property(property="enable_client_portal_password", type="boolean", example=false, description="____________"),
|
||||
* @OA\Property(property="enable_email_markup", type="boolean", example=false, description="____________"),
|
||||
* @OA\Property(property="enable_client_portal_dashboard", type="boolean", example=false, description="____________"),
|
||||
* @OA\Property(property="enable_client_portal", type="boolean", example=false, description="____________"),
|
||||
* @OA\Property(property="email_template_statement", type="string", example="template matter", description="____________"),
|
||||
* @OA\Property(property="email_subject_statement", type="string", example="subject matter", description="____________"),
|
||||
* @OA\Property(property="signature_on_pdf", type="boolean", example=false, description="____________"),
|
||||
* @OA\Property(property="quote_footer", type="string", example="the quote footer", description="____________"),
|
||||
* @OA\Property(property="email_subject_custom1", type="string", example="Custom Subject 1", description="____________"),
|
||||
* @OA\Property(property="email_subject_custom2", type="string", example="Custom Subject 2", description="____________"),
|
||||
* @OA\Property(property="email_subject_custom3", type="string", example="Custom Subject 3", description="____________"),
|
||||
* @OA\Property(property="email_template_custom1", type="string", example="<HTML>", description="____________"),
|
||||
* @OA\Property(property="email_template_custom2", type="string", example="<HTML>", description="____________"),
|
||||
* @OA\Property(property="email_template_custom3", type="string", example="<HTML>", description="____________"),
|
||||
* @OA\Property(property="enable_reminder1", type="boolean", example=false, description="____________"),
|
||||
* @OA\Property(property="enable_reminder2", type="boolean", example=false, description="____________"),
|
||||
* @OA\Property(property="enable_reminder3", type="boolean", example=false, description="____________"),
|
||||
* @OA\Property(property="hide_paid_to_date", type="boolean", example=false, description="Flags whether to hide the paid to date field"),
|
||||
* @OA\Property(property="embed_documents", type="boolean", example=false, description="Toggled whether to embed documents in the PDF"),
|
||||
* @OA\Property(property="all_pages_header", type="boolean", example=false, description="The header for the PDF"),
|
||||
* @OA\Property(property="all_pages_footer", type="boolean", example=false, description="The footer for the PDF"),
|
||||
* @OA\Property(property="document_email_attachment", type="boolean", example=false, description="Toggles whether to attach documents in the email"),
|
||||
* @OA\Property(property="enable_client_portal_password", type="boolean", example=false, description="Toggles password protection of the client portal"),
|
||||
* @OA\Property(property="enable_email_markup", type="boolean", example=false, description="Toggles the use of markdown in emails"),
|
||||
* @OA\Property(property="enable_client_portal_dashboard", type="boolean", example=false, description="Toggles whether the client dashboard is shown in the client portal"),
|
||||
* @OA\Property(property="enable_client_portal", type="boolean", example=false, description="Toggles whether the entire client portal is displayed to the client, or only the context"),
|
||||
* @OA\Property(property="email_template_statement", type="string", example="template matter", description="The body of the email for statements"),
|
||||
* @OA\Property(property="email_subject_statement", type="string", example="subject matter", description="The subject of the email for statements"),
|
||||
* @OA\Property(property="signature_on_pdf", type="boolean", example=false, description="Toggles whether the signature (if available) is displayed on the PDF"),
|
||||
* @OA\Property(property="quote_footer", type="string", example="the quote footer", description="The default quote footer"),
|
||||
* @OA\Property(property="email_subject_custom1", type="string", example="Custom Subject 1", description="Custom reminder template subject"),
|
||||
* @OA\Property(property="email_subject_custom2", type="string", example="Custom Subject 2", description="Custom reminder template subject"),
|
||||
* @OA\Property(property="email_subject_custom3", type="string", example="Custom Subject 3", description="Custom reminder template subject"),
|
||||
* @OA\Property(property="email_template_custom1", type="string", example="<HTML>", description="Custom reminder template body"),
|
||||
* @OA\Property(property="email_template_custom2", type="string", example="<HTML>", description="Custom reminder template body"),
|
||||
* @OA\Property(property="email_template_custom3", type="string", example="<HTML>", description="Custom reminder template body"),
|
||||
* @OA\Property(property="enable_reminder1", type="boolean", example=false, description="Toggles whether this reminder is enabled"),
|
||||
* @OA\Property(property="enable_reminder2", type="boolean", example=false, description="Toggles whether this reminder is enabled"),
|
||||
* @OA\Property(property="enable_reminder3", type="boolean", example=false, description="Toggles whether this reminder is enabled"),
|
||||
* @OA\Property(property="num_days_reminder1", type="number", example="9", description="The Reminder interval"),
|
||||
* @OA\Property(property="num_days_reminder2", type="number", example="9", description="The Reminder interval"),
|
||||
* @OA\Property(property="num_days_reminder3", type="number", example="9", description="The Reminder interval"),
|
||||
* @OA\Property(property="schedule_reminder1", type="string", example="after_invoice_date", description="(enum: after_invoice_date, before_due_date, after_due_date)"),
|
||||
* @OA\Property(property="schedule_reminder2", type="string", example="after_invoice_date", description="(enum: after_invoice_date, before_due_date, after_due_date)"),
|
||||
* @OA\Property(property="schedule_reminder3", type="string", example="after_invoice_date", description="(enum: after_invoice_date, before_due_date, after_due_date)"),
|
||||
* @OA\Property(property="late_fee_amount1", type="number", example=10.00, description="____________"),
|
||||
* @OA\Property(property="late_fee_amount2", type="number", example=20.00, description="____________"),
|
||||
* @OA\Property(property="late_fee_amount3", type="number", example=100.00, description="____________"),
|
||||
* @OA\Property(property="endless_reminder_frequency_id", type="string", example="1", description="____________"),
|
||||
* @OA\Property(property="client_online_payment_notification", type="boolean", example=false, description="____________"),
|
||||
* @OA\Property(property="client_manual_payment_notification", type="boolean", example=false, description="____________"),
|
||||
* @OA\Property(property="late_fee_amount1", type="number", example=10.00, description="The late fee amount for reminder 1"),
|
||||
* @OA\Property(property="late_fee_amount2", type="number", example=20.00, description="The late fee amount for reminder 2"),
|
||||
* @OA\Property(property="late_fee_amount3", type="number", example=100.00, description="The late fee amount for reminder 2"),
|
||||
* @OA\Property(property="endless_reminder_frequency_id", type="string", example="1", description="The frequency id of the endless reminder"),
|
||||
* @OA\Property(property="client_online_payment_notification", type="boolean", example=false, description="Determines if a client should receive the notification for a online payment"),
|
||||
* @OA\Property(property="client_manual_payment_notification", type="boolean", example=false, description="Determines if a client should receive the notification for a manually entered payment"),
|
||||
* )
|
||||
*/
|
||||
|
@ -3,8 +3,8 @@
|
||||
* @OA\Schema(
|
||||
* schema="CreditPaymentable",
|
||||
* type="object",
|
||||
* @OA\Property(property="credit_id", type="string", example="Opnel5aKBz", description="______"),
|
||||
* @OA\Property(property="amount", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="credit_id", type="string", example="Opnel5aKBz", description="The credit hashed id"),
|
||||
* @OA\Property(property="amount", type="string", example="2", description="The credit amount"),
|
||||
*
|
||||
* )
|
||||
*/
|
||||
|
@ -3,33 +3,33 @@
|
||||
* @OA\Schema(
|
||||
* schema="Credit",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="_________"),
|
||||
* @OA\Property(property="user_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="assigned_user_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="company_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="client_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="status_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="The credit hashed id"),
|
||||
* @OA\Property(property="user_id", type="string", example="", description="The user hashed id"),
|
||||
* @OA\Property(property="assigned_user_id", type="string", example="", description="The assigned user hashed id"),
|
||||
* @OA\Property(property="company_id", type="string", example="", description="The company hashed id"),
|
||||
* @OA\Property(property="client_id", type="string", example="", description="The client hashed id"),
|
||||
* @OA\Property(property="status_id", type="string", example="", description="The status field id infors of the current status of the credit"),
|
||||
* @OA\Property(property="invoice_id", type="string", example="", description="The linked invoice this credit is applied to"),
|
||||
* @OA\Property(property="number", type="string", example="QUOTE_101", description="The credit number - is a unique alpha numeric number per credit per company"),
|
||||
* @OA\Property(property="po_number", type="string", example="", description="________"),
|
||||
* @OA\Property(property="terms", type="string", example="", description="________"),
|
||||
* @OA\Property(property="public_notes", type="string", example="", description="________"),
|
||||
* @OA\Property(property="private_notes", type="string", example="", description="________"),
|
||||
* @OA\Property(property="footer", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value1", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value2", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value3", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value4", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_name1", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_name2", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_rate1", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="tax_rate2", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="tax_name3", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_rate3", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="po_number", type="string", example="", description="The purchase order number this credit refers to"),
|
||||
* @OA\Property(property="terms", type="string", example="", description="The credit terms field"),
|
||||
* @OA\Property(property="public_notes", type="string", example="", description="The public notes field of the credit"),
|
||||
* @OA\Property(property="private_notes", type="string", example="", description="The private notes field of the credit"),
|
||||
* @OA\Property(property="footer", type="string", example="", description="The credit footer text"),
|
||||
* @OA\Property(property="custom_value1", type="string", example="", description="A Custom value"),
|
||||
* @OA\Property(property="custom_value2", type="string", example="", description="A Custom value"),
|
||||
* @OA\Property(property="custom_value3", type="string", example="", description="A Custom value"),
|
||||
* @OA\Property(property="custom_value4", type="string", example="", description="A Custom value"),
|
||||
* @OA\Property(property="tax_name1", type="string", example="", description="The tax name"),
|
||||
* @OA\Property(property="tax_name2", type="string", example="", description="The tax rate"),
|
||||
* @OA\Property(property="tax_rate1", type="number", format="float", example="10.00", description="The tax name"),
|
||||
* @OA\Property(property="tax_rate2", type="number", format="float", example="10.00", description="The tax rate"),
|
||||
* @OA\Property(property="tax_name3", type="string", example="", description="The tax name"),
|
||||
* @OA\Property(property="tax_rate3", type="number", format="float", example="10.00", description="The tax rate"),
|
||||
* @OA\Property(property="total_taxes", type="number", format="float", example="10.00", description="The total taxes for the credit"),
|
||||
* @OA\Property(property="line_items", type="object", example="", description="_________"),
|
||||
* @OA\Property(property="amount", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="balance", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="line_items", type="object", example="", description="The line items array containing the line items of the credit"),
|
||||
* @OA\Property(property="amount", type="number", format="float", example="10.00", description="The total credit amount"),
|
||||
* @OA\Property(property="balance", type="number", format="float", example="10.00", description="The credit balance"),
|
||||
* @OA\Property(property="paid_to_date", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="discount", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="partial", type="number", format="float", example="10.00", description="_________"),
|
||||
|
@ -3,18 +3,18 @@
|
||||
* @OA\Schema(
|
||||
* schema="Document",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="AS3df3A", description="The design hashed id"),
|
||||
* @OA\Property(property="user_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="assigned_user_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="project_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="vendor_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="name", type="string", example="Beauty", description="The design name"),
|
||||
* @OA\Property(property="url", type="string", example="Beauty", description="The design name"),
|
||||
* @OA\Property(property="preview", type="string", example="Beauty", description="The design name"),
|
||||
* @OA\Property(property="type", type="string", example="Beauty", description="The design name"),
|
||||
* @OA\Property(property="disk", type="string", example="Beauty", description="The design name"),
|
||||
* @OA\Property(property="hash", type="string", example="Beauty", description="The design name"),
|
||||
* @OA\Property(property="is_deleted", type="boolean", example=true, description="Flag to determine if the design is deleted"),
|
||||
* @OA\Property(property="id", type="string", example="AS3df3A", description="The document hashed id"),
|
||||
* @OA\Property(property="user_id", type="string", example="", description="The user hashed id"),
|
||||
* @OA\Property(property="assigned_user_id", type="string", example="", description="The assigned user hashed id"),
|
||||
* @OA\Property(property="project_id", type="string", example="", description="The project associated with this document"),
|
||||
* @OA\Property(property="vendor_id", type="string", example="", description="The vendor associated with this documents"),
|
||||
* @OA\Property(property="name", type="string", example="Beauty", description="The document name"),
|
||||
* @OA\Property(property="url", type="string", example="Beauty", description="The document url"),
|
||||
* @OA\Property(property="preview", type="string", example="Beauty", description="The document preview url"),
|
||||
* @OA\Property(property="type", type="string", example="Beauty", description="The document type"),
|
||||
* @OA\Property(property="disk", type="string", example="Beauty", description="The document disk"),
|
||||
* @OA\Property(property="hash", type="string", example="Beauty", description="The document hashed"),
|
||||
* @OA\Property(property="is_deleted", type="boolean", example=true, description="Flag to determine if the document is deleted"),
|
||||
* @OA\Property(property="is_default", type="boolean", example=true, description="Flag to determine if the document is a default doc"),
|
||||
* @OA\Property(property="created_at", type="number", format="integer", example="134341234234", description="Timestamp"),
|
||||
* @OA\Property(property="updated_at", type="number", format="integer", example="134341234234", description="Timestamp"),
|
||||
|
@ -3,11 +3,11 @@
|
||||
* @OA\Schema(
|
||||
* schema="ExpenseCategory",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="______"),
|
||||
* @OA\Property(property="name", type="string", example="Accounting", description="______"),
|
||||
* @OA\Property(property="user_id", type="string", example="XS987sD", description="______"),
|
||||
* @OA\Property(property="is_deleted", type="boolean", example=true, description="______"),
|
||||
* @OA\Property(property="updated_at", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="created_at", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="The expense hashed id"),
|
||||
* @OA\Property(property="name", type="string", example="Accounting", description="The expense category name"),
|
||||
* @OA\Property(property="user_id", type="string", example="XS987sD", description="The user hashed id"),
|
||||
* @OA\Property(property="is_deleted", type="boolean", example=true, description="Flag determining whether the expense category has been deleted"),
|
||||
* @OA\Property(property="updated_at", type="integer", example="2", description="The updated at timestamp"),
|
||||
* @OA\Property(property="created_at", type="integer", example="2", description="The created at timestamp"),
|
||||
* )
|
||||
*/
|
||||
|
@ -3,40 +3,40 @@
|
||||
* @OA\Schema(
|
||||
* schema="Expense",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="_________"),
|
||||
* @OA\Property(property="user_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="assigned_user_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="company_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="client_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="invoice_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="bank_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="invoice_currency_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="expense_currency_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="invoice_category_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="payment_type_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="recurring_expense_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="private_notes", type="string", example="", description="________"),
|
||||
* @OA\Property(property="public_notes", type="string", example="", description="________"),
|
||||
* @OA\Property(property="transaction_reference", type="string", example="", description="________"),
|
||||
* @OA\Property(property="transcation_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value1", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value2", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value3", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value4", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_name1", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_name2", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_rate1", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="tax_rate2", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="tax_name3", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_rate3", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="amount", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="foreign_amount", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="exchange_rate", type="number", format="float", example="0.80", description="_________"),
|
||||
* @OA\Property(property="date", type="string", example="", description="________"),
|
||||
* @OA\Property(property="payment_date", type="string", example="", description="________"),
|
||||
* @OA\Property(property="should_be_invoiced", type="boolean", example=true, description="_________"),
|
||||
* @OA\Property(property="is_deleted", type="boolean", example=true, description="_________"),
|
||||
* @OA\Property(property="invoice_documents", type="boolean", example=true, description=""),
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="The expense hashed id"),
|
||||
* @OA\Property(property="user_id", type="string", example="", description="The user hashed id"),
|
||||
* @OA\Property(property="assigned_user_id", type="string", example="", description="The assigned user hashed id"),
|
||||
* @OA\Property(property="company_id", type="string", example="", description="The company hashed id"),
|
||||
* @OA\Property(property="client_id", type="string", example="", description="The client hashed id"),
|
||||
* @OA\Property(property="invoice_id", type="string", example="", description="The related invoice hashed id"),
|
||||
* @OA\Property(property="bank_id", type="string", example="", description="The bank id related to this expense"),
|
||||
* @OA\Property(property="invoice_currency_id", type="string", example="", description="The currency id of the related invoice"),
|
||||
* @OA\Property(property="expense_currency_id", type="string", example="", description="The currency id of the expense"),
|
||||
* @OA\Property(property="invoice_category_id", type="string", example="", description="The invoice category id"),
|
||||
* @OA\Property(property="payment_type_id", type="string", example="", description="The payment type id"),
|
||||
* @OA\Property(property="recurring_expense_id", type="string", example="", description="The related recurring expense this expense was created from"),
|
||||
* @OA\Property(property="private_notes", type="string", example="", description="The private notes of the expense"),
|
||||
* @OA\Property(property="public_notes", type="string", example="", description="The public notes of the expense"),
|
||||
* @OA\Property(property="transaction_reference", type="string", example="", description="The transaction references of the expense"),
|
||||
* @OA\Property(property="transcation_id", type="string", example="", description="The transaction id of the expense"),
|
||||
* @OA\Property(property="custom_value1", type="string", example="", description="A custom value"),
|
||||
* @OA\Property(property="custom_value2", type="string", example="", description="A custom value"),
|
||||
* @OA\Property(property="custom_value3", type="string", example="", description="A custom value"),
|
||||
* @OA\Property(property="custom_value4", type="string", example="", description="A custom value"),
|
||||
* @OA\Property(property="tax_name1", type="string", example="", description="Tax name"),
|
||||
* @OA\Property(property="tax_name2", type="string", example="", description="Tax name"),
|
||||
* @OA\Property(property="tax_rate1", type="number", format="float", example="10.00", description="Tax rate"),
|
||||
* @OA\Property(property="tax_rate2", type="number", format="float", example="10.00", description="Tax rate"),
|
||||
* @OA\Property(property="tax_name3", type="string", example="", description="Tax name"),
|
||||
* @OA\Property(property="tax_rate3", type="number", format="float", example="10.00", description="Tax rate"),
|
||||
* @OA\Property(property="amount", type="number", format="float", example="10.00", description="The total expense amont"),
|
||||
* @OA\Property(property="foreign_amount", type="number", format="float", example="10.00", description="The total foreign amount of the expense"),
|
||||
* @OA\Property(property="exchange_rate", type="number", format="float", example="0.80", description="The exchange rate at the time of the expense"),
|
||||
* @OA\Property(property="date", type="string", example="2022-12-01", description="The expense date formate Y-m-d"),
|
||||
* @OA\Property(property="payment_date", type="string", example="", description="The date of payment for the expense, format Y-m-d"),
|
||||
* @OA\Property(property="should_be_invoiced", type="boolean", example=true, description="Flag whether the expense should be invoiced"),
|
||||
* @OA\Property(property="is_deleted", type="boolean", example=true, description="Boolean determining whether the expense has been deleted"),
|
||||
* @OA\Property(property="invoice_documents", type="boolean", example=true, description="Passing the expense documents over to the invoice"),
|
||||
* @OA\Property(property="updated_at", type="number", format="integer", example="1434342123", description="Timestamp"),
|
||||
* @OA\Property(property="archived_at", type="number", format="integer", example="1434342123", description="Timestamp"),
|
||||
* )
|
||||
|
@ -3,17 +3,17 @@
|
||||
* @OA\Schema(
|
||||
* schema="FeesAndLimits",
|
||||
* type="object",
|
||||
* @OA\Property(property="min_limit", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="max_limit", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="fee_amount", type="number", format="float", example="2.0", description="______"),
|
||||
* @OA\Property(property="fee_percent", type="number", format="float", example="2.0", description="______"),
|
||||
* @OA\Property(property="fee_tax_name1", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="fee_tax_name2", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="fee_tax_name3", type="string", example="2", description="______"),
|
||||
* @OA\Property(property="fee_tax_rate1", type="number", format="float", example="2.0", description="______"),
|
||||
* @OA\Property(property="fee_tax_rate2", type="number", format="float", example="2.0", description="______"),
|
||||
* @OA\Property(property="fee_tax_rate3", type="number", format="float", example="2.0", description="______"),
|
||||
* @OA\Property(property="fee_cap", type="number", format="float", example="2.0", description="______"),
|
||||
* @OA\Property(property="adjust_fee_percent", type="boolean", example=true, description="______"),
|
||||
* @OA\Property(property="min_limit", type="string", example="2", description="The minimum amount accepted for this gateway"),
|
||||
* @OA\Property(property="max_limit", type="string", example="2", description="The maximum amount accepted for this gateway"),
|
||||
* @OA\Property(property="fee_amount", type="number", format="float", example="2.0", description="The gateway fee amount"),
|
||||
* @OA\Property(property="fee_percent", type="number", format="float", example="2.0", description="The gateway fee percentage"),
|
||||
* @OA\Property(property="fee_tax_name1", type="string", example="GST", description="Fee tax name"),
|
||||
* @OA\Property(property="fee_tax_name2", type="string", example="VAT", description="Fee tax name"),
|
||||
* @OA\Property(property="fee_tax_name3", type="string", example="CA Sales Tax", description="Fee tax name"),
|
||||
* @OA\Property(property="fee_tax_rate1", type="number", format="float", example="10.0", description="The tax rate"),
|
||||
* @OA\Property(property="fee_tax_rate2", type="number", format="float", example="17.5", description="The tax rate"),
|
||||
* @OA\Property(property="fee_tax_rate3", type="number", format="float", example="25.0", description="The tax rate"),
|
||||
* @OA\Property(property="fee_cap", type="number", format="float", example="2.0", description="If set the fee amount will be no higher than this amount"),
|
||||
* @OA\Property(property="adjust_fee_percent", type="boolean", example=true, description="Adjusts the fee to match the exact gateway fee."),
|
||||
* )
|
||||
*/
|
||||
|
@ -3,10 +3,10 @@
|
||||
* @OA\Schema(
|
||||
* schema="GroupSetting",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="_________"),
|
||||
* @OA\Property(property="user_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="company_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="name", type="string", example="", description="________"),
|
||||
* @OA\Property(property="settings", type="object", example="", description="________"),
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="The group setting hashed id"),
|
||||
* @OA\Property(property="user_id", type="string", example="Opnel5aKBz", description="The user hashed id"),
|
||||
* @OA\Property(property="company_id", type="string", example="Opnel5aKBz", description="The company hashed id"),
|
||||
* @OA\Property(property="name", type="string", example="A groupies group", description="The name of the group"),
|
||||
* @OA\Property(property="settings", type="object", example="", description="The settings object"),
|
||||
* )
|
||||
*/
|
||||
|
@ -3,43 +3,43 @@
|
||||
* @OA\Schema(
|
||||
* schema="Invoice",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="_________"),
|
||||
* @OA\Property(property="user_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="assigned_user_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="company_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="client_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="status_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="The invoice hashed id"),
|
||||
* @OA\Property(property="user_id", type="string", example="Opnel5aKBz", description="The user hashed id"),
|
||||
* @OA\Property(property="assigned_user_id", type="string", example="Opnel5aKBz", description="The assigned user hashed id"),
|
||||
* @OA\Property(property="company_id", type="string", example="Opnel5aKBz", description="The company hashed id"),
|
||||
* @OA\Property(property="client_id", type="string", example="Opnel5aKBz", description="The client hashed id"),
|
||||
* @OA\Property(property="status_id", type="string", example="4", description="The invoice status variable"),
|
||||
* @OA\Property(property="number", type="string", example="INV_101", description="The invoice number - is a unique alpha numeric number per invoice per company"),
|
||||
* @OA\Property(property="po_number", type="string", example="", description="________"),
|
||||
* @OA\Property(property="terms", type="string", example="", description="________"),
|
||||
* @OA\Property(property="public_notes", type="string", example="", description="________"),
|
||||
* @OA\Property(property="private_notes", type="string", example="", description="________"),
|
||||
* @OA\Property(property="footer", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value1", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value2", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value3", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value4", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_name1", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_name2", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_rate1", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="tax_rate2", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="tax_name3", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_rate3", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="po_number", type="string", example="PO-1234", description="The purchase order associated with this invoice"),
|
||||
* @OA\Property(property="terms", type="string", example="These are invoice terms", description="The invoice terms"),
|
||||
* @OA\Property(property="public_notes", type="string", example="These are some public notes", description="The public notes of the invoice"),
|
||||
* @OA\Property(property="private_notes", type="string", example="These are some private notes", description="The private notes of the invoice"),
|
||||
* @OA\Property(property="footer", type="string", example="", description="The invoice footer notes"),
|
||||
* @OA\Property(property="custom_value1", type="string", example="2022-10-01", description="A custom field value"),
|
||||
* @OA\Property(property="custom_value2", type="string", example="Something custom", description="A custom field value"),
|
||||
* @OA\Property(property="custom_value3", type="string", example="", description="A custom field value"),
|
||||
* @OA\Property(property="custom_value4", type="string", example="", description="A custom field value"),
|
||||
* @OA\Property(property="tax_name1", type="string", example="", description="The tax name"),
|
||||
* @OA\Property(property="tax_name2", type="string", example="", description="The tax name"),
|
||||
* @OA\Property(property="tax_rate1", type="number", format="float", example="10.00", description="The tax rate"),
|
||||
* @OA\Property(property="tax_rate2", type="number", format="float", example="10.00", description="The tax rate"),
|
||||
* @OA\Property(property="tax_name3", type="string", example="", description="The tax name"),
|
||||
* @OA\Property(property="tax_rate3", type="number", format="float", example="10.00", description="The tax rate"),
|
||||
* @OA\Property(property="total_taxes", type="number", format="float", example="10.00", description="The total taxes for the invoice"),
|
||||
* @OA\Property(property="line_items", type="object", example="", description="_________"),
|
||||
* @OA\Property(property="amount", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="balance", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="paid_to_date", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="discount", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="partial", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="is_amount_discount", type="boolean", example=true, description="_________"),
|
||||
* @OA\Property(property="is_deleted", type="boolean", example=true, description="_________"),
|
||||
* @OA\Property(property="line_items", type="object", example="", description="An array of objects which define the line items of the invoice"),
|
||||
* @OA\Property(property="amount", type="number", format="float", example="10.00", description="The invoice amount"),
|
||||
* @OA\Property(property="balance", type="number", format="float", example="10.00", description="The invoice balance"),
|
||||
* @OA\Property(property="paid_to_date", type="number", format="float", example="10.00", description="The amount paid on the invoice to date"),
|
||||
* @OA\Property(property="discount", type="number", format="float", example="10.00", description="The invoice discount, can be an amount or a percentage"),
|
||||
* @OA\Property(property="partial", type="number", format="float", example="10.00", description="The deposit/partial amount"),
|
||||
* @OA\Property(property="is_amount_discount", type="boolean", example=true, description="Flag determining if the discount is an amount or a percentage"),
|
||||
* @OA\Property(property="is_deleted", type="boolean", example=true, description="Defines if the invoice has been deleted"),
|
||||
* @OA\Property(property="uses_inclusive_taxes", type="boolean", example=true, description="Defines the type of taxes used as either inclusive or exclusive"),
|
||||
* @OA\Property(property="date", type="string", format="date", example="1994-07-30", description="The Invoice Date"),
|
||||
* @OA\Property(property="last_sent_date", type="string", format="date", example="1994-07-30", description="The last date the invoice was sent out"),
|
||||
* @OA\Property(property="next_send_date", type="string", format="date", example="1994-07-30", description="The Next date for a reminder to be sent"),
|
||||
* @OA\Property(property="partial_due_date", type="string", format="date", example="1994-07-30", description="_________"),
|
||||
* @OA\Property(property="due_date", type="string", format="date", example="1994-07-30", description="_________"),
|
||||
* @OA\Property(property="partial_due_date", type="string", format="date", example="1994-07-30", description="The due date for the deposit/partial amount"),
|
||||
* @OA\Property(property="due_date", type="string", format="date", example="1994-07-30", description="The due date of the invoice"),
|
||||
* @OA\Property(property="settings",ref="#/components/schemas/CompanySettings"),
|
||||
* @OA\Property(property="last_viewed", type="number", format="integer", example="1434342123", description="Timestamp"),
|
||||
* @OA\Property(property="updated_at", type="number", format="integer", example="1434342123", description="Timestamp"),
|
||||
|
@ -3,18 +3,18 @@
|
||||
* @OA\Schema(
|
||||
* schema="Payment",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="______"),
|
||||
* @OA\Property(property="client_id", type="string", example="Opnel5aKBz", description="______"),
|
||||
* @OA\Property(property="invitation_id", type="string", example="Opnel5aKBz", description="______"),
|
||||
* @OA\Property(property="client_contact_id", type="string", example="Opnel5aKBz", description="______"),
|
||||
* @OA\Property(property="user_id", type="string", example="Opnel5aKBz", description="______"),
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="The payment hashed id"),
|
||||
* @OA\Property(property="client_id", type="string", example="Opnel5aKBz", description="The client hashed id"),
|
||||
* @OA\Property(property="invitation_id", type="string", example="Opnel5aKBz", description="The invitation hashed id"),
|
||||
* @OA\Property(property="client_contact_id", type="string", example="Opnel5aKBz", description="The client contact hashed id"),
|
||||
* @OA\Property(property="user_id", type="string", example="Opnel5aKBz", description="The user hashed id"),
|
||||
* @OA\Property(property="type_id", type="string", example="1", description="The Payment Type ID"),
|
||||
* @OA\Property(property="date", type="string", example="1-1-2014", description="The Payment date"),
|
||||
* @OA\Property(property="transaction_reference", type="string", example="xcsSxcs124asd", description="The transaction reference as defined by the payment gateway"),
|
||||
* @OA\Property(property="assigned_user_id", type="string", example="Opnel5aKBz", description="______"),
|
||||
* @OA\Property(property="private_notes", type="string", example="The payment was refunded due to error", description="______"),
|
||||
* @OA\Property(property="is_manual", type="boolean", example=true, description="______"),
|
||||
* @OA\Property(property="is_deleted", type="boolean", example=true, description="______"),
|
||||
* @OA\Property(property="assigned_user_id", type="string", example="Opnel5aKBz", description="The assigned user hashed id"),
|
||||
* @OA\Property(property="private_notes", type="string", example="The payment was refunded due to error", description="The private notes of the payment"),
|
||||
* @OA\Property(property="is_manual", type="boolean", example=true, description="Flags whether the payment was made manually or processed via a gateway"),
|
||||
* @OA\Property(property="is_deleted", type="boolean", example=true, description="Defines if the payment has been deleted"),
|
||||
* @OA\Property(property="amount", type="number", example=10.00, description="The amount of this payment"),
|
||||
* @OA\Property(property="refunded", type="number", example=10.00, description="The refunded amount of this payment"),
|
||||
* @OA\Property(property="updated_at", type="number", format="integer", example="1434342123", description="Timestamp"),
|
||||
|
@ -6,8 +6,8 @@
|
||||
* @OA\Property(property="id", type="string", example="AS3df3A", description="The paymentable hashed id"),
|
||||
* @OA\Property(property="invoice_id", type="string", example="AS3df3A", description="The invoice hashed id"),
|
||||
* @OA\Property(property="credit_id", type="string", example="AS3df3A", description="The credit hashed id"),
|
||||
* @OA\Property(property="refunded", type="number", format="float", example="10.00", description="______"),
|
||||
* @OA\Property(property="amount", type="number", format="float", example="10.00", description="______"),
|
||||
* @OA\Property(property="refunded", type="number", format="float", example="10.00", description="The amount that has been refunded for this payment"),
|
||||
* @OA\Property(property="amount", type="number", format="float", example="10.00", description="The amount that has been applied to the payment"),
|
||||
* @OA\Property(property="updated_at", type="number", format="integer", example="1434342123", description="Timestamp"),
|
||||
* @OA\Property(property="created_at", type="number", format="integer", example="1434342123", description="Timestamp"),*
|
||||
* )
|
||||
|
@ -3,6 +3,6 @@
|
||||
* @OA\Schema(
|
||||
* schema="Product",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="______"),
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="The product hashed id"),
|
||||
* )
|
||||
*/
|
||||
|
@ -3,7 +3,7 @@
|
||||
* @OA\Schema(
|
||||
* schema="Project",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="______"),
|
||||
* @OA\Property(property="name", type="string", example="New Project", description="______"),
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="The project hashed id"),
|
||||
* @OA\Property(property="name", type="string", example="New Project", description="The project name"),
|
||||
* )
|
||||
*/
|
||||
|
@ -3,43 +3,43 @@
|
||||
* @OA\Schema(
|
||||
* schema="Quote",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="_________"),
|
||||
* @OA\Property(property="user_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="assigned_user_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="company_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="client_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="status_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="The quote hashed id"),
|
||||
* @OA\Property(property="user_id", type="string", example="", description="The user hashed id"),
|
||||
* @OA\Property(property="assigned_user_id", type="string", example="", description="The assigned user hashed id"),
|
||||
* @OA\Property(property="company_id", type="string", example="", description="The company hashed id"),
|
||||
* @OA\Property(property="client_id", type="string", example="", description="The client hashed id"),
|
||||
* @OA\Property(property="status_id", type="string", example="", description="The status of the quote"),
|
||||
* @OA\Property(property="number", type="string", example="QUOTE_101", description="The quote number - is a unique alpha numeric number per quote per company"),
|
||||
* @OA\Property(property="po_number", type="string", example="", description="________"),
|
||||
* @OA\Property(property="terms", type="string", example="", description="________"),
|
||||
* @OA\Property(property="public_notes", type="string", example="", description="________"),
|
||||
* @OA\Property(property="private_notes", type="string", example="", description="________"),
|
||||
* @OA\Property(property="footer", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value1", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value2", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value3", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value4", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_name1", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_name2", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_rate1", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="tax_rate2", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="tax_name3", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_rate3", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="po_number", type="string", example="PO-1234", description="The purchase order number associated with this quote"),
|
||||
* @OA\Property(property="terms", type="string", example="These are some quote terms. Valid for 14 days.", description="The quote terms"),
|
||||
* @OA\Property(property="public_notes", type="string", example="These are public notes which the client may see", description="Public notes for the quote"),
|
||||
* @OA\Property(property="private_notes", type="string", example="These are private notes, not to be disclosed to the client", description="Private notes for the quote"),
|
||||
* @OA\Property(property="footer", type="string", example="The text goes in the footer of the quote", description="Footer text of quote"),
|
||||
* @OA\Property(property="custom_value1", type="string", example="A custom value", description="Custom value field"),
|
||||
* @OA\Property(property="custom_value2", type="string", example="A custom value", description="Custom value field"),
|
||||
* @OA\Property(property="custom_value3", type="string", example="A custom value", description="Custom value field"),
|
||||
* @OA\Property(property="custom_value4", type="string", example="A custom value", description="Custom value field"),
|
||||
* @OA\Property(property="tax_name1", type="string", example="GST", description="The tax name"),
|
||||
* @OA\Property(property="tax_name2", type="string", example="VAT", description="The tax name"),
|
||||
* @OA\Property(property="tax_rate1", type="number", format="float", example="10.00", description="The tax rate"),
|
||||
* @OA\Property(property="tax_rate2", type="number", format="float", example="10.00", description="The tax rate"),
|
||||
* @OA\Property(property="tax_name3", type="string", example="", description="The tax name"),
|
||||
* @OA\Property(property="tax_rate3", type="number", format="float", example="10.00", description="The tax rate"),
|
||||
* @OA\Property(property="total_taxes", type="number", format="float", example="10.00", description="The total taxes for the quote"),
|
||||
* @OA\Property(property="line_items", type="object", example="", description="_________"),
|
||||
* @OA\Property(property="amount", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="balance", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="paid_to_date", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="discount", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="partial", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="is_amount_discount", type="boolean", example=true, description="_________"),
|
||||
* @OA\Property(property="is_deleted", type="boolean", example=true, description="_________"),
|
||||
* @OA\Property(property="line_items", type="object", example="", description="An array of line items of the quote"),
|
||||
* @OA\Property(property="amount", type="number", format="float", example="10.00", description="The total amount of the quote"),
|
||||
* @OA\Property(property="balance", type="number", format="float", example="10.00", description="The balance due of the quote"),
|
||||
* @OA\Property(property="paid_to_date", type="number", format="float", example="10.00", description="The amount that has been paid to date on the quote"),
|
||||
* @OA\Property(property="discount", type="number", format="float", example="10.00", description="The quote discount"),
|
||||
* @OA\Property(property="partial", type="number", format="float", example="10.00", description="The partial/deposit amount"),
|
||||
* @OA\Property(property="is_amount_discount", type="boolean", example=true, description="Boolean flag determining if the quote is an amount or percentage"),
|
||||
* @OA\Property(property="is_deleted", type="boolean", example=true, description="Boolean flag determining if the quote has been deleted"),
|
||||
* @OA\Property(property="uses_inclusive_taxes", type="boolean", example=true, description="Defines the type of taxes used as either inclusive or exclusive"),
|
||||
* @OA\Property(property="date", type="string", format="date", example="1994-07-30", description="The Quote Date"),
|
||||
* @OA\Property(property="last_sent_date", type="string", format="date", example="1994-07-30", description="The last date the quote was sent out"),
|
||||
* @OA\Property(property="next_send_date", type="string", format="date", example="1994-07-30", description="The Next date for a reminder to be sent"),
|
||||
* @OA\Property(property="partial_due_date", type="string", format="date", example="1994-07-30", description="_________"),
|
||||
* @OA\Property(property="due_date", type="string", format="date", example="1994-07-30", description="_________"),
|
||||
* @OA\Property(property="partial_due_date", type="string", format="date", example="1994-07-30", description="The date when the partial/deposit is due"),
|
||||
* @OA\Property(property="due_date", type="string", format="date", example="1994-07-30", description="The date the quote is valid until"),
|
||||
* @OA\Property(property="settings",ref="#/components/schemas/CompanySettings"),
|
||||
* @OA\Property(property="last_viewed", type="number", format="integer", example="1434342123", description="Timestamp"),
|
||||
* @OA\Property(property="updated_at", type="number", format="integer", example="1434342123", description="Timestamp"),
|
||||
|
@ -3,44 +3,43 @@
|
||||
* @OA\Schema(
|
||||
* schema="RecurringExpense",
|
||||
* type="object",
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="_________"),
|
||||
* @OA\Property(property="user_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="assigned_user_id", type="string", example="", description="__________"),
|
||||
* @OA\Property(property="company_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="client_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="invoice_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="bank_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="invoice_currency_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="expense_currency_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="invoice_category_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="payment_type_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="recurring_expense_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="private_notes", type="string", example="", description="________"),
|
||||
* @OA\Property(property="public_notes", type="string", example="", description="________"),
|
||||
* @OA\Property(property="transaction_reference", type="string", example="", description="________"),
|
||||
* @OA\Property(property="transcation_id", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value1", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value2", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value3", type="string", example="", description="________"),
|
||||
* @OA\Property(property="custom_value4", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_name1", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_name2", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_rate1", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="tax_rate2", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="tax_name3", type="string", example="", description="________"),
|
||||
* @OA\Property(property="tax_rate3", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="amount", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="frequency_id", type="number", format="int", example="1", description="_________"),
|
||||
* @OA\Property(property="remaining_cycles", type="number", format="int", example="1", description="_________"),
|
||||
* @OA\Property(property="foreign_amount", type="number", format="float", example="10.00", description="_________"),
|
||||
* @OA\Property(property="exchange_rate", type="number", format="float", example="0.80", description="_________"),
|
||||
* @OA\Property(property="date", type="string", example="", description="________"),
|
||||
* @OA\Property(property="payment_date", type="string", example="", description="________"),
|
||||
* @OA\Property(property="should_be_invoiced", type="boolean", example=true, description="_________"),
|
||||
* @OA\Property(property="is_deleted", type="boolean", example=true, description="_________"),
|
||||
* @OA\Property(property="id", type="string", example="Opnel5aKBz", description="The hashed id of the recurring expense"),
|
||||
* @OA\Property(property="user_id", type="string", example="Opnel5aKBz", description="The hashed id of the user who created the recurring expense"),
|
||||
* @OA\Property(property="assigned_user_id", type="string", example="Opnel5aKBz", description="The hashed id of the user assigned to this recurring expense"),
|
||||
* @OA\Property(property="company_id", type="string", example="Opnel5aKBz", description="The hashed id of the company"),
|
||||
* @OA\Property(property="client_id", type="string", example="Opnel5aKBz", description="The hashed id of the client"),
|
||||
* @OA\Property(property="invoice_id", type="string", example="Opnel5aKBz", description="The hashed id of the invoice"),
|
||||
* @OA\Property(property="bank_id", type="string", example="22", description="The id of the bank associated with this recurring expense"),
|
||||
* @OA\Property(property="invoice_currency_id", type="string", example="1", description="The currency id of the invoice associated with this recurring expense"),
|
||||
* @OA\Property(property="expense_currency_id", type="string", example="1", description="The currency id of the expense associated with this recurring expense"),
|
||||
* @OA\Property(property="invoice_category_id", type="string", example="1", description="The category id of the invoice"),
|
||||
* @OA\Property(property="payment_type_id", type="string", example="1", description="The payment type id"),
|
||||
* @OA\Property(property="private_notes", type="string", example="Private and confidential", description="The recurring expense private notes"),
|
||||
* @OA\Property(property="public_notes", type="string", example="This is the best client in the world", description="The recurring expense public notes"),
|
||||
* @OA\Property(property="transaction_reference", type="string", example="EXP-1223-2333", description="The recurring expense transaction reference"),
|
||||
* @OA\Property(property="transcation_id", type="string", example="1233312312", description="The transaction id of the recurring expense"),
|
||||
* @OA\Property(property="custom_value1", type="string", example="$1000", description="Custom value field"),
|
||||
* @OA\Property(property="custom_value2", type="string", example="2022-10-10", description="Custom value field"),
|
||||
* @OA\Property(property="custom_value3", type="string", example="short text", description="Custom value field"),
|
||||
* @OA\Property(property="custom_value4", type="string", example="very long text", description="Custom value field"),
|
||||
* @OA\Property(property="tax_name1", type="string", example="GST", description="The tax name"),
|
||||
* @OA\Property(property="tax_name2", type="string", example="VAT", description="The tax name"),
|
||||
* @OA\Property(property="tax_rate1", type="number", format="float", example="10.00", description="The tax rate"),
|
||||
* @OA\Property(property="tax_rate2", type="number", format="float", example="10.00", description="The tax rate"),
|
||||
* @OA\Property(property="tax_name3", type="string", example="", description="The tax name"),
|
||||
* @OA\Property(property="tax_rate3", type="number", format="float", example="10.00", description="The tax rate"),
|
||||
* @OA\Property(property="amount", type="number", format="float", example="10.00", description="The total amount of the recurring expense"),
|
||||
* @OA\Property(property="frequency_id", type="number", format="int", example="1", description="The frequency this recurring expense fires"),
|
||||
* @OA\Property(property="remaining_cycles", type="number", format="int", example="1", description="The number of remaining cycles for this recurring expense"),
|
||||
* @OA\Property(property="foreign_amount", type="number", format="float", example="10.00", description="The foreign currency amount of the recurring expense"),
|
||||
* @OA\Property(property="exchange_rate", type="number", format="float", example="0.80", description="The exchange rate for the expernse"),
|
||||
* @OA\Property(property="date", type="string", example="", description="The date of the expense"),
|
||||
* @OA\Property(property="payment_date", type="string", example="", description="The date the expense was paid"),
|
||||
* @OA\Property(property="should_be_invoiced", type="boolean", example=true, description="Boolean flag determining if the expense should be invoiced"),
|
||||
* @OA\Property(property="is_deleted", type="boolean", example=true, description="Boolean flag determining if the recurring expense is deleted"),
|
||||
* @OA\Property(property="last_sent_date", type="string", format="date", example="1994-07-30", description="The Date it was sent last"),
|
||||
* @OA\Property(property="next_send_date", type="string", format="date", example="1994-07-30", description="The next send date"),
|
||||
* @OA\Property(property="invoice_documents", type="boolean", example=true, description=""),
|
||||
* @OA\Property(property="invoice_documents", type="boolean", example=true, description="Boolean flag determining if the documents associated with this expense should be passed onto the invoice if it is converted to an invoice"),
|
||||
* @OA\Property(property="updated_at", type="number", format="integer", example="1434342123", description="Timestamp"),
|
||||
* @OA\Property(property="archived_at", type="number", format="integer", example="1434342123", description="Timestamp"),
|
||||
* )
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user