Track signup platform (#3014)

* update company settings and OpenAPI definitions

* Fixes for tests

* Add extra variables to company settings

* Track signup platform when new account signup processed
This commit is contained in:
David Bomba 2019-10-24 15:46:24 +11:00 committed by GitHub
parent adfced11d6
commit a60613aa26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 205 additions and 75 deletions

View File

@ -26,9 +26,10 @@ class CompanySettings extends BaseSettings
public $language_id = '';
public $show_currency_code = false;
public $currency_id = '1';
public $payment_terms = 1;
public $company_gateway_ids = '';
public $currency_id = '1';
public $custom_value1 = '';
public $custom_value2 = '';
@ -41,6 +42,8 @@ class CompanySettings extends BaseSettings
public $custom_invoice_taxes4 = false;
public $default_task_rate = 0;
public $payment_terms = 1;
public $send_reminders = false;
public $show_tasks_in_portal = false;
@ -75,6 +78,27 @@ class CompanySettings extends BaseSettings
public $credit_number_pattern = '';
public $credit_number_counter = 1;
public $task_number_prefix = '';
public $task_number_pattern = '';
public $task_number_counter = 1;
public $expense_number_prefix = '';
public $expense_number_pattern = '';
public $expense_number_counter = 1;
public $vendor_number_prefix = '';
public $vendor_number_pattern = '';
public $vendor_number_counter = 1;
public $ticket_number_prefix = '';
public $ticket_number_pattern = '';
public $ticket_number_counter = 1;
public $payment_number_prefix = '';
public $payment_number_pattern = '';
public $payment_number_counter = 1;
public $shared_invoice_quote_counter = false;
public $recurring_invoice_number_prefix = 'R';
@ -107,7 +131,22 @@ class CompanySettings extends BaseSettings
public $payment_type_id = '1';
public $custom_fields = '';
public $invoice_fields = '';
public $email_footer = '';
public $enable_portal_password = false;
public $show_accept_invoice_terms = false;
public $show_accept_quote_terms = false;
public $require_invoice_signature = false;
public $require_quote_signature = false;
//email settings
public $reply_to_email = '';
public $bcc_email = '';
public $pdf_email_attachment = false;
public $ubl_email_attachment = false;
public $email_style = ''; //plain, light, dark, custom
public $email_style_custom = ''; //the template itself
public $email_subject_invoice = '';
public $email_subject_quote = '';
public $email_subject_payment = '';
@ -120,11 +159,7 @@ class CompanySettings extends BaseSettings
public $email_template_reminder1 = '';
public $email_template_reminder2 = '';
public $email_template_reminder3 = '';
public $enable_portal_password = false;
public $show_accept_invoice_terms = false;
public $show_accept_quote_terms = false;
public $require_invoice_signature = false;
public $require_quote_signature = false;
public $email_footer = '';
/* Company Meta data that we can use to build sub companies*/
@ -143,6 +178,28 @@ class CompanySettings extends BaseSettings
public $id_number = '';
public static $casts = [
'task_number_prefix' => 'string',
'task_number_pattern' => 'string',
'task_number_counter' => 'int',
'expense_number_prefix' => 'string',
'expense_number_pattern' => 'string',
'expense_number_counter' => 'int',
'vendor_number_prefix' => 'string',
'vendor_number_pattern' => 'string',
'vendor_number_counter' => 'int',
'ticket_number_prefix' => 'string',
'ticket_number_pattern' => 'string',
'ticket_number_counter' => 'int',
'payment_number_prefix' => 'string',
'payment_number_pattern' => 'string',
'payment_number_counter' => 'int',
'reply_to_email' => 'string',
'bcc_email' => 'string',
'pdf_email_attachment' => 'bool',
'ubl_email_attachment' => 'bool',
'email_style' => 'string',
'email_style_custom' => 'string',
'company_gateway_ids' => 'string',
'address1' => 'string',
'address2' => 'string',
'city' => 'string',

View File

@ -12,7 +12,7 @@
* @OA\Property(property="update_details", type="boolean", example=true, description="______"),
* @OA\Property(property="adjust_fee_percent", type="boolean", example=true, description="______"),
* @OA\Property(property="config", type="string", example="2", description="______"),
* @OA\Property(property="priority_id", type="string", example="2", description="______"),
* @OA\Property(property="priority", type="string", example="2", description="______"),
* @OA\Property(property="user_id", type="string", example="2", description="______"),
* @OA\Property(property="min_limit", type="string", example="2", description="______"),
* @OA\Property(property="max_limit", type="string", example="2", description="______"),

View File

@ -10,6 +10,7 @@
* @OA\Property(property="show_currency_code", type="boolean", example=true, description="____________"),
* @OA\Property(property="currency_id", type="string", example=true, description="The settings currency id"),
* @OA\Property(property="payment_terms", type="integer", example="1", description="-1 sets no payment term, 0 sets payment due immediately, positive integers indicates payment terms in days"),
* @OA\Property(property="company_gateway_ids", type="string", example="1,2,3,4", description="A commad separate list of available gateways"),
* @OA\Property(property="custom_value1", type="string", example="Custom Label", description="____________"),
* @OA\Property(property="custom_value2", type="string", example="Custom Label", description="____________"),
* @OA\Property(property="custom_value3", type="string", example="Custom Label", description="____________"),
@ -21,6 +22,13 @@
* @OA\Property(property="default_task_rate", type="number", format="float", example="10.00", description="____________"),
* @OA\Property(property="send_reminders", type="boolean", example=true, description="____________"),
* @OA\Property(property="show_tasks_in_portal", type="boolean", example=true, description="____________"),
* @OA\Property(property="email_style", type="string", example="light", description="options include plain,light,dark,custom"),
* @OA\Property(property="reply_to_email", type="string", example="email@gmail.com", description="The reply to email address"),
* @OA\Property(property="bcc_email", type="string", example="email@gmail.com, contact@gmail.com", description="A comma separate list of BCC emails"),
*
* @OA\Property(property="pdf_email_attachment", type="boolean", example=true, description="Toggles whether to attach PDF as attachment"),
* @OA\Property(property="ubl_email_attachment", type="boolean", example=true, description="Toggles whether to attach UBL as attachment"),
* @OA\Property(property="email_style_custom", type="string", example="<HTML></HTML>", description="The custom template"),
* @OA\Property(property="custom_message_dashboard", type="string", example="Please pay invoices immediately", description="____________"),
* @OA\Property(property="custom_message_unpaid_invoice", type="string", example="Please pay invoices immediately", description="____________"),
* @OA\Property(property="custom_message_paid_invoice", type="string", example="Thanks for paying this invoice!", description="____________"),
@ -29,6 +37,22 @@
* @OA\Property(property="auto_archive_invoice", type="boolean", example=true, description="____________"),
* @OA\Property(property="inclusive_taxes", type="boolean", example=true, description="____________"),
* @OA\Property(property="translations", type="object", example="", description="JSON payload of customized translations"),
* @OA\Property(property="task_number_prefix", type="string", example="R", description="This string is prepended to the task number"),
* @OA\Property(property="task_number_pattern", type="string", example="{$year}-{$counter}", description="Allows customisation of the task number pattern"),
* @OA\Property(property="task_number_counter", type="integer", example="1", description="____________"),
* @OA\Property(property="expense_number_prefix", type="string", example="R", description="This string is prepended to the expense number"),
* @OA\Property(property="expense_number_pattern", type="string", example="{$year}-{$counter}", description="Allows customisation of the expense number pattern"),
* @OA\Property(property="expense_number_counter", type="integer", example="1", description="____________"),
* @OA\Property(property="vendor_number_prefix", type="string", example="R", description="This string is prepended to the vendor number"),
* @OA\Property(property="vendor_number_pattern", type="string", example="{$year}-{$counter}", description="Allows customisation of the vendor number pattern"),
* @OA\Property(property="vendor_number_counter", type="integer", example="1", description="____________"),
* @OA\Property(property="ticket_number_prefix", type="string", example="R", description="This string is prepended to the ticket number"),
* @OA\Property(property="ticket_number_pattern", type="string", example="{$year}-{$counter}", description="Allows customisation of the ticket number pattern"),
* @OA\Property(property="ticket_number_counter", type="integer", example="1", description="____________"),
*
* @OA\Property(property="payment_number_prefix", type="string", example="R", description="This string is prepended to the payment number"),
* @OA\Property(property="payment_number_pattern", type="string", example="{$year}-{$counter}", description="Allows customisation of the payment number pattern"),
* @OA\Property(property="payment_number_counter", type="integer", example="1", description="____________"),
* @OA\Property(property="invoice_number_prefix", type="string", example="R", description="This string is prepended to the invoice number"),
* @OA\Property(property="invoice_number_pattern", type="string", example="{$year}-{$counter}", description="Allows customisation of the invoice number pattern"),
* @OA\Property(property="invoice_number_counter", type="integer", example="1", description="____________"),
@ -58,11 +82,11 @@
* @OA\Property(property="invoice_footer", type="string", example="1", description="The default invoice footer"),
* @OA\Property(property="invoice_labels", type="string", example="1", description="JSON string of invoice labels"),
* @OA\Property(property="show_item_taxes", type="boolean", example=true, description="Toggles whether the itemised taxes are displayed"),
* @OA\Property(property="tax_rate1", type="float", example="10", description="The tax rate (float)"),
* @OA\Property(property="tax_rate1", type="number", example="10", description="The tax rate (float)"),
* @OA\Property(property="tax_name1", type="string", example="GST", description="The tax name"),
* @OA\Property(property="tax_rate2", type="float", example="10", description="The tax rate (float)"),
* @OA\Property(property="tax_rate2", type="number", example="10", description="The tax rate (float)"),
* @OA\Property(property="tax_name2", type="string", example="GST", description="The tax name"),
* @OA\Property(property="tax_rate3", type="float", example="10", description="The tax rate (float)"),
* @OA\Property(property="tax_rate3", type="number", example="10", description="The tax rate (float)"),
* @OA\Property(property="tax_name3", type="string", example="GST", description="The tax name"),
* @OA\Property(property="enable_second_tax_rate", type="boolean", example=true, description="Toggles whether the a second tax rate can be applied"),
* @OA\Property(property="payment_type_id", type="string", example="1", description="The default payment type id"),
@ -87,7 +111,7 @@
* @OA\Property(property="require_invoice_signature", type="boolean", example=true, description="Toggles whether a invoice signature is required"),
* @OA\Property(property="require_quote_signature", type="boolean", example=true, description="Toggles whether a quote signature is required"),
* @OA\Property(property="name", type="string", example="Acme Co", description="The company name"),
* @OA\Property(property="company_logo", type="file", example="logo.png", description="The company logo file"),
* @OA\Property(property="company_logo", type="object", example="logo.png", description="The company logo file"),
* @OA\Property(property="website", type="string", example="www.acme.com", description="The company website URL"),
* @OA\Property(property="address1", type="string", example="Suite 888", description="____________"),
* @OA\Property(property="address2", type="string", example="5 Jimbo Way", description="____________"),

View File

@ -16,6 +16,7 @@ use App\Models\CompanyToken;
use Closure;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
class PasswordProtection
{
@ -55,7 +56,7 @@ class PasswordProtection
}
Cache::add(auth()->user()->email."_logged_in", 'logged_in', now()->addMinutes(5));
Cache::add(auth()->user()->email."_logged_in", Str::random(64), now()->addMinutes(10));
return $next($request);
}

View File

@ -34,6 +34,8 @@ class CreateAccountRequest extends Request
*/
public function rules()
{
$this->sanitize();
return [
//'email' => 'required|string|email|max:100',
'first_name' => 'required|string|max:100',
@ -50,7 +52,9 @@ class CreateAccountRequest extends Request
{
$input = $this->all();
// $this->replace($input);
$input['user_agent'] = request()->server('HTTP_USER_AGENT');
$this->replace($input);
return $this->all();
}

View File

@ -42,6 +42,7 @@ class Account extends BaseModel
'utm_campaign',
'utm_term',
'utm_content',
'user_agent',
];
/**

View File

@ -271,7 +271,12 @@ class Client extends BaseModel
*/
public function getCreditCardGateway() :?CompanyGateway
{
$gateways = $this->company->company_gateways;
$company_gateways = $this->getSetting('company_gateway_ids');
if($company_gateways)
$gateways = $this->company->company_gateways->whereIn('id', $payment_gateways);
else
$gateways = $this->company->company_gateways;
foreach($gateways as $gateway)
{
@ -315,7 +320,12 @@ class Client extends BaseModel
//Also need to harvest the list of client gateway tokens and present these
//for instant payment
$gateways = $this->company->company_gateways;
$company_gateways = $this->client->getSetting('company_gateway_ids');
if($company_gateways)
$gateways = $this->company->company_gateways->whereIn('id', $payment_gateways);
else
$gateways = $this->company->company_gateways;
$gateways->filter(function ($method) use ($amount){
if($method->min_limit !== null && $amount < $method->min_limit)

View File

@ -137,7 +137,7 @@ class Company extends BaseModel
*/
public function company_gateways()
{
return $this->hasMany(CompanyGateway::class)->orderBy('priority_id','ASC');
return $this->hasMany(CompanyGateway::class)->orderBy('priority','DESC');
}
/**

View File

@ -29,7 +29,7 @@ class CompanyGateway extends BaseModel
'show_shipping_address',
'update_details',
'config',
'priority_id',
'priority',
'min_limit',
'max_limit',
'fee_amount',

View File

@ -52,7 +52,7 @@ class CompanyGatewayTransformer extends EntityTransformer
'show_shipping_address' => (bool)$company_gateway->show_shipping_address,
'update_details' => (bool)$company_gateway->update_details,
'config' => (string) $company_gateway->getConfigTransformed(),
'priority_id' => (int)$company_gateway->priority_id,
'priority' => (int)$company_gateway->priority,
'min_limit' => (float)$company_gateway->min_limit ?: null,
'max_limit' => (float)$company_gateway->max_limit ?: null,
'fee_amount' => (float) $company_gateway->fee_amount ?: null,

View File

@ -76,6 +76,9 @@ class Number
if ($client->country->decimal_separator)
$decimal = $client->country->decimal_separator;
if($client->country->swap_currency_symbol)
$swapSymbol = $client->country->swap_currency_symbol;
$value = number_format($value, $precision, $decimal, $thousand);
$symbol = $currency->symbol;

View File

@ -101,7 +101,8 @@ class CreateUsersTable extends Migration
$table->date('plan_started')->nullable();
$table->date('plan_paid')->nullable();
$table->date('plan_expires')->nullable();
$table->string('user_agent')->nullable();
$table->unsignedInteger('payment_id')->nullable()->index();
$table->unsignedInteger('default_company_id');
@ -368,7 +369,7 @@ class CreateUsersTable extends Migration
$table->boolean('show_shipping_address')->default(true)->nullable();
$table->boolean('update_details')->default(false)->nullable();
$table->text('config');
$table->unsignedInteger('priority_id')->default(0);
$table->unsignedInteger('priority')->default(0);
$table->decimal('min_limit', 13, 2)->nullable();
$table->decimal('max_limit', 13, 2)->nullable();

View File

@ -203,7 +203,7 @@ class RandomDataSeeder extends Seeder
$cg->show_shipping_address = true;
$cg->update_details = true;
$cg->config = encrypt(config('ninja.testvars.stripe'));
$cg->priority_id = 1;
$cg->priority = 1;
$cg->save();
$cg = new CompanyGateway;
@ -215,7 +215,7 @@ class RandomDataSeeder extends Seeder
$cg->show_shipping_address = true;
$cg->update_details = true;
$cg->config = encrypt(config('ninja.testvars.stripe'));
$cg->priority_id = 2;
$cg->priority = 2;
$cg->save();
}
@ -230,7 +230,7 @@ class RandomDataSeeder extends Seeder
$cg->show_shipping_address = true;
$cg->update_details = true;
$cg->config = encrypt(config('ninja.testvars.paypal'));
$cg->priority_id = 3;
$cg->priority = 3;
$cg->save();
}

View File

@ -29,77 +29,77 @@ class ClientModelTest extends TestCase
}
// public function testPaymentMethods()
// {
public function testPaymentMethods()
{
// $amount = 40;
$amount = 40;
// $company_gateways = $this->client->getSetting('company_gateways');
$company_gateways = $this->client->getSetting('company_gateway_ids');
// //todo create a test where we actually SET a value in the settings->company_gateways object and test if we can harvest.
//todo create a test where we actually SET a value in the settings->company_gateways object and test if we can harvest.
// if($company_gateways)
// $gateways = $this->company->company_gateways->whereIn('id', $payment_gateways);
// else
// $gateways = $this->company->company_gateways;
if($company_gateways)
$gateways = $this->company->company_gateways->whereIn('id', $payment_gateways);
else
$gateways = $this->company->company_gateways;
// $this->assertNotNull($gateways);
$this->assertNotNull($gateways);
// $pre_count = $gateways->count();
$pre_count = $gateways->count();
// $gateways->filter(function ($method) use ($amount){
// if($method->min_limit !== null && $amount < $method->min_limit)
// return false;
$gateways->filter(function ($method) use ($amount){
if($method->min_limit !== null && $amount < $method->min_limit)
return false;
// if($method->max_limit !== null && $amount > $method->min_limit)
// return false;
// });
if($method->max_limit !== null && $amount > $method->min_limit)
return false;
});
// $post_count = $gateways->count();
$post_count = $gateways->count();
// $this->assertEquals($pre_count, $post_count);
$this->assertEquals($pre_count, $post_count);
// $payment_methods = [];
$payment_methods = [];
// foreach($gateways as $gateway)
// foreach($gateway->driver($this->client)->gatewayTypes() as $type)
// $payment_methods[] = [$gateway->id => $type];
foreach($gateways as $gateway)
foreach($gateway->driver($this->client)->gatewayTypes() as $type)
$payment_methods[] = [$gateway->id => $type];
// $this->assertEquals(8, count($payment_methods));
$this->assertEquals(8, count($payment_methods));
// $payment_methods_collections = collect($payment_methods);
$payment_methods_collections = collect($payment_methods);
// //** Plucks the remaining keys into its own collection
// $payment_methods_intersect = $payment_methods_collections->intersectByKeys( $payment_methods_collections->flatten(1)->unique() );
//** Plucks the remaining keys into its own collection
$payment_methods_intersect = $payment_methods_collections->intersectByKeys( $payment_methods_collections->flatten(1)->unique() );
// $this->assertEquals(4, $payment_methods_intersect->count());
$this->assertEquals(4, $payment_methods_intersect->count());
// $payment_urls = [];
$payment_urls = [];
// foreach($payment_methods_intersect as $key => $child_array)
// {
// foreach($child_array as $gateway_id => $gateway_type_id)
// {
foreach($payment_methods_intersect as $key => $child_array)
{
foreach($child_array as $gateway_id => $gateway_type_id)
{
// $gateway = $gateways->where('id', $gateway_id)->first();
$gateway = $gateways->where('id', $gateway_id)->first();
// $this->assertNotNull($gateway);
$this->assertNotNull($gateway);
// $fee_label = $gateway->calcGatewayFeeLabel($amount, $this->client);
$fee_label = $gateway->calcGatewayFeeLabel($amount, $this->client);
// $payment_urls[] = [
// 'label' => ctrans('texts.' . $gateway->getTypeAlias($gateway_type_id)) . $fee_label,
// 'url' => URL::signedRoute('client.payments.process', [
// 'company_gateway_id' => $gateway_id,
// 'gateway_type_id' => $gateway_type_id])
// ];
// }
$payment_urls[] = [
'label' => ctrans('texts.' . $gateway->getTypeAlias($gateway_type_id)) . $fee_label,
'url' => URL::signedRoute('client.payments.process', [
'company_gateway_id' => $gateway_id,
'gateway_type_id' => $gateway_type_id])
];
}
// }
}
// $this->assertEquals(4, count($payment_urls));
// }
$this->assertEquals(4, count($payment_urls));
}
}

View File

@ -4,6 +4,7 @@ namespace Tests\Feature;
use App\DataMapper\ClientSettings;
use App\DataMapper\CompanySettings;
use App\Factory\InvoiceFactory;
use App\Models\Account;
use App\Models\Client;
use App\Models\Invoice;
@ -140,13 +141,41 @@ class InvoiceTest extends TestCase
])->put('/api/v1/invoices/'.$this->encodePrimaryKey($this->invoice->id), $invoice_update)
->assertStatus(200);
$response = $this->withHeaders([
}
public function testPostNewInvoice()
{
$invoice = [
'status_id' => 1,
'invoice_number' => 'dfdfd',
'discount' => 0,
'is_amount_discount' => 1,
'po_number' => '3434343',
'public_notes' => 'notes',
'is_deleted' => 0,
'custom_value1' => 0,
'custom_value2' => 0,
'custom_value3' => 0,
'custom_value4' => 0,
'status' => 1,
'client_id' => $this->encodePrimaryKey($this->client->id),
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/invoices/', $invoice)
->assertStatus(200);
}
public function testDeleteInvoice()
{
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->delete('/api/v1/invoices/'.$this->encodePrimaryKey($this->invoice->id));
$response->assertStatus(200);
}
}

View File

@ -203,7 +203,7 @@ trait MockAccountData
$cg->show_shipping_address = true;
$cg->update_details = true;
$cg->config = encrypt(config('ninja.testvars.stripe'));
$cg->priority_id = 1;
$cg->priority = 1;
$cg->save();
@ -216,7 +216,7 @@ trait MockAccountData
$cg->show_shipping_address = true;
$cg->update_details = true;
$cg->config = encrypt(config('ninja.testvars.stripe'));
$cg->priority_id = 2;
$cg->priority = 2;
$cg->save();
}