diff --git a/app/Console/Commands/GroupCountryField.php b/app/Console/Commands/GroupCountryField.php index 97a044518d..7d0cffc931 100644 --- a/app/Console/Commands/GroupCountryField.php +++ b/app/Console/Commands/GroupCountryField.php @@ -3,7 +3,6 @@ namespace App\Console\Commands; use App\Group; -use App\Helpers\Fixometer; use Illuminate\Console\Command; class GroupCountryField extends Command @@ -30,7 +29,7 @@ public function handle(): void $groups = Group::all(); foreach ($groups as $group) { - $group->country = Fixometer::getCountryFromCountryCode($group->country_code); + $group->country = Group::countryNameForCode($group->country_code); $group->save(); } } diff --git a/app/Group.php b/app/Group.php index 1a2dbebb32..097de77cf5 100644 --- a/app/Group.php +++ b/app/Group.php @@ -148,6 +148,32 @@ public function toArray() // Setters + /** + * Keep the legacy `country` column in step with `country_code`. `country` is still read by external + * consumers (e.g. ORA exports, direct DB reporting) so it must be populated as soon as the group is saved, + * rather than waiting for the hourly groups:country job. Countries are stored in English. + */ + public function setCountryCodeAttribute($value) + { + $this->attributes['country_code'] = $value; + $this->attributes['country'] = self::countryNameForCode($value); + } + + /** + * The English country name stored in the legacy `country` column; '' for an empty or unknown code. Group + * imports have used 'UK' for the United Kingdom, which isn't an ISO code. + */ + public static function countryNameForCode($code): string + { + if (! $code) { + return ''; + } + + $code = strtoupper($code) === 'UK' ? 'GB' : $code; + + return \App\Helpers\Fixometer::getAllCountries('en')[$code] ?? ''; + } + //Getters public function findAll() { diff --git a/database/migrations/2026_09_23_000000_backfill_group_country_from_country_code.php b/database/migrations/2026_09_23_000000_backfill_group_country_from_country_code.php new file mode 100644 index 0000000000..10be9b9108 --- /dev/null +++ b/database/migrations/2026_09_23_000000_backfill_group_country_from_country_code.php @@ -0,0 +1,38 @@ +whereNotNull('country_code') + ->where(function ($q) { + $q->whereNull('country')->orWhere('country', ''); + }) + ->get(['idgroups', 'country_code']); + + foreach ($groups as $group) { + $country = Group::countryNameForCode($group->country_code); + + if ($country !== '') { + DB::table('groups')->where('idgroups', $group->idgroups)->update(['country' => $country]); + } else { + Log::warning("Group {$group->idgroups}: no country name for code '{$group->country_code}'"); + } + } + } + + public function down(): void + { + // Data-only backfill; nothing to undo. + } +}; diff --git a/tests/Feature/Groups/GroupCountryTest.php b/tests/Feature/Groups/GroupCountryTest.php index 1394b6ee6a..f607aa994b 100644 --- a/tests/Feature/Groups/GroupCountryTest.php +++ b/tests/Feature/Groups/GroupCountryTest.php @@ -29,4 +29,28 @@ public function testSync(): void { $group = Group::find($group->idgroups); $this->assertEquals('United Kingdom', $group->country); } + + public function testCountrySetOnSaveWithoutJob(): void { + // fr-BE has its own country names (e.g. 'Belgique'); the stored value must still be English. + app()->setLocale('fr-BE'); + + $group = Group::factory()->create(['country_code' => 'BE']); + $this->assertEquals('Belgium', Group::find($group->idgroups)->country); + + $group->country_code = 'GB'; + $group->save(); + $this->assertEquals('United Kingdom', Group::find($group->idgroups)->country); + } + + public function testUnknownAndLegacyCodes(): void { + $this->assertEquals('United Kingdom', Group::countryNameForCode('UK')); + $this->assertEquals('', Group::countryNameForCode('ZZ')); + $this->assertEquals('', Group::countryNameForCode(null)); + + // The model and the hourly job agree, so the column doesn't flip between values. + $group = Group::factory()->create(['country_code' => 'ZZ']); + $this->assertEquals('', Group::find($group->idgroups)->country); + $this->artisan('groups:country'); + $this->assertEquals('', Group::find($group->idgroups)->country); + } }