Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions app/Http/Controllers/AuthController.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public function loginCallback()
'Please register for the Convention first before trying to obtain a fursuit badge.');
}

$isNewUser = User::where('remote_id', $socialLiteUser->getId())->doesntExist();

$user = User::updateOrCreate([
'remote_id' => $socialLiteUser->getId(),
], [
Expand Down Expand Up @@ -76,6 +78,34 @@ public function loginCallback()
expiresIn: 3500
);

if ($isNewUser) {
$fursuit = \Illuminate\Support\Facades\Http::attsrv()
->withToken($socialLiteUser->token)
->get('/attendees/' . $regId . '/packages/fursuit')
->json();
if ($fursuit['present'] && $fursuit['count'] > 0) {

$fursuitAdditional = \Illuminate\Support\Facades\Http::attsrv()
->withToken($socialLiteUser->token)
->get('/attendees/' . $regId . '/packages/fursuitadd')
->json();

$copies = $fursuitAdditional['present'] ? $fursuitAdditional['count'] : 0;

$user->has_free_badge = true;
$user->free_badge_copies = $copies;
$user->save();


\Illuminate\Support\Facades\Http::attsrv()
->withToken($socialLiteUser->token)
->post('/attendees/' . $regId . '/additional-info/fursuitbadge', [
'created' => false,
]);
}

}

Auth::login($user, true);
if(Session::exists('catch-em-all-redirect')) {
Session::forget('catch-em-all-redirect');
Expand Down
32 changes: 29 additions & 3 deletions app/Http/Controllers/BadgeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ public function create(Request $request)
Gate::authorize('create', Badge::class);
return Inertia::render('Badges/BadgesCreate', [
'species' => Species::has('fursuits', count: 5)->orWhere('checked', true)->get('name'),
'isFree' => auth()->user()->badges()->where('is_free_badge', true)->doesntExist(),
'isFree' => auth()->user()->hasFreeBadge(),
'freeBadgeCopies' => auth()->user()->hasFreeBadge() ? auth()->user()->free_badge_copies : 0,
]);
}

Expand Down Expand Up @@ -71,7 +72,7 @@ public function store(BadgeCreateRequest $request)
]);

// is Free Badge
$isFreeBadge = $request->user()->badges()->where('is_free_badge', true)->doesntExist();
$isFreeBadge = $request->user()->hasFreeBadge();

// Returns in cents
$total = BadgeCalculationService::calculate(
Expand All @@ -98,7 +99,32 @@ public function store(BadgeCreateRequest $request)
// Pay for Badge (force pay as we allow negative balance)
$request->user()->forcePay($badge);

if ($validated['upgrades']['spareCopy']) {
if ($isFreeBadge) {
$total = BadgeCalculationService::calculate(isSpareCopy: true);
for ($i = 0; $i < $request->user()->free_badge_copies; $i++) {
$clone = $badge->replicate();
$clone->is_free_badge = false;
$clone->extra_copy = true;
$clone->total = round($total);
$clone->subtotal = round($total / 1.19);
$clone->tax = round($clone->total - $clone->subtotal);
$clone->extra_copy_of = $badge->id;
$clone->save();
$request->user()->forcePay($clone->fresh());
}
$request->user()->wallet->deposit($total * $request->user()->free_badge_copies, ['title' => 'Fuirsuit Badge', 'description' => 'Already paid with the EF registration system']);
$request->user()->free_badge_copies = 0;
$request->user()->has_free_badge = false;
$request->user()->save();

// Mark fursuitbadge as created
\Illuminate\Support\Facades\Http::attsrv()
->withToken($request->user()->token)
->post('/attendees/' . $request->user()->attendee_id . '/additional-info/fursuitbadge', [
'created' => true,
]);

} elseif ($validated['upgrades']['spareCopy']) {
$total = BadgeCalculationService::calculate(isSpareCopy: true);
$clone = $badge->replicate();
$clone->is_free_badge = false;
Expand Down
9 changes: 9 additions & 0 deletions app/Models/Badge/Badge.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,13 @@ public function getActivitylogOptions(): LogOptions
return LogOptions::defaults()
->logOnly(['*']);
}

public function isCopyOfFreeBadge(): bool
{
if ($this->extra_copy_of !== null) {
$originalBadge = self::find($this->extra_copy_of);
return $originalBadge ? $originalBadge->is_free_badge : false;
}
return false;
}
}
7 changes: 7 additions & 0 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class User extends Authenticatable implements FilamentUser, Wallet, WalletFloat,
'token' => 'encrypted',
'token_expires_at' => 'datetime',
'attendee_id' => 'integer',
'has_free_badge' => 'bool',
"free_badge_copies" => "integer",
];

public function badges()
Expand All @@ -72,4 +74,9 @@ public function canAccessPanel(Panel $panel): bool
{
return $this->is_admin || $this->is_reviewer;
}

public function hasFreeBadge(): bool
{
return $this->has_free_badge;
}
}
6 changes: 5 additions & 1 deletion app/Services/BadgeCalculationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ public static function calculate(
return 200;
}

$baseFee = $isFreeBadge ? 0 : 200;
if ($isFreeBadge) {
return 0;
}

