mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-01 20:17:35 -04:00 
			
		
		
		
	Tax Reports
This commit is contained in:
		
							parent
							
								
									d1b3fa12ba
								
							
						
					
					
						commit
						e591dbb7cd
					
				| @ -11,14 +11,14 @@ | ||||
| 
 | ||||
| namespace App\DataMapper\Schedule; | ||||
| 
 | ||||
| class EmailProductSalesReport | ||||
| class EmailReport | ||||
| { | ||||
|     /** | ||||
|      * Defines the template name | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     public string $template = 'email_product_sales_report'; | ||||
|     public string $template = 'email_report'; | ||||
| 
 | ||||
|     /** | ||||
|      * An array of clients hashed_ids | ||||
| @ -66,5 +66,8 @@ class EmailProductSalesReport | ||||
|      * @var string | ||||
|      */ | ||||
|     public string $end_date = ''; | ||||
|      | ||||
|     /** @var string $report_name */ | ||||
| 
 | ||||
|     public string $report_name = ''; | ||||
| } | ||||
| @ -45,6 +45,7 @@ class StoreSchedulerRequest extends Request | ||||
|             'parameters.end_date' => ['bail', 'sometimes', 'date:Y-m-d', 'required_if:parameters.date_rate,custom', 'after_or_equal:parameters.start_date'], | ||||
|             'parameters.entity' => ['bail', 'sometimes', 'string', 'in:invoice,credit,quote,purchase_order'], | ||||
|             'parameters.entity_id' => ['bail', 'sometimes', 'string'], | ||||
|             'parameters.report_name' => ['bail','sometimes', 'string', 'required_if:template,email_report', 'in:ar_summary_report,ar_detail_report,tax_summary_report,user_sales_report,client_sales_report,client_balance_report,product_sales_report'], | ||||
|         ]; | ||||
| 
 | ||||
|         return $rules; | ||||
|  | ||||
| @ -19,9 +19,14 @@ use App\Utils\Traits\MakesDates; | ||||
| use App\Jobs\Mail\NinjaMailerJob; | ||||
| use App\Jobs\Mail\NinjaMailerObject; | ||||
| use App\Export\CSV\ProductSalesExport; | ||||
| use App\DataMapper\Schedule\EmailStatement; | ||||
| use App\Services\Report\ARDetailReport; | ||||
| use App\Services\Report\ARSummaryReport; | ||||
| use App\Services\Report\ClientBalanceReport; | ||||
| use App\Services\Report\ClientSalesReport; | ||||
| use App\Services\Report\TaxSummaryReport; | ||||
| use App\Services\Report\UserSalesReport; | ||||
| 
 | ||||
