Merge v5-dev

This commit is contained in:
David Bomba 2023-08-30 11:28:37 +10:00
commit 492c1ef1ed
56 changed files with 2504 additions and 1265 deletions

View File

@ -20,6 +20,7 @@ use App\Libraries\MultiDB;
use App\Models\DateFormat;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\App;
use Illuminate\Database\Eloquent\Builder;
use App\Transformers\ActivityTransformer;
class ActivityExport extends BaseExport
@ -39,10 +40,6 @@ class ActivityExport extends BaseExport
'address' => 'address',
];
private array $decorate_keys = [
];
public function __construct(Company $company, array $input)
{
$this->company = $company;
@ -50,45 +47,27 @@ class ActivityExport extends BaseExport
$this->entity_transformer = new ActivityTransformer();
}
public function run()
public function returnJson()
{
MultiDB::setDb($this->company->db);
App::forgetInstance('translator');
App::setLocale($this->company->locale());
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
$query = $this->init();
$this->date_format = DateFormat::find($this->company->settings->date_format_id)->format;
$headerdisplay = $this->buildHeader();
//load the CSV document from a string
$this->csv = Writer::createFromString();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $value, 'display_value' => $headerdisplay[$value]];
})->toArray();
ksort($this->entity_keys);
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
}
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Activity::query()
->where('company_id', $this->company->id);
$query = $this->addDateRange($query);
$query->cursor()
->each(function ($entity) {
$this->buildRow($entity);
});
return $this->csv->toString();
$report = $query->cursor()
->map(function ($credit) {
return $this->buildActivityRow($credit);
})->toArray();
return array_merge(['columns' => $header], $report);
}
private function buildRow(Activity $activity)
private function buildActivityRow(Activity $activity): array
{
$this->csv->insertOne([
return [
Carbon::parse($activity->created_at)->format($this->date_format),
ctrans("texts.activity_{$activity->activity_type_id}",[
'client' => $activity->client ? $activity->client->present()->name() : '',
@ -108,7 +87,57 @@ class ActivityExport extends BaseExport
'recurring_expense' => $activity->recurring_expense ? $activity->recurring_expense->number : '',
]),
$activity->ip,
]);
];
}
private function init(): Builder
{
MultiDB::setDb($this->company->db);
App::forgetInstance('translator');
App::setLocale($this->company->locale());
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
$this->date_format = DateFormat::find($this->company->settings->date_format_id)->format;
ksort($this->entity_keys);
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
}
$query = Activity::query()
->where('company_id', $this->company->id);
$query = $this->addDateRange($query);
return $query;
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor()
->each(function ($entity) {
$this->buildRow($entity);
});
return $this->csv->toString();
}
private function buildRow(Activity $activity)
{
$this->csv->insertOne($this->buildActivityRow($activity));
}

View File

