faker = \Faker\Factory::create(); $this->withoutMiddleware( ThrottleRequests::class ); $this->withoutExceptionHandling(); Invoice::withTrashed()->cursor()->each(function ($i) { $i->forceDelete();}); $this->buildData(); if (config('ninja.testvars.travis') !== false) { $this->markTestSkipped('Skip test no company gateways installed'); } } public $company; public $user; public $payload; public $account; public $client; public $token; public $cu; private $all_client_report_keys = [ "client.name", "client.user", "client.assigned_user", "client.balance", "client.address1", "client.address2", "client.city", "client.country_id", "client.currency_id", "client.custom_value1", "client.custom_value2", "client.custom_value3", "client.custom_value4", "client.industry_id", "client.id_number", "client.paid_to_date", "client.payment_terms", "client.phone", "client.postal_code", "client.private_notes", "client.public_notes", "client.size_id", "client.shipping_address1", "client.shipping_address2", "client.shipping_city", "client.shipping_state", "client.shipping_postal_code", "client.shipping_country_id", "client.state", "client.vat_number", "client.website", "contact.first_name", "contact.last_name", "contact.email", "contact.phone", "contact.custom_value1", "contact.custom_value2", "contact.custom_value3", "contact.custom_value4", ]; private $all_payment_report_keys = [ 'payment.date', 'payment.amount', 'payment.refunded', 'payment.applied', 'payment.transaction_reference', 'payment.currency', 'payment.exchange_rate', 'payment.number', 'payment.method', 'payment.status', 'payment.private_notes', 'payment.custom_value1', 'payment.custom_value2', 'payment.custom_value3', 'payment.custom_value4', 'payment.user_id', 'payment.assigned_user_id' ]; private $all_invoice_report_keys = [ 'invoice.number', 'invoice.amount', 'invoice.balance', 'invoice.paid_to_date', 'invoice.discount', 'invoice.po_number', 'invoice.date', 'invoice.due_date', 'invoice.terms', 'invoice.footer', 'invoice.status', 'invoice.public_notes', 'invoice.private_notes', 'invoice.uses_inclusive_taxes', 'invoice.is_amount_discount', 'invoice.partial', 'invoice.partial_due_date', 'invoice.custom_value1', 'invoice.custom_value2', 'invoice.custom_value3', 'invoice.custom_value4', 'invoice.custom_surcharge1', 'invoice.custom_surcharge2', 'invoice.custom_surcharge3', 'invoice.custom_surcharge4', 'invoice.exchange_rate', 'invoice.total_taxes', 'invoice.assigned_user_id', 'invoice.user_id', ]; /** * start_date - Y-m-d end_date - Y-m-d date_range - all last7 last30 this_month last_month this_quarter last_quarter this_year custom is_income_billed - true = Invoiced || false = Payments expense_billed - true = Expensed || false = Expenses marked as paid include_tax - true tax_included || false - tax_excluded */ private function buildData() { $this->account = Account::factory()->create([ 'hosted_client_count' => 1000, 'hosted_company_count' => 1000, ]); $this->account->num_users = 3; $this->account->save(); $this->user = User::factory()->create([ 'account_id' => $this->account->id, 'confirmation_code' => 'xyz123', 'email' => $this->faker->unique()->safeEmail(), ]); $settings = CompanySettings::defaults(); $settings->client_online_payment_notification = false; $settings->client_manual_payment_notification = false; $this->company = Company::factory()->create([ 'account_id' => $this->account->id, 'settings' => $settings, ]); $this->company->settings = $settings; $this->company->save(); $this->cu = CompanyUserFactory::create($this->user->id, $this->company->id, $this->account->id); $this->cu->is_owner = true; $this->cu->is_admin = true; $this->cu->is_locked = false; $this->cu->save(); $this->token = \Illuminate\Support\Str::random(64); $company_token = new CompanyToken; $company_token->user_id = $this->user->id; $company_token->company_id = $this->company->id; $company_token->account_id = $this->account->id; $company_token->name = 'test token'; $company_token->token = $this->token; $company_token->is_system = true; $company_token->save(); $this->payload = [ 'start_date' => '2000-01-01', 'end_date' => '2030-01-11', 'date_range' => 'custom', 'is_income_billed' => true, 'include_tax' => false, ]; $this->client = Client::factory()->create([ 'user_id' => $this->user->id, // 'assigned_user_id', $this->user->id, 'company_id' => $this->company->id, 'is_deleted' => 0, 'name' => 'bob', 'address1' => '1234', 'balance' => 100, 'paid_to_date' => 50, ]); ClientContact::factory()->create([ 'user_id' => $this->user->id, 'client_id' => $this->client->id, 'company_id' => $this->company->id, 'is_primary' => 1, 'first_name' => 'john', 'last_name' => 'doe', 'email' => 'john@doe.com' ]); } public function testForcedInsertionOfMandatoryColumns() { $forced = ['client.name']; $report_keys = ['invoice.number','client.name', 'invoice.amount']; $array = array_merge($report_keys, array_diff($forced, $report_keys)); $this->assertEquals('client.name', $array[1]); $report_keys = ['invoice.number','invoice.amount']; $array = array_merge($report_keys, array_diff($forced, $report_keys)); $this->assertEquals('client.name', $array[2]); } private function poll($hash) { $response = Http::retry(100, 400, throw: false) ->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post(config('ninja.app_url')."/api/v1/exports/preview/{$hash}"); return $response; } public function testProductJsonFiltering() { $query = Invoice::query(); $products = explode(",", "clown,joker,batman,bob the builder"); foreach($products as $product) { $query->where(function ($q) use ($product) { $q->orWhereJsonContains('line_items', ['product_key' => $product]); }); } $this->assertEquals(0, $query->count()); $item = InvoiceItemFactory::create(); $item->product_key = 'haloumi'; $line_items = []; $line_items[] = $item; Invoice::factory()->create( [ 'company_id' => $this->company->id, 'user_id' => $this->user->id, 'client_id' => $this->client->id, 'line_items' => $line_items ] ); $query->where(function ($q) use ($products) { foreach($products as $product) { $q->orWhereJsonContains('line_items', ['product_key' => $product]); } }); $this->assertEquals(0, $query->count()); $item = InvoiceItemFactory::create(); $item->product_key = 'batman'; $line_items = []; $line_items[] = $item; $item = InvoiceItemFactory::create(); $item->product_key = 'bob the builder'; $line_items[] = $item; Invoice::factory()->create( [ 'company_id' => $this->company->id, 'user_id' => $this->user->id, 'client_id' => $this->client->id, 'line_items' => $line_items ] ); $query = Invoice::query(); $query->where(function ($q) use ($products) { foreach($products as $product) { $q->orWhereJsonContains('line_items', ['product_key' => $product]); } }); $this->assertEquals(1, $query->count()); $query = Invoice::query(); $query->where(function ($q) { $q->orWhereJsonContains('line_items', ['product_key' => 'bob the builder']); }); $this->assertEquals(1, $query->count()); Invoice::withTrashed()->cursor()->each(function ($i) { $i->forceDelete();}); } public function testProductKeyFilterQueries() { $item = InvoiceItemFactory::create(); $item->product_key = 'haloumi'; $line_items = []; $line_items[] = $item; $q = Invoice::whereJsonContains('line_items', ['product_key' => 'haloumi']); $this->assertEquals(0, $q->count()); Invoice::factory()->create( [ 'company_id' => $this->company->id, 'user_id' => $this->user->id, 'client_id' => $this->client->id, 'line_items' => $line_items ] ); $this->assertEquals(1, $q->count()); $q->forceDelete(); Invoice::factory()->create( [ 'company_id' => $this->company->id, 'user_id' => $this->user->id, 'client_id' => $this->client->id, 'line_items' => $line_items ] ); $item = InvoiceItemFactory::create(); $item->product_key = 'bob the builder'; $line_items = []; $line_items[] = $item; $q = Invoice::whereJsonContains('line_items', ['product_key' => 'bob the builder']); $this->assertEquals(0, $q->count()); Invoice::factory()->create( [ 'company_id' => $this->company->id, 'user_id' => $this->user->id, 'client_id' => $this->client->id, 'line_items' => $line_items ] ); $this->assertEquals(1, $q->count()); $q = Invoice::whereJsonContains('line_items', ['product_key' => 'Bob the builder']); $this->assertEquals(0, $q->count()); $q = Invoice::whereJsonContains('line_items', ['product_key' => 'bob']); $this->assertEquals(0, $q->count()); $q->forceDelete(); Invoice::withTrashed()->cursor()->each(function ($i) { $i->forceDelete();}); } public function testVendorCsvGeneration() { $vendor = \App\Models\Vendor::factory()->create( [ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'name' => 'Vendor 1', 'city' => 'city', 'address1' => 'address1', 'address2' => 'address2', 'postal_code' => 'postal_code', 'phone' => 'work_phone', 'private_notes' => 'private_notes', 'public_notes' => 'public_notes', 'website' => 'website', 'number' => '1234', ] ); $data = [ 'date_range' => 'all', 'report_keys' => [], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/vendors', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('Vendor 1', $this->getFirstValueByColumn($csv, 'Vendor Name')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Vendor Number')); $this->assertEquals('city', $this->getFirstValueByColumn($csv, 'Vendor City')); $this->assertEquals('address1', $this->getFirstValueByColumn($csv, 'Vendor Street')); $this->assertEquals('address2', $this->getFirstValueByColumn($csv, 'Vendor Apt/Suite')); $this->assertEquals('postal_code', $this->getFirstValueByColumn($csv, 'Vendor Postal Code')); $this->assertEquals('work_phone', $this->getFirstValueByColumn($csv, 'Vendor Phone')); $this->assertEquals('private_notes', $this->getFirstValueByColumn($csv, 'Vendor Private Notes')); $this->assertEquals('public_notes', $this->getFirstValueByColumn($csv, 'Vendor Public Notes')); $this->assertEquals('website', $this->getFirstValueByColumn($csv, 'Vendor Website')); $data = [ 'date_range' => 'all', // 'end_date' => 'bail|required_if:date_range,custom|nullable|date', // 'start_date' => 'bail|required_if:date_range,custom|nullable|date', 'report_keys' => [], 'send_email' => false, // 'status' => 'sometimes|string|nullable|in:all,draft,sent,viewed,paid,unpaid,overdue', ]; $export = new VendorExport($this->company, $data); $data = $export->returnJson(); $this->assertNotNull($data); $this->assertEquals('Vendor Name', $this->traverseJson($data, 'columns.9.display_value')); $this->assertEquals('vendor', $this->traverseJson($data, '0.0.entity')); $this->assertEquals('address1', $this->traverseJson($data, '0.0.id')); $this->assertNull($this->traverseJson($data, '0.0.hashed_id')); $this->assertEquals('address1', $this->traverseJson($data, '0.0.value')); $this->assertEquals('vendor.address1', $this->traverseJson($data, '0.0.identifier')); $this->assertEquals('address1', $this->traverseJson($data, '0.0.display_value')); } public function testVendorCustomColumnCsvGeneration() { \App\Models\Vendor::query()->cursor()->each(function ($t) { $t->forceDelete(); }); $vendor = \App\Models\Vendor::factory()->create( [ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'name' => 'Vendor 1', 'city' => 'city', 'address1' => 'address1', 'address2' => 'address2', 'postal_code' => 'postal_code', 'phone' => 'work_phone', 'private_notes' => 'private_notes', 'public_notes' => 'public_notes', 'website' => 'website', 'number' => '1234', ] ); $data = [ 'date_range' => 'all', 'report_keys' => ["vendor.name", "vendor.city", "vendor.number"], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/vendors', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('Vendor 1', $this->getFirstValueByColumn($csv, 'Vendor Name')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Vendor Number')); $this->assertEquals('city', $this->getFirstValueByColumn($csv, 'Vendor City')); $export = new VendorExport($this->company, $data); $data = $export->returnJson(); $this->assertNotNull($data); // $this->assertEquals(0, $this->traverseJson($data, 'columns.0.identifier')); $this->assertEquals('Vendor Name', $this->traverseJson($data, 'columns.0.display_value')); $this->assertEquals('vendor', $this->traverseJson($data, '0.0.entity')); $this->assertEquals('name', $this->traverseJson($data, '0.0.id')); $this->assertNull($this->traverseJson($data, '0.0.hashed_id')); $this->assertEquals('Vendor 1', $this->traverseJson($data, '0.0.value')); $this->assertEquals('vendor.name', $this->traverseJson($data, '0.0.identifier')); $this->assertEquals('Vendor 1', $this->traverseJson($data, '0.0.display_value')); $this->assertEquals('number', $this->traverseJson($data, '0.2.id')); } public function testTaskCustomColumnsCsvGeneration() { $invoice = \App\Models\Invoice::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'date' => '2023-01-01', 'amount' => 1000, 'balance' => 1000, 'number' => '123456', 'status_id' => 2, 'discount' => 10, 'po_number' => '12345', 'public_notes' => 'Public5', 'private_notes' => 'Private5', 'terms' => 'Terms5', ]); $log = '[[1689547165,1689550765,"sumtin",true]]'; \App\Models\Task::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'invoice_id' => $invoice->id, 'description' => 'test1', 'time_log' => $log, 'custom_value1' => 'Custom 11', 'custom_value2' => 'Custom 22', 'custom_value3' => 'Custom 33', 'custom_value4' => 'Custom 44', ]); $data = [ 'date_range' => 'all', 'report_keys' => [ 'client.name', 'invoice.number', 'invoice.amount', 'task.start_date', 'task.end_date', 'task.duration', 'task.description', 'task.custom_value1', 'task.custom_value2', 'task.custom_value3', 'task.custom_value4', ], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/tasks', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); // nlog($csv); $this->assertEquals(3600, $this->getFirstValueByColumn($csv, 'Task Duration')); $this->assertEquals('test1', $this->getFirstValueByColumn($csv, 'Task Description')); $this->assertEquals('16/Jul/2023', $this->getFirstValueByColumn($csv, 'Task Start Date')); $this->assertEquals('16/Jul/2023', $this->getFirstValueByColumn($csv, 'Task End Date')); $this->assertEquals('Custom 11', $this->getFirstValueByColumn($csv, 'Task Custom Value 1')); $this->assertEquals('Custom 22', $this->getFirstValueByColumn($csv, 'Task Custom Value 2')); $this->assertEquals('Custom 33', $this->getFirstValueByColumn($csv, 'Task Custom Value 3')); $this->assertEquals('Custom 44', $this->getFirstValueByColumn($csv, 'Task Custom Value 4')); $this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name')); $this->assertEquals('123456', $this->getFirstValueByColumn($csv, 'Invoice Invoice Number')); $this->assertEquals(1000, $this->getFirstValueByColumn($csv, 'Invoice Amount')); $export = new TaskExport($this->company, $data); $data = $export->returnJson(); $this->assertNotNull($data); // $this->assertEquals(0, $this->traverseJson($data, 'columns.0.identifier')); $this->assertEquals('Client Name', $this->traverseJson($data, 'columns.0.display_value')); $this->assertEquals('client', $this->traverseJson($data, '0.0.entity')); $this->assertEquals('name', $this->traverseJson($data, '0.0.id')); $this->assertNotNull($this->traverseJson($data, '0.0.hashed_id')); $this->assertEquals('bob', $this->traverseJson($data, '0.0.value')); $this->assertEquals('client.name', $this->traverseJson($data, '0.0.identifier')); $this->assertEquals('bob', $this->traverseJson($data, '0.0.display_value')); $data = [ 'date_range' => 'all', 'report_keys' => $this->all_client_report_keys, 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/tasks', $data)->assertStatus(200); $data = [ 'date_range' => 'all', 'report_keys' => array_merge(["task.date","task.number"], $this->all_invoice_report_keys), 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/tasks', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); } public function testTasksCsvGeneration() { \App\Models\Task::query()->cursor()->each(function ($t) { $t->forceDelete(); }); $log = '[[1689547165,1689550765,"sumtin",true]]'; \App\Models\Task::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'description' => 'test', 'time_log' => $log, 'custom_value1' => 'Custom 1', 'custom_value2' => 'Custom 2', 'custom_value3' => 'Custom 3', 'custom_value4' => 'Custom 4', ]); $data = [ 'date_range' => 'all', 'report_keys' => [], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/tasks', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals(3600, $this->getFirstValueByColumn($csv, 'Task Duration')); $this->assertEquals('test', $this->getFirstValueByColumn($csv, 'Task Description')); $this->assertEquals('16/Jul/2023', $this->getFirstValueByColumn($csv, 'Task Start Date')); $this->assertEquals('16/Jul/2023', $this->getFirstValueByColumn($csv, 'Task End Date')); $this->assertEquals('Custom 1', $this->getFirstValueByColumn($csv, 'Task Custom Value 1')); $this->assertEquals('Custom 2', $this->getFirstValueByColumn($csv, 'Task Custom Value 2')); $this->assertEquals('Custom 3', $this->getFirstValueByColumn($csv, 'Task Custom Value 3')); $this->assertEquals('Custom 4', $this->getFirstValueByColumn($csv, 'Task Custom Value 4')); } public function testProductsCsvGeneration() { \App\Models\Product::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'product_key' => 'product_key', 'notes' => 'notes', 'cost' => 100, 'quantity' => 1, 'custom_value1' => 'Custom 1', 'custom_value2' => 'Custom 2', 'custom_value3' => 'Custom 3', 'custom_value4' => 'Custom 4', ]); $data = [ 'date_range' => 'all', 'report_keys' => [], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/products', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('product_key', $this->getFirstValueByColumn($csv, 'Product')); $this->assertEquals('notes', $this->getFirstValueByColumn($csv, 'Notes')); $this->assertEquals(100, $this->getFirstValueByColumn($csv, 'Cost')); $this->assertEquals(1, $this->getFirstValueByColumn($csv, 'Quantity')); $this->assertEquals('Custom 1', $this->getFirstValueByColumn($csv, 'Custom Value 1')); $this->assertEquals('Custom 2', $this->getFirstValueByColumn($csv, 'Custom Value 2')); $this->assertEquals('Custom 3', $this->getFirstValueByColumn($csv, 'Custom Value 3')); $this->assertEquals('Custom 4', $this->getFirstValueByColumn($csv, 'Custom Value 4')); $export = new ProductExport($this->company, $data); $data = $export->returnJson(); $this->assertNotNull($data); // $this->assertEquals(0, $this->traverseJson($data, 'columns.0.identifier')); $this->assertEquals('Custom Value 1', $this->traverseJson($data, 'columns.0.display_value')); $this->assertEquals('custom_value1', $this->traverseJson($data, '0.0.entity')); $this->assertEquals('custom_value1', $this->traverseJson($data, '0.0.id')); $this->assertNull($this->traverseJson($data, '0.0.hashed_id')); $this->assertEquals('Custom 1', $this->traverseJson($data, '0.0.value')); $this->assertEquals('custom_value1', $this->traverseJson($data, '0.0.identifier')); $this->assertEquals('Custom 1', $this->traverseJson($data, '0.0.display_value')); } public function testPaymentCsvGeneration() { $invoice = \App\Models\Invoice::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'date' => '2023-01-01', 'amount' => 100, 'balance' => 100, 'number' => '12345', 'status_id' => 2, 'discount' => 10, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', ]); $invoice->client->balance = 100; $invoice->client->paid_to_date = 0; $invoice->push(); $invoice->service()->markPaid()->save(); $data = [ 'date_range' => 'all', 'report_keys' => [ "payment.date", "payment.amount", "invoice.number", "invoice.amount", "client.name", "client.balance", "client.paid_to_date" ], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/payments', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); // nlog($csv); $this->assertEquals(100, $this->getFirstValueByColumn($csv, 'Payment Amount')); $this->assertEquals(now()->addSeconds($this->company->timezone()->utc_offset)->format('Y-m-d'), $this->getFirstValueByColumn($csv, 'Payment Date')); $this->assertEquals('12345', $this->getFirstValueByColumn($csv, 'Invoice Invoice Number')); $this->assertEquals(100, $this->getFirstValueByColumn($csv, 'Invoice Amount')); $this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name')); $this->assertEquals(0, $this->getFirstValueByColumn($csv, 'Client Balance')); $this->assertEquals(100, $this->getFirstValueByColumn($csv, 'Client Paid to Date')); $export = new PaymentExport($this->company, $data); $data = $export->returnJson(); $this->assertNotNull($data); // $this->assertEquals(0, $this->traverseJson($data, 'columns.0.identifier')); $this->assertEquals('Payment Date', $this->traverseJson($data, 'columns.0.display_value')); // $this->assertEquals(1, $this->traverseJson($data, 'columns.1.identifier')); $this->assertEquals('Payment Amount', $this->traverseJson($data, 'columns.1.display_value')); // $this->assertEquals(2, $this->traverseJson($data, 'columns.2.identifier')); $this->assertEquals('Invoice Invoice Number', $this->traverseJson($data, 'columns.2.display_value')); // $this->assertEquals(4, $this->traverseJson($data, 'columns.4.identifier')); $this->assertEquals('Client Name', $this->traverseJson($data, 'columns.4.display_value')); $this->assertEquals('payment', $this->traverseJson($data, '0.0.entity')); $this->assertEquals('date', $this->traverseJson($data, '0.0.id')); $this->assertNull($this->traverseJson($data, '0.0.hashed_id')); $this->assertEquals('payment.date', $this->traverseJson($data, '0.0.identifier')); $data = [ 'date_range' => 'all', 'report_keys' => $this->all_client_report_keys, 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/payments', $data)->assertStatus(200); $data = [ 'date_range' => 'all', 'report_keys' => array_merge(["payment.amount","payment.date"], $this->all_invoice_report_keys), 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/payments', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); } public function testPaymentCustomFieldsCsvGeneration() { \App\Models\Payment::factory()->create([ 'amount' => 500, 'date' => '2020-01-01', 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'transaction_reference' => '1234', ]); $data = [ 'date_range' => 'all', 'report_keys' => [], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/payments', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals(500, $this->getFirstValueByColumn($csv, 'Payment Amount')); $this->assertEquals(0, $this->getFirstValueByColumn($csv, 'Payment Applied')); $this->assertEquals(0, $this->getFirstValueByColumn($csv, 'Payment Refunded')); $this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Payment Date')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Payment Transaction Reference')); } public function testClientCsvGeneration() { $data = [ 'date_range' => 'all', 'report_keys' => [], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/clients', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $reader = Reader::createFromString($csv); $reader->setHeaderOffset(0); $res = $reader->fetchColumnByName('Street'); $res = iterator_to_array($res, true); $this->assertEquals('1234', $res[1]); $res = $reader->fetchColumnByName('Name'); $res = iterator_to_array($res, true); $this->assertEquals('bob', $res[1]); } public function testClientCustomColumnsCsvGeneration() { $data = [ 'date_range' => 'all', 'report_keys' => ["client.name","client.user","client.assigned_user","client.balance","client.paid_to_date","client.currency_id"], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/clients', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Name')); $this->assertEquals(100, $this->getFirstValueByColumn($csv, 'Balance')); $this->assertEquals(50, $this->getFirstValueByColumn($csv, 'Paid to Date')); $this->assertEquals($this->user->present()->name(), $this->getFirstValueByColumn($csv, 'Client User')); $this->assertEquals('', $this->getFirstValueByColumn($csv, 'Client Assigned User')); $this->assertEquals('USD', $this->getFirstValueByColumn($csv, 'Client Currency')); } public function testCreditJsonReport() { Credit::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'amount' => 100, 'balance' => 50, 'number' => '1234', 'status_id' => 2, 'discount' => 10, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', ]); $data = [ 'date_range' => 'all', 'report_keys' => ["client.name","credit.number","credit.amount","payment.date", "payment.amount"], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->postJson('/api/v1/reports/credits?output=json', $data); $response->assertStatus(200); $arr = $response->json(); $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->postJson('/api/v1/reports/preview/'.$arr['message']); $response->assertStatus(409); } public function testCreditCustomColumnsCsvGeneration() { Credit::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'amount' => 100, 'balance' => 50, 'number' => '1234', 'status_id' => 2, 'discount' => 10, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', ]); $data = [ 'date_range' => 'all', 'report_keys' => ["client.name","credit.number","credit.amount","payment.date", "payment.amount"], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/credits', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Credit Credit Number')); $this->assertEquals('Unpaid', $this->getFirstValueByColumn($csv, 'Payment Amount')); $this->assertEquals('', $this->getFirstValueByColumn($csv, 'Payment Date')); $data = [ 'date_range' => 'all', 'report_keys' => $this->all_payment_report_keys, 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/credits', $data)->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); } public function testInvoiceCustomColumnsCsvGeneration() { \App\Models\Invoice::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'amount' => 100, 'balance' => 50, 'number' => '1234', 'status_id' => 2, 'discount' => 10, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', ]); $data = [ 'date_range' => 'all', 'report_keys' => ["client.name","invoice.number","invoice.amount","payment.date", "payment.amount","invoice.user"], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/invoices', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Invoice Invoice Number')); $this->assertEquals('Unpaid', $this->getFirstValueByColumn($csv, 'Payment Amount')); $this->assertEquals('', $this->getFirstValueByColumn($csv, 'Payment Date')); $data = [ 'date_range' => 'all', 'report_keys' => $this->all_client_report_keys, 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/invoices', $data)->assertStatus(200); $data = [ 'date_range' => 'all', 'report_keys' => $this->all_payment_report_keys, 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/invoices', $data)->assertStatus(200); } public function testRecurringInvoiceCustomColumnsCsvGeneration() { \App\Models\RecurringInvoice::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'amount' => 100, 'balance' => 50, 'number' => '1234', 'status_id' => 2, 'discount' => 10, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', 'frequency_id' => 1, ]); $data = [ 'date_range' => 'all', 'report_keys' => ["client.name","recurring_invoice.number","recurring_invoice.amount", "recurring_invoice.frequency_id"], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/recurring_invoices', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Recurring Invoice Invoice Number')); $this->assertEquals('Daily', $this->getFirstValueByColumn($csv, 'Recurring Invoice How Often')); $data = [ 'date_range' => 'all', 'report_keys' => $this->all_client_report_keys, 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/recurring_invoices', $data)->assertStatus(200); } public function testRecurringInvoiceColumnsCsvGeneration() { \App\Models\RecurringInvoice::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'amount' => 100, 'balance' => 50, 'number' => '1234', 'status_id' => 2, 'discount' => 10, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', 'frequency_id' => 1, ]); $data = [ 'date_range' => 'all', 'report_keys' => [], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/recurring_invoices', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Recurring Invoice Invoice Number')); $this->assertEquals('Daily', $this->getFirstValueByColumn($csv, 'Recurring Invoice How Often')); $this->assertEquals('Active', $this->getFirstValueByColumn($csv, 'Recurring Invoice Status')); } public function testInvoiceItemsCustomColumnsCsvGeneration() { \App\Models\Invoice::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'amount' => 100, 'balance' => 50, 'number' => '1234', 'status_id' => 2, 'discount' => 10, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', 'line_items' => [ [ 'quantity' => 10, 'cost' => 100, 'line_total' => 1000, 'is_amount_discount' => true, 'discount' => 0, 'notes' => 'item notes', 'product_key' => 'product key', 'custom_value1' => 'custom 1', 'custom_value2' => 'custom 2', 'custom_value3' => 'custom 3', 'custom_value4' => 'custom 4', 'tax_name1' => 'GST', 'tax_rate1' => 10.00, 'type_id' => '1', ], ] ]); $data = [ 'date_range' => 'all', 'report_keys' => ["client.name","invoice.number","invoice.amount","payment.date", "payment.amount", "item.quantity", "item.cost", "item.line_total", "item.discount", "item.notes", "item.product_key", "item.custom_value1", "item.tax_name1", "item.tax_rate1",], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/invoice_items', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Invoice Invoice Number')); $this->assertEquals('Unpaid', $this->getFirstValueByColumn($csv, 'Payment Amount')); $this->assertEquals('', $this->getFirstValueByColumn($csv, 'Payment Date')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Quantity')); $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Item Cost')); $this->assertEquals('1000', $this->getFirstValueByColumn($csv, 'Item Line Total')); $this->assertEquals('0', $this->getFirstValueByColumn($csv, 'Item Discount')); $this->assertEquals('item notes', $this->getFirstValueByColumn($csv, 'Item Notes')); $this->assertEquals('product key', $this->getFirstValueByColumn($csv, 'Item Product')); $this->assertEquals('custom 1', $this->getFirstValueByColumn($csv, 'Item Custom Value 1')); $this->assertEquals('GST', $this->getFirstValueByColumn($csv, 'Item Tax Name 1')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Tax Rate 1')); $data = [ 'date_range' => 'all', 'report_keys' => $this->all_client_report_keys, 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/invoice_items', $data)->assertStatus(200); $data = [ 'date_range' => 'all', 'report_keys' => $this->all_payment_report_keys, 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/invoice_items', $data)->assertStatus(200); $data = [ 'date_range' => 'all', 'report_keys' => $this->all_payment_report_keys, 'send_email' => false, 'product_key' => 'haloumi,cheese', ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->postJson('/api/v1/reports/invoice_items', $data)->assertStatus(200); } public function testQuoteItemsCustomColumnsCsvGeneration() { $q = \App\Models\Quote::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'amount' => 100, 'balance' => 50, 'number' => '1234', 'status_id' => 2, 'discount' => 10, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', 'line_items' => [ [ 'quantity' => 10, 'cost' => 100, 'line_total' => 1000, 'is_amount_discount' => true, 'discount' => 0, 'notes' => 'item notes', 'product_key' => 'product key', 'custom_value1' => 'custom 1', 'custom_value2' => 'custom 2', 'custom_value3' => 'custom 3', 'custom_value4' => 'custom 4', 'tax_name1' => 'GST', 'tax_rate1' => 10.00, 'type_id' => '1', ], ] ]); $data = [ 'date_range' => 'all', 'report_keys' => ["client.name","quote.number","quote.amount", "item.quantity", "item.cost", "item.line_total", "item.discount", "item.notes", "item.product_key", "item.custom_value1", "item.tax_name1", "item.tax_rate1",], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/quote_items', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Quote Number')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Quantity')); $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Item Cost')); $this->assertEquals('1000', $this->getFirstValueByColumn($csv, 'Item Line Total')); $this->assertEquals('0', $this->getFirstValueByColumn($csv, 'Item Discount')); $this->assertEquals('item notes', $this->getFirstValueByColumn($csv, 'Item Notes')); $this->assertEquals('product key', $this->getFirstValueByColumn($csv, 'Item Product')); $this->assertEquals('custom 1', $this->getFirstValueByColumn($csv, 'Item Custom Value 1')); $this->assertEquals('GST', $this->getFirstValueByColumn($csv, 'Item Tax Name 1')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Tax Rate 1')); $data = [ 'date_range' => 'all', 'report_keys' => $this->all_client_report_keys, 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/quote_items', $data)->assertStatus(200); } public function testPurchaseOrderCsvGeneration() { $vendor = \App\Models\Vendor::factory()->create( [ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'name' => 'Vendor 1', ] ); \App\Models\PurchaseOrder::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'vendor_id' => $vendor->id, 'amount' => 100, 'balance' => 50, 'status_id' => 2, 'discount' => 10, 'number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', ]); $data = [ 'date_range' => 'all', 'report_keys' => [], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/purchase_orders', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Amount')); $this->assertEquals('50', $this->getFirstValueByColumn($csv, 'Balance')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Discount')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Number')); $this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Public Notes')); $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Private Notes')); $this->assertEquals('Terms', $this->getFirstValueByColumn($csv, 'Terms')); } public function testPurchaseOrderItemsCustomColumnsCsvGeneration() { $vendor = \App\Models\Vendor::factory()->create( [ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'name' => 'Vendor 1', ] ); \App\Models\PurchaseOrder::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'vendor_id' => $vendor->id, 'amount' => 100, 'balance' => 50, 'number' => '1234', 'po_number' => '1234', 'status_id' => 2, 'discount' => 10, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', 'line_items' => [ [ 'quantity' => 10, 'cost' => 100, 'line_total' => 1000, 'is_amount_discount' => true, 'discount' => 0, 'notes' => 'item notes', 'product_key' => 'product key', 'custom_value1' => 'custom 1', 'custom_value2' => 'custom 2', 'custom_value3' => 'custom 3', 'custom_value4' => 'custom 4', 'tax_name1' => 'GST', 'tax_rate1' => 10.00, 'type_id' => '1', ], ] ]); $data = [ 'date_range' => 'all', 'report_keys' => ["vendor.name","purchase_order.number","purchase_order.amount", "item.quantity", "item.cost", "item.line_total", "item.discount", "item.notes", "item.product_key", "item.custom_value1", "item.tax_name1", "item.tax_rate1",], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/purchase_order_items', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('Vendor 1', $this->getFirstValueByColumn($csv, 'Vendor Name')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Purchase Order Number')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Quantity')); $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Item Cost')); $this->assertEquals('1000', $this->getFirstValueByColumn($csv, 'Item Line Total')); $this->assertEquals('0', $this->getFirstValueByColumn($csv, 'Item Discount')); $this->assertEquals('item notes', $this->getFirstValueByColumn($csv, 'Item Notes')); $this->assertEquals('product key', $this->getFirstValueByColumn($csv, 'Item Product')); $this->assertEquals('custom 1', $this->getFirstValueByColumn($csv, 'Item Custom Value 1')); $this->assertEquals('GST', $this->getFirstValueByColumn($csv, 'Item Tax Name 1')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Tax Rate 1')); } public function testQuoteCustomColumnsCsvGeneration() { \App\Models\Quote::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'amount' => 100, 'balance' => 50, 'number' => '1234', 'status_id' => 2, 'discount' => 10, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', ]); $data = [ 'date_range' => 'all', 'report_keys' => ["client.name","quote.number","quote.amount"], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/quotes', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Quote Number')); $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Quote Amount')); $data = [ 'date_range' => 'all', 'report_keys' => $this->all_client_report_keys, 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/quotes', $data)->assertStatus(200); } public function testInvoicePaidCustomColumnsCsvGeneration() { $invoice = \App\Models\Invoice::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'date' => '2023-01-01', 'amount' => 100, 'balance' => 100, 'number' => '12345', 'status_id' => 2, 'discount' => 10, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', ]); $invoice->service()->markPaid()->save(); $data = [ 'date_range' => 'all', 'report_keys' => ["client.name","invoice.number","invoice.amount", "payment.date", "payment.amount"], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/invoices', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name')); $this->assertEquals('12345', $this->getFirstValueByColumn($csv, 'Invoice Invoice Number')); $this->assertEquals(100, $this->getFirstValueByColumn($csv, 'Payment Amount')); $this->assertEquals(now()->addSeconds($this->company->timezone()->utc_offset)->format('Y-m-d'), $this->getFirstValueByColumn($csv, 'Payment Date')); } public function testClientContactCsvGeneration() { $data = [ 'date_range' => 'all', 'report_keys' => [], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/contacts', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $reader = Reader::createFromString($csv); $reader->setHeaderOffset(0); $res = $reader->fetchColumnByName('Contact First Name'); $res = iterator_to_array($res, true); $this->assertEquals('john', $res[1]); $res = $reader->fetchColumnByName('Contact Last Name'); $res = iterator_to_array($res, true); $this->assertEquals('doe', $res[1]); $res = $reader->fetchColumnByName('Contact Email'); $res = iterator_to_array($res, true); $this->assertEquals('john@doe.com', $res[1]); } private function traverseJson($array, $keys) { $value = data_get($array, $keys, false); return $value; } private function getFirstValueByColumn($csv, $column) { $reader = Reader::createFromString($csv); $reader->setHeaderOffset(0); $res = $reader->fetchColumnByName($column); $res = iterator_to_array($res, true); return $res[1]; } public function testCreditCsvGeneration() { Credit::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'amount' => 100, 'balance' => 50, 'status_id' => 2, 'discount' => 10, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', ]); $data = [ 'date_range' => 'all', 'report_keys' => [], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/credits', $data); $response->assertStatus(200); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Credit Amount')); $this->assertEquals('50', $this->getFirstValueByColumn($csv, 'Credit Balance')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Credit Discount')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Credit PO Number')); $this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Credit Public Notes')); $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Credit Private Notes')); $this->assertEquals('Terms', $this->getFirstValueByColumn($csv, 'Credit Terms')); $data = [ 'date_range' => 'all', 'report_keys' => $this->all_client_report_keys, 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/credits', $data)->assertStatus(200); $data = [ 'date_range' => 'all', 'report_keys' => $this->all_payment_report_keys, 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/credits', $data)->assertStatus(200); } public function testInvoiceCsvGeneration() { Invoice::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'amount' => 100, 'balance' => 50, 'status_id' => 2, 'discount' => 10, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', 'date' => '2020-01-01', 'due_date' => '2021-01-02', 'partial_due_date' => '2021-01-03', 'partial' => 10, 'discount' => 10, 'custom_value1' => 'Custom 1', 'custom_value2' => 'Custom 2', 'custom_value3' => 'Custom 3', 'custom_value4' => 'Custom 4', 'footer' => 'Footer', 'tax_name1' => 'Tax 1', 'tax_rate1' => 10, 'tax_name2' => 'Tax 2', 'tax_rate2' => 20, 'tax_name3' => 'Tax 3', 'tax_rate3' => 30, ]); $data = [ 'date_range' => 'all', 'report_keys' => [], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/invoices', $data); $response->assertStatus(200); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Invoice Amount')); $this->assertEquals('50', $this->getFirstValueByColumn($csv, 'Invoice Balance')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Invoice Discount')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Invoice PO Number')); $this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Invoice Public Notes')); $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Invoice Private Notes')); $this->assertEquals('Terms', $this->getFirstValueByColumn($csv, 'Invoice Terms')); $this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Invoice Date')); $this->assertEquals('2021-01-02', $this->getFirstValueByColumn($csv, 'Invoice Due Date')); $this->assertEquals('2021-01-03', $this->getFirstValueByColumn($csv, 'Invoice Partial Due Date')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Invoice Partial/Deposit')); $this->assertEquals('Custom 1', $this->getFirstValueByColumn($csv, 'Invoice Custom Value 1')); $this->assertEquals('Custom 2', $this->getFirstValueByColumn($csv, 'Invoice Custom Value 2')); $this->assertEquals('Custom 3', $this->getFirstValueByColumn($csv, 'Invoice Custom Value 3')); $this->assertEquals('Custom 4', $this->getFirstValueByColumn($csv, 'Invoice Custom Value 4')); $this->assertEquals('Footer', $this->getFirstValueByColumn($csv, 'Invoice Footer')); $this->assertEquals('Tax 1', $this->getFirstValueByColumn($csv, 'Invoice Tax Name 1')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Invoice Tax Rate 1')); $this->assertEquals('Tax 2', $this->getFirstValueByColumn($csv, 'Invoice Tax Name 2')); $this->assertEquals('20', $this->getFirstValueByColumn($csv, 'Invoice Tax Rate 2')); $this->assertEquals('Tax 3', $this->getFirstValueByColumn($csv, 'Invoice Tax Name 3')); $this->assertEquals('30', $this->getFirstValueByColumn($csv, 'Invoice Tax Rate 3')); $this->assertEquals('Sent', $this->getFirstValueByColumn($csv, 'Invoice Status')); } public function testRecurringInvoiceCsvGeneration() { \App\Models\RecurringInvoice::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'amount' => 100, 'balance' => 50, 'status_id' => 2, 'discount' => 10, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', 'date' => '2020-01-01', 'due_date' => '2021-01-02', 'partial_due_date' => '2021-01-03', 'partial' => 10, 'discount' => 10, 'custom_value1' => 'Custom 1', 'custom_value2' => 'Custom 2', 'custom_value3' => 'Custom 3', 'custom_value4' => 'Custom 4', 'footer' => 'Footer', 'tax_name1' => 'Tax 1', 'tax_rate1' => 10, 'tax_name2' => 'Tax 2', 'tax_rate2' => 20, 'tax_name3' => 'Tax 3', 'tax_rate3' => 30, 'frequency_id' => 1, ]); $data = [ 'date_range' => 'all', 'report_keys' => [], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/recurring_invoices', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Recurring Invoice Amount')); $this->assertEquals('50', $this->getFirstValueByColumn($csv, 'Recurring Invoice Balance')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Recurring Invoice Discount')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Recurring Invoice PO Number')); $this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Recurring Invoice Public Notes')); $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Recurring Invoice Private Notes')); $this->assertEquals('Terms', $this->getFirstValueByColumn($csv, 'Recurring Invoice Terms')); $this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Recurring Invoice Date')); $this->assertEquals('2021-01-02', $this->getFirstValueByColumn($csv, 'Recurring Invoice Due Date')); $this->assertEquals('2021-01-03', $this->getFirstValueByColumn($csv, 'Recurring Invoice Partial Due Date')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Recurring Invoice Partial/Deposit')); $this->assertEquals('Custom 1', $this->getFirstValueByColumn($csv, 'Recurring Invoice Custom Value 1')); $this->assertEquals('Custom 2', $this->getFirstValueByColumn($csv, 'Recurring Invoice Custom Value 2')); $this->assertEquals('Custom 3', $this->getFirstValueByColumn($csv, 'Recurring Invoice Custom Value 3')); $this->assertEquals('Custom 4', $this->getFirstValueByColumn($csv, 'Recurring Invoice Custom Value 4')); $this->assertEquals('Footer', $this->getFirstValueByColumn($csv, 'Recurring Invoice Footer')); $this->assertEquals('Tax 1', $this->getFirstValueByColumn($csv, 'Recurring Invoice Tax Name 1')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Recurring Invoice Tax Rate 1')); $this->assertEquals('Tax 2', $this->getFirstValueByColumn($csv, 'Recurring Invoice Tax Name 2')); $this->assertEquals('20', $this->getFirstValueByColumn($csv, 'Recurring Invoice Tax Rate 2')); $this->assertEquals('Tax 3', $this->getFirstValueByColumn($csv, 'Recurring Invoice Tax Name 3')); $this->assertEquals('30', $this->getFirstValueByColumn($csv, 'Recurring Invoice Tax Rate 3')); $this->assertEquals('Daily', $this->getFirstValueByColumn($csv, 'Recurring Invoice How Often')); } public function testQuoteCsvGeneration() { \App\Models\Quote::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'amount' => 100, 'balance' => 50, 'status_id' => 2, 'discount' => 10, 'po_number' => '1234', 'public_notes' => 'Public', 'private_notes' => 'Private', 'terms' => 'Terms', 'date' => '2020-01-01', 'due_date' => '2020-01-01', 'partial_due_date' => '2021-01-03', 'partial' => 10, 'discount' => 10, 'custom_value1' => 'Custom 1', 'custom_value2' => 'Custom 2', 'custom_value3' => 'Custom 3', 'custom_value4' => 'Custom 4', 'footer' => 'Footer', 'tax_name1' => 'Tax 1', 'tax_rate1' => 10, 'tax_name2' => 'Tax 2', 'tax_rate2' => 20, 'tax_name3' => 'Tax 3', 'tax_rate3' => 30, ]); $data = [ 'date_range' => 'all', 'report_keys' => [], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/quotes', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Quote Amount')); $this->assertEquals('50', $this->getFirstValueByColumn($csv, 'Quote Balance')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Quote Discount')); $this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Quote PO Number')); $this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Quote Public Notes')); $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Quote Private Notes')); $this->assertEquals('Terms', $this->getFirstValueByColumn($csv, 'Quote Terms')); $this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Quote Date')); $this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Quote Valid Until')); $this->assertEquals('2021-01-03', $this->getFirstValueByColumn($csv, 'Quote Partial Due Date')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Quote Partial/Deposit')); $this->assertEquals('Custom 1', $this->getFirstValueByColumn($csv, 'Quote Custom Value 1')); $this->assertEquals('Custom 2', $this->getFirstValueByColumn($csv, 'Quote Custom Value 2')); $this->assertEquals('Custom 3', $this->getFirstValueByColumn($csv, 'Quote Custom Value 3')); $this->assertEquals('Custom 4', $this->getFirstValueByColumn($csv, 'Quote Custom Value 4')); $this->assertEquals('Footer', $this->getFirstValueByColumn($csv, 'Quote Footer')); $this->assertEquals('Tax 1', $this->getFirstValueByColumn($csv, 'Quote Tax Name 1')); $this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Quote Tax Rate 1')); $this->assertEquals('Tax 2', $this->getFirstValueByColumn($csv, 'Quote Tax Name 2')); $this->assertEquals('20', $this->getFirstValueByColumn($csv, 'Quote Tax Rate 2')); $this->assertEquals('Tax 3', $this->getFirstValueByColumn($csv, 'Quote Tax Name 3')); $this->assertEquals('30', $this->getFirstValueByColumn($csv, 'Quote Tax Rate 3')); $this->assertEquals('Expired', $this->getFirstValueByColumn($csv, 'Quote Status')); } public function testExpenseCsvGeneration() { Expense::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'amount' => 100, 'public_notes' => 'Public', 'private_notes' => 'Private', ]); $data = [ 'date_range' => 'all', 'report_keys' => [], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/expenses', $data); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Expense Amount')); $this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Expense Public Notes')); $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Expense Private Notes')); $this->assertEquals($this->user->present()->name(), $this->getFirstValueByColumn($csv, 'Expense User')); $data = [ 'date_range' => 'all', 'report_keys' => $this->all_client_report_keys, 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/expenses', $data)->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); } public function testExpenseCustomColumnsCsvGeneration() { $vendor = \App\Models\Vendor::factory()->create( [ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'name' => 'Vendor 1', ] ); Expense::factory()->create([ 'user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id, 'vendor_id' => $vendor->id, 'amount' => 100, 'public_notes' => 'Public', 'private_notes' => 'Private', 'currency_id' => 1, ]); $data = [ 'date_range' => 'all', 'report_keys' => ['client.name','vendor.name','expense.amount','expense.currency_id'], 'send_email' => false, ]; $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->post('/api/v1/reports/expenses', $data); $response->assertStatus(200); $arr = $response->json(); $hash = $arr['message']; $response = $this->poll($hash); $csv = $response->body(); $this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name')); $this->assertEquals('Vendor 1', $this->getFirstValueByColumn($csv, 'Vendor Name')); $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Expense Amount')); $this->assertEquals('USD', $this->getFirstValueByColumn($csv, 'Expense Currency')); } }