mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
commit
75a578ff23
@ -52,7 +52,10 @@ class StoreInvoiceRequest extends Request
|
|||||||
|
|
||||||
$rules['invitations.*.client_contact_id'] = 'distinct';
|
$rules['invitations.*.client_contact_id'] = 'distinct';
|
||||||
|
|
||||||
$rules['number'] = new UniqueInvoiceNumberRule($this->all());
|
if ($this->input('number')) {
|
||||||
|
$rules['number'] = 'unique:invoices,number,'.$this->id.',id,company_id,'.auth()->user()->company()->id;
|
||||||
|
}
|
||||||
|
// $rules['number'] = new UniqueInvoiceNumberRule($this->all());
|
||||||
|
|
||||||
$rules['project_id'] = ['bail', 'sometimes', new ValidProjectForClient($this->all())];
|
$rules['project_id'] = ['bail', 'sometimes', new ValidProjectForClient($this->all())];
|
||||||
|
|
||||||
@ -66,7 +69,7 @@ class StoreInvoiceRequest extends Request
|
|||||||
$input = $this->decodePrimaryKeys($input);
|
$input = $this->decodePrimaryKeys($input);
|
||||||
|
|
||||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||||
//$input['line_items'] = json_encode($input['line_items']);
|
|
||||||
$this->replace($input);
|
$this->replace($input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,10 @@ class StoreTaskRequest extends Request
|
|||||||
{
|
{
|
||||||
$rules = [];
|
$rules = [];
|
||||||
|
|
||||||
|
if ($this->input('number')) {
|
||||||
|
$rules['number'] = 'unique:tasks,number,'.$this->id.',id,company_id,'.auth()->user()->company()->id;
|
||||||
|
}
|
||||||
|
|
||||||
return $this->globalRules($rules);
|
return $this->globalRules($rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +51,10 @@ class StoreTaskRequest extends Request
|
|||||||
|
|
||||||
$input = $this->decodePrimaryKeys($this->all());
|
$input = $this->decodePrimaryKeys($this->all());
|
||||||
|
|
||||||
|
if (array_key_exists('status_id', $input) && is_string($input['status_id'])) {
|
||||||
|
$input['status_id'] = $this->decodePrimaryKey($input['status_id']);
|
||||||
|
}
|
||||||
|
|
||||||
$this->replace($input);
|
$this->replace($input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace App\Mail\Engine;
|
namespace App\Mail\Engine;
|
||||||
|
|
||||||
|
use App\Utils\HtmlEngine;
|
||||||
use App\Utils\Number;
|
use App\Utils\Number;
|
||||||
|
|
||||||
class QuoteEmailEngine extends BaseEmailEngine
|
class QuoteEmailEngine extends BaseEmailEngine
|
||||||
|
@ -53,6 +53,7 @@ class Expense extends BaseModel
|
|||||||
'custom_value2',
|
'custom_value2',
|
||||||
'custom_value3',
|
'custom_value3',
|
||||||
'custom_value4',
|
'custom_value4',
|
||||||
|
'number',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
|
@ -39,6 +39,7 @@ class Task extends BaseModel
|
|||||||
'status_sort_order',
|
'status_sort_order',
|
||||||
'invoice_documents',
|
'invoice_documents',
|
||||||
'rate',
|
'rate',
|
||||||
|
'number',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $touches = [];
|
protected $touches = [];
|
||||||
@ -97,9 +98,9 @@ class Task extends BaseModel
|
|||||||
$parts = json_decode($this->time_log) ?: [];
|
$parts = json_decode($this->time_log) ?: [];
|
||||||
|
|
||||||
if (count($parts)) {
|
if (count($parts)) {
|
||||||
return Carbon::createFromTimeStamp($parts[0][0]);
|
return Carbon::createFromTimeStamp($parts[0][0])->timestamp;
|
||||||
} else {
|
} else {
|
||||||
return '';
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,16 +45,53 @@ class TaskRepository extends BaseRepository
|
|||||||
*
|
*
|
||||||
* @return task|null task Object
|
* @return task|null task Object
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public function save(array $data, Task $task) : ?Task
|
public function save(array $data, Task $task) : ?Task
|
||||||
{
|
{
|
||||||
|
|
||||||
$task->fill($data);
|
$task->fill($data);
|
||||||
|
$task->save();
|
||||||
|
|
||||||
if(!$task->start_time)
|
$task->start_time = $task->start_time ?: $task->calcStartTime();
|
||||||
$task->start_time = $task->calcStartTime();
|
$task->number = empty($task->number) ? $this->getNextTaskNumber($task) : $task->number;
|
||||||
|
|
||||||
|
if (isset($data['description'])) {
|
||||||
|
$task->description = trim($data['description']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($data['status_sort_order'])) {
|
||||||
|
$task->status_sort_order = $data['status_sort_order'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($data['time_log'])) {
|
||||||
|
$time_log = json_decode($data['time_log']);
|
||||||
|
} elseif ($task->time_log) {
|
||||||
|
$time_log = json_decode($task->time_log);
|
||||||
|
} else {
|
||||||
|
$time_log = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
array_multisort($time_log);
|
||||||
|
|
||||||
|
if (isset($data['action'])) {
|
||||||
|
if ($data['action'] == 'start') {
|
||||||
|
$task->is_running = true;
|
||||||
|
$time_log[] = [strtotime('now'), false];
|
||||||
|
} elseif ($data['action'] == 'resume') {
|
||||||
|
$task->is_running = true;
|
||||||
|
$time_log[] = [strtotime('now'), false];
|
||||||
|
} elseif ($data['action'] == 'stop' && $task->is_running) {
|
||||||
|
$time_log[count($time_log) - 1][1] = time();
|
||||||
|
$task->is_running = false;
|
||||||
|
} elseif ($data['action'] == 'offline'){
|
||||||
|
$task->is_running = $data['is_running'] ? 1 : 0;
|
||||||
|
}
|
||||||
|
} elseif (isset($data['is_running'])) {
|
||||||
|
$task->is_running = $data['is_running'] ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$task->time_log = json_encode($time_log);
|
||||||
$task->duration = $task->calcDuration();
|
$task->duration = $task->calcDuration();
|
||||||
|
|
||||||
$task->save();
|
$task->save();
|
||||||
|
|
||||||
if (array_key_exists('documents', $data)) {
|
if (array_key_exists('documents', $data)) {
|
||||||
|
@ -198,7 +198,8 @@ trait ClientGroupSettingsSaver
|
|||||||
switch ($key) {
|
switch ($key) {
|
||||||
case 'int':
|
case 'int':
|
||||||
case 'integer':
|
case 'integer':
|
||||||
return ctype_digit(strval(abs($value)));
|
// return ctype_digit(strval(abs($value)));
|
||||||
|
return ctype_digit(strval($value));
|
||||||
case 'real':
|
case 'real':
|
||||||
case 'float':
|
case 'float':
|
||||||
case 'double':
|
case 'double':
|
||||||
|
@ -20,6 +20,7 @@ use App\Models\Payment;
|
|||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\Quote;
|
use App\Models\Quote;
|
||||||
use App\Models\RecurringInvoice;
|
use App\Models\RecurringInvoice;
|
||||||
|
use App\Models\Task;
|
||||||
use App\Models\Timezone;
|
use App\Models\Timezone;
|
||||||
use App\Models\Vendor;
|
use App\Models\Vendor;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
@ -312,6 +313,45 @@ trait GeneratesCounter
|
|||||||
return $vendor_number;
|
return $vendor_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the next task number.
|
||||||
|
*
|
||||||
|
* @param Task $task The task
|
||||||
|
* @return string The next task number.
|
||||||
|
*/
|
||||||
|
public function getNextTaskNumber(Task $task) :string
|
||||||
|
{
|
||||||
|
$this->resetCompanyCounters($task->company);
|
||||||
|
|
||||||
|
$counter = $task->company->settings->task_number_counter;
|
||||||
|
$setting_entity = $task->company->settings->task_number_counter;
|
||||||
|
|
||||||
|
$task_number = $this->checkEntityNumber(Task::class, $task, $counter, $task->company->settings->counter_padding, $task->company->settings->task_number_pattern);
|
||||||
|
|
||||||
|
$this->incrementCounter($task->company, 'task_number_counter');
|
||||||
|
|
||||||
|
return $task_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the next expense number.
|
||||||
|
*
|
||||||
|
* @param Expense $expense The expense
|
||||||
|
* @return string The next expense number.
|
||||||
|
*/
|
||||||
|
public function getNextExpenseNumber(Expense $expense) :string
|
||||||
|
{
|
||||||
|
$this->resetCompanyCounters($expense->company);
|
||||||
|
|
||||||
|
$counter = $expense->company->settings->expense_number_counter;
|
||||||
|
$setting_entity = $expense->company->settings->expense_number_counter;
|
||||||
|
|
||||||
|
$expense_number = $this->checkEntityNumber(Expense::class, $expense, $counter, $expense->company->settings->counter_padding, $expense->company->settings->expense_number_pattern);
|
||||||
|
|
||||||
|
$this->incrementCounter($expense->company, 'expense_number_counter');
|
||||||
|
|
||||||
|
return $expense_number;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if it has shared counter.
|
* Determines if it has shared counter.
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class ChangeStartTimeColumnType extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('tasks', function (Blueprint $table){
|
||||||
|
$table->unsignedInteger('duration')->nullable()->change();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
@ -79,6 +79,18 @@ class TaskApiTest extends TestCase
|
|||||||
$response->assertStatus(200);
|
$response->assertStatus(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testTasksGet()
|
||||||
|
{
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $this->token,
|
||||||
|
])->get('/api/v1/tasks');
|
||||||
|
|
||||||
|
$response->assertStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function testTaskGet()
|
public function testTaskGet()
|
||||||
{
|
{
|
||||||
$response = $this->withHeaders([
|
$response = $this->withHeaders([
|
||||||
|
@ -106,12 +106,12 @@ class AuthorizeTest extends TestCase
|
|||||||
$controller = new GetCustomerProfileIdsController($request);
|
$controller = new GetCustomerProfileIdsController($request);
|
||||||
$response = $controller->executeWithApiResponse(\net\authorize\api\constants\ANetEnvironment::SANDBOX);
|
$response = $controller->executeWithApiResponse(\net\authorize\api\constants\ANetEnvironment::SANDBOX);
|
||||||
if (($response != null) && ($response->getMessages()->getResultCode() == 'Ok')) {
|
if (($response != null) && ($response->getMessages()->getResultCode() == 'Ok')) {
|
||||||
info("GetCustomerProfileId's SUCCESS: "."\n");
|
// info("GetCustomerProfileId's SUCCESS: "."\n");
|
||||||
info(print_r($response->getIds(), 1));
|
// info(print_r($response->getIds(), 1));
|
||||||
} else {
|
} else {
|
||||||
info("GetCustomerProfileId's ERROR : Invalid response\n");
|
// info("GetCustomerProfileId's ERROR : Invalid response\n");
|
||||||
$errorMessages = $response->getMessages()->getMessage();
|
$errorMessages = $response->getMessages()->getMessage();
|
||||||
info('Response : '.$errorMessages[0]->getCode().' '.$errorMessages[0]->getText()."\n");
|
// info('Response : '.$errorMessages[0]->getCode().' '.$errorMessages[0]->getText()."\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->assertNotNull($response);
|
$this->assertNotNull($response);
|
||||||
@ -179,14 +179,14 @@ class AuthorizeTest extends TestCase
|
|||||||
if (($response != null) && ($response->getMessages()->getResultCode() == 'Ok')) {
|
if (($response != null) && ($response->getMessages()->getResultCode() == 'Ok')) {
|
||||||
info('Succesfully created customer profile : '.$response->getCustomerProfileId()."\n");
|
info('Succesfully created customer profile : '.$response->getCustomerProfileId()."\n");
|
||||||
$paymentProfiles = $response->getCustomerPaymentProfileIdList();
|
$paymentProfiles = $response->getCustomerPaymentProfileIdList();
|
||||||
info(print_r($paymentProfiles, 1));
|
// info(print_r($paymentProfiles, 1));
|
||||||
} else {
|
} else {
|
||||||
info("ERROR : Invalid response\n");
|
info("ERROR : Invalid response\n");
|
||||||
$errorMessages = $response->getMessages()->getMessage();
|
$errorMessages = $response->getMessages()->getMessage();
|
||||||
info('Response : '.$errorMessages[0]->getCode().' '.$errorMessages[0]->getText()."\n");
|
// info('Response : '.$errorMessages[0]->getCode().' '.$errorMessages[0]->getText()."\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
info('the new customer profile id = '.$response->getCustomerProfileId());
|
// info('the new customer profile id = '.$response->getCustomerProfileId());
|
||||||
|
|
||||||
$this->assertNotNull($response);
|
$this->assertNotNull($response);
|
||||||
}
|
}
|
||||||
@ -208,8 +208,8 @@ class AuthorizeTest extends TestCase
|
|||||||
$response = $controller->executeWithApiResponse(\net\authorize\api\constants\ANetEnvironment::SANDBOX);
|
$response = $controller->executeWithApiResponse(\net\authorize\api\constants\ANetEnvironment::SANDBOX);
|
||||||
|
|
||||||
if (($response != null) && ($response->getMessages()->getResultCode() == 'Ok')) {
|
if (($response != null) && ($response->getMessages()->getResultCode() == 'Ok')) {
|
||||||
info('got profile');
|
// info('got profile');
|
||||||
info(print_r($response->getProfile(), 1));
|
// info(print_r($response->getProfile(), 1));
|
||||||
} else {
|
} else {
|
||||||
info("ERROR : Invalid response\n");
|
info("ERROR : Invalid response\n");
|
||||||
}
|
}
|
||||||
@ -276,11 +276,11 @@ class AuthorizeTest extends TestCase
|
|||||||
$response = $controller->executeWithApiResponse(\net\authorize\api\constants\ANetEnvironment::SANDBOX);
|
$response = $controller->executeWithApiResponse(\net\authorize\api\constants\ANetEnvironment::SANDBOX);
|
||||||
|
|
||||||
if (($response != null) && ($response->getMessages()->getResultCode() == 'Ok')) {
|
if (($response != null) && ($response->getMessages()->getResultCode() == 'Ok')) {
|
||||||
info('Create Customer Payment Profile SUCCESS: '.$response->getCustomerPaymentProfileId()."\n");
|
// info('Create Customer Payment Profile SUCCESS: '.$response->getCustomerPaymentProfileId()."\n");
|
||||||
} else {
|
} else {
|
||||||
info("Create Customer Payment Profile: ERROR Invalid response\n");
|
// info("Create Customer Payment Profile: ERROR Invalid response\n");
|
||||||
$errorMessages = $response->getMessages()->getMessage();
|
$errorMessages = $response->getMessages()->getMessage();
|
||||||
info('Response : '.$errorMessages[0]->getCode().' '.$errorMessages[0]->getText()."\n");
|
// info('Response : '.$errorMessages[0]->getCode().' '.$errorMessages[0]->getText()."\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->assertNotNull($response);
|
$this->assertNotNull($response);
|
||||||
@ -354,26 +354,5 @@ class AuthorizeTest extends TestCase
|
|||||||
|
|
||||||
$this->assertNotNull($tresponse);
|
$this->assertNotNull($tresponse);
|
||||||
|
|
||||||
/* Testing refunds - need to research more as payments are in a pending state so cannot be 'refunded'*/
|
|
||||||
|
|
||||||
// info("transaction reference = " . $tresponse->getTransId());
|
|
||||||
|
|
||||||
// $payment = PaymentFactory::create($this->company->id, $this->user->id);
|
|
||||||
// $payment->amount = 400;
|
|
||||||
// $payment->client_id = $this->client->id;
|
|
||||||
// $payment->date = now();
|
|
||||||
// $payment->transaction_reference = $tresponse->getTransId();
|
|
||||||
// $payment->company_gateway_id = 1;
|
|
||||||
|
|
||||||
// $payment->save();
|
|
||||||
|
|
||||||
// $company_gateway = CompanyGateway::where('gateway_key', '3b6621f970ab18887c4f6dca78d3f8bb')->first();
|
|
||||||
|
|
||||||
// $authorize_payment_driver = new AuthorizePaymentDriver($company_gateway, $this->client);
|
|
||||||
// $response = $authorize_payment_driver->refund($payment, 350);
|
|
||||||
|
|
||||||
// info(print_r($response,1));
|
|
||||||
|
|
||||||
// $this->assertTrue(is_array($response));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user