@ -13,6 +13,7 @@ namespace App\Export\CSV;
use App\Utils\Number;
use App\Models\Client;
use App\Utils\Helpers;
use App\Models\Company;
use App\Models\Expense;
use App\Models\Invoice;
@ -28,7 +29,7 @@ use League\Fractal\Serializer\ArraySerializer;
class BaseExport
{
use MakesHash;
public Company $company;
public array $input;
@ -43,8 +44,6 @@ class BaseExport
public string $client_description = 'All Clients';
public array $forced_keys = [];
protected array $vendor_report_keys = [
'address1' => 'vendor.address1',
'address2' => 'vendor.address2',
@ -134,6 +133,7 @@ class BaseExport
"private_notes" => "invoice.private_notes",
"uses_inclusive_taxes" => "invoice.uses_inclusive_taxes",
"is_amount_discount" => "invoice.is_amount_discount",
"discount" => "invoice.discount",
"partial" => "invoice.partial",
"partial_due_date" => "invoice.partial_due_date",
"surcharge1" => "invoice.custom_surcharge1",
@ -144,6 +144,16 @@ class BaseExport
"tax_amount" => "invoice.total_taxes",
"assigned_user" => "invoice.assigned_user_id",
"user" => "invoice.user_id",
"custom_value1" => "invoice.custom_value1",
"custom_value2" => "invoice.custom_value2",
"custom_value3" => "invoice.custom_value3",
"custom_value4" => "invoice.custom_value4",
'tax_name1' => 'invoice.tax_name1',
'tax_name2' => 'invoice.tax_name2',
'tax_name3' => 'invoice.tax_name3',
'tax_rate1' => 'invoice.tax_rate1',
'tax_rate2' => 'invoice.tax_rate2',
'tax_rate3' => 'invoice.tax_rate3',
];
protected array $recurring_invoice_report_keys = [
@ -161,6 +171,7 @@ class BaseExport
"private_notes" => "recurring_invoice.private_notes",
"uses_inclusive_taxes" => "recurring_invoice.uses_inclusive_taxes",
"is_amount_discount" => "recurring_invoice.is_amount_discount",
"discount" => "recurring_invoice.discount",
"partial" => "recurring_invoice.partial",
"partial_due_date" => "recurring_invoice.partial_due_date",
"surcharge1" => "recurring_invoice.custom_surcharge1",
@ -172,17 +183,23 @@ class BaseExport
"assigned_user" => "recurring_invoice.assigned_user_id",
"user" => "recurring_invoice.user_id",
"frequency_id" => "recurring_invoice.frequency_id",
"next_send_date" => "recurring_invoice.next_send_date"
"next_send_date" => "recurring_invoice.next_send_date",
"custom_value1" => "recurring_invoice.custom_value1",
"custom_value2" => "recurring_invoice.custom_value2",
"custom_value3" => "recurring_invoice.custom_value3",
"custom_value4" => "recurring_invoice.custom_value4",
'tax_name1' => 'recurring_invoice.tax_name1',
'tax_name2' => 'recurring_invoice.tax_name2',
'tax_name3' => 'recurring_invoice.tax_name3',
'tax_rate1' => 'recurring_invoice.tax_rate1',
'tax_rate2' => 'recurring_invoice.tax_rate2',
'tax_rate3' => 'recurring_invoice.tax_rate3',
];
protected array $purchase_order_report_keys = [
'amount' => 'purchase_order.amount',
'balance' => 'purchase_order.balance',
'vendor' => 'purchase_order.vendor_id',
// 'custom_surcharge1' => 'purchase_order.custom_surcharge1',
// 'custom_surcharge2' => 'purchase_order.custom_surcharge2',
// 'custom_surcharge3' => 'purchase_order.custom_surcharge3',
// 'custom_surcharge4' => 'purchase_order.custom_surcharge4',
'custom_value1' => 'purchase_order.custom_value1',
'custom_value2' => 'purchase_order.custom_value2',
'custom_value3' => 'purchase_order.custom_value3',
@ -211,17 +228,37 @@ class BaseExport
'currency_id' => 'purchase_order.currency_id',
];
protected array $product_report_keys = [
'project' => 'project_id',
'vendor' => 'vendor_id',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'product_key' => 'product_key',
'notes' => 'notes',
'cost' => 'cost',
'price' => 'price',
'quantity' => 'quantity',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
];
protected array $item_report_keys = [
"quantity" => "item.quantity",
"cost" => "item.cost",
"product_key" => "item.product_key",
"notes" => "item.notes",
"item_tax1" => "item.tax_name1",
"item_tax_rate1" => "item.tax_rate1",
"item_tax2" => "item.tax_name2",
"item_tax_rate2" => "item.tax_rate2",
"item_tax3" => "item.tax_name3",
"item_tax_rate3" => "item.tax_rate3",
"tax_name1" => "item.tax_name1",
"tax_rate1" => "item.tax_rate1",
"tax_name2" => "item.tax_name2",
"tax_rate2" => "item.tax_rate2",
"tax_name3" => "item.tax_name3",
"tax_rate3" => "item.tax_rate3",
"custom_value1" => "item.custom_value1",
"custom_value2" => "item.custom_value2",
"custom_value3" => "item.custom_value3",
@ -229,6 +266,9 @@ class BaseExport
"discount" => "item.discount",
"type" => "item.type_id",
"tax_category" => "item.tax_id",
'is_amount_discount' => 'item.is_amount_discount',
'line_total' => 'item.line_total',
'gross_line_total' => 'item.gross_line_total',
];
protected array $quote_report_keys = [
@ -250,6 +290,7 @@ class BaseExport
"private_notes" => "quote.private_notes",
"uses_inclusive_taxes" => "quote.uses_inclusive_taxes",
"is_amount_discount" => "quote.is_amount_discount",
"discount" => "quote.discount",
"partial" => "quote.partial",
"partial_due_date" => "quote.partial_due_date",
"surcharge1" => "quote.custom_surcharge1",
@ -260,6 +301,12 @@ class BaseExport
"tax_amount" => "quote.total_taxes",
"assigned_user" => "quote.assigned_user_id",
"user" => "quote.user_id",
'tax_name1' => 'quote.tax_name1',
'tax_name2' => 'quote.tax_name2',
'tax_name3' => 'quote.tax_name3',
'tax_rate1' => 'quote.tax_rate1',
'tax_rate2' => 'quote.tax_rate2',
'tax_rate3' => 'quote.tax_rate3',
];
protected array $credit_report_keys = [
@ -271,6 +318,7 @@ class BaseExport
"date" => "credit.date",
"due_date" => "credit.due_date",
"terms" => "credit.terms",
"discount" => "credit.discount",
"footer" => "credit.footer",
"status" => "credit.status",
"public_notes" => "credit.public_notes",
@ -283,6 +331,10 @@ class BaseExport
"surcharge2" => "credit.custom_surcharge2",
"surcharge3" => "credit.custom_surcharge3",
"surcharge4" => "credit.custom_surcharge4",
"custom_value1" => "credit.custom_value1",
"custom_value2" => "credit.custom_value2",
"custom_value3" => "credit.custom_value3",
"custom_value4" => "credit.custom_value4",
"exchange_rate" => "credit.exchange_rate",
"tax_amount" => "credit.total_taxes",
"assigned_user" => "credit.assigned_user_id",
@ -829,17 +881,32 @@ class BaseExport
return $query->whereBetween($this->date_key, [now()->startOfYear(), now()])->orderBy($this->date_key, 'ASC');
}
}
/**
* Returns the merged array of
* the entity with the matching
* item report keys
*
* @param string $entity_report_keys
* @return array
*/
public function mergeItemsKeys(string $entity_report_keys): array
{
return array_merge($this->{$entity_report_keys}, $this->item_report_keys);
}
public function buildHeader() :array
{
$helper = new Helpers();
$header = [];
// nlog($this->input['report_keys']);
foreach (array_merge($this->input['report_keys'], $this->forced_keys) as $value) {
foreach ($this->input['report_keys'] as $value) {
$key = array_search($value, $this->entity_keys);
nlog("{$key} => {$value}");
$original_key = $key;
// nlog("{$key} => {$value}");
$prefix = '';
if(!$key) {
@ -897,6 +964,11 @@ class BaseExport
$key = array_search($value, $this->purchase_order_report_keys);
}
if(!$key) {
$prefix = '';
$key = array_search($value, $this->product_report_keys);
}
if(!$key) {
$prefix = '';
}
@ -913,11 +985,38 @@ class BaseExport
$key = str_replace('contact.', '', $key);
$key = str_replace('payment.', '', $key);
$key = str_replace('expense.', '', $key);
// nlog($key);
if(in_array($key, ['quote1','quote2','quote3','quote4','credit1','credit2','credit3','credit4','purchase_order1','purchase_order2','purchase_order3','purchase_order4']))
$key = str_replace('product.', '', $key);
if(stripos($value, 'custom_value') !== false)
{
$number = substr($key, -1);
$header[] = ctrans('texts.item') . " ". ctrans("texts.custom_value{$number}");
$parts = explode(".", $value);
if(count($parts) == 2 && in_array($parts[0], ['credit','quote','invoice','purchase_order','recurring_invoice'])){
$entity = "invoice".substr($parts[1], -1);
$prefix = ctrans("texts.".$parts[0]);
$fallback = "custom_value".substr($parts[1], -1);
$custom_field_label = $helper->makeCustomField($this->company->custom_fields, $entity);
if(strlen($custom_field_label) > 1)
$header[] = $custom_field_label;
else {
$header[] = $prefix . " ". ctrans("texts.{$fallback}");
}
}
elseif(count($parts) == 2 && stripos($parts[0], 'contact') !== false) {
$entity = "contact".substr($parts[1], -1);
$custom_field_string = strlen($helper->makeCustomField($this->company->custom_fields, $entity)) > 1 ? $helper->makeCustomField($this->company->custom_fields, $entity) : ctrans("texts.{$parts[1]}");
$header[] = ctrans("texts.{$parts[0]}") . " " . $custom_field_string;
}
elseif(count($parts) == 2 && in_array(substr($original_key, 0, -1), ['credit','quote','invoice','purchase_order','recurring_invoice'])){
$custom_field_string = strlen($helper->makeCustomField($this->company->custom_fields, "product".substr($original_key,-1))) > 1 ? $helper->makeCustomField($this->company->custom_fields, "product".substr($original_key,-1)) : ctrans("texts.{$parts[1]}");
$header[] = ctrans("texts.{$parts[0]}") . " " . $custom_field_string;
}
else{
$header[] = "{$prefix}" . ctrans("texts.{$key}");
}
}
else
{
@ -926,7 +1025,7 @@ class BaseExport
}
// nlog($header);
return $header;
}
}

View File

@ -17,6 +17,7 @@ use App\Models\Company;
use App\Transformers\ClientContactTransformer;
use App\Transformers\ClientTransformer;
use App\Utils\Ninja;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App;
use League\Csv\Writer;
@ -72,16 +73,6 @@ class ClientExport extends BaseExport
'status' => 'status'
];
private array $decorate_keys = [
'client.country_id',
'client.shipping_country_id',
'client.currency',
'client.industry',
];
public array $forced_keys = [
];
public function __construct(Company $company, array $input)
{
$this->company = $company;
@ -90,7 +81,27 @@ class ClientExport extends BaseExport
$this->contact_transformer = new ClientContactTransformer();
}
public function run()
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $value, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($client) {
return $this->buildRow($client);
})->toArray();
return array_merge(['columns' => $header], $report);
}
public function init(): Builder
{
MultiDB::setDb($this->company->db);
App::forgetInstance('translator');
@ -98,15 +109,9 @@ class ClientExport extends BaseExport
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
$this->input['report_keys'] = array_values($this->client_report_keys);
}
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Client::query()->with('contacts')
->withTrashed()
@ -115,6 +120,20 @@ class ClientExport extends BaseExport
$query = $this->addDateRange($query);
return $query;
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor()
->each(function ($client) {
$this->csv->insertOne($this->buildRow($client));

View File

@ -18,6 +18,7 @@ use App\Models\Company;
use App\Transformers\ClientContactTransformer;
use App\Transformers\ClientTransformer;
use App\Utils\Ninja;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App;
use League\Csv\Writer;
@ -32,54 +33,6 @@ class ContactExport extends BaseExport
public string $date_key = 'created_at';
public array $entity_keys = [
'address1' => 'client.address1',
'address2' => 'client.address2',
'balance' => 'client.balance',
'city' => 'client.city',
'country' => 'client.country_id',
'credit_balance' => 'client.credit_balance',
'custom_value1' => 'client.custom_value1',
'custom_value2' => 'client.custom_value2',
'custom_value3' => 'client.custom_value3',
'custom_value4' => 'client.custom_value4',
'id_number' => 'client.id_number',
'industry' => 'client.industry_id',
'last_login' => 'client.last_login',
'name' => 'client.name',
'number' => 'client.number',
'paid_to_date' => 'client.paid_to_date',
'client_phone' => 'client.phone',
'postal_code' => 'client.postal_code',
'private_notes' => 'client.private_notes',
'public_notes' => 'client.public_notes',
'shipping_address1' => 'client.shipping_address1',
'shipping_address2' => 'client.shipping_address2',
'shipping_city' => 'client.shipping_city',
'shipping_country' => 'client.shipping_country_id',
'shipping_postal_code' => 'client.shipping_postal_code',
'shipping_state' => 'client.shipping_state',
'state' => 'client.state',
'vat_number' => 'client.vat_number',
'website' => 'client.website',
'currency' => 'client.currency',
'first_name' => 'contact.first_name',
'last_name' => 'contact.last_name',
'contact_phone' => 'contact.phone',
'contact_custom_value1' => 'contact.custom_value1',
'contact_custom_value2' => 'contact.custom_value2',
'contact_custom_value3' => 'contact.custom_value3',
'contact_custom_value4' => 'contact.custom_value4',
'email' => 'contact.email',
];
private array $decorate_keys = [
'client.country_id',
'client.shipping_country_id',
'client.currency',
'client.industry',
];
public function __construct(Company $company, array $input)
{
$this->company = $company;
@ -88,29 +41,39 @@ class ContactExport extends BaseExport
$this->contact_transformer = new ClientContactTransformer();
}
public function run()
private function init(): Builder
{
MultiDB::setDb($this->company->db);
App::forgetInstance('translator');
App::setLocale($this->company->locale());
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
$this->input['report_keys'] = array_values($this->client_report_keys);
}
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = ClientContact::query()
->where('company_id', $this->company->id);
$query = $this->addDateRange($query);
return $query;
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor()->each(function ($contact) {
$this->csv->insertOne($this->buildRow($contact));
});
@ -118,6 +81,26 @@ class ContactExport extends BaseExport
return $this->csv->toString();
}
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $value, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($contact) {
return $this->buildRow($contact);
})->toArray();
return array_merge(['columns' => $header], $report);
}
private function buildRow(ClientContact $contact) :array
{
$transformed_contact = false;
@ -129,14 +112,13 @@ class ContactExport extends BaseExport
foreach (array_values($this->input['report_keys']) as $key) {
$parts = explode('.', $key);
$keyval = array_search($key, $this->entity_keys);
if ($parts[0] == 'client' && array_key_exists($parts[1], $transformed_client)) {
$entity[$keyval] = $transformed_client[$parts[1]];
$entity[$key] = $transformed_client[$parts[1]];
} elseif ($parts[0] == 'contact' && array_key_exists($parts[1], $transformed_contact)) {
$entity[$keyval] = $transformed_contact[$parts[1]];
$entity[$key] = $transformed_contact[$parts[1]];
} else {
$entity[$keyval] = '';
$entity[$key] = '';
}
}

View File

@ -30,51 +30,6 @@ class CreditExport extends BaseExport
public Writer $csv;
public array $entity_keys = [
'amount' => 'amount',
'balance' => 'balance',
'client' => 'client_id',
'country' => 'country_id',
'custom_surcharge1' => 'custom_surcharge1',
'custom_surcharge2' => 'custom_surcharge2',
'custom_surcharge3' => 'custom_surcharge3',
'custom_surcharge4' => 'custom_surcharge4',
'currency' => 'currency',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'date' => 'date',
'discount' => 'discount',
'due_date' => 'due_date',
'exchange_rate' => 'exchange_rate',
'footer' => 'footer',
'invoice' => 'invoice_id',
'number' => 'number',
'paid_to_date' => 'paid_to_date',
'partial' => 'partial',
'partial_due_date' => 'partial_due_date',
'po_number' => 'po_number',
'private_notes' => 'private_notes',
'public_notes' => 'public_notes',
'status' => 'status_id',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'terms' => 'terms',
'total_taxes' => 'total_taxes',
];
private array $decorate_keys = [
'country',
'client',
'invoice',
'currency',
];
public function __construct(Company $company, array $input)
{
$this->company = $company;
@ -86,34 +41,36 @@ class CreditExport extends BaseExport
{
$query = $this->init();
$header = $this->buildHeader();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $value, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($credit) {
$row = $this->buildRow($credit);
return $this->processMetaData($row, $credit);
})->toArray();
return array_merge([$header], $report);
return array_merge(['columns' => $header], $report);
}
private function processMetaData(array $row, Credit $credit): array
{
$clean_row = [];
foreach ($this->input['report_keys'] as $key => $value) {
foreach (array_values($this->input['report_keys']) as $key => $value) {
$report_keys = explode(".", $value);
$column_key = str_replace("credit.", "", $value);
$column_key = array_search($column_key, $this->entity_keys);
$column_key = $value;
$clean_row[$key]['entity'] = $report_keys[0];
$clean_row[$key]['id'] = $report_keys[1] ?? $report_keys[0];
$clean_row[$key]['hashed_id'] = $report_keys[0] == 'credit' ? null : $credit->{$report_keys[0]}->hashed_id ?? null;
$clean_row[$key]['value'] = $row[$column_key];
$clean_row[$key]['identifier'] = $value;
if(in_array($clean_row[$key]['id'], ['amount', 'balance', 'partial', 'refunded', 'applied','unit_cost','cost','price']))
if(in_array($clean_row[$key]['id'], ['paid_to_date','total_taxes','amount', 'balance', 'partial', 'refunded', 'applied','unit_cost','cost','price']))
$clean_row[$key]['display_value'] = Number::formatMoney($row[$column_key], $credit->client);
else
$clean_row[$key]['display_value'] = $row[$column_key];
@ -133,20 +90,13 @@ class CreditExport extends BaseExport
$t->replace(Ninja::transformTranslations($this->company->settings));
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
// $this->input['report_keys'] = collect(array_values($this->entity_keys))->map(function ($value){
// // if(in_array($value,['client_id','country_id']))
// // return $value;
// // else
// return 'credit.'.$value;
// })->toArray();
$this->input['report_keys'] = array_values($this->credit_report_keys);
}
$query = Credit::query()
->withTrashed()
->with('client')->where('company_id', $this->company->id)
->with('client')
->where('company_id', $this->company->id)
->where('is_deleted', 0);
$query = $this->addDateRange($query);
@ -162,11 +112,9 @@ class CreditExport extends BaseExport
//insert the header
$this->csv->insertOne($this->buildHeader());
// nlog($this->input['report_keys']);
$query->cursor()
->each(function ($credit) {
// nlog($this->buildRow($credit));
$this->csv->insertOne($this->buildRow($credit));
});
@ -180,22 +128,22 @@ class CreditExport extends BaseExport
$entity = [];
foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
if(!$keyval)
$keyval = array_search(str_replace("credit.", "", $key), $this->entity_keys) ?? $key;
if(!$keyval)
$keyval = $key;
$keyval = $key;
$credit_key = str_replace("credit.", "", $key);
$searched_credit_key = array_search(str_replace("credit.", "", $key), $this->credit_report_keys) ?? $key;
if (array_key_exists($key, $transformed_credit)) {
$entity[$keyval] = $transformed_credit[$key];
} elseif (array_key_exists($keyval, $transformed_credit)) {
if (isset($transformed_credit[$credit_key])) {
$entity[$keyval] = $transformed_credit[$credit_key];
} elseif (isset($transformed_credit[$keyval])) {
$entity[$keyval] = $transformed_credit[$keyval];
} elseif(isset($transformed_credit[$searched_credit_key])){
$entity[$keyval] = $transformed_credit[$searched_credit_key];
}
else {
$entity[$keyval] = $this->resolveKey($keyval, $credit, $this->credit_transformer);
}
}
return $this->decorateAdvancedFields($credit, $entity);

View File

@ -16,6 +16,7 @@ use App\Models\Company;
use App\Models\Document;
use App\Transformers\DocumentTransformer;
use App\Utils\Ninja;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App;
use League\Csv\Writer;
@ -30,16 +31,11 @@ class DocumentExport extends BaseExport
public array $entity_keys = [
'record_type' => 'record_type',
// 'record_name' => 'record_name',
'name' => 'name',
'type' => 'type',
'created_at' => 'created_at',
];
private array $decorate_keys = [
];
public function __construct(Company $company, array $input)
{
$this->company = $company;
@ -47,28 +43,55 @@ class DocumentExport extends BaseExport
$this->entity_transformer = new DocumentTransformer();
}
public function run()
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $value, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($document) {
$row = $this->buildRow($document);
})->toArray();
return array_merge(['columns' => $header], $report);
}
private function init(): Builder
{
MultiDB::setDb($this->company->db);
App::forgetInstance('translator');
App::setLocale($this->company->locale());
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
}
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Document::query()->where('company_id', $this->company->id);
$query = $this->addDateRange($query);
return $query;
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor()
->each(function ($entity) {
$this->csv->insertOne($this->buildRow($entity));

View File

@ -16,6 +16,7 @@ use App\Models\Company;
use App\Models\Expense;
use App\Transformers\ExpenseTransformer;
use App\Utils\Ninja;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App;
use League\Csv\Writer;
@ -28,51 +29,6 @@ class ExpenseExport extends BaseExport
public Writer $csv;
public array $entity_keys = [
'amount' => 'expense.amount',
'category' => 'expense.category',
'client' => 'expense.client_id',
'custom_value1' => 'expense.custom_value1',
'custom_value2' => 'expense.custom_value2',
'custom_value3' => 'expense.custom_value3',
'custom_value4' => 'expense.custom_value4',
'currency' => 'expense.currency_id',
'date' => 'expense.date',
'exchange_rate' => 'expense.exchange_rate',
'converted_amount' => 'expense.foreign_amount',
'invoice_currency_id' => 'expense.invoice_currency_id',
'payment_date' => 'expense.payment_date',
'number' => 'expense.number',
'payment_type_id' => 'expense.payment_type_id',
'private_notes' => 'expense.private_notes',
'project' => 'expense.project_id',
'public_notes' => 'expense.public_notes',
'tax_amount1' => 'expense.tax_amount1',
'tax_amount2' => 'expense.tax_amount2',
'tax_amount3' => 'expense.tax_amount3',
'tax_name1' => 'expense.tax_name1',
'tax_name2' => 'expense.tax_name2',
'tax_name3' => 'expense.tax_name3',
'tax_rate1' => 'expense.tax_rate1',
'tax_rate2' => 'expense.tax_rate2',
'tax_rate3' => 'expense.tax_rate3',
'transaction_reference' => 'expense.transaction_reference',
'vendor' => 'expense.vendor_id',
'invoice' => 'expense.invoice_id',
'user' => 'expense.user',
'assigned_user' => 'expense.assigned_user',
];
private array $decorate_keys = [
'client',
'currency',
'invoice',
'category',
'vendor',
'project',
'payment_type_id',
];
public function __construct(Company $company, array $input)
{
$this->company = $company;
@ -80,24 +36,38 @@ class ExpenseExport extends BaseExport
$this->expense_transformer = new ExpenseTransformer();
}
public function run()
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $value, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($resource) {
return $this->buildRow($resource);
})->toArray();
return array_merge(['columns' => $header], $report);
}
private function init(): Builder
{
MultiDB::setDb($this->company->db);
App::forgetInstance('translator');
App::setLocale($this->company->locale());
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
$this->input['report_keys'] = array_values($this->expense_report_keys);
}
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Expense::query()
->with('client')
->withTrashed()
@ -106,6 +76,20 @@ class ExpenseExport extends BaseExport
$query = $this->addDateRange($query);
return $query;
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor()
->each(function ($expense) {
$this->csv->insertOne($this->buildRow($expense));
@ -122,7 +106,6 @@ class ExpenseExport extends BaseExport
foreach (array_values($this->input['report_keys']) as $key) {
$parts = explode('.', $key);
$keyval = array_search($key, $this->entity_keys);
if (is_array($parts) && $parts[0] == 'expense' && array_key_exists($parts[1], $transformed_expense)) {
$entity[$key] = $transformed_expense[$parts[1]];

View File

@ -20,6 +20,7 @@ use App\Libraries\MultiDB;
use App\Export\CSV\BaseExport;
use Illuminate\Support\Facades\App;
use App\Transformers\InvoiceTransformer;
use Illuminate\Contracts\Database\Eloquent\Builder;
class InvoiceExport extends BaseExport
{
@ -29,56 +30,6 @@ class InvoiceExport extends BaseExport
public Writer $csv;
public array $entity_keys = [
'amount' => 'amount',
'balance' => 'balance',
'client' => 'client_id',
'custom_surcharge1' => 'custom_surcharge1',
'custom_surcharge2' => 'custom_surcharge2',
'custom_surcharge3' => 'custom_surcharge3',
'custom_surcharge4' => 'custom_surcharge4',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'date' => 'date',
'discount' => 'discount',
'due_date' => 'due_date',
'exchange_rate' => 'exchange_rate',
'footer' => 'footer',
'number' => 'number',
'paid_to_date' => 'paid_to_date',
'partial' => 'partial',
'partial_due_date' => 'partial_due_date',
'po_number' => 'po_number',
'private_notes' => 'private_notes',
'public_notes' => 'public_notes',
'status' => 'status_id',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'terms' => 'terms',
'total_taxes' => 'total_taxes',
'currency_id' => 'currency_id',
'payment_number' => 'payment_number',
'payment_date' => 'payment_date',
'payment_amount' => 'payment_amount',
'method' => 'method',
];
private array $decorate_keys = [
'country',
'client',
'currency_id',
'status',
'vendor',
'project',
];
public function __construct(Company $company, array $input)
{
$this->company = $company;
@ -86,24 +37,19 @@ class InvoiceExport extends BaseExport
$this->invoice_transformer = new InvoiceTransformer();
}
public function run()
public function init(): Builder
{
MultiDB::setDb($this->company->db);
App::forgetInstance('translator');
App::setLocale($this->company->locale());
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
$this->input['report_keys'] = array_values($this->invoice_report_keys);
}
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Invoice::query()
->withTrashed()
->with('client')
@ -112,10 +58,43 @@ class InvoiceExport extends BaseExport
$query = $this->addDateRange($query);
if(isset($this->input['status'])){
if(isset($this->input['status'])) {
$query = $this->addInvoiceStatusFilter($query, $this->input['status']);
}
return $query;
}
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $value, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($resource) {
return $this->buildRow($resource);
})->toArray();
return array_merge(['columns' => $header], $report);
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor()
->each(function ($invoice) {
$this->csv->insertOne($this->buildRow($invoice));
@ -131,24 +110,15 @@ class InvoiceExport extends BaseExport
$entity = [];
foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
if(!$keyval) {
$keyval = array_search(str_replace("invoice.", "", $key), $this->entity_keys) ?? $key;
$parts = explode('.', $key);
if (is_array($parts) && $parts[0] == 'invoice' && array_key_exists($parts[1], $transformed_invoice)) {
$entity[$key] = $transformed_invoice[$parts[1]];
} else {
$entity[$key] = $this->resolveKey($key, $invoice, $this->invoice_transformer);
}
if(!$keyval) {
$keyval = $key;
}
if (array_key_exists($key, $transformed_invoice)) {
$entity[$keyval] = $transformed_invoice[$key];
} elseif (array_key_exists($keyval, $transformed_invoice)) {
$entity[$keyval] = $transformed_invoice[$keyval];
}
else {
$entity[$keyval] = $this->resolveKey($keyval, $invoice, $this->invoice_transformer);
}
}
return $this->decorateAdvancedFields($invoice, $entity);
@ -156,31 +126,22 @@ class InvoiceExport extends BaseExport
private function decorateAdvancedFields(Invoice $invoice, array $entity) :array
{
if (in_array('country_id', $this->input['report_keys'])) {
$entity['country'] = $invoice->client->country ? ctrans("texts.country_{$invoice->client->country->name}") : '';
}
if (in_array('currency_id', $this->input['report_keys'])) {
$entity['currency_id'] = $invoice->client->currency() ? $invoice->client->currency()->code : $invoice->company->currency()->code;
}
if (in_array('client_id', $this->input['report_keys'])) {
$entity['client'] = $invoice->client->present()->name();
}
if (in_array('status_id', $this->input['report_keys'])) {
$entity['status'] = $invoice->stringStatus($invoice->status_id);
}
// $payment_exists = $invoice->payments()->exists();
if (in_array('invoice.country_id', $this->input['report_keys'])) {
$entity['invoice.country_id'] = $invoice->client->country ? ctrans("texts.country_{$invoice->client->country->name}") : '';
}
// $entity['payment_number'] = $payment_exists ? $invoice->payments()->pluck('number')->implode(',') : '';
if (in_array('invoice.currency_id', $this->input['report_keys'])) {
$entity['invoice.currency_id'] = $invoice->client->currency() ? $invoice->client->currency()->code : $invoice->company->currency()->code;
}
// $entity['payment_date'] = $payment_exists ? $invoice->payments()->pluck('date')->implode(',') : '';
if (in_array('invoice.client_id', $this->input['report_keys'])) {
$entity['invoice.client_id'] = $invoice->client->present()->name();
}
// $entity['payment_amount'] = $payment_exists ? Number::formatMoney($invoice->payments()->sum('paymentables.amount'), $invoice->company) : ctrans('texts.unpaid');
// $entity['method'] = $payment_exists ? $invoice->payments()->first()->translatedType() : "";
if (in_array('invoice.status', $this->input['report_keys'])) {
$entity['invoice.status'] = $invoice->stringStatus($invoice->status_id);
}
return $entity;
}

View File

@ -12,11 +12,11 @@
namespace App\Export\CSV;
use App\Libraries\MultiDB;
use App\Models\Client;
use App\Models\Company;
use App\Models\Invoice;
use App\Transformers\InvoiceTransformer;
use App\Utils\Ninja;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App;
use League\Csv\Writer;
@ -31,64 +31,7 @@ class InvoiceItemExport extends BaseExport
private bool $force_keys = false;
public array $entity_keys = [
'amount' => 'amount',
'balance' => 'balance',
'client' => 'client_id',
'client_number' => 'client.number',
'client_id_number' => 'client.id_number',
'custom_surcharge1' => 'custom_surcharge1',
'custom_surcharge2' => 'custom_surcharge2',
'custom_surcharge3' => 'custom_surcharge3',
'custom_surcharge4' => 'custom_surcharge4',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'date' => 'date',
'discount' => 'discount',
'due_date' => 'due_date',
'exchange_rate' => 'exchange_rate',
'footer' => 'footer',
'number' => 'number',
'paid_to_date' => 'paid_to_date',
'partial' => 'partial',
'partial_due_date' => 'partial_due_date',
'po_number' => 'po_number',
'private_notes' => 'private_notes',
'public_notes' => 'public_notes',
'status' => 'status_id',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'terms' => 'terms',
'total_taxes' => 'total_taxes',
'currency' => 'currency_id',
'quantity' => 'item.quantity',
'cost' => 'item.cost',
'product_key' => 'item.product_key',
'buy_price' => 'item.product_cost',
'notes' => 'item.notes',
'discount' => 'item.discount',
'is_amount_discount' => 'item.is_amount_discount',
'tax_rate1' => 'item.tax_rate1',
'tax_rate2' => 'item.tax_rate2',
'tax_rate3' => 'item.tax_rate3',
'tax_name1' => 'item.tax_name1',
'tax_name2' => 'item.tax_name2',
'tax_name3' => 'item.tax_name3',
'line_total' => 'item.line_total',
'gross_line_total' => 'item.gross_line_total',
'invoice1' => 'item.custom_value1',
'invoice2' => 'item.custom_value2',
'invoice3' => 'item.custom_value3',
'invoice4' => 'item.custom_value4',
'tax_category' => 'item.tax_id',
'type' => 'item.type_id',
];
private array $storage_array = [];
private array $decorate_keys = [
'client',
@ -103,25 +46,20 @@ class InvoiceItemExport extends BaseExport
$this->invoice_transformer = new InvoiceTransformer();
}
public function run()
public function init(): Builder
{
MultiDB::setDb($this->company->db);
App::forgetInstance('translator');
App::setLocale($this->company->locale());
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) {
$this->force_keys = true;
$this->input['report_keys'] = array_values($this->entity_keys);
$this->input['report_keys'] = array_values($this->mergeItemsKeys('invoice_report_keys'));
}
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Invoice::query()
->withTrashed()
->with('client')->where('company_id', $this->company->id)
@ -129,11 +67,46 @@ class InvoiceItemExport extends BaseExport
$query = $this->addDateRange($query);
return $query;
}
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $value, 'display_value' => $headerdisplay[$value]];
})->toArray();
$query->cursor()
->each(function ($resource) {
$this->iterateItems($resource);
});
return array_merge(['columns' => $header], $this->storage_array);
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor()
->each(function ($invoice) {
$this->iterateItems($invoice);
});
$this->csv->insertAll($this->storage_array);
return $this->csv->toString();
}
@ -146,46 +119,32 @@ class InvoiceItemExport extends BaseExport
foreach ($invoice->line_items as $item) {
$item_array = [];
foreach (array_values($this->input['report_keys']) as $key) { //items iterator produces item array
foreach (array_values(array_intersect($this->input['report_keys'], $this->item_report_keys)) as $key) { //items iterator produces item array
if (str_contains($key, "item.")) {
$key = str_replace("item.", "", $key);
$keyval = $key;
$keyval = str_replace("custom_value", "invoice", $key);
if($key == 'type_id')
$keyval = 'type';
$key = 'type';
if($key == 'tax_id')
$keyval = 'tax_category';
$key = 'tax_category';
if (property_exists($item, $key)) {
$item_array[$keyval] = $item->{$key};
} else {
$item_array[$keyval] = '';
$item_array[$key] = $item->{$key};
}
else {
$item_array[$key] = '';
}
}
}
$entity = [];
foreach (array_values($this->input['report_keys']) as $key) { //create an array of report keys only
$keyval = array_search($key, $this->entity_keys);
if (array_key_exists($key, $transformed_items)) {
$entity[$keyval] = $transformed_items[$key];
} else {
$entity[$keyval] = "";
}
}
$transformed_items = array_merge($transformed_invoice, $item_array);
$entity = $this->decorateAdvancedFields($invoice, $transformed_items);
$this->csv->insertOne($entity);
$this->storage_array[] = $entity;
}
}
@ -196,23 +155,19 @@ class InvoiceItemExport extends BaseExport
$entity = [];
foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
$parts = explode('.', $key);
if(!$keyval) {
$keyval = array_search(str_replace("invoice.", "", $key), $this->entity_keys) ?? $key;
}
if(is_array($parts) && $parts[0] == 'item')
continue;
if(!$keyval) {
$keyval = $key;
}
if (array_key_exists($key, $transformed_invoice)) {
$entity[$keyval] = $transformed_invoice[$key];
} elseif (array_key_exists($keyval, $transformed_invoice)) {
$entity[$keyval] = $transformed_invoice[$keyval];
}
else {
$entity[$keyval] = $this->resolveKey($keyval, $invoice, $this->invoice_transformer);
if (is_array($parts) && $parts[0] == 'invoice' && array_key_exists($parts[1], $transformed_invoice)) {
$entity[$key] = $transformed_invoice[$parts[1]];
}else if (array_key_exists($key, $transformed_invoice)) {
$entity[$key] = $transformed_invoice[$key];
}
else {
$entity[$key] = $this->resolveKey($key, $invoice, $this->invoice_transformer);
}
}
@ -233,12 +188,12 @@ class InvoiceItemExport extends BaseExport
$entity['tax_category'] = $invoice->taxTypeString($entity['tax_category']);
}
if($this->force_keys) {
$entity['client'] = $invoice->client->present()->name();
$entity['client_id_number'] = $invoice->client->id_number;
$entity['client_number'] = $invoice->client->number;
$entity['status'] = $invoice->stringStatus($invoice->status_id);
}
// if($this->force_keys) {
// $entity['client'] = $invoice->client->present()->name();
// $entity['client_id_number'] = $invoice->client->id_number;
// $entity['client_number'] = $invoice->client->number;
// $entity['status'] = $invoice->stringStatus($invoice->status_id);
// }
return $entity;
}

