diff --git a/app/DataMapper/CompanySettings.php b/app/DataMapper/CompanySettings.php index a3b5cf613ecd..ab73fd7bb3a3 100644 --- a/app/DataMapper/CompanySettings.php +++ b/app/DataMapper/CompanySettings.php @@ -613,7 +613,6 @@ class CompanySettings extends BaseSettings '$total_taxes', '$line_taxes', '$subtotal', - '$total', '$discount', '$custom_surcharge1', '$custom_surcharge2', @@ -621,6 +620,7 @@ class CompanySettings extends BaseSettings '$custom_surcharge4', '$paid_to_date', '$client.balance', + '$total', ], ]; diff --git a/app/Factory/VendorFactory.php b/app/Factory/VendorFactory.php index 6218200e3232..a618cfc89f80 100644 --- a/app/Factory/VendorFactory.php +++ b/app/Factory/VendorFactory.php @@ -24,13 +24,10 @@ class VendorFactory $vendor->name = ''; $vendor->website = ''; $vendor->private_notes = ''; - $vendor->balance = 0; - $vendor->paid_to_date = 0; + $vendor->public_notes = ''; $vendor->country_id = 4; $vendor->is_deleted = 0; - - $vendor_contact = VendorContactFactory::create($company_id, $user_id); - $vendor->contacts->add($vendor_contact); + $vendor->vendor_hash = Str::random(40); return $vendor; } diff --git a/app/Http/Controllers/VendorController.php b/app/Http/Controllers/VendorController.php index 495eab8eff41..c5bcd59a9a5c 100644 --- a/app/Http/Controllers/VendorController.php +++ b/app/Http/Controllers/VendorController.php @@ -11,7 +11,14 @@ namespace App\Http\Controllers; +use App\Factory\VendorFactory; use App\Filters\VendorFilters; +use App\Http\Requests\Vendor\CreateVendorRequest; +use App\Http\Requests\Vendor\DestroyVendorRequest; +use App\Http\Requests\Vendor\EditVendorRequest; +use App\Http\Requests\Vendor\ShowVendorRequest; +use App\Http\Requests\Vendor\StoreVendorRequest; +use App\Http\Requests\Vendor\UpdateVendorRequest; use App\Jobs\Entity\ActionEntity; use App\Jobs\Util\ProcessBulk; use App\Jobs\Util\UploadAvatar; @@ -31,7 +38,6 @@ use Illuminate\Support\Facades\Log; /** * Class VendorController. - * @covers App\Http\Controllers\VendorController */ class VendorController extends BaseController { @@ -266,7 +272,7 @@ class VendorController extends BaseController return $request->disallowUpdate(); } - $vendor = $this->client_repo->save($request->all(), $vendor); + $vendor = $this->vendor_repo->save($request->all(), $vendor); $this->uploadLogo($request->file('company_logo'), $vendor->company, $vendor); @@ -359,7 +365,7 @@ class VendorController extends BaseController */ public function store(StoreVendorRequest $request) { - $vendor = $this->client_repo->save($request->all(), VendorFactory::create(auth()->user()->company()->id, auth()->user()->id)); + $vendor = $this->vendor_repo->save($request->all(), VendorFactory::create(auth()->user()->company()->id, auth()->user()->id)); $vendor->load('contacts', 'primary_contact'); @@ -485,7 +491,7 @@ class VendorController extends BaseController $vendors->each(function ($vendor, $key) use ($action) { if (auth()->user()->can('edit', $vendor)) { - $this->client_repo->{$action}($vendor); + $this->vendor_repo->{$action}($vendor); } }); diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 4f69d563d31b..5a5f3802fae9 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -56,7 +56,7 @@ class Kernel extends HttpKernel 'bindings', 'query_logging', \App\Http\Middleware\StartupCheck::class, -// \App\Http\Middleware\Cors::class, + \App\Http\Middleware\Cors::class, ], 'contact' => [ 'throttle:60,1', diff --git a/app/Http/Livewire/RecurringInvoicesTable.php b/app/Http/Livewire/RecurringInvoicesTable.php index 725e861bc4d4..29b548c2aef4 100644 --- a/app/Http/Livewire/RecurringInvoicesTable.php +++ b/app/Http/Livewire/RecurringInvoicesTable.php @@ -19,7 +19,7 @@ class RecurringInvoicesTable extends Component $query = $query ->where('client_id', auth('contact')->user()->client->id) - ->whereIn('status_id', [RecurringInvoice::STATUS_PENDING, RecurringInvoice::STATUS_ACTIVE, RecurringInvoice::STATUS_COMPLETED]) + ->whereIn('status_id', [RecurringInvoice::STATUS_PENDING, RecurringInvoice::STATUS_ACTIVE, RecurringInvoice::STATUS_PAUSED,RecurringInvoice::STATUS_COMPLETED]) ->orderBy('status_id', 'asc') ->with('client') ->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc') diff --git a/app/Http/Middleware/Cors.php b/app/Http/Middleware/Cors.php index d471371215bb..86f10e00493a 100644 --- a/app/Http/Middleware/Cors.php +++ b/app/Http/Middleware/Cors.php @@ -16,7 +16,7 @@ class Cors // ALLOW OPTIONS METHOD $headers = [ 'Access-Control-Allow-Methods'=> 'POST, GET, OPTIONS, PUT, DELETE', - 'Access-Control-Allow-Headers'=> 'X-API-COMPANY-KEY,X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range', + 'Access-Control-Allow-Headers'=> 'X-API-COMPANY-KEY,X-CLIENT-VERSION,X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range', ]; return Response::make('OK', 200, $headers); diff --git a/app/Http/Requests/Vendor/StoreVendorRequest.php b/app/Http/Requests/Vendor/StoreVendorRequest.php index c92c52d65c4a..005fcea8a564 100644 --- a/app/Http/Requests/Vendor/StoreVendorRequest.php +++ b/app/Http/Requests/Vendor/StoreVendorRequest.php @@ -42,27 +42,24 @@ class StoreVendorRequest extends Request //$rules['settings'] = new ValidVendorGroupSettingsRule(); $rules['contacts.*.email'] = 'nullable|distinct'; - $contacts = request('contacts'); + // $contacts = request('contacts'); - if (is_array($contacts)) { - for ($i = 0; $i < count($contacts); $i++) { + // if (is_array($contacts)) { + // for ($i = 0; $i < count($contacts); $i++) { - //$rules['contacts.' . $i . '.email'] = 'nullable|email|distinct'; - } - } + // //$rules['contacts.' . $i . '.email'] = 'nullable|email|distinct'; + // } + // } return $rules; } protected function prepareForValidation() { - $input = $this->all(); + // $input = $this->all(); - if (! isset($input['settings'])) { - $input['settings'] = VendorSettings::defaults(); - } - $this->replace($input); + // $this->replace($input); } public function messages() diff --git a/app/Models/RecurringInvoice.php b/app/Models/RecurringInvoice.php index 64de0049e65f..7aadf906fea5 100644 --- a/app/Models/RecurringInvoice.php +++ b/app/Models/RecurringInvoice.php @@ -36,11 +36,11 @@ class RecurringInvoice extends BaseModel /** * Invoice Statuses. */ - const STATUS_DRAFT = 2; - const STATUS_ACTIVE = 3; - const STATUS_CANCELLED = 4; + const STATUS_DRAFT = 1; + const STATUS_ACTIVE = 2; + const STATUS_PAUSED = 3; + const STATUS_COMPLETED = 4; const STATUS_PENDING = -1; - const STATUS_COMPLETED = -2; /** * Recurring intervals //todo MAP WHEN WE MIGRATE. @@ -102,6 +102,7 @@ class RecurringInvoice extends BaseModel 'frequency_id', 'next_send_date', 'remaining_cycles', + 'auto_bill', ]; protected $casts = [ @@ -189,13 +190,10 @@ class RecurringInvoice extends BaseModel public function getStatusAttribute() { - if ($this->status_id == self::STATUS_ACTIVE && $this->next_send_date > Carbon::now()) { //marked as active, but yet to fire first cycle + if ($this->status_id == self::STATUS_ACTIVE && $this->next_send_date > Carbon::now()) return self::STATUS_PENDING; - } elseif ($this->status_id == self::STATUS_ACTIVE && $this->next_send_date > Carbon::now()) { - return self::STATUS_COMPLETED; - } else { + else return $this->status_id; - } } public function nextSendDate() :?Carbon @@ -288,16 +286,16 @@ class RecurringInvoice extends BaseModel return '

'.ctrans('texts.draft').'

'; break; case self::STATUS_PENDING: - return '

'.ctrans('texts.sent').'

'; + return '

'.ctrans('texts.pending').'

'; break; case self::STATUS_ACTIVE: - return '

'.ctrans('texts.partial').'

'; + return '

'.ctrans('texts.active').'

'; break; case self::STATUS_COMPLETED: return '

'.ctrans('texts.status_completed').'

'; break; - case self::STATUS_CANCELLED: - return '

'.ctrans('texts.overdue').'

'; + case self::STATUS_PAUSED: + return '

'.ctrans('texts.paused').'

'; break; default: // code... @@ -368,7 +366,7 @@ class RecurringInvoice extends BaseModel /* Return early if nothing to send back! */ if( $this->status_id == self::STATUS_COMPLETED || $this->status_id == self::STATUS_DRAFT || - $this->status_id == self::STATUS_CANCELLED || + $this->status_id == self::STATUS_PAUSED || $this->remaining_cycles == 0 || !$this->next_send_date) { diff --git a/app/Models/Vendor.php b/app/Models/Vendor.php index 9aae462d21f0..8cd1a54d5686 100644 --- a/app/Models/Vendor.php +++ b/app/Models/Vendor.php @@ -13,6 +13,7 @@ namespace App\Models; use App\Models\Filterable; use App\Models\VendorContact; +use App\Utils\Traits\GeneratesCounter; use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; @@ -21,7 +22,8 @@ class Vendor extends BaseModel { use SoftDeletes; use Filterable; - + use GeneratesCounter; + protected $fillable = [ 'name', 'id_number', @@ -34,6 +36,7 @@ class Vendor extends BaseModel 'postal_code', 'country_id', 'private_notes', + 'public_notes', 'currency_id', 'website', 'transaction_name', @@ -63,6 +66,12 @@ class Vendor extends BaseModel return self::class; } + public function primary_contact() + { + return $this->hasMany(VendorContact::class)->where('is_primary', true); + } + + public function documents() { return $this->morphMany(Document::class, 'documentable'); diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 79542792c87c..ca68f008cef4 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -56,7 +56,8 @@ class AppServiceProvider extends ServiceProvider public function boot() { Relation::morphMap([ - 'invoices' => \App\Models\Invoice::class, + 'invoices' => \App\Models\Invoice::class, + // 'credits' => \App\Models\Credit::class, 'proposals' => \App\Models\Proposal::class, ]); diff --git a/app/Repositories/VendorContactRepository.php b/app/Repositories/VendorContactRepository.php index ba831d338a50..f9aab86646eb 100644 --- a/app/Repositories/VendorContactRepository.php +++ b/app/Repositories/VendorContactRepository.php @@ -13,6 +13,7 @@ namespace App\Repositories; use App\Models\Vendor; use App\Models\VendorContact; +use Illuminate\Support\Facades\Hash; use Illuminate\Support\Str; /** @@ -58,9 +59,17 @@ class VendorContactRepository extends BaseRepository $update_contact->fill($contact); + if (array_key_exists('password', $contact) && strlen($contact['password']) > 1) { + + $update_contact->password = Hash::make($contact['password']); + + } + $update_contact->save(); }); + $vendor->load('contacts'); + //always made sure we have one blank contact to maintain state if ($contacts->count() == 0) { $new_contact = new VendorContact; diff --git a/app/Services/Invoice/HandleReversal.php b/app/Services/Invoice/HandleReversal.php index 5ee609a06086..7a991f80ba09 100644 --- a/app/Services/Invoice/HandleReversal.php +++ b/app/Services/Invoice/HandleReversal.php @@ -18,6 +18,7 @@ use App\Factory\InvoiceItemFactory; use App\Factory\PaymentFactory; use App\Helpers\Invoice\InvoiceSum; use App\Models\Client; +use App\Models\Credit; use App\Models\Invoice; use App\Models\Payment; use App\Models\Paymentable; @@ -55,7 +56,7 @@ class HandleReversal extends AbstractService $total_paid = $this->invoice->amount - $this->invoice->balance; /*Adjust payment applied and the paymentables to the correct amount */ - $paymentables = Paymentable::wherePaymentableType(Invoice::class) + $paymentables = Paymentable::wherePaymentableType('invoices') ->wherePaymentableId($this->invoice->id) ->get(); @@ -95,6 +96,23 @@ class HandleReversal extends AbstractService $credit->service()->markSent()->save(); } + /*If there is a payment linked, then the credit needs to be linked back to that payment in case of refund*/ + if($paymentables->count() > 0){ + + $payment = $paymentables->first()->payment; + $payment->credits()->save($credit); + + $paymentable_credit = $payment->credits() + ->wherePaymentableType(Credit::class) + ->wherePaymentableId($credit->id) + ->first(); + + //harvest the credit record and add in the amount for the credit. + $paymentable_credit->pivot->amount = $total_paid; + $paymentable_credit->pivot->save(); + + } + /* Set invoice balance to 0 */ if ($this->invoice->balance != 0) { $this->invoice->ledger()->updateInvoiceBalance($balance_remaining * -1, $notes)->save(); @@ -119,37 +137,4 @@ class HandleReversal extends AbstractService //create a ledger row for this with the resulting Credit ( also include an explanation in the notes section ) } - // public function run2() - // { - - // /* Check again!! */ - // if (!$this->invoice->invoiceReversable($this->invoice)) { - // return $this->invoice; - // } - - // if($this->invoice->status_id == Invoice::STATUS_CANCELLED) - // $this->invoice = $this->invoice->service()->reverseCancellation()->save(); - - // //$balance_remaining = $this->invoice->balance; - - // //$total_paid = $this->invoice->amount - $this->invoice->balance; - - // /*Adjust payment applied and the paymentables to the correct amount */ - // $paymentables = Paymentable::wherePaymentableType(Invoice::class) - // ->wherePaymentableId($this->invoice->id) - // ->get(); - - // $total_paid = 0; - - // $paymentables->each(function ($paymentable) use ($total_paid) { - - // $reversable_amount = $paymentable->amount - $paymentable->refunded; - // $total_paid -= $reversable_amount; - // $paymentable->amount = $paymentable->refunded; - // $paymentable->save(); - // }); - - // //Unwinding any payments made to this invoice - - // } } diff --git a/app/Transformers/VendorTransformer.php b/app/Transformers/VendorTransformer.php index a5eb2a03aa3a..26cfc5e83c4b 100644 --- a/app/Transformers/VendorTransformer.php +++ b/app/Transformers/VendorTransformer.php @@ -76,6 +76,7 @@ class VendorTransformer extends EntityTransformer 'name' => $vendor->name ?: '', 'website' => $vendor->website ?: '', 'private_notes' => $vendor->private_notes ?: '', + 'public_notes' => $vendor->public_notes ?: '', 'last_login' => (int) $vendor->last_login, 'address1' => $vendor->address1 ?: '', 'address2' => $vendor->address2 ?: '', diff --git a/app/Utils/Traits/GeneratesCounter.php b/app/Utils/Traits/GeneratesCounter.php index 3fd4467f7e73..8716eb374737 100644 --- a/app/Utils/Traits/GeneratesCounter.php +++ b/app/Utils/Traits/GeneratesCounter.php @@ -13,11 +13,13 @@ namespace App\Utils\Traits; use App\Models\Client; use App\Models\Credit; +use App\Models\Expense; use App\Models\Invoice; use App\Models\Payment; use App\Models\Quote; use App\Models\RecurringInvoice; use App\Models\Timezone; +use App\Models\Vendor; use Illuminate\Support\Carbon; /** @@ -238,6 +240,28 @@ trait GeneratesCounter return $client_number; } + + /** + * Gets the next client number. + * + * @param \App\Models\Vendor $vendor The vendor + * @return string The next vendor number. + */ + public function getNextVendorNumber(Vendor $vendor) :string + { + $this->resetCompanyCounters($vendor->company); + + $counter = $vendor->company->settings->vendor_number_counter; + $setting_entity = $vendor->company->settings->vendor_number_counter; + + $vendor_number = $this->checkEntityNumber(Vendor::class, $vendor, $counter, $vendor->company->settings->counter_padding, $vendor->company->settings->vendor_number_pattern); + + $this->incrementCounter($vendor->company, 'vendor_number_counter'); + + return $vendor_number; + } + + /** * Determines if it has shared counter. * @@ -254,33 +278,29 @@ trait GeneratesCounter * Checks that the number has not already been used. * * @param Collection $entity The entity ie App\Models\Client, Invoice, Quote etc - * @param int $counter The counter - * @param int $padding The padding + * @param int $counter The counter + * @param int $padding The padding * - * @return string The padded and prefixed invoice number + * @return string The padded and prefixed entity number */ - private function checkEntityNumber($class, $client, $counter, $padding, $pattern) + private function checkEntityNumber($class, $entity, $counter, $padding, $pattern) { $check = false; do { $number = $this->padCounter($counter, $padding); - $number = $this->applyNumberPattern($client, $number, $pattern); - - if ($class == Invoice::class || $class == RecurringInvoice::class) { - $check = $class::whereCompanyId($client->company_id)->whereNumber($number)->withTrashed()->first(); - } elseif ($class == Client::class) { - $check = $class::whereCompanyId($client->company_id)->whereIdNumber($number)->withTrashed()->first(); - } elseif ($class == Credit::class) { - $check = $class::whereCompanyId($client->company_id)->whereNumber($number)->withTrashed()->first(); - } elseif ($class == Quote::class) { - $check = $class::whereCompanyId($client->company_id)->whereNumber($number)->withTrashed()->first(); - } elseif ($class == Payment::class) { - $check = $class::whereCompanyId($client->company_id)->whereNumber($number)->withTrashed()->first(); - } + $number = $this->applyNumberPattern($entity, $number, $pattern); + if ($class == Invoice::class || $class == RecurringInvoice::class) + $check = $class::whereCompanyId($entity->company_id)->whereNumber($number)->withTrashed()->first(); + elseif ($class == Client::class || $class == Vendor::class) + $check = $class::whereCompanyId($entity->company_id)->whereIdNumber($number)->withTrashed()->first(); + else + $check = $class::whereCompanyId($entity->company_id)->whereNumber($number)->withTrashed()->first(); + $counter++; + } while ($check); return $number; @@ -389,16 +409,74 @@ trait GeneratesCounter $client->company->save(); } + private function resetCompanyCounters($company) + { + $timezone = Timezone::find($company->settings->timezone_id); + + $reset_date = Carbon::parse($company->settings->reset_counter_date, $timezone->name); + + if (! $reset_date->isToday() || ! $company->settings->reset_counter_date) { + return false; + } + + switch ($company->reset_counter_frequency_id) { + case RecurringInvoice::FREQUENCY_WEEKLY: + $reset_date->addWeek(); + break; + case RecurringInvoice::FREQUENCY_TWO_WEEKS: + $reset_date->addWeeks(2); + break; + case RecurringInvoice::FREQUENCY_FOUR_WEEKS: + $reset_date->addWeeks(4); + break; + case RecurringInvoice::FREQUENCY_MONTHLY: + $reset_date->addMonth(); + break; + case RecurringInvoice::FREQUENCY_TWO_MONTHS: + $reset_date->addMonths(2); + break; + case RecurringInvoice::FREQUENCY_THREE_MONTHS: + $reset_date->addMonths(3); + break; + case RecurringInvoice::FREQUENCY_FOUR_MONTHS: + $reset_date->addMonths(4); + break; + case RecurringInvoice::FREQUENCY_SIX_MONTHS: + $reset_date->addMonths(6); + break; + case RecurringInvoice::FREQUENCY_ANNUALLY: + $reset_date->addYear(); + break; + case RecurringInvoice::FREQUENCY_TWO_YEARS: + $reset_date->addYears(2); + break; + } + + $settings = $company->settings; + $settings->reset_counter_date = $reset_date->format('Y-m-d'); + $settings->invoice_number_counter = 1; + $settings->quote_number_counter = 1; + $settings->credit_number_counter = 1; + $settings->vendor_number_counter = 1; + $settings->ticket_number_counter = 1; + $settings->payment_number_counter = 1; + $settings->task_number_counter = 1; + $settings->expense_number_counter = 1; + + $company->settings = $settings; + $company->save(); + } + /** - * { function_description }. + * Formats a entity number by pattern * - * @param \App\Models\Client $client The client - * @param string $counter The counter - * @param null|string $pattern The pattern + * @param \App\Models\BaseModel $entity The entity object + * @param string $counter The counter + * @param null|string $pattern The pattern * - * @return string ( description_of_the_return_value ) + * @return string The formatted number pattern */ - private function applyNumberPattern(Client $client, string $counter, $pattern) :string + private function applyNumberPattern($entity, string $counter, $pattern) :string { if (! $pattern) { return $counter; @@ -417,7 +495,7 @@ trait GeneratesCounter $replace[] = $counter; if (strstr($pattern, '{$user_id}')) { - $user_id = $client->user_id ? $client->user_id : 0; + $user_id = $entity->user_id ? $entity->user_id : 0; $search[] = '{$user_id}'; $replace[] = str_pad(($user_id), 2, '0', STR_PAD_LEFT); } @@ -429,24 +507,24 @@ trait GeneratesCounter $search[] = $matches[0]; /* The following adjusts for the company timezone - may bork tests depending on the time of day the tests are run!!!!!!*/ - $date = Carbon::now($client->company->timezone()->name)->format($format); + $date = Carbon::now($entity->company->timezone()->name)->format($format); $replace[] = str_replace($format, $date, $matches[1]); } $search[] = '{$custom1}'; - $replace[] = $client->custom_value1; + $replace[] = $entity->custom_value1; $search[] = '{$custom2}'; - $replace[] = $client->custom_value2; + $replace[] = $entity->custom_value2; $search[] = '{$custom3}'; - $replace[] = $client->custom_value3; + $replace[] = $entity->custom_value3; $search[] = '{$custom4}'; - $replace[] = $client->custom_value4; + $replace[] = $entity->custom_value4; $search[] = '{$id_number}'; - $replace[] = $client->id_number; + $replace[] = $entity->id_number; return str_replace($search, $replace, $pattern); } diff --git a/database/migrations/2020_09_22_205113_id_number_fields_for_missing_entities.php b/database/migrations/2020_09_22_205113_id_number_fields_for_missing_entities.php new file mode 100644 index 000000000000..a1e665959d6a --- /dev/null +++ b/database/migrations/2020_09_22_205113_id_number_fields_for_missing_entities.php @@ -0,0 +1,45 @@ +string('number')->nullable(); + }); + + Schema::table('tasks', function (Blueprint $table) { + $table->string('number')->nullable(); + }); + + Schema::table('vendors', function (Blueprint $table) { + $table->text('vendor_hash')->nullable(); + $table->text('public_notes')->nullable(); + }); + + Schema::table('vendor_contacts', function (Blueprint $table) { + $table->boolean('send_email')->default(0); + }); + + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index df2ec1ec2253..7f06753b9dc7 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -3272,4 +3272,5 @@ return [ 'password_strength' => 'Password strength too weak', 'thanks' => 'Thanks', + 'paused' => 'Paused', ]; diff --git a/tests/Feature/VendorApiTest.php b/tests/Feature/VendorApiTest.php new file mode 100644 index 000000000000..3ad6fdb38a84 --- /dev/null +++ b/tests/Feature/VendorApiTest.php @@ -0,0 +1,152 @@ +makeTestData(); + + Session::start(); + + $this->faker = \Faker\Factory::create(); + + Model::reguard(); + } + + public function testVendorPost() + { + $data = [ + 'name' => $this->faker->firstName, + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/vendors', $data); + + $response->assertStatus(200); + } + + public function testVendorPut() + { + $data = [ + 'name' => $this->faker->firstName, + 'id_number' => 'Coolio', + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/vendors/'.$this->encodePrimaryKey($this->vendor->id), $data); + + $response->assertStatus(200); + } + + public function testVendorGet() + { + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->get('/api/v1/vendors/'.$this->encodePrimaryKey($this->vendor->id)); + + $response->assertStatus(200); + } + + public function testVendorNotArchived() + { + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->get('/api/v1/vendors/'.$this->encodePrimaryKey($this->vendor->id)); + + $arr = $response->json(); + + $this->assertEquals(0, $arr['data']['archived_at']); + } + + public function testVendorArchived() + { + $data = [ + 'ids' => [$this->encodePrimaryKey($this->vendor->id)], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/vendors/bulk?action=archive', $data); + + $arr = $response->json(); + + $this->assertNotNull($arr['data'][0]['archived_at']); + } + + public function testVendorRestored() + { + $data = [ + 'ids' => [$this->encodePrimaryKey($this->vendor->id)], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/vendors/bulk?action=restore', $data); + + $arr = $response->json(); + + $this->assertEquals(0, $arr['data'][0]['archived_at']); + } + + public function testVendorDeleted() + { + $data = [ + 'ids' => [$this->encodePrimaryKey($this->vendor->id)], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/vendors/bulk?action=delete', $data); + + $arr = $response->json(); + + $this->assertTrue($arr['data'][0]['is_deleted']); + } +} diff --git a/tests/MockAccountData.php b/tests/MockAccountData.php index a98e4c8fe504..c79c756d758c 100644 --- a/tests/MockAccountData.php +++ b/tests/MockAccountData.php @@ -65,6 +65,8 @@ trait MockAccountData public $quote; + public $vendor; + public function makeTestData() { @@ -166,6 +168,26 @@ trait MockAccountData 'send_email' => true, ]); + $this->vendor = factory(\App\Models\Vendor::class)->create([ + 'user_id' => $this->user->id, + 'company_id' => $this->company->id, + ]); + + $vendor_contact = factory(\App\Models\VendorContact::class)->create([ + 'user_id' => $this->user->id, + 'vendor_id' => $this->vendor->id, + 'company_id' => $this->company->id, + 'is_primary' => 1, + 'send_email' => true, + ]); + + $vendor_contact2 = factory(\App\Models\VendorContact::class)->create([ + 'user_id' => $this->user->id, + 'vendor_id' => $this->vendor->id, + 'company_id' => $this->company->id, + 'send_email' => true, + ]); + // $rels = collect($contact, $contact2); // $this->client->setRelation('contacts', $rels); // $this->client->save(); diff --git a/tests/Unit/GeneratesCounterTest.php b/tests/Unit/GeneratesCounterTest.php index fde2585866bb..da4d204b7a47 100644 --- a/tests/Unit/GeneratesCounterTest.php +++ b/tests/Unit/GeneratesCounterTest.php @@ -13,6 +13,7 @@ namespace Tests\Unit; use App\DataMapper\ClientSettings; use App\DataMapper\DefaultSettings; use App\Factory\ClientFactory; +use App\Factory\VendorFactory; use App\Models\Client; use App\Models\Company; use App\Models\Credit; @@ -293,6 +294,25 @@ class GeneratesCounterTest extends TestCase $this->assertEquals($client_number, date('Y').'-'.str_pad($this->client->user_id, 2, '0', STR_PAD_LEFT).'-0002'); } + public function testVendorNumberPattern() + { + $settings = $this->company->settings; + $settings->vendor_number_pattern = '{$year}-{$user_id}-{$counter}'; + $this->company->settings = $settings; + $this->company->save(); + + $vendor = VendorFactory::create($this->company->id, $this->user->id); + $vendor->save(); + + $vendor_number = $this->getNextVendorNumber($vendor); + + $this->assertEquals($vendor_number, date('Y').'-'.str_pad($vendor->user_id, 2, '0', STR_PAD_LEFT).'-0001'); + + $vendor_number = $this->getNextVendorNumber($vendor); + + $this->assertEquals($vendor_number, date('Y').'-'.str_pad($vendor->user_id, 2, '0', STR_PAD_LEFT).'-0002'); + } + /* public function testClientNextNumber()