diff --git a/app/Http/Controllers/MerchandiseController.php b/app/Http/Controllers/MerchandiseController.php index 3ffa09b97..bf0b318b6 100644 --- a/app/Http/Controllers/MerchandiseController.php +++ b/app/Http/Controllers/MerchandiseController.php @@ -6,6 +6,7 @@ namespace App\Http\Controllers; +use App\Http\Requests\DistributeMerchandiseRequest; use App\Http\Resources\DuesTransactionMerchandise as DuesTransactionMerchandiseResource; use App\Http\Resources\Merchandise as MerchandiseResource; use App\Http\Resources\User as UserResource; @@ -15,7 +16,6 @@ use Carbon\Carbon; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\ModelNotFoundException; -use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\JsonResponse; class MerchandiseController extends Controller @@ -69,7 +69,7 @@ public function getDistribution(Merchandise $merchandise, User $user): JsonRespo 'status' => 'error', 'message' => self::NO_DTM, ], - status: 400 + status: 404 ); } @@ -84,8 +84,11 @@ public function getDistribution(Merchandise $merchandise, User $user): JsonRespo ); } - public function distribute(Request $request, Merchandise $merchandise, User $user): JsonResponse - { + public function distribute( + DistributeMerchandiseRequest $request, + Merchandise $merchandise, + User $user + ): JsonResponse { if (! $merchandise->distributable) { return response()->json( data: [ @@ -104,7 +107,7 @@ public function distribute(Request $request, Merchandise $merchandise, User $use 'status' => 'error', 'message' => self::NO_DTM, ], - status: 400 + status: 404 ); } @@ -114,12 +117,13 @@ public function distribute(Request $request, Merchandise $merchandise, User $use 'status' => 'error', 'message' => self::ALREADY_DISTRIBUTED, ], - status: 400 + status: 409 ); } $dtm->provided_at = Carbon::now(); $dtm->provided_by = $request->user()->id; + $dtm->provided_via = $request->provided_via; $dtm->save(); return response()->json( @@ -141,6 +145,7 @@ private static function getDuesTransactionMerchandise( 'dues_transaction_merchandise.id', 'dues_transaction_merchandise.provided_at', 'dues_transaction_merchandise.provided_by', + 'dues_transaction_merchandise.provided_via', 'dues_transaction_merchandise.merchandise_id' ) ->whereHas('transaction', static function (Builder $query) use ($user) { diff --git a/app/Http/Requests/DistributeMerchandiseRequest.php b/app/Http/Requests/DistributeMerchandiseRequest.php new file mode 100644 index 000000000..968294311 --- /dev/null +++ b/app/Http/Requests/DistributeMerchandiseRequest.php @@ -0,0 +1,33 @@ +> + */ + public function rules(): array + { + return [ + 'provided_via' => [ + 'required', + 'string', + ], + ]; + } +} diff --git a/app/Http/Resources/DuesTransactionMerchandise.php b/app/Http/Resources/DuesTransactionMerchandise.php index 8ec18b47d..0d2b03b31 100644 --- a/app/Http/Resources/DuesTransactionMerchandise.php +++ b/app/Http/Resources/DuesTransactionMerchandise.php @@ -28,6 +28,7 @@ public function toArray(Request $request): array 'id' => $this->id, 'provided_at' => $this->provided_at, 'provided_by' => Manager::make($this->providedBy), + 'provided_via' => $this->provided_via, 'merchandise' => $this->when($this->withMerchandise, $this->merchandise), ]; } diff --git a/app/Models/DuesTransactionMerchandise.php b/app/Models/DuesTransactionMerchandise.php index 2290298da..96dd4bb58 100644 --- a/app/Models/DuesTransactionMerchandise.php +++ b/app/Models/DuesTransactionMerchandise.php @@ -15,6 +15,7 @@ * @property int $merchandise_id * @property \Illuminate\Support\Carbon|null $provided_at * @property int|null $provided_by + * @property ?string $provided_via * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at * @property-read \App\Models\User|null $providedBy diff --git a/app/Nova/Actions/DistributeMerchandise.php b/app/Nova/Actions/DistributeMerchandise.php index 9bee6c4f1..6a53b2a52 100644 --- a/app/Nova/Actions/DistributeMerchandise.php +++ b/app/Nova/Actions/DistributeMerchandise.php @@ -93,6 +93,7 @@ static function (JoinClause $join) use ($provided_to): void { $dtm->provided_at = Carbon::now(); $dtm->provided_by = $provided_by->id; + $dtm->provided_via = 'Nova'; $dtm->save(); return Action::message('Marked as picked up!'); @@ -136,6 +137,7 @@ static function (Builder $query) use ($resource): void { ->toArray() ) ->required() + ->searchable() ->rules('required'), ]; } diff --git a/app/Nova/MerchandisePivotFields.php b/app/Nova/MerchandisePivotFields.php index 49261515c..a47171cc0 100644 --- a/app/Nova/MerchandisePivotFields.php +++ b/app/Nova/MerchandisePivotFields.php @@ -6,6 +6,7 @@ use Laravel\Nova\Fields\BelongsTo; use Laravel\Nova\Fields\DateTime; +use Laravel\Nova\Fields\Text; class MerchandisePivotFields { @@ -16,10 +17,15 @@ public function __invoke(): array { return [ DateTime::make('Provided At') - ->onlyOnIndex(), + ->onlyOnIndex() + ->sortable(), BelongsTo::make('Provided By', 'providedBy', User::class) ->onlyOnIndex(), + + Text::make('Provided Via') + ->onlyOnIndex() + ->sortable(), ]; } } diff --git a/database/migrations/2024_07_28_005414_add_provided_via_to_dues_transaction_merchandise.php b/database/migrations/2024_07_28_005414_add_provided_via_to_dues_transaction_merchandise.php new file mode 100644 index 000000000..9800b1cb8 --- /dev/null +++ b/database/migrations/2024_07_28_005414_add_provided_via_to_dues_transaction_merchandise.php @@ -0,0 +1,48 @@ +string('provided_via')->after('provided_by')->nullable(); + }); + + DuesTransactionMerchandise::whereNotNull('provided_at') + ->whereNull('provided_by') + ->whereNull('provided_via') + ->update(['provided_via' => 'Historical dues import']); + + DuesTransactionMerchandise::whereNotNull('provided_at') + ->whereNotNull('provided_by') + ->whereColumn('provided_at', '=', 'updated_at') + ->whereNull('provided_via') + ->update(['provided_via' => 'Nova']); + + DuesTransactionMerchandise::whereNotNull('provided_at') + ->whereNotNull('provided_by') + ->whereColumn('provided_at', '!=', 'updated_at') + ->whereNull('provided_via') + ->update(['provided_via' => 'Legacy web admin']); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('dues_transaction_merchandise', static function (Blueprint $table): void { + $table->dropColumn('provided_via'); + }); + } +}; diff --git a/phpstan.neon b/phpstan.neon index 863dc45e8..a49c5111f 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -13,7 +13,7 @@ parameters: - stubs/Permission.php - stubs/Role.php ignoreErrors: - - '#(?:Dynamic call to static method|Call to an undefined method) Illuminate\\Database\\Eloquent\\(?:Builder|Collection|Relations\\[a-zA-Z]+)?(?:||)?::(?:distinct|doesntHave|first|groupBy|has|havingRaw|join|leftJoin|orderBy|orderByRaw|orWhereNull|select|selectRaw|selectSub|where|whereBetween|whereHas|whereDate|whereNotIn|whereNotNull|count|whereIn|whereBetween|sum|distinct|paid|active|accessActive|inactive|role|pending|pendingSwag|accessInactive|visible|whereNull|current|start|end|availableForPurchase|userCanPurchase|pluck|orderByDesc|withTrashed|exists|limit|doesntExist|storeExcel|buzzCardAccessEligible|from|unpaid|whereRevoked|whereNotExists|orWhereDate)\(\)\.#' + - '#(?:Dynamic call to static method|Call to an undefined method) Illuminate\\Database\\Eloquent\\(?:Builder|Collection|Relations\\[a-zA-Z]+)?(?:||)?::(?:distinct|doesntHave|first|groupBy|has|havingRaw|join|leftJoin|orderBy|orderByRaw|orWhereNull|select|selectRaw|selectSub|where|whereBetween|whereHas|whereDate|whereNotIn|whereNotNull|count|whereIn|whereBetween|sum|distinct|paid|active|accessActive|inactive|role|pending|pendingSwag|accessInactive|visible|whereNull|current|start|end|availableForPurchase|userCanPurchase|pluck|orderByDesc|withTrashed|exists|limit|doesntExist|storeExcel|buzzCardAccessEligible|from|unpaid|whereRevoked|whereNotExists|orWhereDate|whereColumn)\(\)\.#' - '#^Parameter \#1 \$attendance of static method App\\Models\\Attendance\:\:formatAsCsv\(\) expects iterable\, Illuminate\\Support\\Collection\<\(int\|string\), mixed\> given\.$#' - '#^Parameter \#1 \$callback of method Illuminate\\Support\\Collection\<\(int\|string\),mixed\>\:\:mapWithKeys\(\) expects callable\(mixed, int\|string\)\: array, Closure\(object\)\: non\-empty\-array given\.$#' - '#^Parameter \#1 \$callback of method Illuminate\\Support\\Collection\<\(int\|string\),mixed\>\:\:mapWithKeys\(\) expects callable\(mixed, int\|string\)\: array\, Closure\(object\)\: non\-empty\-array\ given\.$#'