View File

@ -16,6 +16,7 @@ use App\Models\Company;
use App\Models\Payment;
use App\Transformers\PaymentTransformer;
use App\Utils\Ninja;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App;
use League\Csv\Writer;
@ -27,39 +28,39 @@ class PaymentExport extends BaseExport
public Writer $csv;
public array $entity_keys = [
'amount' => 'amount',
'applied' => 'applied',
'client' => 'client_id',
'currency' => 'currency_id',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'date' => 'date',
'exchange_currency' => 'exchange_currency_id',
'gateway' => 'gateway_type_id',
'number' => 'number',
'private_notes' => 'private_notes',
'project' => 'project_id',
'refunded' => 'refunded',
'status' => 'status_id',
'transaction_reference' => 'transaction_reference',
'type' => 'type_id',
'vendor' => 'vendor_id',
'invoices' => 'invoices',
];
// public array $entity_keys = [
// 'amount' => 'amount',
// 'applied' => 'applied',
// 'client' => 'client_id',
// 'currency' => 'currency_id',
// 'custom_value1' => 'custom_value1',
// 'custom_value2' => 'custom_value2',
// 'custom_value3' => 'custom_value3',
// 'custom_value4' => 'custom_value4',
// 'date' => 'date',
// 'exchange_currency' => 'exchange_currency_id',
// 'gateway' => 'gateway_type_id',
// 'number' => 'number',
// 'private_notes' => 'private_notes',
// 'project' => 'project_id',
// 'refunded' => 'refunded',
// 'status' => 'status_id',
// 'transaction_reference' => 'transaction_reference',
// 'type' => 'type_id',
// 'vendor' => 'vendor_id',
// 'invoices' => 'invoices',
// ];
private array $decorate_keys = [
'vendor',
'status',
'project',
'client',
'currency',
'exchange_currency',
'type',
'invoices',
];
// private array $decorate_keys = [
// 'vendor',
// 'status',
// 'project',
// 'client',
// 'currency',
// 'exchange_currency',
// 'type',
// 'invoices',
// ];
public function __construct(Company $company, array $input)
{
@ -68,24 +69,19 @@ class PaymentExport extends BaseExport
$this->entity_transformer = new PaymentTransformer();
}
public function run()
private function init(): Builder
{
MultiDB::setDb($this->company->db);
App::forgetInstance('translator');
App::setLocale($this->company->locale());
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
$this->input['report_keys'] = array_values($this->payment_report_keys);
}
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Payment::query()
->withTrashed()
->where('company_id', $this->company->id)
@ -93,6 +89,39 @@ class PaymentExport extends BaseExport
$query = $this->addDateRange($query);
return $query;
}
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) {
return ['identifier' => $value, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($resource) {
return $this->buildRow($resource);
})->toArray();
return array_merge(['columns' => $header], $report);
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor()
->each(function ($entity) {
$this->csv->insertOne($this->buildRow($entity));
@ -108,24 +137,17 @@ class PaymentExport extends BaseExport
$entity = [];
foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
$parts = explode('.', $key);
if(!$keyval) {
$keyval = array_search(str_replace("payment.", "", $key), $this->entity_keys) ?? $key;
if (is_array($parts) && $parts[0] == 'payment' && array_key_exists($parts[1], $transformed_entity)) {
$entity[$key] = $transformed_entity[$parts[1]];
} elseif (array_key_exists($key, $transformed_entity)) {
$entity[$key] = $transformed_entity[$key];
} else {
$entity[$key] = $this->resolveKey($key, $payment, $this->entity_transformer);
}
if(!$keyval) {
$keyval = $key;
}
if (array_key_exists($key, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$key];
} elseif (array_key_exists($keyval, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$keyval];
}
else {
$entity[$keyval] = $this->resolveKey($keyval, $payment, $this->entity_transformer);
}
}
return $this->decorateAdvancedFields($payment, $entity);

View File

@ -17,6 +17,7 @@ use App\Models\Document;
use App\Models\Product;
use App\Transformers\ProductTransformer;
use App\Utils\Ninja;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App;
use League\Csv\Writer;
@ -28,31 +29,6 @@ class ProductExport extends BaseExport
public Writer $csv;
public array $entity_keys = [
'project' => 'project_id',
'vendor' => 'vendor_id',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'product_key' => 'product_key',
'notes' => 'notes',
'cost' => 'cost',
'price' => 'price',
'quantity' => 'quantity',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
];
private array $decorate_keys = [
'vendor',
'project',
];
public function __construct(Company $company, array $input)
{
$this->company = $company;
@ -60,24 +36,37 @@ class ProductExport extends BaseExport
$this->entity_transformer = new ProductTransformer();
}
public function run()
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $value, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($resource) {
return $this->buildRow($resource);
})->toArray();
return array_merge(['columns' => $header], $report);
}
private function init(): Builder
{
MultiDB::setDb($this->company->db);
App::forgetInstance('translator');
App::setLocale($this->company->locale());
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
$this->input['report_keys'] = array_values($this->product_report_keys);
}
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Product::query()
->withTrashed()
->where('company_id', $this->company->id)
@ -85,6 +74,21 @@ class ProductExport extends BaseExport
$query = $this->addDateRange($query);
return $query;
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor()
->each(function ($entity) {
$this->csv->insertOne($this->buildRow($entity));
@ -100,7 +104,7 @@ class ProductExport extends BaseExport
$entity = [];
foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
$keyval = array_search($key, $this->product_report_keys);
if (array_key_exists($key, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$key];

View File

@ -11,14 +11,15 @@
namespace App\Export\CSV;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\PurchaseOrder;
use App\Transformers\PurchaseOrderTransformer;
use App\Utils\Ninja;
use App\Utils\Number;
use Illuminate\Support\Facades\App;
use League\Csv\Writer;
use App\Models\Company;
use App\Libraries\MultiDB;
use App\Models\PurchaseOrder;
use Illuminate\Support\Facades\App;
use App\Transformers\PurchaseOrderTransformer;
use Illuminate\Contracts\Database\Eloquent\Builder;
class PurchaseOrderExport extends BaseExport
{
@ -81,24 +82,19 @@ class PurchaseOrderExport extends BaseExport
$this->purchase_order_transformer = new PurchaseOrderTransformer();
}
public function run()
public function init(): Builder
{
MultiDB::setDb($this->company->db);
App::forgetInstance('translator');
App::setLocale($this->company->locale());
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
$this->input['report_keys'] = array_values($this->purchase_order_report_keys);
}
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = PurchaseOrder::query()
->withTrashed()
->with('vendor')
@ -107,9 +103,38 @@ class PurchaseOrderExport extends BaseExport
$query = $this->addDateRange($query);
// if(isset($this->input['status'])) {
// $query = $this->addPurchaseOrderStatusFilter($query, $this->input['status']);
// }
return $query;
}
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $value, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($resource) {
return $this->buildRow($resource);
})->toArray();
return array_merge(['columns' => $header], $report);
}
public function run()
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor()
->each(function ($purchase_order) {
@ -126,23 +151,16 @@ class PurchaseOrderExport extends BaseExport
$entity = [];
foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
if(!$keyval) {
$keyval = array_search(str_replace("purchase_order.", "", $key), $this->entity_keys) ?? $key;
}
$parts = explode('.', $key);
if(!$keyval) {
$keyval = $key;
}
if (array_key_exists($key, $transformed_purchase_order)) {
$entity[$keyval] = $transformed_purchase_order[$key];
} elseif (array_key_exists($keyval, $transformed_purchase_order)) {
$entity[$keyval] = $transformed_purchase_order[$keyval];
if (is_array($parts) && $parts[0] == 'purchase_order' && array_key_exists($parts[1], $transformed_purchase_order)) {
$entity[$key] = $transformed_purchase_order[$parts[1]];
} else {
$entity[$keyval] = $this->resolveKey($keyval, $purchase_order, $this->purchase_order_transformer);
$entity[$key] = $this->resolveKey($key, $purchase_order, $this->purchase_order_transformer);
}
}
return $this->decorateAdvancedFields($purchase_order, $entity);

View File

@ -16,6 +16,7 @@ use App\Models\Company;
use App\Models\PurchaseOrder;
use App\Transformers\PurchaseOrderTransformer;
use App\Utils\Ninja;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App;
use League\Csv\Writer;
@ -30,70 +31,7 @@ class PurchaseOrderItemExport extends BaseExport
private bool $force_keys = false;
public array $entity_keys = [
'amount' => 'amount',
'balance' => 'balance',
'vendor' => 'vendor_id',
'vendor_number' => 'vendor.number',
'vendor_id_number' => 'vendor.id_number',
// 'custom_surcharge1' => 'custom_surcharge1',
// 'custom_surcharge2' => 'custom_surcharge2',
// 'custom_surcharge3' => 'custom_surcharge3',
// 'custom_surcharge4' => 'custom_surcharge4',
// 'custom_value1' => 'custom_value1',
// 'custom_value2' => 'custom_value2',
// 'custom_value3' => 'custom_value3',
// 'custom_value4' => 'custom_value4',
'date' => 'date',
'discount' => 'discount',
'due_date' => 'due_date',
'exchange_rate' => 'exchange_rate',
'footer' => 'footer',
'number' => 'number',
'paid_to_date' => 'paid_to_date',
'partial' => 'partial',
'partial_due_date' => 'partial_due_date',
'po_number' => 'po_number',
'private_notes' => 'private_notes',
'public_notes' => 'public_notes',
'status' => 'status_id',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'terms' => 'terms',
'total_taxes' => 'total_taxes',
'currency' => 'currency_id',
'quantity' => 'item.quantity',
'cost' => 'item.cost',
'product_key' => 'item.product_key',
'buy_price' => 'item.product_cost',
'notes' => 'item.notes',
'discount' => 'item.discount',
'is_amount_discount' => 'item.is_amount_discount',
'tax_rate1' => 'item.tax_rate1',
'tax_rate2' => 'item.tax_rate2',
'tax_rate3' => 'item.tax_rate3',
'tax_name1' => 'item.tax_name1',
'tax_name2' => 'item.tax_name2',
'tax_name3' => 'item.tax_name3',
'line_total' => 'item.line_total',
'gross_line_total' => 'item.gross_line_total',
'purchase_order1' => 'item.custom_value1',
'purchase_order2' => 'item.custom_value2',
'purchase_order3' => 'item.custom_value3',
'purchase_order4' => 'item.custom_value4',
'tax_category' => 'item.tax_id',
'type' => 'item.type_id',
];
private array $decorate_keys = [
'client',
'currency_id',
'status'
];
private array $storage_array = [];
public function __construct(Company $company, array $input)
{
@ -102,25 +40,20 @@ class PurchaseOrderItemExport extends BaseExport
$this->purchase_order_transformer = new PurchaseOrderTransformer();
}
public function run()
private function init(): Builder
{
MultiDB::setDb($this->company->db);
App::forgetInstance('translator');
App::setLocale($this->company->locale());
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) {
$this->force_keys = true;
$this->input['report_keys'] = array_values($this->entity_keys);
// $this->force_keys = true;
$this->input['report_keys'] = array_values($this->mergeItemsKeys('purchase_order_report_keys'));
}
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = PurchaseOrder::query()
->withTrashed()
->with('vendor')->where('company_id', $this->company->id)
@ -128,12 +61,47 @@ class PurchaseOrderItemExport extends BaseExport
$query = $this->addDateRange($query);
return $query;
}
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $value, 'display_value' => $headerdisplay[$value]];
})->toArray();
$query->cursor()
->each(function ($resource) {
$this->iterateItems($resource);
});
return array_merge(['columns' => $header], $this->storage_array);
}
public function run()
{
//load the CSV document from a string
$this->csv = Writer::createFromString();
$query = $this->init();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor()
->each(function ($purchase_order) {
$this->iterateItems($purchase_order);
});
$this->csv->insertAll($this->storage_array);
return $this->csv->toString();
}
private function iterateItems(PurchaseOrder $purchase_order)
@ -141,7 +109,7 @@ class PurchaseOrderItemExport extends BaseExport
$transformed_purchase_order = $this->buildRow($purchase_order);
$transformed_items = [];
nlog($purchase_order->toArray());
foreach ($purchase_order->line_items as $item) {
$item_array = [];
@ -151,10 +119,6 @@ class PurchaseOrderItemExport extends BaseExport
$key = str_replace("item.", "", $key);
$keyval = $key;
$keyval = str_replace("custom_value", "purchase_order", $key);
if($key == 'type_id') {
$keyval = 'type';
}
@ -164,29 +128,17 @@ class PurchaseOrderItemExport extends BaseExport
}
if (property_exists($item, $key)) {
$item_array[$keyval] = $item->{$key};
$item_array[$key] = $item->{$key};
} else {
$item_array[$keyval] = '';
$item_array[$key] = '';
}
}
}
$entity = [];
foreach (array_values($this->input['report_keys']) as $key) { //create an array of report keys only
$keyval = array_search($key, $this->entity_keys);
if (array_key_exists($key, $transformed_items)) {
$entity[$keyval] = $transformed_items[$key];
} else {
$entity[$keyval] = "";
}
}
$transformed_items = array_merge($transformed_purchase_order, $item_array);
$entity = $this->decorateAdvancedFields($purchase_order, $transformed_items);
$this->csv->insertOne($entity);
$this->storage_array[] = $entity;
}
}
@ -197,22 +149,18 @@ class PurchaseOrderItemExport extends BaseExport
$entity = [];
foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
$parts = explode('.', $key);
if(!$keyval) {
$keyval = array_search(str_replace("purchase_order.", "", $key), $this->entity_keys) ?? $key;
if(is_array($parts) && $parts[0] == 'item') {
continue;
}
if(!$keyval) {
$keyval = $key;
}
if (array_key_exists($key, $transformed_purchase_order)) {
$entity[$keyval] = $transformed_purchase_order[$key];
} elseif (array_key_exists($keyval, $transformed_purchase_order)) {
$entity[$keyval] = $transformed_purchase_order[$keyval];
if (is_array($parts) && $parts[0] == 'purchase_order' && array_key_exists($parts[1], $transformed_purchase_order)) {
$entity[$key] = $transformed_purchase_order[$parts[1]];
} elseif (array_key_exists($key, $transformed_purchase_order)) {
$entity[$key] = $transformed_purchase_order[$key];
} else {
$entity[$keyval] = $this->resolveKey($keyval, $purchase_order, $this->purchase_order_transformer);
$entity[$key] = $this->resolveKey($key, $purchase_order, $this->purchase_order_transformer);
}
}

View File

@ -16,6 +16,7 @@ use App\Models\Company;
use App\Models\Quote;
use App\Transformers\QuoteTransformer;
use App\Utils\Ninja;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App;
use League\Csv\Writer;
@ -28,43 +29,6 @@ class QuoteExport extends BaseExport
public Writer $csv;
public array $entity_keys = [
'amount' => 'amount',
'balance' => 'balance',
'client' => 'client_id',
'custom_surcharge1' => 'custom_surcharge1',
'custom_surcharge2' => 'custom_surcharge2',
'custom_surcharge3' => 'custom_surcharge3',
'custom_surcharge4' => 'custom_surcharge4',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'date' => 'date',
'discount' => 'discount',
'valid_until' => 'due_date',
'exchange_rate' => 'exchange_rate',
'footer' => 'footer',
'number' => 'number',
'paid_to_date' => 'paid_to_date',
'partial' => 'partial',
'partial_due_date' => 'partial_due_date',
'po_number' => 'po_number',
'private_notes' => 'private_notes',
'public_notes' => 'public_notes',
'status' => 'status_id',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'terms' => 'terms',
'total_taxes' => 'total_taxes',
'currency' => 'currency_id',
'invoice' => 'invoice_id',
];
private array $decorate_keys = [
'client',
'currency',
@ -78,24 +42,20 @@ class QuoteExport extends BaseExport
$this->quote_transformer = new QuoteTransformer();
}
public function run()
private function init(): Builder
{
MultiDB::setDb($this->company->db);
App::forgetInstance('translator');
App::setLocale($this->company->locale());
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
$this->input['report_keys'] = array_values($this->quote_report_keys);
}
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Quote::query()
->withTrashed()
->with('client')
@ -104,6 +64,40 @@ class QuoteExport extends BaseExport
$query = $this->addDateRange($query);
return $query;
}
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use ($headerdisplay) {
return ['identifier' => $value, 'display_value' => $headerdisplay[$value]];
})->toArray();
$report = $query->cursor()
->map(function ($resource) {
return $this->buildRow($resource);
})->toArray();
return array_merge(['columns' => $header], $report);
}
public function run()
{
//load the CSV document from a string
$this->csv = Writer::createFromString();
$query = $this->init();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query->cursor()
->each(function ($quote) {
$this->csv->insertOne($this->buildRow($quote));
@ -114,50 +108,42 @@ class QuoteExport extends BaseExport
private function buildRow(Quote $quote) :array
{
$transformed_entity = $this->quote_transformer->transform($quote);
$transformed_invoice = $this->quote_transformer->transform($quote);
$entity = [];
foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
if(!$keyval) {
$keyval = array_search(str_replace("invoice.", "", $key), $this->entity_keys) ?? $key;
$parts = explode('.', $key);
if (is_array($parts) && $parts[0] == 'quote' && array_key_exists($parts[1], $transformed_invoice)) {
$entity[$key] = $transformed_invoice[$parts[1]];
} else {
$entity[$key] = $this->resolveKey($key, $quote, $this->quote_transformer);
}
if(!$keyval) {
$keyval = $key;
}
if (array_key_exists($key, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$key];
} elseif (array_key_exists($keyval, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$keyval];
}
else {
$entity[$keyval] = $this->resolveKey($keyval, $quote, $this->quote_transformer);
}
}
return $this->decorateAdvancedFields($quote, $entity);
}
private function decorateAdvancedFields(Quote $quote, array $entity) :array
{
if (in_array('currency_id', $this->input['report_keys'])) {
$entity['currency'] = $quote->client->currency()->code;
if (in_array('quote.currency_id', $this->input['report_keys'])) {
$entity['quote.currency'] = $quote->client->currency()->code;
}
if (in_array('client_id', $this->input['report_keys'])) {
$entity['client'] = $quote->client->present()->name();
if (in_array('quote.client_id', $this->input['report_keys'])) {
$entity['quote.client'] = $quote->client->present()->name();
}
if (in_array('status_id', $this->input['report_keys'])) {
$entity['status'] = $quote->stringStatus($quote->status_id);
if (in_array('quote.status', $this->input['report_keys'])) {
$entity['quote.status'] = $quote->stringStatus($quote->status_id);
}
if (in_array('invoice_id', $this->input['report_keys'])) {
$entity['invoice'] = $quote->invoice ? $quote->invoice->number : '';
if (in_array('quote.invoice_id', $this->input['report_keys'])) {
$entity['quote.invoice'] = $quote->invoice ? $quote->invoice->number : '';
}
return $entity;

View File

@ -16,6 +16,7 @@ use App\Models\Company;
use App\Models\Quote;
use App\Transformers\QuoteTransformer;
use App\Utils\Ninja;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App;
use League\Csv\Writer;
@ -28,63 +29,7 @@ class QuoteItemExport extends BaseExport
public Writer $csv;
public array $entity_keys = [
'amount' => 'amount',
'balance' => 'balance',
'client' => 'client_id',
'custom_surcharge1' => 'custom_surcharge1',
'custom_surcharge2' => 'custom_surcharge2',
'custom_surcharge3' => 'custom_surcharge3',
'custom_surcharge4' => 'custom_surcharge4',
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
'custom_value3' => 'custom_value3',
'custom_value4' => 'custom_value4',
'date' => 'date',
'discount' => 'discount',
'due_date' => 'due_date',
'exchange_rate' => 'exchange_rate',
'footer' => 'footer',
'number' => 'number',
'paid_to_date' => 'paid_to_date',
'partial' => 'partial',
'partial_due_date' => 'partial_due_date',
'po_number' => 'po_number',
'private_notes' => 'private_notes',
'public_notes' => 'public_notes',
'status' => 'status_id',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'terms' => 'terms',
'total_taxes' => 'total_taxes',
'currency' => 'currency_id',
'quantity' => 'item.quantity',
'cost' => 'item.cost',
'product_key' => 'item.product_key',
'buy_price' => 'item.product_cost',
'cost' => 'item.cost',
'notes' => 'item.notes',
'discount' => 'item.discount',
'is_amount_discount' => 'item.is_amount_discount',
'tax_rate1' => 'item.tax_rate1',
'tax_rate2' => 'item.tax_rate2',
'tax_rate3' => 'item.tax_rate3',
'tax_name1' => 'item.tax_name1',
'tax_name2' => 'item.tax_name2',
'tax_name3' => 'item.tax_name3',
'line_total' => 'item.line_total',
'gross_line_total' => 'item.gross_line_total',
'quote1' => 'item.custom_value1',
'quote2' => 'item.custom_value2',
'quote3' => 'item.custom_value3',
'quote4' => 'item.custom_value4',
'tax_category' => 'item.tax_id',
'type' => 'item.type_id',
];
private array $storage_array;
private array $decorate_keys = [
'client',
@ -98,37 +43,70 @@ class QuoteItemExport extends BaseExport
$this->quote_transformer = new QuoteTransformer();
}
public function run()
public function init(): Builder
{
MultiDB::setDb($this->company->db);
App::forgetInstance('translator');
App::setLocale($this->company->locale());
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->mergeItemsKeys('quote_report_keys'));
}
$query = Quote::query()
->withTrashed()
->with('client')->where('company_id', $this->company->id)
->where('is_deleted', 0);
$query = $this->addDateRange($query);
return $query;
}
public function returnJson()
{
$query = $this->init();
$headerdisplay = $this->buildHeader();
$header = collect($this->input['report_keys'])->map(function ($key, $value) use($headerdisplay){
return ['identifier' => $value, 'display_value' => $headerdisplay[$value]];
})->toArray();
$query->cursor()
->each(function ($resource) {
$this->iterateItems($resource);
});
return array_merge(['columns' => $header], $this->storage_array);
}
public function run()
{
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
}
$query = $this->init();
//insert the header
$this->csv->insertOne($this->buildHeader());
$query = Quote::query()
->withTrashed()
->with('client')->where('company_id', $this->company->id)
->where('is_deleted', 0);
$query = $this->addDateRange($query);
$query->cursor()
->each(function ($quote) {
$this->iterateItems($quote);
});
$this->csv->insertAll($this->storage_array);
return $this->csv->toString();
}
private function iterateItems(Quote $quote)
@ -137,51 +115,34 @@ class QuoteItemExport extends BaseExport
$transformed_items = [];
$transformed_items = [];
foreach ($quote->line_items as $item) {
$item_array = [];
foreach (array_values($this->input['report_keys']) as $key) { //items iterator produces item array
foreach (array_values(array_intersect($this->input['report_keys'], $this->item_report_keys)) as $key) { //items iterator produces item array
if (str_contains($key, "item.")) {
$key = str_replace("item.", "", $key);
$keyval = $key;
$keyval = str_replace("custom_value", "quote", $key);
if($key == 'type_id')
$keyval = 'type';
$key = 'type';
if($key == 'tax_id')
$keyval = 'tax_category';
$key = 'tax_category';
if (property_exists($item, $key)) {
$item_array[$keyval] = $item->{$key};
} else {
$item_array[$keyval] = '';
$item_array[$key] = $item->{$key};
}
else {
$item_array[$key] = '';
}
}
}
$entity = [];
foreach (array_values($this->input['report_keys']) as $key) { //create an array of report keys only
$keyval = array_search($key, $this->entity_keys);
if (array_key_exists($key, $transformed_items)) {
$entity[$keyval] = $transformed_items[$key];
} else {
$entity[$keyval] = "";
}
}
$transformed_items = array_merge($transformed_quote, $item_array);
$entity = $this->decorateAdvancedFields($quote, $transformed_items);
$this->csv->insertOne($entity);
$this->storage_array[] = $entity;
}
}
@ -192,26 +153,23 @@ class QuoteItemExport extends BaseExport
$entity = [];
foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
$parts = explode('.', $key);
if(!$keyval) {
$keyval = array_search(str_replace("quote.", "", $key), $this->entity_keys) ?? $key;
if(is_array($parts) && $parts[0] == 'item') {
continue;
}
if(!$keyval) {
$keyval = $key;
}
if (array_key_exists($key, $transformed_quote)) {
$entity[$keyval] = $transformed_quote[$key];
} elseif (array_key_exists($keyval, $transformed_quote)) {
$entity[$keyval] = $transformed_quote[$keyval];
}
else {
$entity[$keyval] = $this->resolveKey($keyval, $quote, $this->quote_transformer);
if (is_array($parts) && $parts[0] == 'quote' && array_key_exists($parts[1], $transformed_quote)) {
$entity[$key] = $transformed_quote[$parts[1]];
} elseif (array_key_exists($key, $transformed_quote)) {
$entity[$key] = $transformed_quote[$key];
} else {
$entity[$key] = $this->resolveKey($key, $quote, $this->quote_transformer);
}
}
return $this->decorateAdvancedFields($quote, $entity);
}
private function decorateAdvancedFields(Quote $quote, array $entity) :array

View File

@ -67,10 +67,6 @@ class VendorExport extends BaseExport
'vendor.currency',
];
public array $forced_keys = [
// 'vendor.status'
];
public function __construct(Company $company, array $input)
{
$this->company = $company;

View File

@ -298,7 +298,7 @@ abstract class QueryFilters
{
return $this->builder->where(function ($query) {
$query->whereHas('client', function ($sub_query) {
$sub_query->where('is_deleted', 0);
$sub_query->where('is_deleted', 0)->where('deleted_at', null);
})->orWhere('client_id', null);
});
}
@ -310,7 +310,7 @@ abstract class QueryFilters
{
return $this->builder->where(function ($query) {
$query->whereHas('vendor', function ($sub_query) {
$sub_query->where('is_deleted', 0);
$sub_query->where('is_deleted', 0)->where('deleted_at', null);
})->orWhere('vendor_id', null);
});
}

View File

@ -72,7 +72,7 @@ class AccountController extends BaseController
MultiDB::findAndSetDbByAccountKey($account->key);
$cu = CompanyUser::where('user_id', $account->users()->first()->id);
$cu = CompanyUser::query()->where('user_id', $account->users()->first()->id);
$company_user = $cu->first();

View File

@ -71,15 +71,21 @@ class BankTransactionController extends BaseController
public function create(CreateBankTransactionRequest $request)
{
$bank_transaction = BankTransactionFactory::create(auth()->user()->company()->id, auth()->user()->id);
/** @var \App\Models\User $user */
$user = auth()->user();
$bank_transaction = BankTransactionFactory::create($user->company()->id, $user->id);
return $this->itemResponse($bank_transaction);
}
public function store(StoreBankTransactionRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
//stub to store the model
$bank_transaction = $this->bank_transaction_repo->save($request->all(), BankTransactionFactory::create(auth()->user()->company()->id, auth()->user()->id));
$bank_transaction = $this->bank_transaction_repo->save($request->all(), BankTransactionFactory::create($user->company()->id, $user->id));
return $this->itemResponse($bank_transaction);
}

View File

@ -0,0 +1,70 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Controllers;
use App\Http\Requests\Email\ClientEmailHistoryRequest;
use App\Http\Requests\Email\EntityEmailHistoryRequest;
use App\Models\Client;
use App\Models\SystemLog;
use App\Utils\Traits\MakesHash;
class EmailHistoryController extends BaseController
{
use MakesHash;
public function __construct()
{
}
public function clientHistory(ClientEmailHistoryRequest $request, Client $client)
{
$data = SystemLog::where('client_id', $client->id)
->where('category_id', SystemLog::CATEGORY_MAIL)
->orderBy('id', 'DESC')
->cursor()
->map(function ($system_log) {
if($system_log->log['history'] ?? false) {
return $system_log->log['history'];
// return json_decode($system_log->log['history'], true);
}
});
return response()->json($data, 200);
}
/**
* May need to expand on this using
* just the message-id and search for the
* entity in the invitations
*/
public function entityHistory(EntityEmailHistoryRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
$data = SystemLog::where('company_id', $user->company()->id)
->where('category_id', SystemLog::CATEGORY_MAIL)
->whereJsonContains('log->history->entity_id', $this->encodePrimaryKey($request->entity_id))
->orderBy('id', 'DESC')
->cursor()
->map(function ($system_log) {
if($system_log->log['history'] ?? false) {
return $system_log->log['history'];
// return json_decode($system_log->log['history'], true);
}
});
return response()->json($data, 200);
}
}

View File

@ -139,7 +139,9 @@ class GroupSettingController extends BaseController
*/
public function update(UpdateGroupSettingRequest $request, GroupSetting $group_setting)
{
$group_setting = $this->group_setting_repo->save($request->all(), $group_setting);
/** Need this to prevent settings from being overwritten */
if(!$request->file('company_logo'))
$group_setting = $this->group_setting_repo->save($request->all(), $group_setting);
$this->uploadLogo($request->file('company_logo'), $group_setting->company, $group_setting);

View File

@ -14,6 +14,7 @@ namespace App\Http\Controllers\Reports;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Export\CSV\ActivityExport;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest;
@ -31,14 +32,27 @@ class ActivityReportController extends BaseController
public function __invoke(GenericReportRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), ActivityExport::class, $this->filename);
SendToAdmin::dispatch($user->company(), $request->all(), ActivityExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200);
}
// expect a list of visible fields, or use the default
$export = new ActivityExport(auth()->user()->company(), $request->all());
if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), ActivityExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new ActivityExport($user->company(), $request->all());
$csv = $export->run();

View File

@ -11,12 +11,13 @@
namespace App\Http\Controllers\Reports;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Export\CSV\ContactExport;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class ClientContactReportController extends BaseController
{
@ -62,13 +63,29 @@ class ClientContactReportController extends BaseController
*/
public function __invoke(GenericReportRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), ContactExport::class, $this->filename);
SendToAdmin::dispatch($user->company(), $request->all(), ContactExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200);
}
// expect a list of visible fields, or use the default
$export = new ContactExport(auth()->user()->company(), $request->all());
if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), ContactExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
// expect a list of visible fields, or use the default
$export = new ContactExport($user->company(), $request->all());
$csv = $export->run();

View File

@ -11,13 +11,14 @@
namespace App\Http\Controllers\Reports;
use App\Models\Client;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Export\CSV\ClientExport;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Models\Client;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class ClientReportController extends BaseController
{
@ -63,14 +64,26 @@ class ClientReportController extends BaseController
*/
public function __invoke(GenericReportRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), ClientExport::class, $this->filename);
SendToAdmin::dispatch($user->company(), $request->all(), ClientExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200);
}
// expect a list of visible fields, or use the default
$export = new ClientExport(auth()->user()->company(), $request->all());
// expect a list of visible fields, or use the default
if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), ClientExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new ClientExport($user->company(), $request->all());
$csv = $export->run();

