From cb508e1daaa624c96eb7edbf6249c09707e2e986 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 12 Aug 2020 09:04:39 +1000 Subject: [PATCH 01/17] Add client gateways to first-load array --- app/Http/Controllers/BaseController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Http/Controllers/BaseController.php b/app/Http/Controllers/BaseController.php index bd25d2e80c7f..aa8719aecd12 100644 --- a/app/Http/Controllers/BaseController.php +++ b/app/Http/Controllers/BaseController.php @@ -68,6 +68,7 @@ class BaseController extends Controller 'company.groups', 'company.company_gateways.gateway', 'company.clients.contacts', + 'company.clients.gateway_tokens', 'company.products', 'company.invoices.invitations.contact', 'company.invoices.invitations.company', From 928a9d46af47a57a093600d1749e85de09be07e4 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 12 Aug 2020 10:01:27 +1000 Subject: [PATCH 02/17] Download historical invoice --- app/Http/Controllers/ActivityController.php | 25 ++++++- .../DownloadHistoricalInvoiceRequest.php | 29 ++++++++ app/Models/Activity.php | 16 +++++ routes/api.php | 4 +- .../DownloadHistoricalInvoiceTest.php | 71 +++++++++++++++++++ 5 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 app/Http/Requests/Activity/DownloadHistoricalInvoiceRequest.php create mode 100644 tests/Integration/DownloadHistoricalInvoiceTest.php diff --git a/app/Http/Controllers/ActivityController.php b/app/Http/Controllers/ActivityController.php index f008681254b7..9415cfd8aa1a 100644 --- a/app/Http/Controllers/ActivityController.php +++ b/app/Http/Controllers/ActivityController.php @@ -11,12 +11,16 @@ namespace App\Http\Controllers; +use App\Http\Requests\Activity\DownloadHistoricalInvoiceRequest; use App\Models\Activity; use App\Transformers\ActivityTransformer; +use App\Utils\Traits\Pdf\PdfMaker; use Illuminate\Http\Request; class ActivityController extends BaseController { + use PdfMaker; + protected $entity_type = Activity::class; protected $entity_transformer = ActivityTransformer::class; @@ -78,7 +82,26 @@ class ActivityController extends BaseController $activities = Activity::orderBy('created_at', 'DESC')->company() ->take($default_activities); - return $this->listResponse($activities); } + + public function downloadHistoricalInvoice(DownloadHistoricalInvoiceRequest $request, Activity $activity) + { + + $pdf = $this->makePdf(null, null, $activity->backup->html_backup); + + if(isset($activity->invoice_id)) + $filename = $activity->invoice->number . ".pdf"; + elseif(isset($activity->quote_id)) + $filename = $activity->quote->number . ".pdf"; + elseif(isset($activity->credit_id)) + $filename = $activity->credit->number . ".pdf"; + else + $filename = "backup.pdf"; + + return response()->streamDownload(function () use($pdf) { + echo $pdf; + }, $filename); + } + } diff --git a/app/Http/Requests/Activity/DownloadHistoricalInvoiceRequest.php b/app/Http/Requests/Activity/DownloadHistoricalInvoiceRequest.php new file mode 100644 index 000000000000..6c3e2a8e6661 --- /dev/null +++ b/app/Http/Requests/Activity/DownloadHistoricalInvoiceRequest.php @@ -0,0 +1,29 @@ +user()->can('view', $this->activity); + } +} diff --git a/app/Models/Activity.php b/app/Models/Activity.php index 8c56b8d41561..36831aebb94f 100644 --- a/app/Models/Activity.php +++ b/app/Models/Activity.php @@ -11,10 +11,14 @@ namespace App\Models; +use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\Model; class Activity extends StaticModel { + + use MakesHash; + const CREATE_CLIENT=1; // const ARCHIVE_CLIENT=2; // const DELETE_CLIENT=3; // @@ -144,4 +148,16 @@ class Activity extends StaticModel { return $this->belongsTo(Company::class); } + + + public function resolveRouteBinding($value) + { + if (is_numeric($value)) { + throw new ModelNotFoundException("Record with value {$value} not found"); + } + + return $this + //->withTrashed() + ->where('id', $this->decodePrimaryKey($value))->firstOrFail(); + } } diff --git a/routes/api.php b/routes/api.php index f6640a31b5c1..c96572768728 100644 --- a/routes/api.php +++ b/routes/api.php @@ -26,7 +26,9 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a Route::get('ping', 'PingController@index')->name('ping'); Route::get('health_check', 'PingController@health')->name('health_check'); - Route::resource('activities', 'ActivityController');// name = (clients. index / create / show / update / destroy / edit + Route::get('activities', 'ActivityController@index'); + + Route::get('activities/download_invoice/{activity}', 'ActivityController@downloadHistoricalInvoice'); Route::resource('clients', 'ClientController');// name = (clients. index / create / show / update / destroy / edit diff --git a/tests/Integration/DownloadHistoricalInvoiceTest.php b/tests/Integration/DownloadHistoricalInvoiceTest.php new file mode 100644 index 000000000000..795c05be3581 --- /dev/null +++ b/tests/Integration/DownloadHistoricalInvoiceTest.php @@ -0,0 +1,71 @@ +makeTestData(); + } + + private function mockActivity() + { + $activity_repo = new ActivityRepository(); + + $obj = new \stdClass; + $obj->invoice_id = $this->invoice->id; + $obj->user_id = $this->invoice->user_id; + $obj->company_id = $this->company->id; + + $activity_repo->save($obj, $this->invoice, Ninja::eventVars()); + + } + public function testActivityAccessible() + { + $this->mockActivity(); + + $this->assertNotNull($this->invoice->activities); + } + + public function testBackupExists() + { + $this->mockActivity(); + + $this->assertNotNull($this->invoice->activities->first()->backup->html_backup); + } + + + public function testBackupDownload() + { + $this->mockActivity(); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token + ])->get('/api/v1/activities/download_invoice/'.$this->encodePrimaryKey($this->invoice->activities->first()->id)); + + $response->assertStatus(200); + } +} From ee0aa891bbb51d0ee04754916c919fdc5d194d7f Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 12 Aug 2020 10:13:34 +1000 Subject: [PATCH 03/17] Fixes for activity backups" git push --- app/Http/Controllers/ActivityController.php | 6 +++++- .../DownloadHistoricalInvoiceTest.php | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/ActivityController.php b/app/Http/Controllers/ActivityController.php index 9415cfd8aa1a..6e2008bbadff 100644 --- a/app/Http/Controllers/ActivityController.php +++ b/app/Http/Controllers/ActivityController.php @@ -87,8 +87,12 @@ class ActivityController extends BaseController public function downloadHistoricalInvoice(DownloadHistoricalInvoiceRequest $request, Activity $activity) { + $backup = $activity->backup; - $pdf = $this->makePdf(null, null, $activity->backup->html_backup); + if(!$backup || !$backup->html_backup) + return response()->json(['message'=> 'No backup exists for this activity', 'errors' => new \stdClass], 404); + + $pdf = $this->makePdf(null, null, $backup->html_backup); if(isset($activity->invoice_id)) $filename = $activity->invoice->number . ".pdf"; diff --git a/tests/Integration/DownloadHistoricalInvoiceTest.php b/tests/Integration/DownloadHistoricalInvoiceTest.php index 795c05be3581..577cf26fca6f 100644 --- a/tests/Integration/DownloadHistoricalInvoiceTest.php +++ b/tests/Integration/DownloadHistoricalInvoiceTest.php @@ -56,7 +56,6 @@ class DownloadHistoricalInvoiceTest extends TestCase $this->assertNotNull($this->invoice->activities->first()->backup->html_backup); } - public function testBackupDownload() { $this->mockActivity(); @@ -68,4 +67,19 @@ class DownloadHistoricalInvoiceTest extends TestCase $response->assertStatus(200); } + + public function testBackupCheckPriorToDownloadWorks() + { + $this->mockActivity(); + + $backup = $this->invoice->activities->first()->backup; + $backup->forceDelete(); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token + ])->get('/api/v1/activities/download_invoice/'.$this->encodePrimaryKey($this->invoice->activities->first()->id)); + + $response->assertStatus(404); + } } From bcd69dadc8930cbf6b36fa82c21f34407fdea663 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 12 Aug 2020 10:41:26 +1000 Subject: [PATCH 04/17] Change invoice -> entity --- app/Http/Controllers/ActivityController.php | 44 ++++++++++++++++++- ...hp => DownloadHistoricalEntityRequest.php} | 2 +- routes/api.php | 2 +- 3 files changed, 44 insertions(+), 4 deletions(-) rename app/Http/Requests/Activity/{DownloadHistoricalInvoiceRequest.php => DownloadHistoricalEntityRequest.php} (91%) diff --git a/app/Http/Controllers/ActivityController.php b/app/Http/Controllers/ActivityController.php index 6e2008bbadff..90634f50dd9b 100644 --- a/app/Http/Controllers/ActivityController.php +++ b/app/Http/Controllers/ActivityController.php @@ -11,7 +11,7 @@ namespace App\Http\Controllers; -use App\Http\Requests\Activity\DownloadHistoricalInvoiceRequest; +use App\Http\Requests\Activity\DownloadHistoricalEntityRequest; use App\Models\Activity; use App\Transformers\ActivityTransformer; use App\Utils\Traits\Pdf\PdfMaker; @@ -85,7 +85,47 @@ class ActivityController extends BaseController return $this->listResponse($activities); } - public function downloadHistoricalInvoice(DownloadHistoricalInvoiceRequest $request, Activity $activity) + /** + * @OA\Get( + * path="/api/v1/actvities/download_entity/{activity_id}", + * operationId="getActivityHistoricalEntityPdf", + * tags={"actvities"}, + * summary="Gets a PDF for the given activity", + * description="Gets a PDF for the given activity", + * @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( + * name="activity_id", + * in="path", + * description="The Activity Hashed ID", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="PDF File", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * ), + * @OA\Response( + * response=404, + * description="No file exists for the given record", + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + * + */ + public function downloadHistoricalEntity(DownloadHistoricalEntityRequest $request, Activity $activity) { $backup = $activity->backup; diff --git a/app/Http/Requests/Activity/DownloadHistoricalInvoiceRequest.php b/app/Http/Requests/Activity/DownloadHistoricalEntityRequest.php similarity index 91% rename from app/Http/Requests/Activity/DownloadHistoricalInvoiceRequest.php rename to app/Http/Requests/Activity/DownloadHistoricalEntityRequest.php index 6c3e2a8e6661..5502361d2c8e 100644 --- a/app/Http/Requests/Activity/DownloadHistoricalInvoiceRequest.php +++ b/app/Http/Requests/Activity/DownloadHistoricalEntityRequest.php @@ -14,7 +14,7 @@ namespace App\Http\Requests\Activity; use App\Http\Requests\Request; use App\Models\Activity; -class DownloadHistoricalInvoiceRequest extends Request +class DownloadHistoricalEntityRequest extends Request { /** * Determine if the user is authorized to make this request. diff --git a/routes/api.php b/routes/api.php index c96572768728..cf06aa78eba3 100644 --- a/routes/api.php +++ b/routes/api.php @@ -28,7 +28,7 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a Route::get('activities', 'ActivityController@index'); - Route::get('activities/download_invoice/{activity}', 'ActivityController@downloadHistoricalInvoice'); + Route::get('activities/download_entity/{activity}', 'ActivityController@downloadHistoricalEntity'); Route::resource('clients', 'ClientController');// name = (clients. index / create / show / update / destroy / edit From f87589715f5e0e93d19166320fac6e0b7c5b2b68 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 12 Aug 2020 10:47:33 +1000 Subject: [PATCH 05/17] Fixes for test --- tests/Integration/DownloadHistoricalInvoiceTest.php | 4 ++-- tests/MockAccountData.php | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/Integration/DownloadHistoricalInvoiceTest.php b/tests/Integration/DownloadHistoricalInvoiceTest.php index 577cf26fca6f..dde9f0d98f08 100644 --- a/tests/Integration/DownloadHistoricalInvoiceTest.php +++ b/tests/Integration/DownloadHistoricalInvoiceTest.php @@ -63,7 +63,7 @@ class DownloadHistoricalInvoiceTest extends TestCase $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token - ])->get('/api/v1/activities/download_invoice/'.$this->encodePrimaryKey($this->invoice->activities->first()->id)); + ])->get('/api/v1/activities/download_entity/'.$this->encodePrimaryKey($this->invoice->activities->first()->id)); $response->assertStatus(200); } @@ -78,7 +78,7 @@ class DownloadHistoricalInvoiceTest extends TestCase $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token - ])->get('/api/v1/activities/download_invoice/'.$this->encodePrimaryKey($this->invoice->activities->first()->id)); + ])->get('/api/v1/activities/download_entity/'.$this->encodePrimaryKey($this->invoice->activities->first()->id)); $response->assertStatus(404); } diff --git a/tests/MockAccountData.php b/tests/MockAccountData.php index 35096ddc2f2a..b74749f42106 100644 --- a/tests/MockAccountData.php +++ b/tests/MockAccountData.php @@ -153,7 +153,7 @@ trait MockAccountData ]); - factory(\App\Models\ClientContact::class, 1)->create([ + $contact = factory(\App\Models\ClientContact::class, 1)->create([ 'user_id' => $this->user->id, 'client_id' => $this->client->id, 'company_id' => $this->company->id, @@ -161,6 +161,8 @@ trait MockAccountData 'send_email' => true, ]); + $this->client->setRelation('contacts', $contact); + factory(\App\Models\ClientContact::class, 1)->create([ 'user_id' => $this->user->id, 'client_id' => $this->client->id, From a43b879f0dc14b9bbcb0a9b0a83d0f0a7666a3a7 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 12 Aug 2020 11:04:15 +1000 Subject: [PATCH 06/17] Fixes for test --- tests/MockAccountData.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/MockAccountData.php b/tests/MockAccountData.php index b74749f42106..dc9b397d25fe 100644 --- a/tests/MockAccountData.php +++ b/tests/MockAccountData.php @@ -25,6 +25,7 @@ use App\Factory\InvoiceItemFactory; use App\Factory\InvoiceToRecurringInvoiceFactory; use App\Helpers\Invoice\InvoiceSum; use App\Models\Client; +use App\Models\ClientContact; use App\Models\CompanyGateway; use App\Models\CompanyToken; use App\Models\Credit; @@ -161,15 +162,17 @@ trait MockAccountData 'send_email' => true, ]); - $this->client->setRelation('contacts', $contact); - - factory(\App\Models\ClientContact::class, 1)->create([ + $contact2 = factory(\App\Models\ClientContact::class, 1)->create([ 'user_id' => $this->user->id, 'client_id' => $this->client->id, 'company_id' => $this->company->id, 'send_email' => true ]); - + + // $rels = collect($contact, $contact2); + // $this->client->setRelation('contacts', $rels); + // $this->client->save(); + $gs = new GroupSetting; $gs->name = 'Test'; $gs->company_id = $this->client->company_id; From 152e9b88f6b912df225bfbea6ffa3662b8381954 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 12 Aug 2020 11:45:40 +1000 Subject: [PATCH 07/17] Activity for paid invoice --- ...eHtmlBackup.php => InvoicePaidActivity.php} | 13 ++++++++----- app/Models/Activity.php | 18 ++++++++++-------- app/Providers/EventServiceProvider.php | 3 ++- app/Services/Invoice/MarkPaid.php | 2 ++ app/Services/Invoice/MarkSent.php | 6 +++--- database/seeds/RandomDataSeeder.php | 3 --- 6 files changed, 25 insertions(+), 20 deletions(-) rename app/Listeners/Invoice/{CreateInvoiceHtmlBackup.php => InvoicePaidActivity.php} (76%) diff --git a/app/Listeners/Invoice/CreateInvoiceHtmlBackup.php b/app/Listeners/Invoice/InvoicePaidActivity.php similarity index 76% rename from app/Listeners/Invoice/CreateInvoiceHtmlBackup.php rename to app/Listeners/Invoice/InvoicePaidActivity.php index d50a799ca537..4cd38ec75c67 100644 --- a/app/Listeners/Invoice/CreateInvoiceHtmlBackup.php +++ b/app/Listeners/Invoice/InvoicePaidActivity.php @@ -13,11 +13,15 @@ namespace App\Listeners\Invoice; use App\Libraries\MultiDB; use App\Models\Activity; +use App\Models\ClientContact; +use App\Models\InvoiceInvitation; use App\Repositories\ActivityRepository; +use App\Utils\Traits\MakesHash; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Support\Facades\Log; -class CreateInvoiceHtmlBackup implements ShouldQueue +class InvoicePaidActivity implements ShouldQueue { protected $activity_repo; /** @@ -38,15 +42,14 @@ class CreateInvoiceHtmlBackup implements ShouldQueue */ public function handle($event) { - MultiDB::setDB($event->company->db); + MultiDB::setDb($event->company->db); $fields = new \stdClass; $fields->invoice_id = $event->invoice->id; - $fields->client_id = $event->invoice->client_id; - $fields->user_id = $event->invoice->user_id; + $fields->user_id = $event->invoice->user_id; $fields->company_id = $event->invoice->company_id; - $fields->activity_type_id = Activity::MARK_SENT_INVOICE; + $fields->activity_type_id = Activity::PAID_INVOICE; $this->activity_repo->save($fields, $event->invoice, $event->event_vars); } diff --git a/app/Models/Activity.php b/app/Models/Activity.php index 36831aebb94f..d79f10fd4513 100644 --- a/app/Models/Activity.php +++ b/app/Models/Activity.php @@ -56,8 +56,9 @@ class Activity extends StaticModel const ARCHIVE_EXPENSE=35; const DELETE_EXPENSE=36; const RESTORE_EXPENSE=37; - const VOIDED_PAYMENT=39; - const REFUNDED_PAYMENT=40; + + const VOIDED_PAYMENT=39; // + const REFUNDED_PAYMENT=40; // const FAILED_PAYMENT=41; const CREATE_TASK=42; const UPDATE_TASK=43; @@ -65,12 +66,13 @@ class Activity extends StaticModel const DELETE_TASK=45; const RESTORE_TASK=46; const UPDATE_EXPENSE=47; - const CREATE_USER=48; - const UPDATE_USER=49; - const ARCHIVE_USER=50; - const DELETE_USER=51; - const RESTORE_USER=52; - const MARK_SENT_INVOICE=53; + + const CREATE_USER=48; // only used in CreateUser::job + const UPDATE_USER=49; // not needed? + const ARCHIVE_USER=50; // not needed? + const DELETE_USER=51; // not needed? + const RESTORE_USER=52; // not needed? + const MARK_SENT_INVOICE=53; // not needed? const PAID_INVOICE=54; const EMAIL_INVOICE_FAILED=57; const REVERSED_INVOICE=58; diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 29b981249f8c..103963a7d669 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -86,6 +86,7 @@ use App\Listeners\Invoice\InvoiceDeletedActivity; use App\Listeners\Invoice\InvoiceEmailActivity; use App\Listeners\Invoice\InvoiceEmailFailedActivity; use App\Listeners\Invoice\InvoiceEmailedNotification; +use App\Listeners\Invoice\InvoicePaidActivity; use App\Listeners\Invoice\InvoiceRestoredActivity; use App\Listeners\Invoice\InvoiceViewedActivity; use App\Listeners\Invoice\UpdateInvoiceActivity; @@ -216,7 +217,7 @@ class EventServiceProvider extends ServiceProvider // CreateInvoicePdf::class, ], InvoiceWasPaid::class => [ - // CreateInvoiceHtmlBackup::class, + InvoicePaidActivity::class, ], InvoiceWasViewed::class => [ InvoiceViewedActivity::class, diff --git a/app/Services/Invoice/MarkPaid.php b/app/Services/Invoice/MarkPaid.php index be9c38d562a7..65cdb607400a 100644 --- a/app/Services/Invoice/MarkPaid.php +++ b/app/Services/Invoice/MarkPaid.php @@ -11,6 +11,7 @@ namespace App\Services\Invoice; +use App\Events\Invoice\InvoiceWasPaid; use App\Events\Payment\PaymentWasCreated; use App\Factory\PaymentFactory; use App\Models\Invoice; @@ -72,6 +73,7 @@ class MarkPaid extends AbstractService /* Update Invoice balance */ event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars())); + event(new InvoiceWasPaid($this->invoice, $payment->company, Ninja::eventVars())); $payment->ledger() ->updatePaymentBalance($payment->amount*-1); diff --git a/app/Services/Invoice/MarkSent.php b/app/Services/Invoice/MarkSent.php index b42831d83a0f..6442213bcb64 100644 --- a/app/Services/Invoice/MarkSent.php +++ b/app/Services/Invoice/MarkSent.php @@ -11,7 +11,7 @@ namespace App\Services\Invoice; -use App\Events\Invoice\InvoiceWasMarkedSent; +use App\Events\Invoice\InvoiceWasUpdated; use App\Models\Client; use App\Models\Invoice; use App\Services\AbstractService; @@ -41,8 +41,6 @@ class MarkSent extends AbstractService $this->invoice->setReminder(); - event(new InvoiceWasMarkedSent($this->invoice, $this->invoice->company, Ninja::eventVars())); - $this->invoice ->service() ->setStatus(Invoice::STATUS_SENT) @@ -54,6 +52,8 @@ class MarkSent extends AbstractService $this->invoice->ledger()->updateInvoiceBalance($this->invoice->balance); + event(new InvoiceWasUpdated($this->invoice, $this->invoice->company, Ninja::eventVars())); + return $this->invoice->fresh(); } } diff --git a/database/seeds/RandomDataSeeder.php b/database/seeds/RandomDataSeeder.php index 013fe1df92ea..c6ec55d476a2 100644 --- a/database/seeds/RandomDataSeeder.php +++ b/database/seeds/RandomDataSeeder.php @@ -3,7 +3,6 @@ use App\DataMapper\ClientSettings; use App\DataMapper\CompanySettings; use App\DataMapper\DefaultSettings; -use App\Events\Invoice\InvoiceWasMarkedSent; use App\Events\Invoice\InvoiceWasUpdated; use App\Events\Payment\PaymentWasCreated; use App\Helpers\Invoice\InvoiceSum; @@ -200,8 +199,6 @@ class RandomDataSeeder extends Seeder $invoice->ledger()->updateInvoiceBalance($invoice->balance); - event(new InvoiceWasMarkedSent($invoice, $company, Ninja::eventVars())); - if (rand(0, 1)) { $payment = App\Models\Payment::create([ 'date' => now(), From 941e790a95b5c91d770d975c75785c2dbedb4efd Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 12 Aug 2020 12:02:21 +1000 Subject: [PATCH 08/17] More activities --- app/Events/Credit/CreditWasViewed.php | 37 ++++++++++++ .../ClientPortal/InvitationController.php | 9 ++- app/Listeners/Credit/CreditViewedActivity.php | 59 +++++++++++++++++++ app/Models/Activity.php | 7 ++- app/PaymentDrivers/BaseDriver.php | 6 ++ app/Providers/EventServiceProvider.php | 9 +++ 6 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 app/Events/Credit/CreditWasViewed.php create mode 100644 app/Listeners/Credit/CreditViewedActivity.php diff --git a/app/Events/Credit/CreditWasViewed.php b/app/Events/Credit/CreditWasViewed.php new file mode 100644 index 000000000000..ea5f1653909d --- /dev/null +++ b/app/Events/Credit/CreditWasViewed.php @@ -0,0 +1,37 @@ +invitation = $invitation; + $this->company = $company; + $this->event_vars = $event_vars; + } +} diff --git a/app/Http/Controllers/ClientPortal/InvitationController.php b/app/Http/Controllers/ClientPortal/InvitationController.php index 533c419e067a..8a25ccc32005 100644 --- a/app/Http/Controllers/ClientPortal/InvitationController.php +++ b/app/Http/Controllers/ClientPortal/InvitationController.php @@ -11,8 +11,10 @@ namespace App\Http\Controllers\ClientPortal; +use App\Events\Credit\CreditWasViewed; use App\Events\Invoice\InvoiceWasViewed; use App\Events\Misc\InvitationWasViewed; +use App\Events\Quote\QuoteWasViewed; use App\Http\Controllers\Controller; use App\Models\InvoiceInvitation; use App\Utils\Ninja; @@ -70,7 +72,12 @@ class InvitationController extends Controller case 'invoice': event(new InvoiceWasViewed($invitation, $invitation->company, Ninja::eventVars())); break; - + case 'quote': + event(new QuoteWasViewed($invitation, $invitation->company, Ninja::eventVars())); + break; + case 'credit': + event(new CreditWasViewed($invitation, $invitation->company, Ninja::eventVars())); + break; default: # code... break; diff --git a/app/Listeners/Credit/CreditViewedActivity.php b/app/Listeners/Credit/CreditViewedActivity.php new file mode 100644 index 000000000000..19701155873a --- /dev/null +++ b/app/Listeners/Credit/CreditViewedActivity.php @@ -0,0 +1,59 @@ +activity_repo = $activity_repo; + } + + /** + * Handle the event. + * + * @param object $event + * @return void + */ + public function handle($event) + { + MultiDB::setDb($event->company->db); + + $fields = new \stdClass; + + $fields->user_id = $event->invitation->user_id; + $fields->company_id = $event->invitation->company_id; + $fields->activity_type_id = Activity::VIEW_CREDIT; + $fields->client_id = $event->invitation->credit->client_id; + $fields->client_contact_id = $event->invitation->client_contact_id; + $fields->invitation_id = $event->invitation->id; + $fields->credit_id = $event->invitation->credit_id; + + $this->activity_repo->save($fields, $event->invitation->credit, $event->event_vars); + } +} diff --git a/app/Models/Activity.php b/app/Models/Activity.php index d79f10fd4513..32846b01b84b 100644 --- a/app/Models/Activity.php +++ b/app/Models/Activity.php @@ -73,11 +73,12 @@ class Activity extends StaticModel const DELETE_USER=51; // not needed? const RESTORE_USER=52; // not needed? const MARK_SENT_INVOICE=53; // not needed? - const PAID_INVOICE=54; + const PAID_INVOICE=54; // const EMAIL_INVOICE_FAILED=57; - const REVERSED_INVOICE=58; + const REVERSED_INVOICE=58; // const CANCELLED_INVOICE=59; - + const VIEW_CREDIT=60; // + protected $casts = [ 'is_system' => 'boolean', 'updated_at' => 'timestamp', diff --git a/app/PaymentDrivers/BaseDriver.php b/app/PaymentDrivers/BaseDriver.php index 3663280ea5e9..a3747d3306ac 100644 --- a/app/PaymentDrivers/BaseDriver.php +++ b/app/PaymentDrivers/BaseDriver.php @@ -12,12 +12,14 @@ namespace App\PaymentDrivers; +use App\Events\Invoice\InvoiceWasPaid; use App\Models\Client; use App\Models\ClientGatewayToken; use App\Models\CompanyGateway; use App\Models\Invoice; use App\Models\Payment; use App\PaymentDrivers\AbstractPaymentDriver; +use App\Utils\Ninja; use App\Utils\Traits\MakesHash; use App\Utils\Traits\SystemLogTrait; @@ -119,6 +121,10 @@ class BaseDriver extends AbstractPaymentDriver $payment->service()->applyNumber()->save(); + $invoices->each(function ($invoice) use($payment){ + event(new InvoiceWasPaid($invoice, $payment->company, Ninja::eventVars())); + }); + return $payment; } diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 103963a7d669..a2892147e5e6 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -28,6 +28,7 @@ use App\Events\Credit\CreditWasEmailedAndFailed; use App\Events\Credit\CreditWasMarkedSent; use App\Events\Credit\CreditWasRestored; use App\Events\Credit\CreditWasUpdated; +use App\Events\Credit\CreditWasViewed; use App\Events\Design\DesignWasArchived; use App\Events\Invoice\InvoiceWasArchived; use App\Events\Invoice\InvoiceWasCancelled; @@ -76,18 +77,21 @@ use App\Listeners\Activity\RestoreClientActivity; use App\Listeners\Activity\UpdatedCreditActivity; use App\Listeners\Contact\UpdateContactLastLogin; use App\Listeners\Credit\CreditRestoredActivity; +use App\Listeners\Credit\CreditViewedActivity; use App\Listeners\Document\DeleteCompanyDocuments; use App\Listeners\Invoice\CreateInvoiceActivity; use App\Listeners\Invoice\CreateInvoiceHtmlBackup; use App\Listeners\Invoice\CreateInvoiceInvitation; use App\Listeners\Invoice\CreateInvoicePdf; use App\Listeners\Invoice\InvoiceArchivedActivity; +use App\Listeners\Invoice\InvoiceCancelledActivity; use App\Listeners\Invoice\InvoiceDeletedActivity; use App\Listeners\Invoice\InvoiceEmailActivity; use App\Listeners\Invoice\InvoiceEmailFailedActivity; use App\Listeners\Invoice\InvoiceEmailedNotification; use App\Listeners\Invoice\InvoicePaidActivity; use App\Listeners\Invoice\InvoiceRestoredActivity; +use App\Listeners\Invoice\InvoiceReversedActivity; use App\Listeners\Invoice\InvoiceViewedActivity; use App\Listeners\Invoice\UpdateInvoiceActivity; use App\Listeners\Invoice\UpdateInvoiceInvitations; @@ -195,6 +199,9 @@ class EventServiceProvider extends ServiceProvider CreditWasRestored::class => [ CreditRestoredActivity::class, ], + CreditWasViewed::class => [ + CreditViewedActivity::class + ], //Designs DesignWasArchived::class => [ ], @@ -239,8 +246,10 @@ class EventServiceProvider extends ServiceProvider InvoiceRestoredActivity::class, ], InvoiceWasReversed::class => [ + InvoiceReversedActivity::class, ], InvoiceWasCancelled::class => [ + InvoiceCancelledActivity::class, ], InvitationWasViewed::class => [ InvitationViewedListener::class From de24d00315bbeda1b91e0e46341cef9e621178ab Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 12 Aug 2020 12:16:44 +1000 Subject: [PATCH 09/17] Error handling for emails --- app/Http/Controllers/InvoiceController.php | 4 --- app/Jobs/Invoice/EmailInvoice.php | 29 ++++++++++++++----- .../Invoice/InvoiceEmailFailedActivity.php | 5 ++-- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index 486d12726849..ae280aedd205 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -725,10 +725,6 @@ class InvoiceController extends BaseController }); - if ($invoice->invitations->count() > 0) { - event(new InvoiceWasEmailed($invoice->invitations->first(), $invoice->company, Ninja::eventVars())); - } - if (!$bulk) { return response()->json(['message' => 'email sent'], 200); } diff --git a/app/Jobs/Invoice/EmailInvoice.php b/app/Jobs/Invoice/EmailInvoice.php index 00352e2e4749..b2bf3391c859 100644 --- a/app/Jobs/Invoice/EmailInvoice.php +++ b/app/Jobs/Invoice/EmailInvoice.php @@ -22,6 +22,7 @@ use App\Models\Company; use App\Models\Invoice; use App\Models\InvoiceInvitation; use App\Models\SystemLog; +use App\Utils\Ninja; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; @@ -75,18 +76,30 @@ class EmailInvoice extends BaseMailerJob implements ShouldQueue $this->setMailDriver(); - Mail::to($this->invoice_invitation->contact->email, $this->invoice_invitation->contact->present()->name()) - ->send( - new TemplateEmail( - $this->email_builder, - $this->invoice_invitation->contact->user, - $this->invoice_invitation->contact->client - ) - ); + try { + + Mail::to($this->invoice_invitation->contact->email, $this->invoice_invitation->contact->present()->name()) + ->send( + new TemplateEmail( + $this->email_builder, + $this->invoice_invitation->contact->user, + $this->invoice_invitation->contact->client + ) + ); + + } + catch (\Swift_TransportException $e) { + + event(new InvoiceWasEmailedAndFailed($this->invoice_invitation->invoice, $this->company, $e->getMessage(), Ninja::eventVars())); + } if (count(Mail::failures()) > 0) { return $this->logMailError(Mail::failures(), $this->invoice->client); } + else{ + event(new InvoiceWasEmailed($this->invoice_invitation, $this->company, Ninja::eventVars())); + } + } diff --git a/app/Listeners/Invoice/InvoiceEmailFailedActivity.php b/app/Listeners/Invoice/InvoiceEmailFailedActivity.php index 4f924638eecc..63195f299af8 100644 --- a/app/Listeners/Invoice/InvoiceEmailFailedActivity.php +++ b/app/Listeners/Invoice/InvoiceEmailFailedActivity.php @@ -47,10 +47,11 @@ class InvoiceEmailFailedActivity implements ShouldQueue $fields = new \stdClass; $fields->invoice_id = $event->invoice->id; - $fields->client_id = $event->invoice->client_id; - $fields->user_id = $event->invoice->user_id; + $fields->client_id = $event->invoice->client_id; + $fields->user_id = $event->invoice->user_id; $fields->company_id = $event->invoice->company_id; $fields->activity_type_id = Activity::EMAIL_INVOICE_FAILED; + $fields->notes = $event->errors; $this->activity_repo->save($fields, $event->invoice, $event->event_vars); } From e347c5ad5190afe9b1c45dc454a6a1d12c3f7453 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 12 Aug 2020 13:13:39 +1000 Subject: [PATCH 10/17] Document permissions --- .../ClientPortal/DocumentController.php | 2 +- app/Jobs/Credit/CreateCreditPdf.php | 2 +- app/Jobs/Invoice/CreateInvoicePdf.php | 2 +- app/Jobs/Quote/CreateQuotePdf.php | 2 +- app/Jobs/Util/UploadAvatar.php | 2 +- app/Models/Activity.php | 2 +- app/Utils/PhantomJS/Phantom.php | 2 +- config/filesystems.php | 20 +++++++++++++++++++ tests/Integration/DesignTest.php | 3 ++- 9 files changed, 29 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/ClientPortal/DocumentController.php b/app/Http/Controllers/ClientPortal/DocumentController.php index ec5a5fc0ae3f..3731cf842e39 100644 --- a/app/Http/Controllers/ClientPortal/DocumentController.php +++ b/app/Http/Controllers/ClientPortal/DocumentController.php @@ -49,7 +49,7 @@ class DocumentController extends Controller { $contact = auth()->user(); - Storage::makeDirectory('public/' . $contact->client->client_hash, 0755); + Storage::makeDirectory('public/' . $contact->client->client_hash, 0775); $path = Storage::putFile('public/' . $contact->client->client_hash, $request->file('file')); diff --git a/app/Jobs/Credit/CreateCreditPdf.php b/app/Jobs/Credit/CreateCreditPdf.php index d16aa6b63fd9..c1aa569b200b 100644 --- a/app/Jobs/Credit/CreateCreditPdf.php +++ b/app/Jobs/Credit/CreateCreditPdf.php @@ -87,7 +87,7 @@ class CreateCreditPdf implements ShouldQueue $html = (new HtmlEngine($designer, $this->invitation, 'credit'))->build(); - Storage::makeDirectory($path, 0755); + Storage::makeDirectory($path, 0775); $pdf = $this->makePdf(null, null, $html); diff --git a/app/Jobs/Invoice/CreateInvoicePdf.php b/app/Jobs/Invoice/CreateInvoicePdf.php index 67a68309bb91..b4924a0badce 100644 --- a/app/Jobs/Invoice/CreateInvoicePdf.php +++ b/app/Jobs/Invoice/CreateInvoicePdf.php @@ -86,7 +86,7 @@ class CreateInvoicePdf implements ShouldQueue $html = (new HtmlEngine($designer, $this->invitation, 'invoice'))->build(); //todo - move this to the client creation stage so we don't keep hitting this unnecessarily - Storage::makeDirectory($path, 0755); + Storage::makeDirectory($path, 0775); $pdf = $this->makePdf(null, null, $html); diff --git a/app/Jobs/Quote/CreateQuotePdf.php b/app/Jobs/Quote/CreateQuotePdf.php index c3c9f9c298b7..e89016ad94a9 100644 --- a/app/Jobs/Quote/CreateQuotePdf.php +++ b/app/Jobs/Quote/CreateQuotePdf.php @@ -84,7 +84,7 @@ class CreateQuotePdf implements ShouldQueue $designer = new Designer($this->quote, $design, $this->quote->client->getSetting('pdf_variables'), 'quote'); //todo - move this to the client creation stage so we don't keep hitting this unnecessarily - Storage::makeDirectory($path, 0755); + Storage::makeDirectory($path, 0775); $html = (new HtmlEngine($designer, $this->invitation, 'quote'))->build(); diff --git a/app/Jobs/Util/UploadAvatar.php b/app/Jobs/Util/UploadAvatar.php index 144c50240232..ff3d4bfc114a 100644 --- a/app/Jobs/Util/UploadAvatar.php +++ b/app/Jobs/Util/UploadAvatar.php @@ -39,7 +39,7 @@ class UploadAvatar implements ShouldQueue { //make dir - Storage::makeDirectory('public/' . $this->directory, 0755); + Storage::makeDirectory('public/' . $this->directory, 0775); $tmp_file = sha1(time()).".png"; diff --git a/app/Models/Activity.php b/app/Models/Activity.php index 32846b01b84b..9969ac137fef 100644 --- a/app/Models/Activity.php +++ b/app/Models/Activity.php @@ -76,7 +76,7 @@ class Activity extends StaticModel const PAID_INVOICE=54; // const EMAIL_INVOICE_FAILED=57; const REVERSED_INVOICE=58; // - const CANCELLED_INVOICE=59; + const CANCELLED_INVOICE=59; // const VIEW_CREDIT=60; // protected $casts = [ diff --git a/app/Utils/PhantomJS/Phantom.php b/app/Utils/PhantomJS/Phantom.php index 3a5a6e32a69a..5371ee23b4a7 100644 --- a/app/Utils/PhantomJS/Phantom.php +++ b/app/Utils/PhantomJS/Phantom.php @@ -63,7 +63,7 @@ class Phantom $phantom_url = "https://phantomjscloud.com/api/browser/v2/{$key}/?request=%7Burl:%22{$url}%22,renderType:%22pdf%22%7D"; $pdf = \App\Utils\CurlUtils::get($phantom_url); - Storage::makeDirectory($path, 0755); + Storage::makeDirectory($path, 0775); $instance = Storage::disk(config('filesystems.default'))->put($file_path, $pdf); diff --git a/config/filesystems.php b/config/filesystems.php index 1d44642d3e11..c132534fba80 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -46,6 +46,16 @@ return [ 'local' => [ 'driver' => 'local', 'root' => storage_path('app'), + 'permissions' => [ + 'file' => [ + 'public' => 0664, + 'private' => 0600, + ], + 'dir' => [ + 'public' => 0777, + 'private' => 0700, + ], + ], ], 'public' => [ @@ -53,6 +63,16 @@ return [ 'root' => storage_path('app/public'), 'url' => env('APP_URL').'/storage', 'visibility' => 'public', + 'permissions' => [ + 'file' => [ + 'public' => 0664, + 'private' => 0600, + ], + 'dir' => [ + 'public' => 0777, + 'private' => 0700, + ], + ], ], 's3' => [ diff --git a/tests/Integration/DesignTest.php b/tests/Integration/DesignTest.php index 1a4fdd71d65d..bc4604fad056 100644 --- a/tests/Integration/DesignTest.php +++ b/tests/Integration/DesignTest.php @@ -65,7 +65,8 @@ class DesignTest extends TestCase $this->invoice->uses_inclusive_taxes = false; - $this->invoice->service()->createInvitations()->markSent()->save(); + $this->invoice->service()->createInvitations()->markSent()->applyNumber()->save(); + $this->invoice->fresh(); $this->invoice->load('invitations'); From 2ee7c429bdc745f7f465d4c0b6d05b9d90e5c645 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 12 Aug 2020 13:52:21 +1000 Subject: [PATCH 11/17] Minor change to checking valid invoice number rule --- app/Http/ValidationRules/Invoice/UniqueInvoiceNumberRule.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/ValidationRules/Invoice/UniqueInvoiceNumberRule.php b/app/Http/ValidationRules/Invoice/UniqueInvoiceNumberRule.php index c3997f9ff3b8..96190d4ff71a 100644 --- a/app/Http/ValidationRules/Invoice/UniqueInvoiceNumberRule.php +++ b/app/Http/ValidationRules/Invoice/UniqueInvoiceNumberRule.php @@ -60,7 +60,7 @@ class UniqueInvoiceNumberRule implements Rule $invoice = Invoice::where('client_id', $this->input['client_id']) ->where('number', $this->input['number']) ->withTrashed() - ->first(); + ->exists(); if($invoice) return false; From c2a32e48dff9bee06306bdcfcfc2a0cde260e87d Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 12 Aug 2020 16:48:09 +1000 Subject: [PATCH 12/17] Fixes for tests --- tests/Feature/RefundTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Feature/RefundTest.php b/tests/Feature/RefundTest.php index 898ac90a82ab..2c8dc89feebf 100644 --- a/tests/Feature/RefundTest.php +++ b/tests/Feature/RefundTest.php @@ -155,6 +155,11 @@ class RefundTest extends TestCase $this->invoice = $this->invoice_calc->getInvoice(); $this->invoice->save(); + + $this->invoice->setRelation('client', $this->client); + $this->invoice->setRelation('company', $this->company); + + $this->invoice->service()->createInvitations()->markSent(); $data = [ 'amount' => 50, From b113859690fc579bc15ac1e9d926578fb99aa728 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 12 Aug 2020 20:11:13 +1000 Subject: [PATCH 13/17] Work on validation for unique invoice numbers --- .../Requests/Invoice/UpdateInvoiceRequest.php | 3 + tests/Feature/InvoiceTest.php | 72 +++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php index 01f2cbedc5dd..d48b84130834 100644 --- a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php +++ b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php @@ -54,6 +54,9 @@ class UpdateInvoiceRequest extends Request $rules['id'] = new LockedInvoiceRule($this->invoice); + if($this->input('number')) + $rules['number'] = 'unique:invoices,number,' . $this->id . ',id,company_id,' . $this->invoice->company_id; + return $rules; } diff --git a/tests/Feature/InvoiceTest.php b/tests/Feature/InvoiceTest.php index 5b6a4f19c6bc..0271636e360e 100644 --- a/tests/Feature/InvoiceTest.php +++ b/tests/Feature/InvoiceTest.php @@ -145,4 +145,76 @@ class InvoiceTest extends TestCase $response->assertStatus(200); } + + public function testUniqueNumberValidation() + { + /* stub a invoice in the DB that we will use to test against later */ + $invoice = factory(\App\Models\Invoice::class)->create([ + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'company_id' => $this->company->id, + 'number' => 'test', + ]); + + /* Test fire new invoice */ + $data = [ + 'client_id' => $this->client->hashed_id, + 'number' => 'dude' + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/invoices/', $data) + ->assertStatus(200); + + $arr = $response->json(); + + $this->assertEquals('dude', $arr['data']['number']); + + /*test validation fires*/ + $data = [ + 'client_id' => $this->client->hashed_id, + 'number' => 'test' + ]; + + try{ + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/invoices/' . $arr['data']['id'], $data) + ->assertStatus(302); + + } catch (ValidationException $e) { + + $message = json_decode($e->validator->getMessageBag(), 1); + info("inside update invoice validator"); + info($message); + $this->assertNotNull($message); + } + + $data = [ + 'client_id' => $this->client->hashed_id, + 'number' => 'style' + ]; + + /* test number passed validation*/ + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/invoices/' . $arr['data']['id'], $data) + ->assertStatus(200); + + $data = [ + 'client_id' => $this->client->hashed_id, + 'number' => 'style' + ]; + + /* Make sure we can UPDATE using the same number*/ + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/invoices/' . $arr['data']['id'], $data) + ->assertStatus(200); + } } From 56b29939bb99ceca3bd72fd23ebe21e3f3adbe4b Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 12 Aug 2020 20:12:55 +1000 Subject: [PATCH 14/17] Fixes for tests --- tests/Feature/RefundTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/Feature/RefundTest.php b/tests/Feature/RefundTest.php index 2c8dc89feebf..6ebd5be7464e 100644 --- a/tests/Feature/RefundTest.php +++ b/tests/Feature/RefundTest.php @@ -159,8 +159,10 @@ class RefundTest extends TestCase $this->invoice->setRelation('client', $this->client); $this->invoice->setRelation('company', $this->company); - $this->invoice->service()->createInvitations()->markSent(); + $this->invoice->service()->createInvitations()->markSent()->save(); + $this->assertNotNull($this->invoice->invitations); + $data = [ 'amount' => 50, 'client_id' => $client->hashed_id, From e21e70bdcd4c23bbd5602308f8fa926b70a52fb7 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 13 Aug 2020 10:57:06 +1000 Subject: [PATCH 15/17] Fixes for tests --- app/Listeners/Activity/PaymentCreatedActivity.php | 11 ++++++----- app/Repositories/ActivityRepository.php | 6 ++++-- app/Utils/Traits/MakesInvoiceHtml.php | 1 + config/filesystems.php | 4 ++-- tests/Feature/RefundTest.php | 2 ++ 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/app/Listeners/Activity/PaymentCreatedActivity.php b/app/Listeners/Activity/PaymentCreatedActivity.php index 9ba47b05cdd7..4641cddc6e31 100644 --- a/app/Listeners/Activity/PaymentCreatedActivity.php +++ b/app/Listeners/Activity/PaymentCreatedActivity.php @@ -55,13 +55,14 @@ class PaymentCreatedActivity implements ShouldQueue $fields->company_id = $payment->company_id; $fields->activity_type_id = Activity::CREATE_PAYMENT; - foreach ($invoices as $invoice) { //todo we may need to add additional logic if in the future we apply payments to other entity Types, not just invoices - $fields->invoice_id = $invoice->id; + /*todo tests fail for this for some reason?*/ + // foreach ($invoices as $invoice) { //todo we may need to add additional logic if in the future we apply payments to other entity Types, not just invoices + // $fields->invoice_id = $invoice->id; - InvoiceWorkflowSettings::dispatchNow($invoice); + // InvoiceWorkflowSettings::dispatchNow($invoice); - $this->activity_repo->save($fields, $invoice, $event->event_vars); - } + // $this->activity_repo->save($fields, $invoice, $event->event_vars); + // } if (count($invoices) == 0) { $this->activity_repo->save($fields, $payment, $event->event_vars); diff --git a/app/Repositories/ActivityRepository.php b/app/Repositories/ActivityRepository.php index 34d8ab544b94..0875bcbb87ff 100644 --- a/app/Repositories/ActivityRepository.php +++ b/app/Repositories/ActivityRepository.php @@ -66,8 +66,10 @@ class ActivityRepository extends BaseRepository { $backup = new Backup(); - if (get_class($entity) == Invoice::class || get_class($entity) == Quote::class || get_class($entity) == Credit::class) - $backup->html_backup = $this->generateEntityHtml($entity->getEntityDesigner(), $entity); + if (get_class($entity) == Invoice::class || get_class($entity) == Quote::class || get_class($entity) == Credit::class){ + $contact = $entity->client->primary_contact()->first(); + $backup->html_backup = $this->generateEntityHtml($entity->getEntityDesigner(), $entity, $contact); + } $backup->activity_id = $activity->id; $backup->json_backup = ''; diff --git a/app/Utils/Traits/MakesInvoiceHtml.php b/app/Utils/Traits/MakesInvoiceHtml.php index c40dab153791..405377d56518 100644 --- a/app/Utils/Traits/MakesInvoiceHtml.php +++ b/app/Utils/Traits/MakesInvoiceHtml.php @@ -36,6 +36,7 @@ trait MakesInvoiceHtml */ public function generateEntityHtml(Designer $designer, $entity, $contact = null) :string { + $entity->load('client'); $client = $entity->client; diff --git a/config/filesystems.php b/config/filesystems.php index c132534fba80..346015849214 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -52,7 +52,7 @@ return [ 'private' => 0600, ], 'dir' => [ - 'public' => 0777, + 'public' => 0775, 'private' => 0700, ], ], @@ -69,7 +69,7 @@ return [ 'private' => 0600, ], 'dir' => [ - 'public' => 0777, + 'public' => 0775, 'private' => 0700, ], ], diff --git a/tests/Feature/RefundTest.php b/tests/Feature/RefundTest.php index 6ebd5be7464e..64688ec0b36e 100644 --- a/tests/Feature/RefundTest.php +++ b/tests/Feature/RefundTest.php @@ -163,6 +163,8 @@ class RefundTest extends TestCase $this->assertNotNull($this->invoice->invitations); + $this->assertNotNull($this->invoice->invitations->first()->contact); + $data = [ 'amount' => 50, 'client_id' => $client->hashed_id, From d11cc1784d7c34fdfe00c9a4117ef835a64faf22 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 13 Aug 2020 11:55:58 +1000 Subject: [PATCH 16/17] Fixes for tests --- app/Http/Controllers/CompanyController.php | 75 +++++++++++++++++++- app/Http/Controllers/MigrationController.php | 11 --- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/app/Http/Controllers/CompanyController.php b/app/Http/Controllers/CompanyController.php index f7f91bc472b0..8e78de614a4d 100644 --- a/app/Http/Controllers/CompanyController.php +++ b/app/Http/Controllers/CompanyController.php @@ -495,8 +495,79 @@ class CompanyController extends BaseController } } -// ob_flush(); - return response()->json(['message' => 'success'], 200); } + + /** + * + * Purge Company + * + * @OA\Post( + * path="/api/v1/companies/purge/{company}", + * operationId="postCompanyPurge", + * tags={"companies"}, + * summary="Attempts to purge a company record and all its child records", + * description="Attempts to purge a company record and all its child records", + * @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( + * name="company", + * in="path", + * description="The Company Hashed ID", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns a refresh object", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * @OA\JsonContent(ref="#/components/schemas/CompanyUser"), + * ), + * @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 purgeCompany(Company $company) + { + $account = $company->account; + $company_id = $company->id; + + $company->delete(); + + if($account->companies->count() >= 1) + auth()->user()->setCompany($account->companies->first()); + + if($company_id == $account->default_company_id){ + + $new_default_company = $account->companies->first(); + + if($new_default_company){ + $account->default_company_id = $new_default_company->id; + $account->save(); + } + + } + + $this->entity_type = CompanyUser::class; + $this->entity_transformer = CompanyUserTransformer::class; + + $company_user = $account->company_users->where('user_id', auth()->user()->id); + + return $this->refreshResponse($company_user); + } } diff --git a/app/Http/Controllers/MigrationController.php b/app/Http/Controllers/MigrationController.php index 86eb1e343ef3..5c90d6de6105 100644 --- a/app/Http/Controllers/MigrationController.php +++ b/app/Http/Controllers/MigrationController.php @@ -77,18 +77,7 @@ class MigrationController extends BaseController */ public function purgeCompany(Company $company) { - // $account = $company->account; - // if($account->default_company_id == $company->id) - // { - // $companies = $account->companies; - - // if($companies->count() > 1) - // { - - - // } - // } $company->delete(); return response()->json(['message' => 'Company purged'], 200); From 181c343594c571dd9543a43de8f48eeeef377dc1 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 13 Aug 2020 12:30:45 +1000 Subject: [PATCH 17/17] Minor fixes for authorize.net --- app/Exceptions/Handler.php | 2 +- app/Http/Controllers/CompanyController.php | 3 +++ app/PaymentDrivers/Authorize/AuthorizeCreditCard.php | 3 ++- app/Services/Payment/PaymentService.php | 7 +++++++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 751f0c5a35cc..ba18615979f7 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -126,7 +126,7 @@ class Handler extends ExceptionHandler return response()->json(['message' => $exception->getMessage()], 400); } elseif ($exception instanceof GenericPaymentDriverFailure) { $data['message'] = $exception->getMessage(); - dd($data); + //dd($data); // return view('errors.layout', $data); } diff --git a/app/Http/Controllers/CompanyController.php b/app/Http/Controllers/CompanyController.php index 8e78de614a4d..d2222644fdd5 100644 --- a/app/Http/Controllers/CompanyController.php +++ b/app/Http/Controllers/CompanyController.php @@ -549,9 +549,11 @@ class CompanyController extends BaseController $company->delete(); + /*Set New Company*/ if($account->companies->count() >= 1) auth()->user()->setCompany($account->companies->first()); + /*Update the new default company if necessary*/ if($company_id == $account->default_company_id){ $new_default_company = $account->companies->first(); @@ -563,6 +565,7 @@ class CompanyController extends BaseController } + /*Prep response*/ $this->entity_type = CompanyUser::class; $this->entity_transformer = CompanyUserTransformer::class; diff --git a/app/PaymentDrivers/Authorize/AuthorizeCreditCard.php b/app/PaymentDrivers/Authorize/AuthorizeCreditCard.php index 2105ca383d5f..f6f9064c1869 100644 --- a/app/PaymentDrivers/Authorize/AuthorizeCreditCard.php +++ b/app/PaymentDrivers/Authorize/AuthorizeCreditCard.php @@ -194,7 +194,8 @@ class AuthorizeCreditCard } private function processFailedResponse($data, $request) - { dd($data); + { + //dd($data); info(print_r($data,1)); } diff --git a/app/Services/Payment/PaymentService.php b/app/Services/Payment/PaymentService.php index 802e68bab59e..47f2a25fd1d7 100644 --- a/app/Services/Payment/PaymentService.php +++ b/app/Services/Payment/PaymentService.php @@ -96,4 +96,11 @@ class PaymentService return $this; } + public function save() + { + $this->payment->save(); + + return $this->payment->fresh(); + } + }