diff --git a/app/Http/Requests/UpdateAssetRequest.php b/app/Http/Requests/UpdateAssetRequest.php index a749e5816b..1b379358f9 100644 --- a/app/Http/Requests/UpdateAssetRequest.php +++ b/app/Http/Requests/UpdateAssetRequest.php @@ -4,6 +4,7 @@ namespace App\Http\Requests; use App\Http\Requests\Traits\MayContainCustomFields; use App\Models\Asset; +use App\Models\Setting; use Illuminate\Support\Facades\Gate; use Illuminate\Validation\Rule; @@ -41,6 +42,12 @@ class UpdateAssetRequest extends ImageUploadRequest ], ); + // if the purchase cost is passed in as a string **and** the digit_separator is ',' (as is common in the EU) + // then we tweak the purchase_cost rule to make it a string + if (Setting::getSettings()->digit_separator === '1.234,56' && is_string($this->input('purchase_cost'))) { + $rules['purchase_cost'] = ['nullable', 'string']; + } + return $rules; } } diff --git a/app/Models/SnipeModel.php b/app/Models/SnipeModel.php index af12c3d29b..f26946d22a 100644 --- a/app/Models/SnipeModel.php +++ b/app/Models/SnipeModel.php @@ -21,6 +21,11 @@ class SnipeModel extends Model */ public function setPurchaseCostAttribute($value) { + if (is_float($value)) { + //value is *already* a floating-point number. Just assign it directly + $this->attributes['purchase_cost'] = $value; + return; + } $value = Helper::ParseCurrency($value); if ($value == 0) { diff --git a/tests/Feature/Assets/Api/UpdateAssetTest.php b/tests/Feature/Assets/Api/UpdateAssetTest.php index 300d06ae50..7a4e411b3d 100644 --- a/tests/Feature/Assets/Api/UpdateAssetTest.php +++ b/tests/Feature/Assets/Api/UpdateAssetTest.php @@ -103,6 +103,102 @@ class UpdateAssetTest extends TestCase $this->assertEquals('2023-09-03 00:00:00', $updatedAsset->last_audit_date); } + public function testUpdatesPeriodAsCommaSeparatorForPurchaseCost() + { + $this->settings->set([ + 'default_currency' => 'EUR', + 'digit_separator' => '1.234,56', + ]); + + $original_asset = Asset::factory()->create(); + + $response = $this->actingAsForApi(User::factory()->superuser()->create()) + ->patchJson(route('api.assets.update', $original_asset->id), [ + 'asset_tag' => 'random-string', + 'model_id' => AssetModel::factory()->create()->id, + 'status_id' => Statuslabel::factory()->create()->id, + // API also accepts string for comma separated values + 'purchase_cost' => '1.112,34', + ]) + ->assertStatusMessageIs('success'); + + $asset = Asset::find($response['payload']['id']); + + $this->assertEquals(1112.34, $asset->purchase_cost); + } + + public function testUpdatesFloatForPurchaseCost() + { + $this->settings->set([ + 'default_currency' => 'EUR', + 'digit_separator' => '1.234,56', + ]); + + $original_asset = Asset::factory()->create(); + + $response = $this->actingAsForApi(User::factory()->superuser()->create()) + ->patchJson(route('api.assets.update', $original_asset->id), [ + 'asset_tag' => 'random-string', + 'model_id' => AssetModel::factory()->create()->id, + 'status_id' => Statuslabel::factory()->create()->id, + // API also accepts string for comma separated values + 'purchase_cost' => 12.34, + ]) + ->assertStatusMessageIs('success'); + + $asset = Asset::find($response['payload']['id']); + + $this->assertEquals(12.34, $asset->purchase_cost); + } + + public function testUpdatesUSDecimalForPurchaseCost() + { + $this->settings->set([ + 'default_currency' => 'EUR', + 'digit_separator' => '1,234.56', + ]); + + $original_asset = Asset::factory()->create(); + + $response = $this->actingAsForApi(User::factory()->superuser()->create()) + ->patchJson(route('api.assets.update', $original_asset->id), [ + 'asset_tag' => 'random-string', + 'model_id' => AssetModel::factory()->create()->id, + 'status_id' => Statuslabel::factory()->create()->id, + // API also accepts string for comma separated values + 'purchase_cost' => '5412.34', //NOTE - you cannot use thousands-separator here!!!! + ]) + ->assertStatusMessageIs('success'); + + $asset = Asset::find($response['payload']['id']); + + $this->assertEquals(5412.34, $asset->purchase_cost); + } + + public function testUpdatesFloatUSDecimalForPurchaseCost() + { + $this->settings->set([ + 'default_currency' => 'EUR', + 'digit_separator' => '1,234.56', + ]); + + $original_asset = Asset::factory()->create(); + + $response = $this->actingAsForApi(User::factory()->superuser()->create()) + ->patchJson(route('api.assets.update', $original_asset->id), [ + 'asset_tag' => 'random-string', + 'model_id' => AssetModel::factory()->create()->id, + 'status_id' => Statuslabel::factory()->create()->id, + // API also accepts string for comma separated values + 'purchase_cost' => 12.34, + ]) + ->assertStatusMessageIs('success'); + + $asset = Asset::find($response['payload']['id']); + + $this->assertEquals(12.34, $asset->purchase_cost); + } + public function testAssetEolDateIsCalculatedIfPurchaseDateUpdated() { $asset = Asset::factory()->laptopMbp()->noPurchaseOrEolDate()->create();