View File

@ -11,13 +11,14 @@
namespace App\Http\Controllers\Reports;
use App\Models\Client;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Export\CSV\ExpenseExport;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Models\Client;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class ExpenseReportController extends BaseController
{
@ -63,14 +64,27 @@ class ExpenseReportController extends BaseController
*/
public function __invoke(GenericReportRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), ExpenseExport::class, $this->filename);
SendToAdmin::dispatch($user->company(), $request->all(), ExpenseExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200);
}
// expect a list of visible fields, or use the default
$export = new ExpenseExport(auth()->user()->company(), $request->all());
if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), ExpenseExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new ExpenseExport($user->company(), $request->all());
$csv = $export->run();

View File

@ -11,12 +11,13 @@
namespace App\Http\Controllers\Reports;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Export\CSV\InvoiceItemExport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class InvoiceItemReportController extends BaseController
{
@ -62,14 +63,26 @@ class InvoiceItemReportController extends BaseController
*/
public function __invoke(GenericReportRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), InvoiceItemExport::class, $this->filename);
SendToAdmin::dispatch($user->company(), $request->all(), InvoiceItemExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200);
}
// expect a list of visible fields, or use the default
$export = new InvoiceItemExport(auth()->user()->company(), $request->all());
if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), InvoiceItemExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new InvoiceItemExport($user->company(), $request->all());
$csv = $export->run();