| class EmailProductSalesReport | ||||
| class EmailReport | ||||
| { | ||||
|     use MakesHash; | ||||
|     use MakesDates; | ||||
| @ -30,7 +35,7 @@ class EmailProductSalesReport | ||||
| 
 | ||||
|     private bool $multiple_clients = false; | ||||
| 
 | ||||
|     private string $file_name = 'product_sales.csv'; | ||||
|     private string $file_name = 'file.csv'; | ||||
| 
 | ||||
|     public function __construct(public Scheduler $scheduler) | ||||
|     { | ||||
| @ -54,7 +59,25 @@ class EmailProductSalesReport | ||||
|             $data['clients'] = $this->transformKeys($this->scheduler->parameters['clients']); | ||||
|         } | ||||
|          | ||||
|         $export = (new ProductSalesExport($this->scheduler->company, $data)); | ||||
|         $export = false; | ||||
| 
 | ||||
|         match($this->scheduler->parameters['report_name']) | ||||
|         { | ||||
|             'product_sales_report' => $export = (new ProductSalesExport($this->scheduler->company, $data)), | ||||
|             'email_ar_detailed_report' => (new ARDetailReport($this->scheduler->company, $data)), | ||||
|             'email_ar_summary_report' => (new ARSummaryReport($this->scheduler->company, $data)), | ||||
|             'email_tax_summary_report' => (new TaxSummaryReport($this->scheduler->company, $data)), | ||||
|             'email_client_balance_report' => (new ClientBalanceReport($this->scheduler->company, $data)), | ||||
|             'email_client_sales_report' => (new ClientSalesReport($this->scheduler->company, $data)), | ||||
|             'email_user_sales_report' => (new UserSalesReport($this->scheduler->company, $data)), | ||||
|             default => $export = false, | ||||
|         }; | ||||
|          | ||||
|         if(!$export) { | ||||
|             $this->cancelSchedule(); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         $csv = $export->run(); | ||||
| 
 | ||||
|         //todo - potentially we send this to more than one user.
 | ||||
| @ -72,7 +95,10 @@ class EmailProductSalesReport | ||||
|          | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     private function cancelSchedule() | ||||
|     { | ||||
|         $this->scheduler->forceDelete(); | ||||
|     } | ||||
|      | ||||
|     | ||||
| 
 | ||||
| @ -14,7 +14,7 @@ namespace App\Services\Scheduler; | ||||
| use App\Models\Scheduler; | ||||
| use App\Utils\Traits\MakesHash; | ||||
| use App\Utils\Traits\MakesDates; | ||||
| use App\Services\Scheduler\EmailProductSalesReport; | ||||
| use App\Services\Scheduler\EmailReport; | ||||
| 
 | ||||
| class SchedulerService | ||||
| { | ||||
| @ -49,11 +49,15 @@ class SchedulerService | ||||
|         (new EmailStatementService($this->scheduler))->run(); | ||||
|     } | ||||
| 
 | ||||
|     private function email_product_sales_report() | ||||
|     private function email_report() | ||||
|     { | ||||
|         (new EmailProductSalesReport($this->scheduler))->run(); | ||||
|         match($this->scheduler->template){ | ||||
|             'product_sales_report' => (new EmailReport($this->scheduler))->run(), | ||||
|             default => null | ||||
|         };   | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * Sets the next run date of the scheduled task | ||||
|      * | ||||
|  | ||||
							
								
								
									
										203
									
								
								tests/Feature/Export/TaxSummaryReportTest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								tests/Feature/Export/TaxSummaryReportTest.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,203 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Invoice Ninja (https://invoiceninja.com). | ||||
|  * | ||||
|  * @link https://github.com/invoiceninja/invoiceninja source repository | ||||
|  * | ||||
|  * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) | ||||
|  * | ||||
|  * @license https://www.elastic.co/licensing/elastic-license | ||||
|  */ | ||||
| 
 | ||||
| namespace Tests\Feature\Export; | ||||
| 
 | ||||
| use App\DataMapper\CompanySettings; | ||||
| use App\Factory\InvoiceItemFactory; | ||||
| use App\Models\Account; | ||||
| use App\Models\Client; | ||||
| use App\Models\Company; | ||||
| use App\Models\Invoice; | ||||
| use App\Models\User; | ||||
| use App\Services\Report\ARDetailReport; | ||||
| use App\Services\Report\TaxSummaryReport; | ||||
| use App\Utils\Traits\MakesHash; | ||||
| use Illuminate\Routing\Middleware\ThrottleRequests; | ||||
| use Tests\TestCase; | ||||
| 
 | ||||
| /** | ||||
|  * @test | ||||
|  */ | ||||
| class TaxSummaryReportTest extends TestCase | ||||
| { | ||||
|     use MakesHash; | ||||
| 
 | ||||
|     public $faker; | ||||
| 
 | ||||
|     protected function setUp() :void | ||||
|     { | ||||
|         parent::setUp(); | ||||
| 
 | ||||
|         $this->faker = \Faker\Factory::create(); | ||||
| 
 | ||||
|         $this->withoutMiddleware( | ||||
|             ThrottleRequests::class | ||||
|         ); | ||||
| 
 | ||||
|         $this->withoutExceptionHandling(); | ||||
|     } | ||||
| 
 | ||||
|     public $company; | ||||
| 
 | ||||
|     public $user; | ||||
| 
 | ||||
|     public $payload; | ||||
| 
 | ||||
|     public $account; | ||||
| 
 | ||||
|     public $client; | ||||
| 
 | ||||
|     /** | ||||
|      *      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->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, | ||||
|             'company_id' => $this->company->id, | ||||
|             'is_deleted' => 0, | ||||
|         ]); | ||||
|     } | ||||
| 
 | ||||
|     public function testUserSalesInstance() | ||||
|     { | ||||
|         $this->buildData(); | ||||
| 
 | ||||
|         $pl = new TaxSummaryReport($this->company, $this->payload); | ||||
| 
 | ||||
|         $this->assertInstanceOf(TaxSummaryReport::class, $pl); | ||||
| 
 | ||||
|         $this->account->delete(); | ||||
|     } | ||||
| 
 | ||||
|     public function testSimpleReport() | ||||
|     { | ||||
|         $this->buildData(); | ||||
| 
 | ||||
| 
 | ||||
|         $this->payload = [ | ||||
|             'start_date' => '2000-01-01', | ||||
|             'end_date' => '2030-01-11', | ||||
|             'date_range' => 'custom', | ||||
|             'client_id' => $this->client->id, | ||||
|             'report_keys' => [] | ||||
|         ]; | ||||
| 
 | ||||
|         $i = Invoice::factory()->create([ | ||||
|             'client_id' => $this->client->id, | ||||
|             'user_id' => $this->user->id, | ||||
|             'company_id' => $this->company->id, | ||||
|             'amount' => 0, | ||||
|             'balance' => 0, | ||||
|             'status_id' => 2, | ||||
|             'total_taxes' => 1, | ||||
|             'date' => now()->format('Y-m-d'), | ||||
|             'terms' => 'nada', | ||||
|             'discount' => 0, | ||||
|             'tax_rate1' => 10, | ||||
|             'tax_rate2' => 17.5, | ||||
|             'tax_rate3' => 5, | ||||
|             'tax_name1' => 'GST', | ||||
|             'tax_name2' => 'VAT', | ||||
|             'tax_name3' => 'CA Sales Tax', | ||||
|             'uses_inclusive_taxes' => false, | ||||
|             'line_items' => $this->buildLineItems(), | ||||
|         ]); | ||||
| 
 | ||||
|         $i = $i->calc()->getInvoice(); | ||||
| 
 | ||||
|         $pl = new TaxSummaryReport($this->company, $this->payload); | ||||
|         $response = $pl->run(); | ||||
| 
 | ||||
|         $this->assertIsString($response); | ||||
| 
 | ||||
|         $this->account->delete(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     private function buildLineItems() | ||||
|     { | ||||
|         $line_items = []; | ||||
| 
 | ||||
|         $item = InvoiceItemFactory::create(); | ||||
|         $item->quantity = 1; | ||||
|         $item->cost = 10; | ||||
|         $item->product_key = 'test'; | ||||
|         $item->notes = 'test_product'; | ||||
|         // $item->task_id = $this->encodePrimaryKey($this->task->id);
 | ||||
|         // $item->expense_id = $this->encodePrimaryKey($this->expense->id);
 | ||||
| 
 | ||||
|         $line_items[] = $item; | ||||
| 
 | ||||
| 
 | ||||
|         $item = InvoiceItemFactory::create(); | ||||
|         $item->quantity = 1; | ||||
|         $item->cost = 10; | ||||
|         $item->product_key = 'pumpkin'; | ||||
|         $item->notes = 'test_pumpkin'; | ||||
|         // $item->task_id = $this->encodePrimaryKey($this->task->id);
 | ||||
|         // $item->expense_id = $this->encodePrimaryKey($this->expense->id);
 | ||||
| 
 | ||||
|         $line_items[] = $item; | ||||
| 
 | ||||
| 
 | ||||
|         return $line_items; | ||||
|     } | ||||
| } | ||||
| @ -25,7 +25,7 @@ use App\DataMapper\Schedule\EmailStatement; | ||||
| use Illuminate\Validation\ValidationException; | ||||
| use Illuminate\Foundation\Testing\WithoutEvents; | ||||
| use App\Services\Scheduler\EmailStatementService; | ||||
| use App\Services\Scheduler\EmailProductSalesReport; | ||||
| use App\Services\Scheduler\EmailReport; | ||||
| use Illuminate\Foundation\Testing\DatabaseTransactions; | ||||
| use Illuminate\Routing\Middleware\ThrottleRequests; | ||||
| 
 | ||||
| @ -59,18 +59,48 @@ class SchedulerTest extends TestCase | ||||
|         // $this->withoutExceptionHandling();
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public function testReportValidationRules() | ||||
|     { | ||||
|         $data = [ | ||||
|             'name' => 'A test product sales scheduler', | ||||
|             'frequency_id' => RecurringInvoice::FREQUENCY_MONTHLY, | ||||
|             'next_run' => now()->format('Y-m-d'), | ||||
|             'template' => 'email_report', | ||||
|             'parameters' => [ | ||||
|                 'date_range' => EmailStatement::LAST_MONTH, | ||||
|                 'clients' => [], | ||||
|                 'report_keys' => [], | ||||
|                 'client_id' => $this->client->hashed_id, | ||||
|                 'report_name' => '', | ||||
|             ], | ||||
|         ]; | ||||
| 
 | ||||
|         $response = false; | ||||
| 
 | ||||
|         $response = $this->withHeaders([ | ||||
|                 'X-API-SECRET' => config('ninja.api_secret'), | ||||
|                 'X-API-TOKEN' => $this->token, | ||||
|             ])->postJson('/api/v1/task_schedulers', $data); | ||||
| 
 | ||||
|             $response->assertStatus(422); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public function testProductSalesReportGenerationOneClientSeparateParam() | ||||
|     { | ||||
|         $data = [ | ||||
|             'name' => 'A test product sales scheduler', | ||||
|             'frequency_id' => RecurringInvoice::FREQUENCY_MONTHLY, | ||||
|             'next_run' => now()->format('Y-m-d'), | ||||
|             'template' => 'email_product_sales_report', | ||||
|             'template' => 'email_report', | ||||
|             'parameters' => [ | ||||
|                 'date_range' => EmailStatement::LAST_MONTH, | ||||
|                 'clients' => [], | ||||
|                 'report_keys' => [], | ||||
|                 'client_id' => $this->client->hashed_id, | ||||
|                 'report_name' => 'product_sales_report', | ||||
| 
 | ||||
|             ], | ||||
|         ]; | ||||
| @ -99,7 +129,7 @@ class SchedulerTest extends TestCase | ||||
| 
 | ||||
|         $this->assertNotNull($scheduler); | ||||
| 
 | ||||
|         $export = (new EmailProductSalesReport($scheduler))->run(); | ||||
|         $export = (new EmailReport($scheduler))->run(); | ||||
| 
 | ||||
|         $this->assertEquals(now()->addMonth()->format('Y-m-d'), $scheduler->next_run->format('Y-m-d')); | ||||
| 
 | ||||
| @ -111,13 +141,13 @@ class SchedulerTest extends TestCase | ||||
|             'name' => 'A test product sales scheduler', | ||||
|             'frequency_id' => RecurringInvoice::FREQUENCY_MONTHLY, | ||||
|             'next_run' => now()->format('Y-m-d'), | ||||
|             'template' => 'email_product_sales_report', | ||||
|             'template' => 'email_report', | ||||
|             'parameters' => [ | ||||
|                 'date_range' => EmailStatement::LAST_MONTH, | ||||
|                 'clients' => [$this->client->hashed_id], | ||||
|                 'report_keys' => [], | ||||
|                 'client_id' => null, | ||||
| 
 | ||||
|                 'report_name' => 'product_sales_report', | ||||
|             ], | ||||
|         ]; | ||||
| 
 | ||||
| @ -145,7 +175,7 @@ class SchedulerTest extends TestCase | ||||
| 
 | ||||
|         $this->assertNotNull($scheduler); | ||||
| 
 | ||||
|         $export = (new EmailProductSalesReport($scheduler))->run(); | ||||
|         $export = (new EmailReport($scheduler))->run(); | ||||
| 
 | ||||
|         $this->assertEquals(now()->addMonth()->format('Y-m-d'), $scheduler->next_run->format('Y-m-d')); | ||||
| 
 | ||||
| @ -157,13 +187,13 @@ class SchedulerTest extends TestCase | ||||
|             'name' => 'A test product sales scheduler', | ||||
|             'frequency_id' => RecurringInvoice::FREQUENCY_MONTHLY, | ||||
|             'next_run' => now()->format('Y-m-d'), | ||||
|             'template' => 'email_product_sales_report', | ||||
|             'template' => 'email_report', | ||||
|             'parameters' => [ | ||||
|                 'date_range' => EmailStatement::LAST_MONTH, | ||||
|                 'clients' => [], | ||||
|                 'report_keys' => [], | ||||
|                 'client_id' => null, | ||||
| 
 | ||||
|                 'report_name' => 'product_sales_report', | ||||
|             ], | ||||
|         ]; | ||||
| 
 | ||||
| @ -188,7 +218,7 @@ class SchedulerTest extends TestCase | ||||
| 
 | ||||
|         $this->assertNotNull($scheduler); | ||||
| 
 | ||||
|         $export = (new EmailProductSalesReport($scheduler))->run(); | ||||
|         $export = (new EmailReport($scheduler))->run(); | ||||
| 
 | ||||
|         $this->assertEquals(now()->addMonth()->format('Y-m-d'), $scheduler->next_run->format('Y-m-d')); | ||||
| 
 | ||||
| @ -200,10 +230,11 @@ class SchedulerTest extends TestCase | ||||
|             'name' => 'A test product sales scheduler', | ||||
|             'frequency_id' => RecurringInvoice::FREQUENCY_MONTHLY, | ||||
|             'next_run' => now()->format('Y-m-d'), | ||||
|             'template' => 'email_product_sales_report', | ||||
|             'template' => 'email_report', | ||||
|             'parameters' => [ | ||||
|                 'date_range' => EmailStatement::LAST_MONTH, | ||||
|                 'clients' => [], | ||||
|                 'report_name' => 'product_sales_report', | ||||
|             ], | ||||
|         ]; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user