mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-24 02:14:21 -04:00
Multiple fixes and features (#3411)
* Performance improvements for seeding * Differentiating between system notification and user notifications * Remove hard coded webhook url * Working on system and user notifications * notifications * Set the currency on client if blank * Refactor for inserting invoice defaults * Refactor Default Invoice/Quote/Credit objects * working on credits * Implement mark_sent for quotes and credits
This commit is contained in:
parent
cf345b1932
commit
1393179160
@ -5,9 +5,6 @@ APP_DEBUG=true
|
||||
|
||||
APP_URL=http://localhost
|
||||
|
||||
USER_AUTH_PROVIDER=users
|
||||
CONTACT_AUTH_PROVIDER=contacts
|
||||
|
||||
DB_CONNECTION=db-ninja-01
|
||||
MULTI_DB_ENABLED=true
|
||||
|
||||
|
@ -19,6 +19,5 @@ TRAVIS=true
|
||||
API_SECRET=password
|
||||
TEST_USERNAME=user@example.com
|
||||
TEST_PERMISSIONS_USERNAME=permissions@example.com
|
||||
USER_AUTH_PROVIDER=users
|
||||
CONTACT_AUTH_PROVIDER=contacts
|
||||
|
||||
MULTI_DB_ENABLED=true
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Console\Commands\TestData\CreateTestCreditJob;
|
||||
use App\Console\Commands\TestData\CreateTestInvoiceJob;
|
||||
use App\Console\Commands\TestData\CreateTestQuoteJob;
|
||||
use App\DataMapper\DefaultSettings;
|
||||
use App\Events\Invoice\InvoiceWasCreated;
|
||||
use App\Events\Invoice\InvoiceWasMarkedSent;
|
||||
@ -81,15 +84,9 @@ class CreateTestData extends Command
|
||||
$account = factory(\App\Models\Account::class)->create();
|
||||
$company = factory(\App\Models\Company::class)->create([
|
||||
'account_id' => $account->id,
|
||||
'slack_webhook_url' => config('ninja.notification.slack'),
|
||||
]);
|
||||
|
||||
$settings = $company->settings;
|
||||
|
||||
$settings->system_notifications_slack = config('ninja.notification.slack');
|
||||
$settings->system_notifications_email = config('ninja.contact.email');
|
||||
|
||||
$company->settings = $settings;
|
||||
$company->save();
|
||||
|
||||
$account->default_company_id = $company->id;
|
||||
$account->save();
|
||||
@ -172,17 +169,9 @@ class CreateTestData extends Command
|
||||
$account = factory(\App\Models\Account::class)->create();
|
||||
$company = factory(\App\Models\Company::class)->create([
|
||||
'account_id' => $account->id,
|
||||
'slack_webhook_url' => config('ninja.notification.slack'),
|
||||
]);
|
||||
|
||||
|
||||
$settings = $company->settings;
|
||||
|
||||
$settings->system_notifications_slack = config('ninja.notification.slack');
|
||||
$settings->system_notifications_email = config('ninja.contact.email');
|
||||
|
||||
$company->settings = $settings;
|
||||
$company->save();
|
||||
|
||||
$account->default_company_id = $company->id;
|
||||
$account->save();
|
||||
|
||||
@ -279,16 +268,9 @@ class CreateTestData extends Command
|
||||
$account = factory(\App\Models\Account::class)->create();
|
||||
$company = factory(\App\Models\Company::class)->create([
|
||||
'account_id' => $account->id,
|
||||
'slack_webhook_url' => config('ninja.notification.slack'),
|
||||
]);
|
||||
|
||||
$settings = $company->settings;
|
||||
|
||||
$settings->system_notifications_slack = config('ninja.notification.slack');
|
||||
$settings->system_notifications_email = config('ninja.contact.email');
|
||||
|
||||
$company->settings = $settings;
|
||||
$company->save();
|
||||
|
||||
$account->default_company_id = $company->id;
|
||||
$account->save();
|
||||
|
||||
@ -367,24 +349,28 @@ class CreateTestData extends Command
|
||||
|
||||
private function createClient($company, $user)
|
||||
{
|
||||
$client = factory(\App\Models\Client::class)->create([
|
||||
'user_id' => $user->id,
|
||||
'company_id' => $company->id
|
||||
]);
|
||||
|
||||
factory(\App\Models\ClientContact::class, 1)->create([
|
||||
// dispatch(function () use ($company, $user) {
|
||||
|
||||
// });
|
||||
$client = factory(\App\Models\Client::class)->create([
|
||||
'user_id' => $user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $company->id,
|
||||
'is_primary' => 1
|
||||
]);
|
||||
|
||||
factory(\App\Models\ClientContact::class, rand(1, 5))->create([
|
||||
'user_id' => $user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $company->id
|
||||
]);
|
||||
|
||||
factory(\App\Models\ClientContact::class, 1)->create([
|
||||
'user_id' => $user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $company->id,
|
||||
'is_primary' => 1
|
||||
]);
|
||||
|
||||
factory(\App\Models\ClientContact::class, rand(1, 5))->create([
|
||||
'user_id' => $user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $company->id
|
||||
]);
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -445,149 +431,162 @@ class CreateTestData extends Command
|
||||
|
||||
private function createInvoice($client)
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
$invoice = InvoiceFactory::create($client->company->id, $client->user->id, $client->getMergedSettings(), $client);//stub the company and user_id
|
||||
$invoice->client_id = $client->id;
|
||||
// $invoice->date = $faker->date();
|
||||
$dateable = Carbon::now()->subDays(rand(0,90));
|
||||
$invoice->date = $dateable;
|
||||
|
||||
$invoice->line_items = $this->buildLineItems(rand(1,10));
|
||||
$invoice->uses_inclusive_taxes = false;
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$invoice->tax_name1 = 'GST';
|
||||
$invoice->tax_rate1 = 10.00;
|
||||
for($x=0; $x<$this->count; $x++){
|
||||
dispatch(new CreateTestInvoiceJob($client));
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$invoice->tax_name2 = 'VAT';
|
||||
$invoice->tax_rate2 = 17.50;
|
||||
}
|
||||
// $faker = \Faker\Factory::create();
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$invoice->tax_name3 = 'CA Sales Tax';
|
||||
$invoice->tax_rate3 = 5;
|
||||
}
|
||||
// $invoice = InvoiceFactory::create($client->company->id, $client->user->id);//stub the company and user_id
|
||||
// $invoice->client_id = $client->id;
|
||||
// // $invoice->date = $faker->date();
|
||||
// $dateable = Carbon::now()->subDays(rand(0,90));
|
||||
// $invoice->date = $dateable;
|
||||
|
||||
$invoice->save();
|
||||
// $invoice->line_items = $this->buildLineItems(rand(1,10));
|
||||
// $invoice->uses_inclusive_taxes = false;
|
||||
|
||||
$invoice_calc = new InvoiceSum($invoice);
|
||||
$invoice_calc->build();
|
||||
// if (rand(0, 1)) {
|
||||
// $invoice->tax_name1 = 'GST';
|
||||
// $invoice->tax_rate1 = 10.00;
|
||||
// }
|
||||
|
||||
$invoice = $invoice_calc->getInvoice();
|
||||
// if (rand(0, 1)) {
|
||||
// $invoice->tax_name2 = 'VAT';
|
||||
// $invoice->tax_rate2 = 17.50;
|
||||
// }
|
||||
|
||||
$invoice->save();
|
||||
$invoice->service()->createInvitations();
|
||||
// if (rand(0, 1)) {
|
||||
// $invoice->tax_name3 = 'CA Sales Tax';
|
||||
// $invoice->tax_rate3 = 5;
|
||||
// }
|
||||
|
||||
$invoice->ledger()->updateInvoiceBalance($invoice->balance);
|
||||
// $invoice->save();
|
||||
|
||||
//UpdateCompanyLedgerWithInvoice::dispatchNow($invoice, $invoice->balance, $invoice->company);
|
||||
// $invoice_calc = new InvoiceSum($invoice);
|
||||
// $invoice_calc->build();
|
||||
|
||||
$this->invoice_repo->markSent($invoice);
|
||||
// $invoice = $invoice_calc->getInvoice();
|
||||
|
||||
$invoice->service()->createInvitations();
|
||||
// $invoice->save();
|
||||
// $invoice->service()->createInvitations();
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$payment = PaymentFactory::create($client->company->id, $client->user->id);
|
||||
$payment->date = $dateable;
|
||||
$payment->client_id = $client->id;
|
||||
$payment->amount = $invoice->balance;
|
||||
$payment->transaction_reference = rand(0, 500);
|
||||
$payment->type_id = PaymentType::CREDIT_CARD_OTHER;
|
||||
$payment->status_id = Payment::STATUS_COMPLETED;
|
||||
$payment->number = $client->getNextPaymentNumber($client);
|
||||
$payment->save();
|
||||
// $invoice->ledger()->updateInvoiceBalance($invoice->balance);
|
||||
|
||||
$payment->invoices()->save($invoice);
|
||||
// //UpdateCompanyLedgerWithInvoice::dispatchNow($invoice, $invoice->balance, $invoice->company);
|
||||
|
||||
event(new PaymentWasCreated($payment, $payment->company));
|
||||
// $this->invoice_repo->markSent($invoice);
|
||||
|
||||
$payment->service()->updateInvoicePayment();
|
||||
//UpdateInvoicePayment::dispatchNow($payment, $payment->company);
|
||||
}
|
||||
//@todo this slow things down, but gives us PDFs of the invoices for inspection whilst debugging.
|
||||
event(new InvoiceWasCreated($invoice, $invoice->company));
|
||||
// $invoice->service()->createInvitations();
|
||||
|
||||
// if (rand(0, 1)) {
|
||||
// $payment = PaymentFactory::create($client->company->id, $client->user->id);
|
||||
// $payment->date = $dateable;
|
||||
// $payment->client_id = $client->id;
|
||||
// $payment->amount = $invoice->balance;
|
||||
// $payment->transaction_reference = rand(0, 500);
|
||||
// $payment->type_id = PaymentType::CREDIT_CARD_OTHER;
|
||||
// $payment->status_id = Payment::STATUS_COMPLETED;
|
||||
// $payment->number = $client->getNextPaymentNumber($client);
|
||||
// $payment->save();
|
||||
|
||||
// $payment->invoices()->save($invoice);
|
||||
|
||||
// event(new PaymentWasCreated($payment, $payment->company));
|
||||
|
||||
// $payment->service()->updateInvoicePayment();
|
||||
// //UpdateInvoicePayment::dispatchNow($payment, $payment->company);
|
||||
// }
|
||||
// //@todo this slow things down, but gives us PDFs of the invoices for inspection whilst debugging.
|
||||
// event(new InvoiceWasCreated($invoice, $invoice->company));
|
||||
}
|
||||
|
||||
private function createCredit($client)
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
for($x=0; $x<$this->count; $x++){
|
||||
|
||||
$credit = factory(\App\Models\Credit::class)->create(['user_id' => $client->user->id, 'company_id' => $client->company->id, 'client_id' => $client->id]);
|
||||
dispatch(new CreateTestCreditJob($client));
|
||||
|
||||
//$invoice = InvoiceFactory::create($client->company->id, $client->user->id);//stub the company and user_id
|
||||
//$invoice->client_id = $client->id;
|
||||
// $invoice->date = $faker->date();
|
||||
$dateable = Carbon::now()->subDays(rand(0,90));
|
||||
$credit->date = $dateable;
|
||||
|
||||
$credit->line_items = $this->buildLineItems(rand(1,10));
|
||||
$credit->uses_inclusive_taxes = false;
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$credit->tax_name1 = 'GST';
|
||||
$credit->tax_rate1 = 10.00;
|
||||
}
|
||||
// $faker = \Faker\Factory::create();
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$credit->tax_name2 = 'VAT';
|
||||
$credit->tax_rate2 = 17.50;
|
||||
}
|
||||
// $credit = factory(\App\Models\Credit::class)->create(['user_id' => $client->user->id, 'company_id' => $client->company->id, 'client_id' => $client->id]);
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$credit->tax_name3 = 'CA Sales Tax';
|
||||
$credit->tax_rate3 = 5;
|
||||
}
|
||||
// //$invoice = InvoiceFactory::create($client->company->id, $client->user->id);//stub the company and user_id
|
||||
// //$invoice->client_id = $client->id;
|
||||
// // $invoice->date = $faker->date();
|
||||
// $dateable = Carbon::now()->subDays(rand(0,90));
|
||||
// $credit->date = $dateable;
|
||||
|
||||
$credit->save();
|
||||
// $credit->line_items = $this->buildLineItems(rand(1,10));
|
||||
// $credit->uses_inclusive_taxes = false;
|
||||
|
||||
$invoice_calc = new InvoiceSum($credit);
|
||||
$invoice_calc->build();
|
||||
// if (rand(0, 1)) {
|
||||
// $credit->tax_name1 = 'GST';
|
||||
// $credit->tax_rate1 = 10.00;
|
||||
// }
|
||||
|
||||
$credit = $invoice_calc->getCredit();
|
||||
// if (rand(0, 1)) {
|
||||
// $credit->tax_name2 = 'VAT';
|
||||
// $credit->tax_rate2 = 17.50;
|
||||
// }
|
||||
|
||||
$credit->save();
|
||||
// if (rand(0, 1)) {
|
||||
// $credit->tax_name3 = 'CA Sales Tax';
|
||||
// $credit->tax_rate3 = 5;
|
||||
// }
|
||||
|
||||
event(new CreateCreditInvitation($credit));
|
||||
// $credit->save();
|
||||
|
||||
// $invoice_calc = new InvoiceSum($credit);
|
||||
// $invoice_calc->build();
|
||||
|
||||
// $credit = $invoice_calc->getCredit();
|
||||
|
||||
// $credit->save();
|
||||
|
||||
// event(new CreateCreditInvitation($credit));
|
||||
|
||||
}
|
||||
|
||||
private function createQuote($client)
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
for($x=0; $x<$this->count; $x++){
|
||||
|
||||
$quote =factory(\App\Models\Quote::class)->create(['user_id' => $client->user->id, 'company_id' => $client->company->id, 'client_id' => $client->id]);
|
||||
$quote->date = $faker->date();
|
||||
|
||||
$quote->line_items = $this->buildLineItems(rand(1,10));
|
||||
$quote->uses_inclusive_taxes = false;
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$quote->tax_name1 = 'GST';
|
||||
$quote->tax_rate1 = 10.00;
|
||||
dispatch(new CreateTestQuoteJob($client));
|
||||
}
|
||||
// $faker = \Faker\Factory::create();
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$quote->tax_name2 = 'VAT';
|
||||
$quote->tax_rate2 = 17.50;
|
||||
}
|
||||
// $quote =factory(\App\Models\Quote::class)->create(['user_id' => $client->user->id, 'company_id' => $client->company->id, 'client_id' => $client->id]);
|
||||
// $quote->date = $faker->date();
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$quote->tax_name3 = 'CA Sales Tax';
|
||||
$quote->tax_rate3 = 5;
|
||||
}
|
||||
// $quote->line_items = $this->buildLineItems(rand(1,10));
|
||||
// $quote->uses_inclusive_taxes = false;
|
||||
|
||||
$quote->save();
|
||||
// if (rand(0, 1)) {
|
||||
// $quote->tax_name1 = 'GST';
|
||||
// $quote->tax_rate1 = 10.00;
|
||||
// }
|
||||
|
||||
$quote_calc = new InvoiceSum($quote);
|
||||
$quote_calc->build();
|
||||
// if (rand(0, 1)) {
|
||||
// $quote->tax_name2 = 'VAT';
|
||||
// $quote->tax_rate2 = 17.50;
|
||||
// }
|
||||
|
||||
$quote = $quote_calc->getQuote();
|
||||
$quote->service()->markSent()->save();
|
||||
// if (rand(0, 1)) {
|
||||
// $quote->tax_name3 = 'CA Sales Tax';
|
||||
// $quote->tax_rate3 = 5;
|
||||
// }
|
||||
|
||||
CreateQuoteInvitations::dispatch($quote, $quote->company);
|
||||
// $quote->save();
|
||||
|
||||
// $quote_calc = new InvoiceSum($quote);
|
||||
// $quote_calc->build();
|
||||
|
||||
// $quote = $quote_calc->getQuote();
|
||||
// $quote->service()->markSent()->save();
|
||||
|
||||
// CreateQuoteInvitations::dispatch($quote, $quote->company);
|
||||
}
|
||||
|
||||
private function buildLineItems($count = 1)
|
||||
|
@ -131,7 +131,7 @@ class SendTestEmails extends Command
|
||||
]);
|
||||
}
|
||||
|
||||
$invoice = InvoiceFactory::create($company->id, $user->id, $client->getMergedSettings(), $client);
|
||||
$invoice = InvoiceFactory::create($company->id, $user->id);
|
||||
$invoice->client_id = $client->id;
|
||||
$invoice->setRelation('client', $client);
|
||||
$invoice->save();
|
||||
|
142
app/Console/Commands/TestData/CreateTestCreditJob.php
Normal file
142
app/Console/Commands/TestData/CreateTestCreditJob.php
Normal file
@ -0,0 +1,142 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Console\Commands\TestData;
|
||||
|
||||
use App\Events\Invoice\InvoiceWasCreated;
|
||||
use App\Events\Payment\PaymentWasCreated;
|
||||
use App\Factory\InvoiceFactory;
|
||||
use App\Factory\InvoiceItemFactory;
|
||||
use App\Factory\PaymentFactory;
|
||||
use App\Helpers\Invoice\InvoiceSum;
|
||||
use App\Listeners\Credit\CreateCreditInvitation;
|
||||
use App\Models\Client;
|
||||
use App\Models\Payment;
|
||||
use App\Models\PaymentType;
|
||||
use App\Models\Product;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class CreateTestCreditJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, MakesHash;
|
||||
|
||||
protected $client;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
public function __construct(Client $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
$credit = factory(\App\Models\Credit::class)->create(['user_id' => $this->client->user->id, 'company_id' => $this->client->company->id, 'client_id' => $this->client->id]);
|
||||
|
||||
//$invoice = InvoiceFactory::create($this->client->company->id, $this->client->user->id);//stub the company and user_id
|
||||
//$invoice->client_id = $this->client->id;
|
||||
// $invoice->date = $faker->date();
|
||||
$dateable = Carbon::now()->subDays(rand(0,90));
|
||||
$credit->date = $dateable;
|
||||
|
||||
$credit->line_items = $this->buildLineItems(rand(1,10));
|
||||
$credit->uses_inclusive_taxes = false;
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$credit->tax_name1 = 'GST';
|
||||
$credit->tax_rate1 = 10.00;
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$credit->tax_name2 = 'VAT';
|
||||
$credit->tax_rate2 = 17.50;
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$credit->tax_name3 = 'CA Sales Tax';
|
||||
$credit->tax_rate3 = 5;
|
||||
}
|
||||
|
||||
$credit->save();
|
||||
|
||||
$invoice_calc = new InvoiceSum($credit);
|
||||
$invoice_calc->build();
|
||||
|
||||
$credit = $invoice_calc->getCredit();
|
||||
|
||||
$credit->save();
|
||||
|
||||
event(new CreateCreditInvitation($credit));
|
||||
}
|
||||
|
||||
|
||||
private function buildLineItems($count = 1)
|
||||
{
|
||||
$line_items = [];
|
||||
|
||||
for($x=0; $x<$count; $x++)
|
||||
{
|
||||
$item = InvoiceItemFactory::create();
|
||||
$item->quantity = 1;
|
||||
//$item->cost = 10;
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$item->tax_name1 = 'GST';
|
||||
$item->tax_rate1 = 10.00;
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$item->tax_name1 = 'VAT';
|
||||
$item->tax_rate1 = 17.50;
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$item->tax_name1 = 'Sales Tax';
|
||||
$item->tax_rate1 = 5;
|
||||
}
|
||||
|
||||
$product = Product::all()->random();
|
||||
|
||||
$item->cost = (float)$product->cost;
|
||||
$item->product_key = $product->product_key;
|
||||
$item->notes = $product->notes;
|
||||
$item->custom_value1 = $product->custom_value1;
|
||||
$item->custom_value2 = $product->custom_value2;
|
||||
$item->custom_value3 = $product->custom_value3;
|
||||
$item->custom_value4 = $product->custom_value4;
|
||||
|
||||
|
||||
|
||||
$line_items[] = $item;
|
||||
}
|
||||
|
||||
return $line_items;
|
||||
}
|
||||
}
|
167
app/Console/Commands/TestData/CreateTestInvoiceJob.php
Normal file
167
app/Console/Commands/TestData/CreateTestInvoiceJob.php
Normal file
@ -0,0 +1,167 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Console\Commands\TestData;
|
||||
|
||||
use App\Events\Invoice\InvoiceWasCreated;
|
||||
use App\Events\Payment\PaymentWasCreated;
|
||||
use App\Factory\InvoiceFactory;
|
||||
use App\Factory\InvoiceItemFactory;
|
||||
use App\Factory\PaymentFactory;
|
||||
use App\Helpers\Invoice\InvoiceSum;
|
||||
use App\Models\Client;
|
||||
use App\Models\Payment;
|
||||
use App\Models\PaymentType;
|
||||
use App\Models\Product;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class CreateTestInvoiceJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, MakesHash;
|
||||
|
||||
protected $client;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
public function __construct(Client $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
$invoice = InvoiceFactory::create($this->client->company->id, $this->client->user->id);//stub the company and user_id
|
||||
$invoice->client_id = $this->client->id;
|
||||
// $invoice->date = $faker->date();
|
||||
$dateable = Carbon::now()->subDays(rand(0,90));
|
||||
$invoice->date = $dateable;
|
||||
|
||||
$invoice->line_items = $this->buildLineItems(rand(1,10));
|
||||
$invoice->uses_inclusive_taxes = false;
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$invoice->tax_name1 = 'GST';
|
||||
$invoice->tax_rate1 = 10.00;
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$invoice->tax_name2 = 'VAT';
|
||||
$invoice->tax_rate2 = 17.50;
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$invoice->tax_name3 = 'CA Sales Tax';
|
||||
$invoice->tax_rate3 = 5;
|
||||
}
|
||||
|
||||
$invoice->save();
|
||||
|
||||
$invoice_calc = new InvoiceSum($invoice);
|
||||
$invoice_calc->build();
|
||||
|
||||
$invoice = $invoice_calc->getInvoice();
|
||||
|
||||
$invoice->save();
|
||||
$invoice->service()->createInvitations()->markSent()->save();
|
||||
|
||||
$invoice->ledger()->updateInvoiceBalance($invoice->balance);
|
||||
|
||||
//UpdateCompanyLedgerWithInvoice::dispatchNow($invoice, $invoice->balance, $invoice->company);
|
||||
|
||||
//$this->invoice_repo->markSent($invoice);
|
||||
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$payment = PaymentFactory::create($this->client->company->id, $this->client->user->id);
|
||||
$payment->date = $dateable;
|
||||
$payment->client_id = $this->client->id;
|
||||
$payment->amount = $invoice->balance;
|
||||
$payment->transaction_reference = rand(0, 500);
|
||||
$payment->type_id = PaymentType::CREDIT_CARD_OTHER;
|
||||
$payment->status_id = Payment::STATUS_COMPLETED;
|
||||
$payment->number = $this->client->getNextPaymentNumber($this->client);
|
||||
$payment->save();
|
||||
|
||||
$payment->invoices()->save($invoice);
|
||||
|
||||
event(new PaymentWasCreated($payment, $payment->company));
|
||||
|
||||
$payment->service()->updateInvoicePayment();
|
||||
//UpdateInvoicePayment::dispatchNow($payment, $payment->company);
|
||||
}
|
||||
//@todo this slow things down, but gives us PDFs of the invoices for inspection whilst debugging.
|
||||
event(new InvoiceWasCreated($invoice, $invoice->company));
|
||||
}
|
||||
|
||||
|
||||
private function buildLineItems($count = 1)
|
||||
{
|
||||
$line_items = [];
|
||||
|
||||
for($x=0; $x<$count; $x++)
|
||||
{
|
||||
$item = InvoiceItemFactory::create();
|
||||
$item->quantity = 1;
|
||||
//$item->cost = 10;
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$item->tax_name1 = 'GST';
|
||||
$item->tax_rate1 = 10.00;
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$item->tax_name1 = 'VAT';
|
||||
$item->tax_rate1 = 17.50;
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$item->tax_name1 = 'Sales Tax';
|
||||
$item->tax_rate1 = 5;
|
||||
}
|
||||
|
||||
$product = Product::all()->random();
|
||||
|
||||
$item->cost = (float)$product->cost;
|
||||
$item->product_key = $product->product_key;
|
||||
$item->notes = $product->notes;
|
||||
$item->custom_value1 = $product->custom_value1;
|
||||
$item->custom_value2 = $product->custom_value2;
|
||||
$item->custom_value3 = $product->custom_value3;
|
||||
$item->custom_value4 = $product->custom_value4;
|
||||
|
||||
|
||||
|
||||
$line_items[] = $item;
|
||||
}
|
||||
|
||||
return $line_items;
|
||||
}
|
||||
}
|
139
app/Console/Commands/TestData/CreateTestQuoteJob.php
Normal file
139
app/Console/Commands/TestData/CreateTestQuoteJob.php
Normal file
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Console\Commands\TestData;
|
||||
|
||||
use App\Events\Invoice\InvoiceWasCreated;
|
||||
use App\Events\Payment\PaymentWasCreated;
|
||||
use App\Factory\InvoiceFactory;
|
||||
use App\Factory\InvoiceItemFactory;
|
||||
use App\Factory\PaymentFactory;
|
||||
use App\Helpers\Invoice\InvoiceSum;
|
||||
use App\Jobs\Quote\CreateQuoteInvitations;
|
||||
use App\Models\Client;
|
||||
use App\Models\Payment;
|
||||
use App\Models\PaymentType;
|
||||
use App\Models\Product;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class CreateTestQuoteJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, MakesHash;
|
||||
|
||||
protected $client;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
public function __construct(Client $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
$quote =factory(\App\Models\Quote::class)->create(['user_id' => $this->client->user->id, 'company_id' => $this->client->company->id, 'client_id' => $this->client->id]);
|
||||
$quote->date = $faker->date();
|
||||
|
||||
$quote->line_items = $this->buildLineItems(rand(1,10));
|
||||
$quote->uses_inclusive_taxes = false;
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$quote->tax_name1 = 'GST';
|
||||
$quote->tax_rate1 = 10.00;
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$quote->tax_name2 = 'VAT';
|
||||
$quote->tax_rate2 = 17.50;
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$quote->tax_name3 = 'CA Sales Tax';
|
||||
$quote->tax_rate3 = 5;
|
||||
}
|
||||
|
||||
$quote->save();
|
||||
|
||||
$quote_calc = new InvoiceSum($quote);
|
||||
$quote_calc->build();
|
||||
|
||||
$quote = $quote_calc->getQuote();
|
||||
$quote->service()->markSent()->save();
|
||||
|
||||
CreateQuoteInvitations::dispatch($quote, $quote->company);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private function buildLineItems($count = 1)
|
||||
{
|
||||
$line_items = [];
|
||||
|
||||
for($x=0; $x<$count; $x++)
|
||||
{
|
||||
$item = InvoiceItemFactory::create();
|
||||
$item->quantity = 1;
|
||||
//$item->cost = 10;
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$item->tax_name1 = 'GST';
|
||||
$item->tax_rate1 = 10.00;
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$item->tax_name1 = 'VAT';
|
||||
$item->tax_rate1 = 17.50;
|
||||
}
|
||||
|
||||
if (rand(0, 1)) {
|
||||
$item->tax_name1 = 'Sales Tax';
|
||||
$item->tax_rate1 = 5;
|
||||
}
|
||||
|
||||
$product = Product::all()->random();
|
||||
|
||||
$item->cost = (float)$product->cost;
|
||||
$item->product_key = $product->product_key;
|
||||
$item->notes = $product->notes;
|
||||
$item->custom_value1 = $product->custom_value1;
|
||||
$item->custom_value2 = $product->custom_value2;
|
||||
$item->custom_value3 = $product->custom_value3;
|
||||
$item->custom_value4 = $product->custom_value4;
|
||||
|
||||
|
||||
|
||||
$line_items[] = $item;
|
||||
}
|
||||
|
||||
return $line_items;
|
||||
}
|
||||
|
||||
}
|
@ -114,6 +114,7 @@ class CompanySettings extends BaseSettings {
|
||||
public $enabled_item_tax_rates = 0;
|
||||
public $invoice_design_id = '1';
|
||||
public $quote_design_id = '1';
|
||||
public $credit_design_id = '1';
|
||||
public $invoice_footer = '';
|
||||
public $credit_footer = '';
|
||||
public $credit_terms = '';
|
||||
@ -345,6 +346,7 @@ class CompanySettings extends BaseSettings {
|
||||
'phone' => 'string',
|
||||
'postal_code' => 'string',
|
||||
'quote_design_id' => 'string',
|
||||
'credit_design_id' => 'string',
|
||||
'quote_number_pattern' => 'string',
|
||||
'quote_number_counter' => 'integer',
|
||||
'quote_terms' => 'string',
|
||||
|
@ -34,6 +34,7 @@ class CompanyFactory
|
||||
//$company->custom_fields = (object) ['invoice1' => '1', 'invoice2' => '2', 'client1'=>'3'];
|
||||
$company->custom_fields = (object) [];
|
||||
$company->subdomain = '';
|
||||
$company->enabled_modules = 2047;
|
||||
|
||||
return $company;
|
||||
}
|
||||
|
@ -24,9 +24,9 @@ class CreditFactory
|
||||
$credit->discount = 0;
|
||||
$credit->is_amount_discount = true;
|
||||
$credit->po_number = '';
|
||||
$credit->footer = isset($settings) && strlen($settings->credit_footer) > 0 ? $settings->credit_footer : '';
|
||||
$credit->terms = isset($settings) && strlen($settings->credit_terms) > 0 ? $settings->credit_terms : '';
|
||||
$credit->public_notes = isset($client) && strlen($client->public_notes) > 0 ? $client->public_notes : '';
|
||||
$credit->footer = '';
|
||||
$credit->terms = '';
|
||||
$credit->public_notes = '';
|
||||
$credit->private_notes = '';
|
||||
$credit->date = null;
|
||||
$credit->due_date = null;
|
||||
|
@ -19,7 +19,7 @@ use Illuminate\Support\Facades\Log;
|
||||
|
||||
class InvoiceFactory
|
||||
{
|
||||
public static function create(int $company_id, int $user_id, object $settings = null, Client $client = null) :Invoice
|
||||
public static function create(int $company_id, int $user_id) :Invoice
|
||||
{
|
||||
$invoice = new Invoice();
|
||||
$invoice->status_id = Invoice::STATUS_DRAFT;
|
||||
@ -27,9 +27,9 @@ class InvoiceFactory
|
||||
$invoice->discount = 0;
|
||||
$invoice->is_amount_discount = true;
|
||||
$invoice->po_number = '';
|
||||
$invoice->footer = isset($settings) && strlen($settings->invoice_footer) > 0 ? $settings->invoice_footer : '';
|
||||
$invoice->terms = isset($settings) && strlen($settings->invoice_terms) > 0 ? $settings->invoice_terms : '';
|
||||
$invoice->public_notes = isset($settings) && strlen($client->public_notes) > 0 ? $client->public_notes : '';
|
||||
$invoice->footer = '';
|
||||
$invoice->terms = '';
|
||||
$invoice->public_notes = '';
|
||||
$invoice->private_notes = '';
|
||||
$invoice->date = null;
|
||||
$invoice->due_date = null;
|
||||
|
@ -19,7 +19,7 @@ use Illuminate\Support\Facades\Log;
|
||||
|
||||
class QuoteFactory
|
||||
{
|
||||
public static function create(int $company_id, int $user_id, object $settings = null, Client $client = null) :Quote
|
||||
public static function create(int $company_id, int $user_id) :Quote
|
||||
{
|
||||
$quote = new Quote();
|
||||
$quote->status_id = Quote::STATUS_DRAFT;
|
||||
@ -27,9 +27,9 @@ class QuoteFactory
|
||||
$quote->discount = 0;
|
||||
$quote->is_amount_discount = true;
|
||||
$quote->po_number = '';
|
||||
$quote->footer = isset($settings) && strlen($settings->quote_footer) > 0 ? $settings->quote_footer : '';
|
||||
$quote->terms = isset($settings) && strlen($settings->quote_terms) > 0 ? $settings->quote_terms : '';
|
||||
$quote->public_notes = isset($client) && strlen($client->public_notes) > 0 ? $client->public_notes : '';
|
||||
$quote->footer = '';
|
||||
$quote->terms = '';
|
||||
$quote->public_notes = '';
|
||||
$quote->private_notes = '';
|
||||
$quote->date = null;
|
||||
$quote->due_date = null;
|
||||
|
@ -288,6 +288,7 @@ class BaseController extends Controller
|
||||
'company.invoices',
|
||||
'company.payments.paymentables',
|
||||
'company.quotes',
|
||||
'company.credits',
|
||||
'company.vendors.contacts',
|
||||
'company.expenses',
|
||||
'company.tasks',
|
||||
|
@ -18,11 +18,17 @@ use App\Http\Requests\Credit\UpdateCreditRequest;
|
||||
use App\Jobs\Credit\StoreCredit;
|
||||
use App\Jobs\Invoice\EmailCredit;
|
||||
use App\Jobs\Invoice\MarkInvoicePaid;
|
||||
use App\Models\Client;
|
||||
use App\Models\Credit;
|
||||
use App\Repositories\CreditRepository;
|
||||
use App\Transformers\CreditTransformer;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
|
||||
/**
|
||||
* Class CreditController
|
||||
* @package App\Http\Controllers\CreditController
|
||||
*/
|
||||
|
||||
class CreditController extends BaseController
|
||||
{
|
||||
use MakesHash;
|
||||
@ -40,6 +46,48 @@ class CreditController extends BaseController
|
||||
$this->credit_repository = $credit_repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the list of Credits
|
||||
*
|
||||
* @param \App\Filters\CreditFilters $filters The filters
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/credits",
|
||||
* operationId="getCredits",
|
||||
* tags={"invoices"},
|
||||
* summary="Gets a list of credits",
|
||||
* description="Lists credits, search and filters allow fine grained lists to be generated.
|
||||
*
|
||||
* Query parameters can be added to performed more fine grained filtering of the credits, these are handled by the CreditFilters class which defines the methods available",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="A list of credits",
|
||||
* @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-Version"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/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"),
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
*/
|
||||
|
||||
public function index(CreditFilters $filters)
|
||||
{
|
||||
$credits = Credit::filter($filters);
|
||||
@ -47,6 +95,46 @@ class CreditController extends BaseController
|
||||
return $this->listResponse($credits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Credit\CreateCreditRequest $request The request
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/credits/create",
|
||||
* operationId="getCreditsCreate",
|
||||
* tags={"credits"},
|
||||
* summary="Gets a new blank credit 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 credit object",
|
||||
* @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-Version"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/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"),
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
*/
|
||||
public function create(CreateCreditRequest $request)
|
||||
{
|
||||
$credit = CreditFactory::create(auth()->user()->company()->id, auth()->user()->id);
|
||||
@ -54,9 +142,51 @@ class CreditController extends BaseController
|
||||
return $this->itemResponse($credit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Credit\StoreCreditRequest $request The request
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/credits",
|
||||
* operationId="storeCredit",
|
||||
* tags={"credits"},
|
||||
* summary="Adds a credit",
|
||||
* description="Adds an credit to the system",
|
||||
* @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 credit object",
|
||||
* @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-Version"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/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"),
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
*/
|
||||
public function store(StoreCreditRequest $request)
|
||||
{
|
||||
$credit = $this->credit_repository->save($request->all(), CreditFactory::create(auth()->user()->company()->id, auth()->user()->id));
|
||||
$client = Client::find($request->input('client_id'));
|
||||
|
||||
$credit = $this->credit_repository->save($request->all(), $client->setCreditDefaults());
|
||||
|
||||
$credit = StoreCredit::dispatchNow($credit, $request->all(), $credit->company);
|
||||
|
||||
@ -65,16 +195,171 @@ class CreditController extends BaseController
|
||||
return $this->itemResponse($credit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Credit\ShowCreditRequest $request The request
|
||||
* @param \App\Models\Credit $credit The credit
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/credits/{id}",
|
||||
* operationId="showCredit",
|
||||
* tags={"credits"},
|
||||
* summary="Shows an credit",
|
||||
* description="Displays an credit 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 Credit Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the credit object",
|
||||
* @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-Version"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/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"),
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
*/
|
||||
public function show(ShowCreditRequest $request, Credit $credit)
|
||||
{
|
||||
return $this->itemResponse($credit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Invoice\EditInvoiceRequest $request The request
|
||||
* @param \App\Models\Invoice $credit The credit
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/credits/{id}/edit",
|
||||
* operationId="editInvoice",
|
||||
* tags={"credits"},
|
||||
* summary="Shows an credit for editting",
|
||||
* description="Displays an credit 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 Invoice Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the credit object",
|
||||
* @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-Version"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/Invoice"),
|
||||
* ),
|
||||
* @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(EditCreditRequest $request, Credit $credit)
|
||||
{
|
||||
return $this->itemResponse($credit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Credit\UpdateCreditRequest $request The request
|
||||
* @param \App\Models\Credit $Credit The Credit
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
*
|
||||
* @OA\Put(
|
||||
* path="/api/v1/Credits/{id}",
|
||||
* operationId="updateCredit",
|
||||
* tags={"Credits"},
|
||||
* summary="Updates an Credit",
|
||||
* description="Handles the updating of an Credit 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 Credit Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the Credit object",
|
||||
* @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-Version"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/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"),
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
*/
|
||||
public function update(UpdateCreditRequest $request, Credit $credit)
|
||||
{
|
||||
if($request->entityIsDeleted($credit))
|
||||
@ -87,6 +372,56 @@ class CreditController extends BaseController
|
||||
return $this->itemResponse($credit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Credit\DestroyCreditRequest $request
|
||||
* @param \App\Models\Credit $credit
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @OA\Delete(
|
||||
* path="/api/v1/credits/{id}",
|
||||
* operationId="deleteCredit",
|
||||
* tags={"credits"},
|
||||
* summary="Deletes a credit",
|
||||
* description="Handles the deletion of an credit 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 Credit Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns a HTTP status",
|
||||
* @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-Version"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
*/
|
||||
public function destroy(DestroyCreditRequest $request, Credit $credit)
|
||||
{
|
||||
$credit->delete();
|
||||
@ -94,6 +429,57 @@ class CreditController extends BaseController
|
||||
return response()->json([], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform bulk actions on the list view
|
||||
*
|
||||
* @return Collection
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/credits/bulk",
|
||||
* operationId="bulkCredits",
|
||||
* tags={"credits"},
|
||||
* summary="Performs bulk actions on an array of credits",
|
||||
* description="",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/index"),
|
||||
* @OA\RequestBody(
|
||||
* description="User credentials",
|
||||
* required=true,
|
||||
* @OA\MediaType(
|
||||
* mediaType="application/json",
|
||||
* @OA\Schema(
|
||||
* type="array",
|
||||
* @OA\Items(
|
||||
* type="integer",
|
||||
* description="Array of hashed IDs to be bulk 'actioned",
|
||||
* example="[0,1,2,3]",
|
||||
* ),
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="The Bulk Action response",
|
||||
* @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-Version"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\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');
|
||||
@ -150,7 +536,7 @@ class CreditController extends BaseController
|
||||
}
|
||||
break;
|
||||
case 'mark_sent':
|
||||
$credit->markSent();
|
||||
$credit->service()->markSent()->save();
|
||||
|
||||
if (!$bulk) {
|
||||
return $this->itemResponse($credit);
|
||||
|
@ -159,7 +159,7 @@ class InvoiceController extends BaseController {
|
||||
*/
|
||||
public function create(CreateInvoiceRequest $request) {
|
||||
|
||||
$invoice = InvoiceFactory::create(auth()->user()->company()->id, auth()->user()->id, $client->getMergedSettings(), $client);
|
||||
$invoice = InvoiceFactory::create(auth()->user()->company()->id, auth()->user()->id);
|
||||
|
||||
return $this->itemResponse($invoice);
|
||||
}
|
||||
@ -208,7 +208,7 @@ class InvoiceController extends BaseController {
|
||||
|
||||
$client = Client::find($request->input('client_id'));
|
||||
|
||||
$invoice = $this->invoice_repo->save($request->all(), InvoiceFactory::create(auth()->user()->company()->id, auth()->user()->id), $client->getMergedSettings(), $client);
|
||||
$invoice = $this->invoice_repo->save($request->all(), $client->setInvoiceDefaults());
|
||||
|
||||
$invoice = StoreInvoice::dispatchNow($invoice, $request->all(), $invoice->company);//todo potentially this may return mixed ie PDF/$invoice... need to revisit when we implement UI
|
||||
|
||||
@ -514,6 +514,10 @@ class InvoiceController extends BaseController {
|
||||
return response()->json(['message' => 'No Invoices Found']);
|
||||
}
|
||||
|
||||
/*
|
||||
* Download Invoice/s
|
||||
*/
|
||||
|
||||
if($action == 'download' && $invoices->count() > 1)
|
||||
{
|
||||
|
||||
@ -530,7 +534,9 @@ class InvoiceController extends BaseController {
|
||||
return response()->json(['message' => 'Email Sent!'],200);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Send the other actions to the switch
|
||||
*/
|
||||
$invoices->each(function ($invoice, $key) use ($action) {
|
||||
|
||||
if (auth()->user()->can('edit', $invoice)) {
|
||||
|
53
app/Http/Controllers/OpenAPI/CreditSchema.php
Normal file
53
app/Http/Controllers/OpenAPI/CreditSchema.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* @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="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="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="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="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 Credit Date"),
|
||||
* @OA\Property(property="last_sent_date", type="string", format="date", example="1994-07-30", description="The last date the credit 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="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"),
|
||||
* @OA\Property(property="archived_at", type="number", format="integer", example="1434342123", description="Timestamp"),
|
||||
* @OA\Property(property="custom_surcharge1", type="number", format="float", example="10.00", description="First Custom Surcharge"),
|
||||
* @OA\Property(property="custom_surcharge2", type="number", format="float", example="10.00", description="Second Custom Surcharge"),
|
||||
* @OA\Property(property="custom_surcharge3", type="number", format="float", example="10.00", description="Third Custom Surcharge"),
|
||||
* @OA\Property(property="custom_surcharge4", type="number", format="float", example="10.00", description="Fourth Custom Surcharge"),
|
||||
* @OA\Property(property="custom_surcharge_taxes", type="boolean", example=true, description="Toggles charging taxes on custom surcharge amounts"),
|
||||
* )
|
||||
*/
|
@ -24,6 +24,8 @@ use App\Http\Requests\Quote\EditQuoteRequest;
|
||||
use App\Http\Requests\Quote\ShowQuoteRequest;
|
||||
use App\Http\Requests\Quote\StoreQuoteRequest;
|
||||
use App\Http\Requests\Quote\UpdateQuoteRequest;
|
||||
use App\Jobs\Invoice\ZipInvoices;
|
||||
use App\Models\Client;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Quote;
|
||||
use App\Repositories\QuoteRepository;
|
||||
@ -201,7 +203,9 @@ class QuoteController extends BaseController
|
||||
*/
|
||||
public function store(StoreQuoteRequest $request)
|
||||
{
|
||||
$quote = $this->quote_repo->save($request->all(), QuoteFactory::create(auth()->user()->company()->id, auth()->user()->id));
|
||||
$client = Client::find($request->input('client_id'));
|
||||
|
||||
$quote = $this->quote_repo->save($request->all(), $client->setQuoteDefaults());
|
||||
|
||||
return $this->itemResponse($quote);
|
||||
}
|
||||
@ -495,20 +499,55 @@ class QuoteController extends BaseController
|
||||
*/
|
||||
public function bulk()
|
||||
{
|
||||
/*
|
||||
* WIP!
|
||||
*/
|
||||
$action = request()->input('action');
|
||||
|
||||
|
||||
$ids = request()->input('ids');
|
||||
|
||||
$quotes = Quote::withTrashed()->find($this->transformKeys($ids));
|
||||
$quotes = Quote::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
|
||||
|
||||
if (!$quotes) {
|
||||
return response()->json(['message' => 'No Quotes Found']);
|
||||
}
|
||||
|
||||
/*
|
||||
* Download Invoice/s
|
||||
*/
|
||||
|
||||
if($action == 'download' && $quotes->count() > 1)
|
||||
{
|
||||
|
||||
$quotes->each(function ($quote) {
|
||||
|
||||
if(auth()->user()->cannot('view', $quote)){
|
||||
return response()->json(['message'=>'Insufficient privileges to access quote '. $quote->number]);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
ZipInvoices::dispatch($quotes, $quotes->first()->company, auth()->user()->email);
|
||||
|
||||
return response()->json(['message' => 'Email Sent!'],200);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the other actions to the switch
|
||||
*/
|
||||
$quotes->each(function ($quote, $key) use ($action) {
|
||||
|
||||
if (auth()->user()->can('edit', $quote)) {
|
||||
$this->quote_repo->{$action}($quote);
|
||||
$this->performAction($quote, $action, true);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return $this->listResponse(Quote::withTrashed()->whereIn('id', $this->transformKeys($ids)));
|
||||
/* Need to understand which permission are required for the given bulk action ie. view / edit */
|
||||
|
||||
return $this->listResponse(Quote::withTrashed()->whereIn('id', $this->transformKeys($ids))->company());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Quote Actions
|
||||
@ -580,13 +619,19 @@ class QuoteController extends BaseController
|
||||
* )
|
||||
*
|
||||
*/
|
||||
public function action(ActionQuoteRequest $request, Quote $quote, $action)
|
||||
|
||||
public function action(ActionQuoteRequest $request, Quote $quote, $action) {
|
||||
return $this->performAction($quote, $action);
|
||||
}
|
||||
|
||||
|
||||
private function performAction(Quote $quote, $action, $bulk = false)
|
||||
{
|
||||
switch ($action) {
|
||||
case 'clone_to_invoice':
|
||||
|
||||
$this->entity_type = Invoice::class;
|
||||
$this->entity_transformer = InvoiceTransformer::class;
|
||||
$this->entity_type = Quote::class;
|
||||
$this->entity_transformer = QuoteTransformer::class;
|
||||
|
||||
$invoice = CloneQuoteToInvoiceFactory::create($quote, auth()->user()->id);
|
||||
return $this->itemResponse($invoice);
|
||||
@ -618,9 +663,16 @@ class QuoteController extends BaseController
|
||||
case 'email':
|
||||
return response()->json(['message'=>'email sent'], 200);
|
||||
break;
|
||||
case 'mark_sent':
|
||||
$quote->service()->markSent()->save();
|
||||
|
||||
if (!$bulk) {
|
||||
return $this->itemResponse($quote);
|
||||
}
|
||||
default:
|
||||
return response()->json(['message' => "The requested action `{$action}` is not available."], 400);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ use App\DataMapper\ClientSettings;
|
||||
use App\Http\Requests\Request;
|
||||
use App\Http\ValidationRules\ValidClientGroupSettingsRule;
|
||||
use App\Models\Client;
|
||||
use App\Models\GroupSetting;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
@ -80,6 +81,23 @@ class StoreClientRequest extends Request
|
||||
$input['group_settings_id'] = $this->decodePrimaryKey($input['group_settings_id']);
|
||||
}
|
||||
|
||||
if(empty($input['settings']->currency_id))
|
||||
{
|
||||
if(empty($input['group_settings_id']))
|
||||
{
|
||||
$input['settings']->currency_id = auth()->user()->company()->settings->currency_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
$group_settings = GroupSetting::find($input['group_settings_id']);
|
||||
|
||||
if($group_settings && property_exists($group_settings, 'currency_id') && is_int($group_settings->currency_id))
|
||||
$input['settings']->currency_id = $group_settings->currency_id;
|
||||
else
|
||||
$input['settings']->currency_id = auth()->user()->company()->settings->currency_id;
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($input['contacts']))
|
||||
{
|
||||
foreach($input['contacts'] as $key => $contact)
|
||||
|
@ -56,6 +56,8 @@ class StoreCompanyRequest extends Request
|
||||
$input['settings']['pdf_variables'] = CompanySettings::getEntityVariableDefaults();
|
||||
}
|
||||
|
||||
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ use App\Jobs\Company\CreateCompanyToken;
|
||||
use App\Jobs\User\CreateUser;
|
||||
use App\Models\Account;
|
||||
use App\Models\User;
|
||||
use App\Notifications\NewAccountCreated;
|
||||
use App\Notifications\Ninja\NewAccountCreated;
|
||||
use App\Utils\Traits\UserSessionAttributes;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Http\Request;
|
||||
@ -92,14 +92,7 @@ class CreateAccount
|
||||
|
||||
$user->fresh();
|
||||
|
||||
$company->notification(new NewAccountCreated($user, $company))->run();
|
||||
|
||||
// $user->route('slack', $company->settings->system_notifications_slack)
|
||||
// ->route('mail', $company->settings->system_notifications_email)
|
||||
// ->notify(new NewAccountCreated($user, $company));
|
||||
|
||||
// Notification::route('slack', config('ninja.notification.slack'))
|
||||
// ->notify(new NewAccountCreated($user, $company));
|
||||
$company->notification(new NewAccountCreated($user, $company))->ninja();
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
107
app/Jobs/Credit/CreateCreditPdf.php
Normal file
107
app/Jobs/Credit/CreateCreditPdf.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Jobs\Credit;
|
||||
|
||||
use App\Designs\Custom;
|
||||
use App\Designs\Designer;
|
||||
use App\Designs\Modern;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Company;
|
||||
use App\Models\Design;
|
||||
use App\Models\Invoice;
|
||||
use App\Utils\Traits\Pdf\PdfMaker;
|
||||
use App\Utils\Traits\MakesInvoiceHtml;
|
||||
use App\Utils\Traits\NumberFormatter;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Spatie\Browsershot\Browsershot;
|
||||
|
||||
class CreateCreditPdf implements ShouldQueue {
|
||||
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, NumberFormatter, MakesInvoiceHtml, PdfMaker;
|
||||
|
||||
public $credit;
|
||||
|
||||
public $company;
|
||||
|
||||
public $contact;
|
||||
|
||||
private $disk;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($credit, Company $company, ClientContact $contact = null)
|
||||
{
|
||||
|
||||
$this->credit = $credit;
|
||||
|
||||
$this->company = $company;
|
||||
|
||||
$this->contact = $contact;
|
||||
|
||||
$this->disk = $disk ?? config('filesystems.default');
|
||||
|
||||
}
|
||||
|
||||
public function handle() {
|
||||
|
||||
MultiDB::setDB($this->company->db);
|
||||
|
||||
$this->credit->load('client');
|
||||
|
||||
if(!$this->contact)
|
||||
$this->contact = $this->credit->client->primary_contact()->first();
|
||||
|
||||
App::setLocale($this->contact->preferredLocale());
|
||||
|
||||
$path = $this->credit->client->credit_filepath();
|
||||
|
||||
$file_path = $path . $this->credit->number . '.pdf';
|
||||
|
||||
$design = Design::find($this->credit->client->getSetting('credit_design_id'));
|
||||
|
||||
if($design->is_custom){
|
||||
$credit_design = new Custom($design->design);
|
||||
}
|
||||
else{
|
||||
$class = 'App\Designs\\'.$design->name;
|
||||
$credit_design = new $class();
|
||||
}
|
||||
|
||||
$designer = new Designer($credit_design, $this->credit->client->getSetting('pdf_variables'), 'credit');
|
||||
|
||||
//get invoice design
|
||||
$html = $this->generateInvoiceHtml($designer->build($this->credit)->getHtml(), $this->credit, $this->contact);
|
||||
|
||||
//todo - move this to the client creation stage so we don't keep hitting this unnecessarily
|
||||
Storage::makeDirectory($path, 0755);
|
||||
|
||||
//\Log::error($html);
|
||||
$pdf = $this->makePdf(null, null, $html);
|
||||
|
||||
$instance = Storage::disk($this->disk)->put($file_path, $pdf);
|
||||
|
||||
//$instance= Storage::disk($this->disk)->path($file_path);
|
||||
//
|
||||
return $file_path;
|
||||
}
|
||||
|
||||
}
|
@ -18,6 +18,7 @@ use App\Notifications\Payment\NewPaymentNotification;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
class PaymentNotification implements ShouldQueue
|
||||
{
|
||||
@ -46,5 +47,12 @@ class PaymentNotification implements ShouldQueue
|
||||
{
|
||||
$company_user->user->notify(new NewPaymentNotification($payment, $payment->company));
|
||||
}
|
||||
|
||||
if(isset($payment->company->slack_webhook_url)){
|
||||
|
||||
Notification::route('slack', $payment->company->slack_webhook_url)
|
||||
->notify(new NewPaymentNotification($payment, $payment->company, true));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,17 +13,23 @@ namespace App\Models;
|
||||
|
||||
use App\DataMapper\ClientSettings;
|
||||
use App\DataMapper\CompanySettings;
|
||||
use App\Factory\CreditFactory;
|
||||
use App\Factory\InvoiceFactory;
|
||||
use App\Factory\QuoteFactory;
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyGateway;
|
||||
use App\Models\Country;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Currency;
|
||||
use App\Models\DateFormat;
|
||||
use App\Models\DatetimeFormat;
|
||||
use App\Models\Filterable;
|
||||
use App\Models\GatewayType;
|
||||
use App\Models\GroupSetting;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Language;
|
||||
use App\Models\Quote;
|
||||
use App\Models\Timezone;
|
||||
use App\Models\User;
|
||||
use App\Services\Client\ClientService;
|
||||
@ -454,4 +460,31 @@ class Client extends BaseModel implements HasLocalePreference
|
||||
{
|
||||
return $this->client_hash . '/credits/';
|
||||
}
|
||||
|
||||
public function setInvoiceDefaults() :Invoice
|
||||
{
|
||||
$invoice_factory = InvoiceFactory::create($this->company_id, auth()->user()->id);
|
||||
$invoice_factory->terms = $this->getSetting('invoice_terms');
|
||||
$invoice_factory->footer = $this->getSetting('invoice_footer');
|
||||
$invoice_factory->public_notes = isset($this->public_notes) ? $this->public_notes : '';
|
||||
return $invoice_factory;
|
||||
}
|
||||
|
||||
public function setQuoteDefaults() :Quote
|
||||
{
|
||||
$quote_factory = QuoteFactory::create($this->company_id, auth()->user()->id);
|
||||
$quote_factory->terms = $this->getSetting('quote_terms');
|
||||
$quote_factory->footer = $this->getSetting('quote_footer');
|
||||
$quote_factory->public_notes = isset($this->public_notes) ? $this->public_notes : '';
|
||||
return $quote_factory;
|
||||
}
|
||||
|
||||
public function setCreditDefaults() :Credit
|
||||
{
|
||||
$credit_factory = CreditFactory::create($this->company_id, auth()->user()->id);
|
||||
$credit_factory->terms = $this->getSetting('credit_terms');
|
||||
$credit_factory->footer = $this->getSetting('credit_footer');
|
||||
$credit_factory->public_notes = isset($this->public_notes) ? $this->public_notes : '';
|
||||
return $credit_factory;
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,18 @@ class Company extends BaseModel
|
||||
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
|
||||
use \Staudenmeir\EloquentHasManyDeep\HasTableAlias;
|
||||
|
||||
const ENTITY_RECURRING_INVOICE = 'recurring_invoice';
|
||||
const ENTITY_CREDIT = 'credit';
|
||||
const ENTITY_QUOTE = 'quote';
|
||||
const ENTITY_TASK = 'task';
|
||||
const ENTITY_EXPENSE = 'expense';
|
||||
const ENTITY_PROJECT = 'project';
|
||||
const ENTITY_VENDOR = 'vendor';
|
||||
const ENTITY_TICKET = 'ticket';
|
||||
const ENTITY_PROPOSAL = 'proposal';
|
||||
const ENTITY_RECURRING_EXPENSE = 'expense';
|
||||
const ENTITY_RECURRING_TASK = 'task';
|
||||
|
||||
protected $presenter = 'App\Models\Presenters\CompanyPresenter';
|
||||
|
||||
protected $fillable = [
|
||||
@ -100,6 +112,20 @@ class Company extends BaseModel
|
||||
// 'tokens'
|
||||
];
|
||||
|
||||
public static $modules = [
|
||||
self::ENTITY_RECURRING_INVOICE => 1,
|
||||
self::ENTITY_CREDIT => 2,
|
||||
self::ENTITY_QUOTE => 4,
|
||||
self::ENTITY_TASK => 8,
|
||||
self::ENTITY_EXPENSE => 16,
|
||||
self::ENTITY_PROJECT => 32,
|
||||
self::ENTITY_VENDOR => 64,
|
||||
self::ENTITY_TICKET => 128,
|
||||
self::ENTITY_PROPOSAL => 256,
|
||||
self::ENTITY_RECURRING_EXPENSE => 512,
|
||||
self::ENTITY_RECURRING_TASK => 1024,
|
||||
];
|
||||
|
||||
public function getCompanyIdAttribute()
|
||||
{
|
||||
return $this->encodePrimaryKey($this->id);
|
||||
@ -337,9 +363,8 @@ class Company extends BaseModel
|
||||
{
|
||||
//todo need to return the company channel here for hosted users
|
||||
//else the env variable for selfhosted
|
||||
if(config('ninja.environment') == 'selfhosted')
|
||||
return config('ninja.notification.slack');
|
||||
else
|
||||
return $this->settings->system_notifications_slack;
|
||||
//
|
||||
return $this->slack_webhook_url;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -13,12 +13,14 @@ namespace App\Models;
|
||||
|
||||
use App\Helpers\Invoice\InvoiceSum;
|
||||
use App\Helpers\Invoice\InvoiceSumInclusive;
|
||||
use App\Jobs\Credit\CreateCreditPdf;
|
||||
use App\Models\Filterable;
|
||||
use App\Services\Credit\CreditService;
|
||||
use App\Utils\Traits\MakesDates;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class Credit extends BaseModel
|
||||
{
|
||||
@ -64,8 +66,9 @@ class Credit extends BaseModel
|
||||
];
|
||||
|
||||
const STATUS_DRAFT = 1;
|
||||
const STAUS_PARTIAL = 2;
|
||||
const STATUS_APPLIED = 3;
|
||||
const STATUS_SENT = 2;
|
||||
const STATUS_PARTIAL = 3;
|
||||
const STATUS_APPLIED = 4;
|
||||
|
||||
public function assigned_user()
|
||||
{
|
||||
@ -172,5 +175,31 @@ class Credit extends BaseModel
|
||||
$this->status_id = $status;
|
||||
$this->save();
|
||||
}
|
||||
|
||||
public function pdf_file_path($invitation = null)
|
||||
{
|
||||
$storage_path = 'storage/' . $this->client->credit_filepath() . $this->number . '.pdf';
|
||||
|
||||
if (Storage::exists($storage_path))
|
||||
return $storage_path;
|
||||
|
||||
if(!$invitation)
|
||||
CreateCreditPdf::dispatchNow($this, $this->company, $this->client->primary_contact()->first());
|
||||
else
|
||||
CreateCreditPdf::dispatchNow($invitation->credit, $invitation->company, $invitation->contact);
|
||||
|
||||
return $storage_path;
|
||||
|
||||
}
|
||||
|
||||
public function markInvitationsSent()
|
||||
{
|
||||
$this->invitations->each(function ($invitation) {
|
||||
if (!isset($invitation->sent_date)) {
|
||||
$invitation->sent_date = Carbon::now();
|
||||
$invitation->save();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ use App\Utils\Traits\MakesInvoiceValues;
|
||||
use App\Utils\Traits\MakesReminders;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Laracasts\Presenter\PresentableTrait;
|
||||
|
||||
|
@ -303,7 +303,6 @@ class User extends Authenticatable implements MustVerifyEmail
|
||||
|
||||
if($this->company())
|
||||
return $this->company()->slack_webhook_url;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -23,10 +23,13 @@ class NewAccountCreated extends Notification implements ShouldQueue
|
||||
|
||||
protected $company;
|
||||
|
||||
public function __construct($user, $company)
|
||||
public $is_system;
|
||||
|
||||
public function __construct($user, $company, $is_system = false)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->company = $company;
|
||||
$this->is_system = $is_system;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -37,7 +40,6 @@ class NewAccountCreated extends Notification implements ShouldQueue
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
//return ['mail'];
|
||||
return ['slack','mail'];
|
||||
}
|
||||
|
||||
@ -95,8 +97,7 @@ class NewAccountCreated extends Notification implements ShouldQueue
|
||||
|
||||
return (new SlackMessage)
|
||||
->success()
|
||||
->to("#devv2")
|
||||
->from("System")
|
||||
->from(ctrans('texts.notification_bot'))
|
||||
->image('https://app.invoiceninja.com/favicon.png')
|
||||
->content("A new account has been created by {$user_name} - {$email} - from IP: {$ip}");
|
||||
}
|
||||
|
123
app/Notifications/Ninja/InvoiceViewedNotification.php
Normal file
123
app/Notifications/Ninja/InvoiceViewedNotification.php
Normal file
@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications\Payment;
|
||||
|
||||
use App\Utils\Number;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class InvoiceViewedNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
protected $invitation;
|
||||
|
||||
protected $invoice;
|
||||
|
||||
protected $company;
|
||||
|
||||
protected $settings;
|
||||
|
||||
public $is_system;
|
||||
|
||||
protected $contact;
|
||||
|
||||
public function __construct($invitation, $company, $is_system = false, $settings = null)
|
||||
{
|
||||
$this->invoice = $invitation->invoice;
|
||||
$this->contact = $invitation->contact;
|
||||
$this->company = $company;
|
||||
$this->settings = $invoice->client->getMergedSettings();
|
||||
$this->is_system = $is_system;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
|
||||
return $this->is_system ? ['slack'] : ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
|
||||
$amount = Number::formatMoney($this->invoice->amount, $this->invoice->client);
|
||||
$subject = ctrans('texts.notification_invoice_viewed_subject',
|
||||
[
|
||||
'client' => $this->contact->present()->name(),
|
||||
'invoice' => $this->invoice->number,
|
||||
]);
|
||||
|
||||
$data = [
|
||||
'title' => $subject,
|
||||
'message' => ctrans('texts.notification_invoice_viewed',
|
||||
[
|
||||
'amount' => $amount,
|
||||
'client' => $this->contact->present()->name(),
|
||||
'invoice' => $this->invoice->number,
|
||||
]),
|
||||
'url' => config('ninja.site_url') . '/invoices/' . $this->invoice->hashed_id,
|
||||
'button' => ctrans('texts.view_invoice'),
|
||||
'signature' => $this->settings->email_signature,
|
||||
'logo' => $this->company->present()->logo(),
|
||||
];
|
||||
|
||||
|
||||
return (new MailMessage)
|
||||
->subject($subject)
|
||||
->markdown('email.admin.generic', $data);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public function toSlack($notifiable)
|
||||
{
|
||||
$logo = $this->company->present()->logo();
|
||||
$amount = Number::formatMoney($this->invoice->amount, $this->invoice->client);
|
||||
|
||||
return (new SlackMessage)
|
||||
->success()
|
||||
->from(ctrans('texts.notification_bot'))
|
||||
->image($logo)
|
||||
->content(ctrans('texts.notification_invoice_viewed',
|
||||
[
|
||||
'amount' => $amount,
|
||||
'client' => $this->contact->present()->name(),
|
||||
'invoice' => $this->invoice->number,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
104
app/Notifications/Ninja/NewAccountCreated.php
Normal file
104
app/Notifications/Ninja/NewAccountCreated.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications\Ninja;
|
||||
|
||||
use App\Mail\Signup\NewSignup;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class NewAccountCreated extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
protected $user;
|
||||
|
||||
protected $company;
|
||||
|
||||
public $is_system;
|
||||
|
||||
public function __construct($user, $company, $is_system = false)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->company = $company;
|
||||
$this->is_system = $is_system;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['slack','mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
|
||||
$user_name = $this->user->first_name . " " . $this->user->last_name;
|
||||
$email = $this->user->email;
|
||||
$ip = $this->user->ip;
|
||||
|
||||
$data = [
|
||||
'title' => ctrans('texts.new_signup'),
|
||||
'message' => ctrans('texts.new_signup_text', ['user' => $user_name, 'email' => $email, 'ip' => $ip]),
|
||||
'url' => config('ninja.web_url'),
|
||||
'button' => ctrans('texts.account_login'),
|
||||
'signature' => $this->company->settings->email_signature,
|
||||
'logo' => $this->company->present()->logo(),
|
||||
];
|
||||
|
||||
|
||||
return (new MailMessage)
|
||||
->subject(ctrans('texts.new_signup'))
|
||||
->markdown('email.admin.generic', $data);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public function toSlack($notifiable)
|
||||
{
|
||||
|
||||
$this->user->setCompany($this->company);
|
||||
|
||||
$user_name = $this->user->first_name . " " . $this->user->last_name;
|
||||
$email = $this->user->email;
|
||||
$ip = $this->user->ip;
|
||||
|
||||
return (new SlackMessage)
|
||||
->success()
|
||||
->from(ctrans('texts.notification_bot'))
|
||||
->image('https://app.invoiceninja.com/favicon.png')
|
||||
->content("A new account has been created by {$user_name} - {$email} - from IP: {$ip}");
|
||||
}
|
||||
}
|
126
app/Notifications/Payment/NewPartialPaymentNotification.php
Normal file
126
app/Notifications/Payment/NewPartialPaymentNotification.php
Normal file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications\Payment;
|
||||
|
||||
use App\Mail\Signup\NewSignup;
|
||||
use App\Utils\Number;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class NewPartialPaymentNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
protected $payment;
|
||||
|
||||
protected $company;
|
||||
|
||||
protected $settings;
|
||||
|
||||
protected $is_system;
|
||||
|
||||
public function __construct($payment, $company, $is_system = false, $settings = null)
|
||||
{
|
||||
$this->payment = $payment;
|
||||
$this->company = $company;
|
||||
$this->settings = $payment->client->getMergedSettings();
|
||||
$this->is_system = $is_system;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
|
||||
return $this->is_system ? ['slack'] : ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
$amount = Number::formatMoney($this->payment->amount, $this->payment->client);
|
||||
|
||||
$invoice_texts = ctrans('texts.invoice_number_short');
|
||||
|
||||
foreach($this->payment->invoices as $invoice)
|
||||
$invoice_texts .= $invoice->number . ',';
|
||||
|
||||
$invoice_texts = substr($invoice_texts, 0, -1);
|
||||
|
||||
$data = [
|
||||
'title' => ctrans('texts.notification_partial_payment_paid_subject',
|
||||
['client' => $this->payment->client->present()->name()]),
|
||||
'message' => ctrans('texts.notification_partial_payment_paid',
|
||||
['amount' => $amount,
|
||||
'client' => $this->payment->client->present()->name(),
|
||||
'invoice' => $invoice_texts,
|
||||
]),
|
||||
'url' => config('ninja.site_url') . '/payments/' . $this->payment->hashed_id,
|
||||
'button' => ctrans('texts.view_payment'),
|
||||
'signature' => $this->settings->email_signature,
|
||||
'logo' => $this->company->present()->logo(),
|
||||
];
|
||||
|
||||
|
||||
return (new MailMessage)
|
||||
->subject(ctrans('texts.notification_partial_payment_paid_subject',
|
||||
['client' => $this->payment->client->present()->name()])
|
||||
)->markdown('email.admin.generic', $data);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public function toSlack($notifiable)
|
||||
{
|
||||
$logo = $this->company->present()->logo();
|
||||
$amount = Number::formatMoney($this->payment->amount, $this->payment->client);
|
||||
$invoice_texts = ctrans('texts.invoice_number_short');
|
||||
|
||||
foreach($this->payment->invoices as $invoice)
|
||||
$invoice_texts .= $invoice->number . ',';
|
||||
|
||||
$invoice_texts = substr($invoice_texts, 0, -1);
|
||||
|
||||
return (new SlackMessage)
|
||||
->success()
|
||||
//->to("#devv2")
|
||||
->from("System")
|
||||
->image($logo)
|
||||
->content(ctrans('texts.notification_payment_paid',
|
||||
['amount' => $amount,
|
||||
'client' => $this->payment->client->present()->name(),
|
||||
'invoice' => $invoice_texts]));
|
||||
}
|
||||
|
||||
}
|
@ -26,11 +26,14 @@ class NewPaymentNotification extends Notification implements ShouldQueue
|
||||
|
||||
protected $settings;
|
||||
|
||||
public function __construct($payment, $company, $settings = null)
|
||||
protected $is_system;
|
||||
|
||||
public function __construct($payment, $company, $is_system = false, $settings = null)
|
||||
{
|
||||
$this->payment = $payment;
|
||||
$this->company = $company;
|
||||
$this->settings = $payment->client->getMergedSettings();
|
||||
$this->is_system = $is_system;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -41,8 +44,8 @@ class NewPaymentNotification extends Notification implements ShouldQueue
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
//return ['mail'];
|
||||
return ['mail'];
|
||||
|
||||
return $this->is_system ? ['slack'] : ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -58,25 +61,29 @@ class NewPaymentNotification extends Notification implements ShouldQueue
|
||||
$invoice_texts = ctrans('texts.invoice_number_short');
|
||||
|
||||
foreach($this->payment->invoices as $invoice)
|
||||
{
|
||||
$invoice_texts .= $invoice->number . ',';
|
||||
}
|
||||
|
||||
$invoice_texts = rtrim($invoice_texts);
|
||||
$invoice_texts = substr($invoice_texts, 0, -1);
|
||||
|
||||
$data = [
|
||||
'title' => ctrans('texts.notification_payment_paid_subject', ['client' => $this->payment->client->present()->name()]),
|
||||
'message' => ctrans('texts.notification_paid_paid', ['amount' => $amount, 'client' => $this->payment->client->present()->name(), 'invoice' => $invoice_texts]),
|
||||
'title' => ctrans('texts.notification_payment_paid_subject',
|
||||
['client' => $this->payment->client->present()->name()]),
|
||||
'message' => ctrans('texts.notification_payment_paid',
|
||||
['amount' => $amount,
|
||||
'client' => $this->payment->client->present()->name(),
|
||||
'invoice' => $invoice_texts,
|
||||
]),
|
||||
'url' => config('ninja.site_url') . '/payments/' . $this->payment->hashed_id,
|
||||
'button' => ctrans('texts.view_payment'),
|
||||
'signature' => $this->company->settings->email_signature,
|
||||
'signature' => $this->settings->email_signature,
|
||||
'logo' => $this->company->present()->logo(),
|
||||
];
|
||||
|
||||
|
||||
return (new MailMessage)
|
||||
->subject(ctrans('texts.notification_payment_paid_subject', ['client' => $this->payment->client->present()->name()]))
|
||||
->markdown('email.admin.generic', $data);
|
||||
->subject(ctrans('texts.notification_payment_paid_subject',
|
||||
['client' => $this->payment->client->present()->name(),])
|
||||
)->markdown('email.admin.generic', $data);
|
||||
|
||||
|
||||
}
|
||||
@ -97,13 +104,23 @@ class NewPaymentNotification extends Notification implements ShouldQueue
|
||||
public function toSlack($notifiable)
|
||||
{
|
||||
$logo = $this->company->present()->logo();
|
||||
$amount = Number::formatMoney($this->payment->amount, $this->payment->client);
|
||||
$invoice_texts = ctrans('texts.invoice_number_short');
|
||||
|
||||
foreach($this->payment->invoices as $invoice)
|
||||
$invoice_texts .= $invoice->number . ',';
|
||||
|
||||
$invoice_texts = substr($invoice_texts, 0, -1);
|
||||
|
||||
return (new SlackMessage)
|
||||
->success()
|
||||
->to("#devv2")
|
||||
//->to("#devv2")
|
||||
->from("System")
|
||||
->image($logo)
|
||||
->content("A new account has been created by {$user_name} - {$email} - from IP: {$ip}");
|
||||
->content(ctrans('texts.notification_payment_paid',
|
||||
['amount' => $amount,
|
||||
'client' => $this->payment->client->present()->name(),
|
||||
'invoice' => $invoice_texts]));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ namespace App\Providers;
|
||||
|
||||
use App\Events\Client\ClientWasCreated;
|
||||
use App\Events\Contact\ContactLoggedIn;
|
||||
use App\Events\Credit\CreditWasMarkedSent;
|
||||
use App\Events\Invoice\InvoiceWasCreated;
|
||||
use App\Events\Invoice\InvoiceWasEmailed;
|
||||
use App\Events\Invoice\InvoiceWasMarkedSent;
|
||||
@ -100,8 +101,10 @@ class EventServiceProvider extends ServiceProvider
|
||||
'App\Listeners\ActivityListener@restoredClient',
|
||||
],
|
||||
|
||||
//Invoices
|
||||
CreditWasMarkedSent::class => [
|
||||
],
|
||||
|
||||
//Invoices
|
||||
InvoiceWasMarkedSent::class => [
|
||||
CreateInvoiceHtmlBackup::class,
|
||||
],
|
||||
|
@ -23,7 +23,6 @@ class MultiDBProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -42,7 +41,7 @@ class MultiDBProvider extends ServiceProvider
|
||||
|
||||
if (isset($event->job->payload()['db'])) {
|
||||
|
||||
//\Log::error("Provider Setting DB = ".$event->job->payload()['db']);
|
||||
\Log::error("Provider Setting DB = ".$event->job->payload()['db']);
|
||||
|
||||
MultiDB::setDb($event->job->payload()['db']);
|
||||
}
|
||||
|
@ -251,6 +251,10 @@ class BaseRepository
|
||||
$state['finished_amount'] = $model->amount;
|
||||
|
||||
$model = $model->service()->applyNumber()->save();
|
||||
|
||||
if ($model->company->update_products !== false) {
|
||||
UpdateOrCreateProduct::dispatch($model->line_items, $model, $model->company);
|
||||
}
|
||||
|
||||
if ($class->name == Invoice::class) {
|
||||
|
||||
@ -258,10 +262,6 @@ class BaseRepository
|
||||
$model->ledger()->updateInvoiceBalance(($state['finished_amount'] - $state['starting_amount']));
|
||||
}
|
||||
|
||||
if ($model->company->update_products !== false) {
|
||||
UpdateOrCreateProduct::dispatch($model->line_items, $model, $model->company);
|
||||
}
|
||||
|
||||
$model = $model->calc()->getInvoice();
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
namespace App\Services\Credit;
|
||||
|
||||
use App\Models\Credit;
|
||||
use App\Services\Credit\CreateInvitations;
|
||||
use App\Services\Credit\MarkSent;
|
||||
|
||||
class CreditService
|
||||
{
|
||||
@ -36,6 +38,20 @@ class CreditService
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setStatus($status)
|
||||
{
|
||||
$this->credit->status_id = $status;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function markSent()
|
||||
{
|
||||
$this->credit = (new MarkSent($this->credit->client))->run($this->credit);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the credit
|
||||
* @return Credit object
|
||||
|
@ -32,11 +32,32 @@ class NotificationService extends AbstractService
|
||||
|
||||
}
|
||||
|
||||
public function run()
|
||||
public function run($is_system = false)
|
||||
{
|
||||
|
||||
$this->company->owner()->notify($this->notification);
|
||||
|
||||
if($is_system)
|
||||
{
|
||||
$this->notification->is_system = true;
|
||||
|
||||
Notification::route('slack', $this->company->slack_webhook_url)
|
||||
->notify($this->notification);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Hosted notifications
|
||||
* @return void
|
||||
*/
|
||||
public function ninja()
|
||||
{
|
||||
|
||||
Notification::route('slack', config('ninja.notification.slack'))
|
||||
->route('mail', config('ninja.notification.mail'))
|
||||
->notify($this->notification);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
namespace App\Services\Quote;
|
||||
|
||||
use App\Models\Quote;
|
||||
use App\Services\Quote\CreateInvitations;
|
||||
|
||||
class QuoteService
|
||||
{
|
||||
|
@ -74,13 +74,11 @@ return [
|
||||
'providers' => [
|
||||
'users' => [
|
||||
'driver' => 'eloquent',
|
||||
//'driver' => env('USER_AUTH_PROVIDER', 'eloquent'),
|
||||
'model' => App\Models\User::class,
|
||||
],
|
||||
'contacts' => [
|
||||
'driver' => 'eloquent',
|
||||
|
||||
// 'driver' => env('CONTACT_AUTH_PROVIDER', 'eloquent'),
|
||||
'model' => App\Models\ClientContact::class,
|
||||
],
|
||||
|
||||
|
@ -89,6 +89,7 @@ return [
|
||||
],
|
||||
'notification' => [
|
||||
'slack' => env('SLACK_WEBHOOK_URL',''),
|
||||
'mail' => env('HOSTED_EMAIL',''),
|
||||
],
|
||||
'payment_terms' => [
|
||||
[
|
||||
|
@ -3120,8 +3120,10 @@ $LANG = array(
|
||||
'new_signup_text' => 'A new account has been created by :user - :email - from IP address: :ip',
|
||||
|
||||
'notification_payment_paid_subject' => 'Payment was made by :client',
|
||||
'notification_paid_paid' => 'A payment of :amount was made by client :client towards :invoice.',
|
||||
|
||||
'notification_partial_payment_paid_subject' => 'Partial payment was made by :client',
|
||||
'notification_payment_paid' => 'A payment of :amount was made by client :client towards :invoice',
|
||||
'notification_partial_payment_paid' => 'A partial payment of :amount was made by client :client towards :invoice',
|
||||
'notification_bot' => 'Notification Bot',
|
||||
|
||||
'email_link_not_working' => 'If button above isn\'t working for you, please click on the link',
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user