View File

@ -11,12 +11,13 @@
namespace App\Http\Controllers\Reports;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Export\CSV\InvoiceExport;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class InvoiceReportController extends BaseController
{
@ -62,14 +63,26 @@ class InvoiceReportController extends BaseController
*/
public function __invoke(GenericReportRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), InvoiceExport::class, $this->filename);
SendToAdmin::dispatch($user->company(), $request->all(), InvoiceExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200);
}
// expect a list of visible fields, or use the default
$export = new InvoiceExport(auth()->user()->company(), $request->all());
if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), InvoiceExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
// expect a list of visible fields, or use the default
$export = new InvoiceExport($user->company(), $request->all());
$csv = $export->run();

View File

@ -11,13 +11,14 @@
namespace App\Http\Controllers\Reports;
use App\Models\Client;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Export\CSV\PaymentExport;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Models\Client;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class PaymentReportController extends BaseController
{
@ -63,14 +64,26 @@ class PaymentReportController extends BaseController
*/
public function __invoke(GenericReportRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), PaymentExport::class, $this->filename);
SendToAdmin::dispatch($user->company(), $request->all(), PaymentExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200);
}
// expect a list of visible fields, or use the default
$export = new PaymentExport(auth()->user()->company(), $request->all());
if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), PaymentExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new PaymentExport($user->company(), $request->all());
$csv = $export->run();

View File

@ -11,13 +11,14 @@
namespace App\Http\Controllers\Reports;
use App\Models\Client;
use Illuminate\Http\Response;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Export\CSV\ProductExport;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Models\Client;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class ProductReportController extends BaseController
{
@ -63,14 +64,27 @@ class ProductReportController extends BaseController
*/
public function __invoke(GenericReportRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), ProductExport::class, $this->filename);
SendToAdmin::dispatch($user->company(), $request->all(), ProductExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200);
}
// expect a list of visible fields, or use the default
$export = new ProductExport(auth()->user()->company(), $request->all());
if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), ProductExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new ProductExport($user->company(), $request->all());
$csv = $export->run();

View File

@ -11,11 +11,12 @@
namespace App\Http\Controllers\Reports;
use App\Export\CSV\PurchaseOrderItemExport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController;
use App\Export\CSV\PurchaseOrderItemExport;
use App\Http\Requests\Report\GenericReportRequest;
class PurchaseOrderItemReportController extends BaseController
{
@ -30,14 +31,26 @@ class PurchaseOrderItemReportController extends BaseController
public function __invoke(GenericReportRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), PurchaseOrderItemExport::class, $this->filename);
SendToAdmin::dispatch($user->company(), $request->all(), PurchaseOrderItemExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200);
}
// expect a list of visible fields, or use the default
$export = new PurchaseOrderItemExport(auth()->user()->company(), $request->all());
if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), PurchaseOrderItemExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new PurchaseOrderItemExport($user->company(), $request->all());
$csv = $export->run();

View File

@ -11,11 +11,12 @@
namespace App\Http\Controllers\Reports;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Export\CSV\PurchaseOrderExport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
class PurchaseOrderReportController extends BaseController
{
@ -30,14 +31,29 @@ class PurchaseOrderReportController extends BaseController
public function __invoke(GenericReportRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), PurchaseOrderExport::class, $this->filename);
SendToAdmin::dispatch($user->company(), $request->all(), PurchaseOrderExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200);
}
// expect a list of visible fields, or use the default
$export = new PurchaseOrderExport(auth()->user()->company(), $request->all());
if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), PurchaseOrderExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new PurchaseOrderExport($user->company(), $request->all());
$csv = $export->run();

View File