$baseFee = 200;
if ($isLate) {
$baseFee += 200;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('has_free_badge')->default(false)->after('remember_token');
$table->integer('free_badge_copies')->default(0)->after('has_free_badge');
});
}
};
34 changes: 20 additions & 14 deletions resources/js/Pages/Badges/BadgesCreate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ defineOptions({

const props = defineProps({
species: Array,
isFree: Boolean
isFree: Boolean,
freeBadgeCopies: Number,
})

const imageModalOpen = ref(false)
Expand All @@ -36,7 +37,7 @@ const form = useForm('post', route('badges.store'), {
publish: false,
tos: false,
upgrades: {
spareCopy: false
spareCopy: props.freeBadgeCopies > 0,
}
})

Expand All @@ -62,17 +63,24 @@ const basePrice = computed(() => {
})

const latePrice = computed(() => {
if (dayjs().isAfter(dayjs(usePage().props.event.preorder_ends_at))) {
if (dayjs().isAfter(dayjs(usePage().props.event.preorder_ends_at)) && props.isFree === false) {
return 2;
}
return 0;
})

const total = computed(() => {
let total = basePrice.value + latePrice.value;
if (form.upgrades.spareCopy) {
total += 2;
const copiesPrice = computed(() => {
let price = 0
if (props.freeBadgeCopies > 0) {
price += props.freeBadgeCopies * 2;
} else if (form.upgrades.spareCopy) {
price += 2;
}
return price;
})

const total = computed(() => {
let total = basePrice.value + latePrice.value + copiesPrice.value;
return total;
})
</script>
Expand Down Expand Up @@ -202,7 +210,7 @@ const total = computed(() => {
<div class="flex gap-3">
<div class="flex flex-row gap-2 mt-3">
<InputSwitch v-model="form.upgrades.spareCopy" id="extra2"
aria-describedby="extra2-help"/>
aria-describedby="extra2-help" :disabled="props.isFree"/>
</div>
<div>
<label class="font-semibold block" for="extra2">Spare Copy
Expand Down Expand Up @@ -254,9 +262,9 @@ const total = computed(() => {
<small>Orders placed after the Preorder Deadline will be charged a late fee.</small>
</div>
<div v-if="form.upgrades.spareCopy"
class="flex justify-between mb-4 border-b border-dotted border-gray-900">
<span>Spare Copy</span>
<span>2,00 €</span>
class="flex justify-between mb-4 border-b border-dotted border-gray-900">
<span>Spare Copy{{ props.freeBadgeCopies > 1 ? " x" + props.freeBadgeCopies : "" }}</span>
<span>{{ copiesPrice }},00 €</span>
</div>
<!-- End Options -->
<div class="flex justify-between text-2xl border-b border-double border-gray-900">
Expand All @@ -274,6 +282,4 @@ const total = computed(() => {
</div>
</template>

<style scoped>

</style>
<style scoped></style>
16 changes: 8 additions & 8 deletions resources/js/Pages/Welcome.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ const messages = computed(() => {
<div v-if="messages.showButtons" class="w-full">
<div class="flex flex-col md:flex-row gap-3 text-white w-full"
v-if="usePage().props.auth.user !== null">
<!-- Action Select -->
<Button @click="router.visit(route('badges.create'))" icon="pi pi-id-card" class="w-full" v-if="usePage().props.auth.user.badges.length === 0 && showState === 'preorder'" label="Claim your first free Fursuit Badge!"/>
<!-- Claim Additional Fursuit Badges -->
<Button @click="router.visit(route('badges.create'))" icon="pi pi-id-card" class="w-full" v-else-if="usePage().props.auth.user.badges.length === 0">Get your first Fursuit Badge!</Button>
<Button @click="router.visit(route('badges.create'))" icon="pi pi-id-card" class="w-full" v-if="usePage().props.auth.user.has_free_badge" label="Customize First Fursuit Badge"/>
<Button @click="router.visit(route('badges.create'))" icon="pi pi-id-card" severity="warning" class="w-full" v-if="usePage().props.auth.user.badges.length === 0 && !usePage().props.auth.user.has_free_badge"
label="Buy Fursuit Badges"/>
<!-- Buy Additional Fursuit Badges -->
<Button @click="router.visit(route('badges.create'))" icon="pi pi-id-card" severity="warning" v-if="usePage().props.auth.user.badges.length > 0" class="w-full"
<Button @click="router.visit(route('badges.create'))" icon="pi pi-id-card" severity="warning" class="w-full" v-if="usePage().props.auth.user.badges.length > 0"
label="Buy Additional Fursuit Badges"/>
<!-- Manage Badges -->
<Button @click="router.visit(route('badges.index'))" icon="pi pi-id-card" class="w-full" v-if="usePage().props.auth.user.badges.length > 0" label="Review Ordered Badges"/>
Expand Down Expand Up @@ -130,14 +130,14 @@ const messages = computed(() => {
</p>
<div class="mt-4">
<h1 class="text-2xl font-semibold font-main">How to Get Your Badge:</h1>
<ul class="list-disc pl-6 mt-2">
<li class="mt-2">
<ul class="list-disc pl-6 mt-2 gap-2 flex flex-col">
<li>
<strong>First Preoder Badge Free:</strong> Simply register for Eurofurence and get your first fursuit badge for free.
</li>
<li class="mt-2">
<li>
<strong>Additional Badges & Late Orders:</strong> Order more for just 2 € each.
</li>
<li class="mt-2">
<li>
<strong>On-Site Services:</strong> Need a last-minute badge? We’ve got you covered with our late printing service for a small fee.
</li>
</ul>
Expand Down
4 changes: 4 additions & 0 deletions tests/Feature/BadgeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@

beforeEach(function () {
$this->user = User::factory()->create();
$this->user->update([
'has_free_badge' => false,
'free_badge_copies' => 0,
]);
$event = \App\Models\Event::factory()->create([
'starts_at' => \Carbon\Carbon::parse('2024-06-01'),
'ends_at' => \Carbon\Carbon::parse('2024-06-30'),
Expand Down