@ -11,12 +11,13 @@
namespace App\Http\Controllers\Reports;
use Illuminate\Http\Response;
use App\Export\CSV\QuoteExport;
use App\Utils\Traits\MakesHash;
use App\Jobs\Report\SendToAdmin;
use App\Jobs\Report\PreviewReport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
class QuoteReportController extends BaseController
{
@ -62,14 +63,26 @@ class QuoteReportController extends BaseController
*/
public function __invoke(GenericReportRequest $request)
{
/** @var \App\Models\User $user */
$user = auth()->user();
if ($request->has('send_email') && $request->get('send_email')) {
SendToAdmin::dispatch(auth()->user()->company(), $request->all(), QuoteExport::class, $this->filename);
SendToAdmin::dispatch($user->company(), $request->all(), QuoteExport::class, $this->filename);
return response()->json(['message' => 'working...'], 200);
}
// expect a list of visible fields, or use the default
$export = new QuoteExport(auth()->user()->company(), $request->all());
if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
PreviewReport::dispatch($user->company(), $request->all(), QuoteExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new QuoteExport($user->company(), $request->all());
$csv = $export->run();

View File

@ -0,0 +1,55 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Requests\Email;
use App\Http\Requests\Request;
use App\Utils\Traits\MakesHash;
use Illuminate\Support\Str;
class ClientEmailHistoryRequest extends Request
{
use MakesHash;
private string $error_message = '';
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() : bool
{
/** @var \App\Models\User $user */
$user = auth()->user();
return $user->can('view', $this->client);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
];
}
public function prepareForValidation()
{
$input = $this->all();
$this->replace($input);
}
}

View File

@ -0,0 +1,62 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Requests\Email;
use Illuminate\Support\Str;
use App\Http\Requests\Request;
use App\Utils\Traits\MakesHash;
use Illuminate\Validation\Rule;
class EntityEmailHistoryRequest extends Request
{
use MakesHash;
private string $error_message = '';
private string $entity_plural = '';
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() : bool
{
//handle authorization in controller
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
/** @var \App\Models\User $user */
$user = auth()->user();
return [
'entity' => 'bail|required|string|in:invoice,quote,credit,recurring_invoice,purchase_order',
'entity_id' => ['bail','required',Rule::exists($this->entity_plural, 'id')->where('company_id', $user->company()->id)],
];
}
public function prepareForValidation()
{
$input = $this->all();
$this->entity_plural = Str::plural($input['entity']) ?? '';
$input['entity_id'] = $this->decodePrimaryKey($input['entity_id']);
$this->replace($input);
}
}

View File

@ -51,7 +51,10 @@ class SendEmailRequest extends Request
{
$input = $this->all();
$settings = auth()->user()->company()->settings;
/** @var \App\Models\User $user */
$user = auth()->user();
$settings = $user->company()->settings;
if (empty($input['template'])) {
$input['template'] = '';

View File

@ -19,6 +19,7 @@ use Illuminate\Contracts\Validation\Rule;
class BlackListRule implements Rule
{
private array $blacklist = [
'pretreer.com',
'candassociates.com',
'vusra.com',
'fourthgenet.com',

View File

@ -11,27 +11,24 @@
namespace App\Jobs\PostMark;
use App\DataMapper\Analytics\Mail\EmailBounce;
use App\DataMapper\Analytics\Mail\EmailSpam;
use App\Jobs\Util\SystemLogger;
use App\Models\SystemLog;
use App\Libraries\MultiDB;
use App\Models\Company;
use Postmark\PostmarkClient;
use Illuminate\Bus\Queueable;
use App\Jobs\Util\SystemLogger;
use App\Models\QuoteInvitation;
use App\Models\CreditInvitation;
use App\Models\InvoiceInvitation;
use App\Models\Payment;
use App\Models\PurchaseOrderInvitation;
use App\Models\QuoteInvitation;
use App\Models\RecurringInvoiceInvitation;
use App\Models\SystemLog;
use App\Notifications\Ninja\EmailBounceNotification;
use App\Notifications\Ninja\EmailSpamNotification;
use App\Utils\Ninja;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Turbo124\Beacon\Facades\LightLogs;
use App\Models\PurchaseOrderInvitation;
use Illuminate\Queue\InteractsWithQueue;
use App\Models\RecurringInvoiceInvitation;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use App\DataMapper\Analytics\Mail\EmailSpam;
use App\DataMapper\Analytics\Mail\EmailBounce;
use App\Notifications\Ninja\EmailSpamNotification;
class ProcessPostmarkWebhook implements ShouldQueue
{
@ -41,6 +38,16 @@ class ProcessPostmarkWebhook implements ShouldQueue
public $invitation;
private $entity;
private array $default_response = [
'recipients' => '',
'subject' => 'Message not found.',
'entity' => '',
'entity_id' => '',
'events' => [],
];
/**
* Create a new job instance.
*
@ -126,8 +133,10 @@ class ProcessPostmarkWebhook implements ShouldQueue
$this->invitation->opened_date = now();
$this->invitation->save();
$data = array_merge($this->request, ['history' => $this->fetchMessage()]);
(new SystemLogger(
$this->request,
$data,
SystemLog::CATEGORY_MAIL,
SystemLog::EVENT_MAIL_OPENED,
SystemLog::TYPE_WEBHOOK_RESPONSE,
@ -155,8 +164,10 @@ class ProcessPostmarkWebhook implements ShouldQueue
$this->invitation->email_status = 'delivered';
$this->invitation->save();
$data = array_merge($this->request, ['history' => $this->fetchMessage()]);
(new SystemLogger(
$this->request,
$data,
SystemLog::CATEGORY_MAIL,
SystemLog::EVENT_MAIL_DELIVERY,
SystemLog::TYPE_WEBHOOK_RESPONSE,
@ -204,7 +215,9 @@ class ProcessPostmarkWebhook implements ShouldQueue
LightLogs::create($bounce)->send();
(new SystemLogger($this->request, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_BOUNCED, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle();
$data = array_merge($this->request, ['history' => $this->fetchMessage()]);
(new SystemLogger($data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_BOUNCED, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle();
// if(config('ninja.notification.slack'))
// $this->invitation->company->notification(new EmailBounceNotification($this->invitation->company->account))->ninja();
@ -248,7 +261,9 @@ class ProcessPostmarkWebhook implements ShouldQueue
LightLogs::create($spam)->send();
(new SystemLogger($this->request, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle();
$data = array_merge($this->request, ['history' => $this->fetchMessage()]);
(new SystemLogger($data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle();
if (config('ninja.notification.slack')) {
$this->invitation->company->notification(new EmailSpamNotification($this->invitation->company->account))->ninja();
@ -260,17 +275,65 @@ class ProcessPostmarkWebhook implements ShouldQueue
$invitation = false;
if ($invitation = InvoiceInvitation::where('message_id', $message_id)->first()) {
$this->entity = 'invoice';
return $invitation;
} elseif ($invitation = QuoteInvitation::where('message_id', $message_id)->first()) {
$this->entity = 'quote';
return $invitation;
} elseif ($invitation = RecurringInvoiceInvitation::where('message_id', $message_id)->first()) {
$this->entity = 'recurring_invoice';
return $invitation;
} elseif ($invitation = CreditInvitation::where('message_id', $message_id)->first()) {
$this->entity = 'credit';
return $invitation;
} elseif ($invitation = PurchaseOrderInvitation::where('message_id', $message_id)->first()) {
$this->entity = 'purchase_order';
return $invitation;
} else {
return $invitation;
}
}
private function fetchMessage(): array
{
if(strlen($this->request['MessageID']) < 1){
return $this->default_response;
}
try {
$postmark = new PostmarkClient(config('services.postmark.token'));
$messageDetail = $postmark->getOutboundMessageDetails($this->request['MessageID']);
$recipients = collect($messageDetail['recipients'])->flatten()->implode(',');
$subject = $messageDetail->subject ?? '';
$events = collect($messageDetail->messageevents)->map(function ($event) {
return [
'recipient' => $event->Recipient ?? '',
'status' => $event->Type ?? '',
'delivery_message' => $event->Details->DeliveryMessage ?? $event->Details->Summary ?? '',
'server' => $event->Details->DestinationServer ?? '',
'server_ip' => $event->Details->DestinationIP ?? '',
'date' => \Carbon\Carbon::parse($event->ReceivedAt)->format('Y-m-d H:m:s') ?? '',
];
})->toArray();
return [
'recipients' => $recipients,
'subject' => $subject,
'entity' => $this->entity ?? '',
'entity_id' => $this->invitation->{$this->entity}->hashed_id ?? '',
'events' => $events,
];
}
catch (\Exception $e) {
return $this->default_response;
}
}
}

View File

@ -39,7 +39,8 @@ class PreviewReport implements ShouldQueue
/** @var \App\Export\CSV\CreditExport $export */
$export = new $this->report_class($this->company, $this->request);
$report = $export->returnJson();
nlog($report);
nlog($this->report_class);
// nlog($report);
Cache::put($this->hash, $report, 60 * 60);
}

View File

@ -159,6 +159,7 @@ class PaymentEmailEngine extends BaseEmailEngine
$data['$entity'] = ['value' => '', 'label' => ctrans('texts.payment')];
$data['$payment.amount'] = ['value' => Number::formatMoney($this->payment->amount, $this->client) ?: '&nbsp;', 'label' => ctrans('texts.amount')];
$data['$payment.refunded'] = ['value' => Number::formatMoney($this->payment->refunded, $this->client) ?: '&nbsp;', 'label' => ctrans('texts.refund')];
$data['$payment.unapplied'] = ['value' => Number::formatMoney(($this->payment->amount - $this->payment->refunded - $this->payment->applied), $this->client) ?: '&nbsp;', 'label' => ctrans('texts.refund')];
$data['$amount'] = &$data['$payment.amount'];
$data['$payment.date'] = ['value' => $this->translateDate($this->payment->date, $this->client->date_format(), $this->client->locale()), 'label' => ctrans('texts.payment_date')];
$data['$transaction_reference'] = ['value' => $this->payment->transaction_reference, 'label' => ctrans('texts.transaction_reference')];

View File

@ -146,7 +146,7 @@ class SquareWebhook implements ShouldQueue
$data = [
'payment_type' => $this->source_type[$square_payment->source_type],
'amount' => $payment_hash->amount_with_fee,
'amount' => $payment_hash->amount_with_fee(),
'transaction_reference' => $square_payment->id,
'gateway_type_id' => GatewayType::BANK_TRANSFER,
];

View File

@ -394,8 +394,10 @@ class SquarePaymentDriver extends BaseDriver
//getsubscriptionid here
$subscription_id = $this->checkWebhooks();
if(!$subscription_id)
return nlog('No Subscription Found');
if(!$subscription_id){
nlog('No Subscription Found');
return;
}
$api_response = $this->square->getWebhookSubscriptionsApi()->testWebhookSubscription($subscription_id, $body);

View File

@ -153,7 +153,7 @@ class BaseRepository
$model->client_id = $data['client_id'];
}
$client = Client::with('group_settings')->where('id', $model->client_id)->withTrashed()->firstOrFail();
$client = Client::query()->with('group_settings')->where('id', $model->client_id)->withTrashed()->firstOrFail();
$state = [];

View File

@ -113,6 +113,11 @@ class ExpenseRepository extends BaseRepository
$expense->saveQuietly();
$expense->transaction->expense_id = $exp_ids;
if(strlen($exp_ids) <= 2) {
$expense->transaction->status_id = 1;
}
$expense->transaction->saveQuietly();
}

View File

@ -0,0 +1,96 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Services\Client;
use App\Models\Client;
use App\Models\SystemLog;
use Postmark\PostmarkClient;
use App\Services\AbstractService;
/** @deprecated */
class EmailHistory extends AbstractService
{
private string $postmark_token;
private PostmarkClient $postmark;
private array $default_response = [
'subject' => 'Message not found.',
'status' => '',
'recipient' => '',
'type' => '',
'delivery_message' => '',
'server' => '',
'server_ip' => '',
];
public function __construct(public Client $client)
{
}
public function run(): array
{
// $settings = $this->client->getMergedSettings();
// if($settings->email_sending_method == 'default'){
// $this->postmark_token = config('services.postmark.token');
// }
// elseif($settings->email_sending_method == 'client_postmark'){
// $this->postmark_token = $settings->postmark_secret;
// }
// else{
// return [];
// }
// $this->postmark = new PostmarkClient($this->postmark_token);
return SystemLog::query()
->where('client_id', $this->client->id)
->where('category_id', SystemLog::CATEGORY_MAIL)
->orderBy('id','DESC')
->cursor()
->map(function ($system_log) {
if($system_log->log['history'] ?? false){
return json_decode($system_log->log['history'],true);
}
})->toArray();
}
private function fetchMessage(string $message_id): array
{
if(strlen($message_id) < 1){
return $this->default_response;
}
try {
$messageDetail = $this->postmark->getOutboundMessageDetails($message_id);
return [
'subject' => $messageDetail->subject ?? '',
'status' => $messageDetail->status ?? '',
'recipient' => $messageDetail->messageevents[0]['Recipient'] ?? '',
'type' => $messageDetail->messageevents[0]->Type ?? '',
'delivery_message' => $messageDetail->messageevents[0]->Details->DeliveryMessage ?? '',
'server' => $messageDetail->messageevents[0]->Details->DestinationServer ?? '',
'server_ip' => $messageDetail->messageevents[0]->Details->DestinationIP ?? '',
];
}
catch (\Exception $e) {
return $this->default_response;
}
}
}

View File

@ -240,7 +240,6 @@ class Email implements ShouldQueue
}
if ($this->client_mailgun_secret) {
$mailer->mailgun_config($this->client_mailgun_secret, $this->client_mailgun_domain, $this->client_mailgun_endpoint);
}
@ -254,6 +253,7 @@ class Email implements ShouldQueue
LightLogs::create(new EmailSuccess($this->company->company_key))
->send();
} catch(\Symfony\Component\Mime\Exception\RfcComplianceException $e) {
nlog("Mailer failed with a Logic Exception {$e->getMessage()}");
$this->fail();

View File

@ -60,6 +60,7 @@ class DeletePayment
BankTransaction::query()->where('payment_id', $this->payment->id)->cursor()->each(function ($bt){
$bt->payment_id = null;
$bt->status_id = 1;
$bt->save();
});

View File

@ -76,6 +76,7 @@
"omnipay/paypal": "^3.0",
"payfast/payfast-php-sdk": "^1.1",
"pragmarx/google2fa": "^8.0",
"psr/http-message": "^1.0",
"pusher/pusher-php-server": "^7.2",
"razorpay/razorpay": "2.*",
"sentry/sentry-laravel": "^3",
@ -96,7 +97,7 @@
"twilio/sdk": "^6.40",
"webpatser/laravel-countries": "dev-master#75992ad",
"wepay/php-sdk": "^0.3",
"psr/http-message": "^1.0"
"wildbit/postmark-php": "^4.0"
},
"require-dev": {
"php": "^8.1",

368
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "8e1e0864e98afc97b30e13631480c86b",
"content-hash": "7c3f126aafc640beb01f58c7047f6e23",
"packages": [
{
"name": "adrienrn/php-mimetyper",
@ -525,16 +525,16 @@
},
{
"name": "aws/aws-sdk-php",
"version": "3.279.7",
"version": "3.279.9",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "223f97f8f12765b42a682569b434ac0210cca93a"
"reference": "cbf446e410c04a405192cc0d018f29a91fe36375"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/223f97f8f12765b42a682569b434ac0210cca93a",
"reference": "223f97f8f12765b42a682569b434ac0210cca93a",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/cbf446e410c04a405192cc0d018f29a91fe36375",
"reference": "cbf446e410c04a405192cc0d018f29a91fe36375",
"shasum": ""
},
"require": {
@ -614,9 +614,9 @@
"support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.279.7"
"source": "https://github.com/aws/aws-sdk-php/tree/3.279.9"
},
"time": "2023-08-25T18:07:43+00:00"
"time": "2023-08-29T18:11:18+00:00"
},
{
"name": "bacon/bacon-qr-code",
@ -2586,16 +2586,16 @@
},
{
"name": "google/apiclient-services",
"version": "v0.312.1",
"version": "v0.313.0",
"source": {
"type": "git",
"url": "https://github.com/googleapis/google-api-php-client-services.git",
"reference": "d13797cf251ec0d62f00b70dfa8642aa9550900d"
"reference": "e41289c4488563af75bd291972f0fa00949e084a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/d13797cf251ec0d62f00b70dfa8642aa9550900d",
"reference": "d13797cf251ec0d62f00b70dfa8642aa9550900d",
"url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/e41289c4488563af75bd291972f0fa00949e084a",
"reference": "e41289c4488563af75bd291972f0fa00949e084a",
"shasum": ""
},
"require": {
@ -2624,9 +2624,9 @@
],
"support": {
"issues": "https://github.com/googleapis/google-api-php-client-services/issues",
"source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.312.1"
"source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.313.0"
},
"time": "2023-08-21T00:52:13+00:00"
"time": "2023-08-25T01:10:13+00:00"
},
{
"name": "google/auth",
@ -2803,22 +2803,22 @@
},
{
"name": "guzzlehttp/guzzle",
"version": "7.7.0",
"version": "7.8.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "fb7566caccf22d74d1ab270de3551f72a58399f5"
"reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5",
"reference": "fb7566caccf22d74d1ab270de3551f72a58399f5",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/1110f66a6530a40fe7aea0378fe608ee2b2248f9",
"reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.5.3 || ^2.0",
"guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
"guzzlehttp/promises": "^1.5.3 || ^2.0.1",
"guzzlehttp/psr7": "^1.9.1 || ^2.5.1",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0"
@ -2909,7 +2909,7 @@
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/7.7.0"
"source": "https://github.com/guzzle/guzzle/tree/7.8.0"
},
"funding": [
{
@ -2925,7 +2925,7 @@
"type": "tidelift"
}
],
"time": "2023-05-21T14:04:53+00:00"
"time": "2023-08-27T10:20:53+00:00"
},
{
"name": "guzzlehttp/promises",
@ -3012,16 +3012,16 @@
},
{
"name": "guzzlehttp/psr7",
"version": "2.6.0",
"version": "2.6.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77"
"reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/8bd7c33a0734ae1c5d074360512beb716bef3f77",
"reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/be45764272e8873c72dbe3d2edcfdfcc3bc9f727",
"reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727",
"shasum": ""
},
"require": {
@ -3108,7 +3108,7 @@
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/2.6.0"
"source": "https://github.com/guzzle/psr7/tree/2.6.1"
},
"funding": [
{
@ -3124,20 +3124,20 @@
"type": "tidelift"
}
],
"time": "2023-08-03T15:06:02+00:00"
"time": "2023-08-27T10:13:57+00:00"
},
{
"name": "guzzlehttp/uri-template",
"version": "v1.0.1",
"version": "v1.0.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/uri-template.git",
"reference": "b945d74a55a25a949158444f09ec0d3c120d69e2"
"reference": "61bf437fc2197f587f6857d3ff903a24f1731b5d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/uri-template/zipball/b945d74a55a25a949158444f09ec0d3c120d69e2",
"reference": "b945d74a55a25a949158444f09ec0d3c120d69e2",
"url": "https://api.github.com/repos/guzzle/uri-template/zipball/61bf437fc2197f587f6857d3ff903a24f1731b5d",
"reference": "61bf437fc2197f587f6857d3ff903a24f1731b5d",
"shasum": ""
},
"require": {
@ -3145,15 +3145,11 @@
"symfony/polyfill-php80": "^1.17"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.1",
"phpunit/phpunit": "^8.5.19 || ^9.5.8",
"uri-template/tests": "1.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\UriTemplate\\": "src"
@ -3192,7 +3188,7 @@
],
"support": {
"issues": "https://github.com/guzzle/uri-template/issues",
"source": "https://github.com/guzzle/uri-template/tree/v1.0.1"
"source": "https://github.com/guzzle/uri-template/tree/v1.0.2"
},
"funding": [
{
@ -3208,7 +3204,7 @@
"type": "tidelift"
}
],
"time": "2021-10-07T12:57:01+00:00"
"time": "2023-08-27T10:19:19+00:00"
},
{
"name": "halaxa/json-machine",
@ -4026,16 +4022,16 @@
},
{
"name": "jms/serializer",
"version": "3.27.0",
"version": "3.28.0",
"source": {
"type": "git",
"url": "https://github.com/schmittjoh/serializer.git",
"reference": "e8c812460d7b47b15bc0ccd78901276bd44ad452"
"reference": "5a5a03a71a28a480189c5a0ca95893c19f1d120c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/schmittjoh/serializer/zipball/e8c812460d7b47b15bc0ccd78901276bd44ad452",
"reference": "e8c812460d7b47b15bc0ccd78901276bd44ad452",
"url": "https://api.github.com/repos/schmittjoh/serializer/zipball/5a5a03a71a28a480189c5a0ca95893c19f1d120c",
"reference": "5a5a03a71a28a480189c5a0ca95893c19f1d120c",
"shasum": ""
},
"require": {
@ -4047,7 +4043,7 @@
"phpstan/phpdoc-parser": "^0.4 || ^0.5 || ^1.0"
},
"require-dev": {
"doctrine/coding-standard": "^8.1",
"doctrine/coding-standard": "^12.0",
"doctrine/orm": "~2.1",
"doctrine/persistence": "^1.3.3|^2.0|^3.0",
"doctrine/phpcr-odm": "^1.3|^2.0",
@ -4110,7 +4106,7 @@
],
"support": {
"issues": "https://github.com/schmittjoh/serializer/issues",
"source": "https://github.com/schmittjoh/serializer/tree/3.27.0"
"source": "https://github.com/schmittjoh/serializer/tree/3.28.0"
},
"funding": [
{
@ -4118,7 +4114,7 @@
"type": "github"
}
],
"time": "2023-07-29T22:33:44+00:00"
"time": "2023-08-03T14:43:08+00:00"
},
{
"name": "josemmo/facturae-php",
@ -4335,16 +4331,16 @@
},
{
"name": "laravel/framework",
"version": "v10.20.0",
"version": "v10.21.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "a655dca3fbe83897e22adff652b1878ba352d041"
"reference": "96b15c7ac382a9adb4a56d40c640e782d669a112"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/a655dca3fbe83897e22adff652b1878ba352d041",
"reference": "a655dca3fbe83897e22adff652b1878ba352d041",
"url": "https://api.github.com/repos/laravel/framework/zipball/96b15c7ac382a9adb4a56d40c640e782d669a112",
"reference": "96b15c7ac382a9adb4a56d40c640e782d669a112",
"shasum": ""
},
"require": {
@ -4531,7 +4527,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2023-08-22T13:37:09+00:00"
"time": "2023-08-29T13:55:56+00:00"
},
{
"name": "laravel/prompts",
@ -4774,16 +4770,16 @@
},
{
"name": "laravel/tinker",
"version": "v2.8.1",
"version": "v2.8.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/tinker.git",
"reference": "04a2d3bd0d650c0764f70bf49d1ee39393e4eb10"
"reference": "b936d415b252b499e8c3b1f795cd4fc20f57e1f3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/tinker/zipball/04a2d3bd0d650c0764f70bf49d1ee39393e4eb10",
"reference": "04a2d3bd0d650c0764f70bf49d1ee39393e4eb10",
"url": "https://api.github.com/repos/laravel/tinker/zipball/b936d415b252b499e8c3b1f795cd4fc20f57e1f3",
"reference": "b936d415b252b499e8c3b1f795cd4fc20f57e1f3",
"shasum": ""
},
"require": {
@ -4796,6 +4792,7 @@
},
"require-dev": {
"mockery/mockery": "~1.3.3|^1.4.2",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^8.5.8|^9.3.3"
},
"suggest": {
@ -4836,9 +4833,9 @@
],
"support": {
"issues": "https://github.com/laravel/tinker/issues",
"source": "https://github.com/laravel/tinker/tree/v2.8.1"
"source": "https://github.com/laravel/tinker/tree/v2.8.2"
},
"time": "2023-02-15T16:40:09+00:00"
"time": "2023-08-15T14:27:00+00:00"
},
{
"name": "laravel/ui",
@ -9981,22 +9978,22 @@
},
{
"name": "socialiteproviders/manager",
"version": "v4.3.0",
"version": "v4.4.0",
"source": {
"type": "git",
"url": "https://github.com/SocialiteProviders/Manager.git",
"reference": "47402cbc5b7ef445317e799bf12fd5a12062206c"
"reference": "df5e45b53d918ec3d689f014d98a6c838b98ed96"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/47402cbc5b7ef445317e799bf12fd5a12062206c",
"reference": "47402cbc5b7ef445317e799bf12fd5a12062206c",
"url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/df5e45b53d918ec3d689f014d98a6c838b98ed96",
"reference": "df5e45b53d918ec3d689f014d98a6c838b98ed96",
"shasum": ""
},
"require": {
"illuminate/support": "^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0",
"laravel/socialite": "~5.0",
"php": "^7.4 || ^8.0"
"php": "^8.0"
},
"require-dev": {
"mockery/mockery": "^1.2",
@ -10051,7 +10048,7 @@
"issues": "https://github.com/socialiteproviders/manager/issues",
"source": "https://github.com/socialiteproviders/manager"
},
"time": "2023-01-26T23:11:27+00:00"
"time": "2023-08-27T23:46:34+00:00"
},
{
"name": "socialiteproviders/microsoft",
@ -11747,16 +11744,16 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"shasum": ""
},
"require": {
@ -11771,7 +11768,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -11809,7 +11806,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0"
},
"funding": [
{
@ -11825,20 +11822,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354"
"reference": "875e90aeea2777b6f135677f618529449334a612"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612",
"reference": "875e90aeea2777b6f135677f618529449334a612",
"shasum": ""
},
"require": {
@ -11850,7 +11847,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -11890,7 +11887,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0"
},
"funding": [
{
@ -11906,20 +11903,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-intl-icu",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-icu.git",
"reference": "a3d9148e2c363588e05abbdd4ee4f971f0a5330c"
"reference": "e46b4da57951a16053cd751f63f4a24292788157"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/a3d9148e2c363588e05abbdd4ee4f971f0a5330c",
"reference": "a3d9148e2c363588e05abbdd4ee4f971f0a5330c",
"url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/e46b4da57951a16053cd751f63f4a24292788157",
"reference": "e46b4da57951a16053cd751f63f4a24292788157",
"shasum": ""
},
"require": {
@ -11931,7 +11928,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -11977,7 +11974,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.28.0"
},
"funding": [
{
@ -11993,20 +11990,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-03-21T17:27:24+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "639084e360537a19f9ee352433b84ce831f3d2da"
"reference": "ecaafce9f77234a6a449d29e49267ba10499116d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da",
"reference": "639084e360537a19f9ee352433b84ce831f3d2da",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/ecaafce9f77234a6a449d29e49267ba10499116d",
"reference": "ecaafce9f77234a6a449d29e49267ba10499116d",
"shasum": ""
},
"require": {
@ -12020,7 +12017,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -12064,7 +12061,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.28.0"
},
"funding": [
{
@ -12080,20 +12077,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:30:37+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
"reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
"reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
"shasum": ""
},
"require": {
@ -12105,7 +12102,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -12148,7 +12145,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0"
},
"funding": [
{
@ -12164,20 +12161,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
"reference": "42292d99c55abe617799667f454222c54c60e229"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
"reference": "42292d99c55abe617799667f454222c54c60e229",
"shasum": ""
},
"require": {
@ -12192,7 +12189,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -12231,7 +12228,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
},
"funding": [
{
@ -12247,20 +12244,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-07-28T09:04:16+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97"
"reference": "70f4aebd92afca2f865444d30a4d2151c13c3179"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179",
"reference": "70f4aebd92afca2f865444d30a4d2151c13c3179",
"shasum": ""
},
"require": {
@ -12269,7 +12266,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -12307,7 +12304,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0"
},
"funding": [
{
@ -12323,20 +12320,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-php73",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php73.git",
"reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9"
"reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9",
"reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fe2f306d1d9d346a7fee353d0d5012e401e984b5",
"reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5",
"shasum": ""
},
"require": {
@ -12345,7 +12342,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -12386,7 +12383,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php73/tree/v1.28.0"
},
"funding": [
{
@ -12402,20 +12399,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
"reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
"shasum": ""
},
"require": {
@ -12424,7 +12421,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -12469,7 +12466,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0"
},
"funding": [
{
@ -12485,20 +12482,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-php83",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php83.git",
"reference": "508c652ba3ccf69f8c97f251534f229791b52a57"
"reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/508c652ba3ccf69f8c97f251534f229791b52a57",
"reference": "508c652ba3ccf69f8c97f251534f229791b52a57",
"url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11",
"reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11",
"shasum": ""
},
"require": {
@ -12508,7 +12505,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -12521,7 +12518,10 @@
],
"psr-4": {
"Symfony\\Polyfill\\Php83\\": ""
}
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@ -12546,7 +12546,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php83/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php83/tree/v1.28.0"
},
"funding": [
{
@ -12562,20 +12562,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-08-16T06:22:46+00:00"
},
{
"name": "symfony/polyfill-uuid",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-uuid.git",
"reference": "f3cf1a645c2734236ed1e2e671e273eeb3586166"
"reference": "9c44518a5aff8da565c8a55dbe85d2769e6f630e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/f3cf1a645c2734236ed1e2e671e273eeb3586166",
"reference": "f3cf1a645c2734236ed1e2e671e273eeb3586166",
"url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/9c44518a5aff8da565c8a55dbe85d2769e6f630e",
"reference": "9c44518a5aff8da565c8a55dbe85d2769e6f630e",
"shasum": ""
},
"require": {
@ -12590,7 +12590,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -12628,7 +12628,7 @@
"uuid"
],
"support": {
"source": "https://github.com/symfony/polyfill-uuid/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-uuid/tree/v1.28.0"
},
"funding": [
{
@ -12644,7 +12644,7 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/postmark-mailer",
@ -14277,6 +14277,44 @@
"source": "https://github.com/wepay/PHP-SDK/tree/master"
},
"time": "2017-01-21T07:03:26+00:00"
},
{
"name": "wildbit/postmark-php",
"version": "v4.0.5",
"source": {
"type": "git",
"url": "https://github.com/ActiveCampaign/postmark-php.git",
"reference": "b71efba061de7cf7e1f853d211b1c5edce4e3c5b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ActiveCampaign/postmark-php/zipball/b71efba061de7cf7e1f853d211b1c5edce4e3c5b",
"reference": "b71efba061de7cf7e1f853d211b1c5edce4e3c5b",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "^6.0|^7.0",
"php": ">=7.0.0"
},
"require-dev": {
"phpunit/phpunit": "^6.0.0"
},
"type": "library",
"autoload": {
"psr-0": {
"Postmark\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "The officially supported client for Postmark (http://postmarkapp.com)",
"support": {
"issues": "https://github.com/ActiveCampaign/postmark-php/issues",
"source": "https://github.com/ActiveCampaign/postmark-php/tree/v4.0.5"
},
"time": "2023-02-03T15:00:17+00:00"
}
],
"packages-dev": [
@ -14512,16 +14550,16 @@
},
{
"name": "brianium/paratest",
"version": "v7.2.5",
"version": "v7.2.6",
"source": {
"type": "git",
"url": "https://github.com/paratestphp/paratest.git",
"reference": "4d7ad5b6564f63baa1b948ecad05439f22880942"
"reference": "7f372b5bb59b4271adedc67d3129df29b84c4173"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paratestphp/paratest/zipball/4d7ad5b6564f63baa1b948ecad05439f22880942",
"reference": "4d7ad5b6564f63baa1b948ecad05439f22880942",
"url": "https://api.github.com/repos/paratestphp/paratest/zipball/7f372b5bb59b4271adedc67d3129df29b84c4173",
"reference": "7f372b5bb59b4271adedc67d3129df29b84c4173",
"shasum": ""
},
"require": {
@ -14535,19 +14573,19 @@
"phpunit/php-code-coverage": "^10.1.3",
"phpunit/php-file-iterator": "^4.0.2",
"phpunit/php-timer": "^6.0",
"phpunit/phpunit": "^10.3.1",
"phpunit/phpunit": "^10.3.2",
"sebastian/environment": "^6.0.1",
"symfony/console": "^6.3.2",
"symfony/process": "^6.3.2"
"symfony/console": "^6.3.4",
"symfony/process": "^6.3.4"
},
"require-dev": {
"doctrine/coding-standard": "^12.0.0",
"ext-pcov": "*",
"ext-posix": "*",
"infection/infection": "^0.27.0",
"phpstan/phpstan": "^1.10.26",
"phpstan/phpstan-deprecation-rules": "^1.1.3",
"phpstan/phpstan-phpunit": "^1.3.13",
"phpstan/phpstan": "^1.10.32",
"phpstan/phpstan-deprecation-rules": "^1.1.4",
"phpstan/phpstan-phpunit": "^1.3.14",
"phpstan/phpstan-strict-rules": "^1.5.1",
"squizlabs/php_codesniffer": "^3.7.2",
"symfony/filesystem": "^6.3.1"
@ -14591,7 +14629,7 @@
],
"support": {
"issues": "https://github.com/paratestphp/paratest/issues",
"source": "https://github.com/paratestphp/paratest/tree/v7.2.5"
"source": "https://github.com/paratestphp/paratest/tree/v7.2.6"
},
"funding": [
{
@ -14603,7 +14641,7 @@
"type": "paypal"
}
],
"time": "2023-08-08T13:23:59+00:00"
"time": "2023-08-29T07:47:39+00:00"
},
{
"name": "composer/class-map-generator",
@ -15030,16 +15068,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.23.0",
"version": "v3.24.0",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "35af3cbbacfa91e164b252a28ec0b644f1ed4e78"
"reference": "bb6c9d7945dcbf6942e151b018c44d3767e21403"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/35af3cbbacfa91e164b252a28ec0b644f1ed4e78",
"reference": "35af3cbbacfa91e164b252a28ec0b644f1ed4e78",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/bb6c9d7945dcbf6942e151b018c44d3767e21403",
"reference": "bb6c9d7945dcbf6942e151b018c44d3767e21403",
"shasum": ""
},
"require": {
@ -15115,7 +15153,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.23.0"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.24.0"
},
"funding": [
{
@ -15123,7 +15161,7 @@
"type": "github"
}
],
"time": "2023-08-14T12:27:35+00:00"
"time": "2023-08-29T23:18:45+00:00"
},
{
"name": "hamcrest/hamcrest-php",
@ -17598,16 +17636,16 @@
},
{
"name": "symfony/polyfill-php81",
"version": "v1.27.0",
"version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php81.git",
"reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a"
"reference": "7581cd600fa9fd681b797d00b02f068e2f13263b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a",
"reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a",
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b",
"reference": "7581cd600fa9fd681b797d00b02f068e2f13263b",
"shasum": ""
},
"require": {
@ -17616,7 +17654,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@ -17657,7 +17695,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0"
},
"funding": [
{
@ -17673,7 +17711,7 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/stopwatch",

View File

@ -1150,7 +1150,7 @@ $LANG = array(
'plan_status' => 'Plan Status',
'plan_upgrade' => 'Upgrade',
'plan_change' => 'Change Plan',
'plan_change' => 'Manage Plan',
'pending_change_to' => 'Changes To',
'plan_changes_to' => ':plan on :date',
'plan_term_changes_to' => ':plan (:term) on :date',
@ -4330,7 +4330,7 @@ $LANG = array(
'include_drafts' => 'Include Drafts',
'include_drafts_help' => 'Include draft records in reports',
'is_invoiced' => 'Is Invoiced',
'change_plan' => 'Change Plan',
'change_plan' => 'Manage Plan',
'persist_data' => 'Persist Data',
'customer_count' => 'Customer Count',
'verify_customers' => 'Verify Customers',
@ -5158,8 +5158,7 @@ $LANG = array(
'unlinked_transaction' => 'Successfully unlinked transaction',
'view_dashboard_permission' => 'Allow user to access the dashboard, data is limited to available permissions',
'marked_sent_credits' => 'Successfully marked credits sent',
);
);
return $LANG;

View File

@ -58,6 +58,7 @@ use App\Http\Controllers\TaskStatusController;
use App\Http\Controllers\Bank\YodleeController;
use App\Http\Controllers\CompanyUserController;
use App\Http\Controllers\PaymentTermController;
use App\Http\Controllers\EmailHistoryController;
use App\Http\Controllers\GroupSettingController;
use App\Http\Controllers\OneTimeTokenController;
use App\Http\Controllers\SubscriptionController;
@ -202,6 +203,8 @@ Route::group(['middleware' => ['throttle:api', 'api_db', 'token_auth', 'locale']
Route::post('documents/bulk', [DocumentController::class, 'bulk'])->name('documents.bulk');
Route::post('emails', [EmailController::class, 'send'])->name('email.send')->middleware('user_verified');
Route::post('emails/clientHistory/{client}', [EmailHistoryController::class, 'clientHistory'])->name('email.clientHistory');
Route::post('emails/entityHistory', [EmailHistoryController::class, 'entityHistory'])->name('email.entityHistory');
Route::resource('expenses', ExpenseController::class); // name = (expenses. index / create / show / update / destroy / edit
Route::put('expenses/{expense}/upload', [ExpenseController::class, 'upload']);

View File

@ -43,6 +43,23 @@ class ReportApiTest extends TestCase
}
public function testActivityCSVExport()
{
$data = [
'send_email' => false,
'date_range' => 'all',
'report_keys' => [],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/activities', $data)
->assertStatus(200);
}
public function testUserSalesReportApiRoute()
{
$data = [
@ -126,6 +143,8 @@ class ReportApiTest extends TestCase
}
public function testClientBalanceReportApiRoute()
{
$data = [

View File

@ -527,7 +527,7 @@ class ReportCsvGenerationTest extends TestCase
])->post('/api/v1/reports/products', $data);
$csv = $response->streamedContent();
// nlog($csv);
$this->assertEquals('product_key', $this->getFirstValueByColumn($csv, 'Product'));
$this->assertEquals('notes', $this->getFirstValueByColumn($csv, 'Notes'));
$this->assertEquals(100, $this->getFirstValueByColumn($csv, 'Cost'));
@ -649,11 +649,11 @@ class ReportCsvGenerationTest extends TestCase
$csv = $response->streamedContent();
$this->assertEquals(500, $this->getFirstValueByColumn($csv, 'Amount'));
$this->assertEquals(0, $this->getFirstValueByColumn($csv, 'Applied'));
$this->assertEquals(0, $this->getFirstValueByColumn($csv, 'Refunded'));
$this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Date'));
$this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Transaction Reference'));
$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'));
}
@ -673,7 +673,7 @@ class ReportCsvGenerationTest extends TestCase
])->post('/api/v1/reports/clients', $data);
$csv = $response->streamedContent();
// nlog($csv);
$reader = Reader::createFromString($csv);
$reader->setHeaderOffset(0);
@ -748,7 +748,7 @@ class ReportCsvGenerationTest extends TestCase
$arr = $response->json();
nlog($arr['message']);
// nlog($arr['message']);
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
@ -849,7 +849,7 @@ class ReportCsvGenerationTest extends TestCase
])->post('/api/v1/reports/invoices', $data);
$csv = $response->streamedContent();
// nlog($csv);
$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'));
@ -985,20 +985,20 @@ class ReportCsvGenerationTest extends TestCase
])->post('/api/v1/reports/invoice_items', $data);
$csv = $response->streamedContent();
// nlog($csv);//
$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, 'Quantity'));
$this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Cost'));
$this->assertEquals('1000', $this->getFirstValueByColumn($csv, 'Line Total'));
$this->assertEquals('0', $this->getFirstValueByColumn($csv, 'Discount'));
$this->assertEquals('item notes', $this->getFirstValueByColumn($csv, 'Notes'));
$this->assertEquals('product key', $this->getFirstValueByColumn($csv, 'Product'));
$this->assertEquals('custom 1', $this->getFirstValueByColumn($csv, 'Custom Invoice 1'));
$this->assertEquals('GST', $this->getFirstValueByColumn($csv, 'Tax Name 1'));
$this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Tax Rate 1'));
$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 = [
@ -1082,15 +1082,15 @@ class ReportCsvGenerationTest extends TestCase
$this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name'));
$this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Quote Number'));
$this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Quantity'));
$this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Cost'));
$this->assertEquals('1000', $this->getFirstValueByColumn($csv, 'Line Total'));
$this->assertEquals('0', $this->getFirstValueByColumn($csv, 'Discount'));
$this->assertEquals('item notes', $this->getFirstValueByColumn($csv, 'Notes'));
$this->assertEquals('product key', $this->getFirstValueByColumn($csv, 'Product'));
$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, 'Tax Name 1'));
$this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Tax Rate 1'));
$this->assertEquals('GST', $this->getFirstValueByColumn($csv, 'Item Tax Name 1'));
$this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Tax Rate 1'));
$data = [
@ -1222,15 +1222,15 @@ class ReportCsvGenerationTest extends TestCase
$this->assertEquals('Vendor 1', $this->getFirstValueByColumn($csv, 'Vendor Name'));
$this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Purchase Order Number'));
$this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Quantity'));
$this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Cost'));
$this->assertEquals('1000', $this->getFirstValueByColumn($csv, 'Line Total'));
$this->assertEquals('0', $this->getFirstValueByColumn($csv, 'Discount'));
$this->assertEquals('item notes', $this->getFirstValueByColumn($csv, 'Notes'));
$this->assertEquals('product key', $this->getFirstValueByColumn($csv, 'Product'));
$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, 'Tax Name 1'));
$this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Tax Rate 1'));
$this->assertEquals('GST', $this->getFirstValueByColumn($csv, 'Item Tax Name 1'));
$this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Item Tax Rate 1'));
}
@ -1347,17 +1347,17 @@ class ReportCsvGenerationTest extends TestCase
$reader = Reader::createFromString($csv);
$reader->setHeaderOffset(0);
$res = $reader->fetchColumnByName('First Name');
$res = $reader->fetchColumnByName('Contact First Name');
$res = iterator_to_array($res, true);
$this->assertEquals('john', $res[1]);
$res = $reader->fetchColumnByName('Last Name');
$res = $reader->fetchColumnByName('Contact Last Name');
$res = iterator_to_array($res, true);
$this->assertEquals('doe', $res[1]);
$res = $reader->fetchColumnByName('Email');
$res = $reader->fetchColumnByName('Contact Email');
$res = iterator_to_array($res, true);
$this->assertEquals('john@doe.com', $res[1]);
@ -1406,14 +1406,14 @@ class ReportCsvGenerationTest extends TestCase
$response->assertStatus(200);
$csv = $response->streamedContent();
nlog($csv);
$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, 'PO Number'));
$this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Public Notes'));
$this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Private Notes'));
$this->assertEquals('Terms', $this->getFirstValueByColumn($csv, 'Terms'));
$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 = [
@ -1492,29 +1492,29 @@ nlog($csv);
$csv = $response->streamedContent();
$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, 'PO Number'));
$this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Public Notes'));
$this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Private Notes'));
$this->assertEquals('Terms', $this->getFirstValueByColumn($csv, 'Terms'));
$this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Date'));
$this->assertEquals('2021-01-02', $this->getFirstValueByColumn($csv, 'Due Date'));
$this->assertEquals('2021-01-03', $this->getFirstValueByColumn($csv, 'Partial Due Date'));
$this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Partial/Deposit'));
$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'));
$this->assertEquals('Footer', $this->getFirstValueByColumn($csv, 'Footer'));
$this->assertEquals('Tax 1', $this->getFirstValueByColumn($csv, 'Tax Name 1'));
$this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Tax Rate 1'));
$this->assertEquals('Tax 2', $this->getFirstValueByColumn($csv, 'Tax Name 2'));
$this->assertEquals('20', $this->getFirstValueByColumn($csv, 'Tax Rate 2'));
$this->assertEquals('Tax 3', $this->getFirstValueByColumn($csv, 'Tax Name 3'));
$this->assertEquals('30', $this->getFirstValueByColumn($csv, 'Tax Rate 3'));
$this->assertEquals('Sent', $this->getFirstValueByColumn($csv, 'Status'));
$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'));
}
@ -1642,30 +1642,32 @@ nlog($csv);
$response->assertStatus(200);
$csv = $response->streamedContent();
//nlog($csv);
$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, 'PO Number'));
$this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Public Notes'));
$this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Private Notes'));
$this->assertEquals('Terms', $this->getFirstValueByColumn($csv, 'Terms'));
$this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Date'));
$this->assertEquals('2020-01-01', $this->getFirstValueByColumn($csv, 'Valid Until'));
$this->assertEquals('2021-01-03', $this->getFirstValueByColumn($csv, 'Partial Due Date'));
$this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Partial/Deposit'));
$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'));
$this->assertEquals('Footer', $this->getFirstValueByColumn($csv, 'Footer'));
$this->assertEquals('Tax 1', $this->getFirstValueByColumn($csv, 'Tax Name 1'));
$this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Tax Rate 1'));
$this->assertEquals('Tax 2', $this->getFirstValueByColumn($csv, 'Tax Name 2'));
$this->assertEquals('20', $this->getFirstValueByColumn($csv, 'Tax Rate 2'));
$this->assertEquals('Tax 3', $this->getFirstValueByColumn($csv, 'Tax Name 3'));
$this->assertEquals('30', $this->getFirstValueByColumn($csv, 'Tax Rate 3'));
$this->assertEquals('Expired', $this->getFirstValueByColumn($csv, 'Status'));
$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'));
}
@ -1696,10 +1698,10 @@ nlog($csv);
$csv = $response->streamedContent();
$this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Amount'));
$this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Public Notes'));
$this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Private Notes'));
$this->assertEquals($this->user->present()->name(), $this->getFirstValueByColumn($csv, 'User'));
$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 = [
@ -1758,8 +1760,8 @@ nlog($csv);
$this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name'));
$this->assertEquals('Vendor 1', $this->getFirstValueByColumn($csv, 'Vendor Name'));
$this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Amount'));
$this->assertEquals('USD', $this->getFirstValueByColumn($csv, 'Currency'));
$this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Expense Amount'));
$this->assertEquals('USD', $this->getFirstValueByColumn($csv, 'Expense Currency'));
}

View File

@ -12,10 +12,24 @@
namespace Tests\Feature\Export;
use Tests\TestCase;
use App\Models\Client;
use App\Models\Expense;
use App\Models\Document;
use Tests\MockAccountData;
use App\Export\CSV\QuoteExport;
use App\Utils\Traits\MakesHash;
use App\Export\CSV\ClientExport;
use App\Export\CSV\CreditExport;
use App\Export\CSV\ContactExport;
use App\Export\CSV\ExpenseExport;
use App\Export\CSV\InvoiceExport;
use App\Export\CSV\PaymentExport;
use App\Export\CSV\ProductExport;
use App\Export\CSV\ActivityExport;
use App\Export\CSV\DocumentExport;
use App\Jobs\Report\PreviewReport;
use Illuminate\Support\Facades\Cache;
use App\Export\CSV\PurchaseOrderExport;
use Illuminate\Routing\Middleware\ThrottleRequests;
/**
@ -44,6 +58,407 @@ class ReportPreviewTest extends TestCase
}
public function testProductJsonExport()
{
\App\Models\Product::factory()->count(5)->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
]);
$data = [
'send_email' => false,
'date_range' => 'all',
'report_keys' => [],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/products?output=json', $data)
->assertStatus(200);
$p = (new PreviewReport($this->company, $data, ProductExport::class, '123'))->handle();
$this->assertNull($p);
$r = Cache::pull('123');
$this->assertNotNull($r);
}
public function testPaymentJsonExport()
{
\App\Models\Payment::factory()->count(5)->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $this->client->id,
]);
$data = [
'send_email' => false,
'date_range' => 'all',
'report_keys' => [],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/payments?output=json', $data)
->assertStatus(200);
$p = (new PreviewReport($this->company, $data, PaymentExport::class, '123'))->handle();
$this->assertNull($p);
$r = Cache::pull('123');
$this->assertNotNull($r);
}
public function testPurchaseOrderItemJsonExport()
{
\App\Models\PurchaseOrder::factory()->count(5)->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'vendor_id' => $this->vendor->id,
]);
$data = [
'send_email' => false,
'date_range' => 'all',
'report_keys' => [],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/purchase_order_items?output=json', $data)
->assertStatus(200);
$p = (new PreviewReport($this->company, $data, \App\Export\CSV\PurchaseOrderItemExport::class, '123'))->handle();
$this->assertNull($p);
$r = Cache::pull('123');
$this->assertNotNull($r);
//nlog($r);
}
public function testQuoteItemJsonExport()
{
\App\Models\Quote::factory()->count(5)->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $this->client->id,
]);
$data = [
'send_email' => false,
'date_range' => 'all',
'report_keys' => [],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/quote_items?output=json', $data)
->assertStatus(200);
$p = (new PreviewReport($this->company, $data, \App\Export\CSV\QuoteItemExport::class, '123'))->handle();
$this->assertNull($p);
$r = Cache::pull('123');
$this->assertNotNull($r);
//nlog($r);
}
public function testInvoiceItemJsonExport()
{
\App\Models\Invoice::factory()->count(5)->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $this->client->id,
]);
$data = [
'send_email' => false,
'date_range' => 'all',
'report_keys' => [],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/invoice_items?output=json', $data)
->assertStatus(200);
$p = (new PreviewReport($this->company, $data, \App\Export\CSV\InvoiceItemExport::class, '123'))->handle();
$this->assertNull($p);
$r = Cache::pull('123');
$this->assertNotNull($r);
//nlog($r);
}
public function testPurchaseOrderJsonExport()
{
\App\Models\PurchaseOrder::factory()->count(5)->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'vendor_id' => $this->vendor->id,
]);
$data = [
'send_email' => false,
'date_range' => 'all',
'report_keys' => [],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/purchase_orders?output=json', $data)
->assertStatus(200);
$p = (new PreviewReport($this->company, $data, PurchaseOrderExport::class, '123'))->handle();
$this->assertNull($p);
$r = Cache::pull('123');
$this->assertNotNull($r);
}
public function testQuoteJsonExport()
{
\App\Models\Quote::factory()->count(5)->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $this->client->id,
]);
$data = [
'send_email' => false,
'date_range' => 'all',
'report_keys' => [],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/quotes?output=json', $data)
->assertStatus(200);
$p = (new PreviewReport($this->company, $data, QuoteExport::class, '123'))->handle();
$this->assertNull($p);
$r = Cache::pull('123');
$this->assertNotNull($r);
}
public function testInvoiceJsonExport()
{
\App\Models\Invoice::factory()->count(5)->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $this->client->id,
]);
$data = [
'send_email' => false,
'date_range' => 'all',
'report_keys' => [],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/invoices?output=json', $data)
->assertStatus(200);
$p = (new PreviewReport($this->company, $data, InvoiceExport::class, '123'))->handle();
$this->assertNull($p);
$r = Cache::pull('123');
$this->assertNotNull($r);
}
public function testExpenseJsonExport()
{
Expense::factory()->count(5)->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
]);
$data = [
'send_email' => false,
'date_range' => 'all',
'report_keys' => [],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/expenses?output=json', $data)
->assertStatus(200);
$p = (new PreviewReport($this->company, $data, ExpenseExport::class, '123'))->handle();
$this->assertNull($p);
$r = Cache::pull('123');
$this->assertNotNull($r);
//nlog($r);
}
public function testDocumentJsonExport()
{
Document::factory()->count(5)->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'documentable_type' => Client::class,
'documentable_id' => $this->client->id,
]);
$data = [
'send_email' => false,
'date_range' => 'all',
'report_keys' => [],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/documents?output=json', $data)
->assertStatus(200);
$p = (new PreviewReport($this->company, $data, DocumentExport::class, '123'))->handle();
$this->assertNull($p);
$r = Cache::pull('123');
$this->assertNotNull($r);
//nlog($r);
}
public function testClientExportJson()
{
$data = [
'send_email' => false,
'date_range' => 'all',
'report_keys' => [],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/clients?output=json', $data)
->assertStatus(200);
$data = [
'send_email' => false,
'date_range' => 'all',
'report_keys' => ['client.name','client.balance'],
];
$p = (new PreviewReport($this->company, $data, ClientExport::class, 'client_export1'))->handle();
$this->assertNull($p);
$r = Cache::pull('client_export1');
$this->assertNotNull($r);
}
public function testClientContactExportJsonLimitedKeys()
{
$data = [
'send_email' => false,
'date_range' => 'all',
'report_keys' => [],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/client_contacts?output=json', $data)
->assertStatus(200);
$data = [
'send_email' => false,
'date_range' => 'all',
'report_keys' => ['client.name','client.balance','contact.email'],
];
$p = (new PreviewReport($this->company, $data, ContactExport::class, '123'))->handle();
$this->assertNull($p);
$r = Cache::pull('123');
$this->assertNotNull($r);
}
public function testActivityCSVExportJson()
{
$data = [
'send_email' => false,
'date_range' => 'all',
'report_keys' => [],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/activities?output=json', $data)
->assertStatus(200);
$p = (new PreviewReport($this->company, $data, ActivityExport::class, '123'))->handle();
$this->assertNull($p);
$r = Cache::pull('123');
$this->assertNotNull($r);
}
public function testCreditExportPreview()
{
@ -57,6 +472,10 @@ class ReportPreviewTest extends TestCase
$this->assertNull($p);
$r = Cache::pull('123');
$this->assertNotNull($r);
}
public function testCreditPreview()
@ -73,5 +492,6 @@ class ReportPreviewTest extends TestCase
])->postJson('/api/v1/reports/credits?output=json', $data)
->assertStatus(200);
}
}

View File

@ -11,15 +11,16 @@
namespace Tests\Feature;
use Tests\TestCase;
use App\Models\SystemLog;
use Tests\MockAccountData;
use App\Jobs\Entity\EmailEntity;
use App\Utils\Traits\GeneratesCounter;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Session;
use Illuminate\Validation\ValidationException;
use Tests\MockAccountData;
use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseTransactions;
/**
* @test
@ -47,6 +48,109 @@ class InvoiceEmailTest extends TestCase
}
public function testClientEmailHistory()
{
$system_log = new SystemLog();
$system_log->company_id = $this->company->id;
$system_log->client_id = $this->client->id;
$system_log->category_id = SystemLog::CATEGORY_MAIL;
$system_log->event_id = SystemLog::EVENT_MAIL_SEND;
$system_log->type_id = SystemLog::TYPE_WEBHOOK_RESPONSE;
$system_log->log = [
'history' => [
'entity_id' => $this->invoice->hashed_id,
'entity_type' => 'invoice',
'subject' => 'Invoice #1',
'events' => [
[
'recipient' => 'bob@gmail.com',
'status' => 'Delivered',
'delivery_message' => 'A message that was deliveryed',
'server' => 'email.mx.com',
'server_ip' => '127.0.0.1',
'date' => \Carbon\Carbon::parse('2023-10-10')->format('Y-m-d H:m:s') ?? '',
],
],
]
];
$system_log->save();
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/emails/clientHistory/'.$this->client->hashed_id);
$response->assertStatus(200);
$arr = $response->json();
$this->assertEquals('invoice', $arr[0]['entity_type']);
$count = SystemLog::where('client_id', $this->client->id)
->where('category_id', SystemLog::CATEGORY_MAIL)
->orderBy('id', 'DESC')
->count();
$this->assertEquals(1, $count);
}
public function testEntityEmailHistory()
{
$system_log = new SystemLog();
$system_log->company_id = $this->company->id;
$system_log->client_id = $this->client->id;
$system_log->category_id = SystemLog::CATEGORY_MAIL;
$system_log->event_id = SystemLog::EVENT_MAIL_SEND;
$system_log->type_id = SystemLog::TYPE_WEBHOOK_RESPONSE;
$system_log->log = [
'history' => [
'entity_id' => $this->invoice->hashed_id,
'entity_type' => 'invoice',
'subject' => 'Invoice #1',
'events' => [
[
'recipient' => 'bob@gmail.com',
'status' => 'Delivered',
'delivery_message' => 'A message that was deliveryed',
'server' => 'email.mx.com',
'server_ip' => '127.0.0.1',
'date' => \Carbon\Carbon::parse('2023-10-10')->format('Y-m-d H:m:s') ?? '',
],
],
]
];
$system_log->save();
$data = [
'entity' => 'invoice',
'entity_id' => $this->invoice->hashed_id,
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/emails/entityHistory/', $data);
$response->assertStatus(200);
$arr = $response->json();
$this->assertEquals('invoice', $arr[0]['entity_type']);
$this->assertEquals($this->invoice->hashed_id, $arr[0]['entity_id']);
$count = SystemLog::where('company_id', $this->company->id)
->where('category_id', SystemLog::CATEGORY_MAIL)
->whereJsonContains('log->history->entity_id', $this->invoice->hashed_id)
->count();
$this->assertEquals(1, $count);
}
public function testTemplateValidation()
{
$data = [

View File

@ -11,15 +11,23 @@
namespace Tests\Feature;
use App\Jobs\Util\ReminderJob;
use App\Models\Invoice;
use App\Utils\Traits\MakesHash;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Support\Carbon;
use Tests\MockAccountData;
use Tests\TestCase;
use App\Models\User;
use App\Models\Client;
use App\Models\Account;
use App\Models\Company;
use App\Models\Invoice;
use Tests\MockAccountData;
use App\Models\CompanyToken;
use App\Models\ClientContact;
use App\Jobs\Util\ReminderJob;
use Illuminate\Support\Carbon;
use App\Utils\Traits\MakesHash;
use App\DataMapper\CompanySettings;
use App\Factory\CompanyUserFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Foundation\Testing\DatabaseTransactions;
/**
* @test
@ -49,10 +57,201 @@ class ReminderTest extends TestCase
$this->withoutExceptionHandling();
}
public $company;
public $user;
public $payload;
public $account;
public $client;
public $token;
public $cu;
public $invoice;
private function buildData($settings = null)
{
$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(),
]);
if(!$settings)
{
$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->client = Client::factory()->create([
'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'
]);
$this->invoice = Invoice::factory()->create([
'user_id' => $this->user->id,
'company_id' => $this->company->id,
'client_id' => $this->client->id,
'date' => now()->addSeconds($this->client->timezone_offset())->format('Y-m-d'),
'next_send_date' => null,
'due_date' => Carbon::now()->addSeconds($this->client->timezone_offset())->addDays(5)->format('Y-m-d'),
'last_sent_date' => now()->addSeconds($this->client->timezone_offset()),
'reminder_last_sent' => null,
'status_id' => 2,
'amount' => 10,
'balance' => 10,
]);
}
public function testsForTranslationsInReminders()
{
$translations = new \stdClass;
$translations->late_fee_added = "Fee added :date";
$settings = $this->company->settings;
$settings->enable_reminder1 = true;
$settings->schedule_reminder1 = 'after_invoice_date';
$settings->num_days_reminder1 = 1;
$settings->enable_reminder2 = true;
$settings->schedule_reminder2 = 'after_invoice_date';
$settings->num_days_reminder2 = 2;
$settings->enable_reminder3 = true;
$settings->schedule_reminder3 = 'after_invoice_date';
$settings->num_days_reminder3 = 3;
$settings->timezone_id = '29';
$settings->entity_send_time = 0;
$settings->endless_reminder_frequency_id = '';
$settings->enable_reminder_endless = false;
$settings->translations = $translations;
$settings->late_fee_amount1 = '101';
$settings->late_fee_amount2 = '102';
$settings->late_fee_amount3 = '103';
$this->buildData(($settings));
$this->assertEquals("Fee added :date", $this->company->settings->translations->late_fee_added);
$fetched_settings = $this->client->getMergedSettings();
$this->assertEquals("Fee added :date", $fetched_settings->translations->late_fee_added);
$this->invoice->service()->setReminder($settings)->save();
$this->invoice = $this->invoice->fresh();
$this->assertEquals(now()->addSeconds($this->client->timezone_offset())->format('Y-m-d'), $this->invoice->date);
$this->assertNotNull($this->invoice->next_send_date);
$this->assertEquals(now()->addDay()->addSeconds($this->client->timezone_offset())->format('Y-m-d 00:00:00'), $this->invoice->next_send_date);
$this->travelTo(now()->addDay()->startOfDay()->addHour());
(new ReminderJob())->handle();
$this->invoice = $this->invoice->fresh();
$this->assertNotNull($this->invoice->reminder1_sent);
$this->assertNotNull($this->invoice->reminder_last_sent);
$fee = collect($this->invoice->line_items)->where('type_id', 5)->first();
$this->assertEquals(101, $fee->cost);
$this->assertEquals('Fee added '.now()->format('d/M/Y'), $fee->notes);
$this->travelTo(now()->addDay()->startOfDay()->addHour());
(new ReminderJob())->handle();
$this->invoice = $this->invoice->fresh();
$this->assertNotNull($this->invoice->reminder2_sent);
$this->assertNotNull($this->invoice->reminder_last_sent);
$fee = collect($this->invoice->line_items)->where('cost', 102)->first();
$this->assertEquals(102, $fee->cost);
$this->assertEquals('Fee added '.now()->format('d/M/Y'), $fee->notes);
$this->travelTo(now()->addDay()->startOfDay()->addHour());
(new ReminderJob())->handle();
$this->invoice = $this->invoice->fresh();
$this->assertNotNull($this->invoice->reminder3_sent);
$this->assertNotNull($this->invoice->reminder_last_sent);
$fee = collect($this->invoice->line_items)->where('cost', 103)->first();
$this->assertEquals(103, $fee->cost);
$this->assertEquals('Fee added '.now()->format('d/M/Y'), $fee->notes);
// $this->travelTo(now()->addHours(1));
// }
$this->travelBack();
}
public function testForReminderFiringCorrectly()
{
$this->invoice->status_id = 2;
$this->invoice->amount = 10;
$this->invoice->balance = 10;
$this->invoice->next_send_date = null;
$this->invoice->date = now()->format('Y-m-d');
$this->invoice->last_sent_date = now();

View File

@ -572,6 +572,8 @@ trait MockAccountData
$this->purchase_order->tax_rate2 = 0;
$this->purchase_order->tax_rate3 = 0;
$this->purchase_order->line_items = InvoiceItemFactory::generate(5);
$this->purchase_order->uses_inclusive_taxes = false;
$this->purchase_order->save();