'owner-rtp', 'name' => 'Owner', 'email' => 'owner-rtp@example.com', ]); } private function location(User $owner): PosLocation { return PosLocation::create([ 'owner_ref' => $owner->public_id, 'name' => 'Front counter', 'currency' => 'GHS', 'is_default' => true, ]); } protected function setUp(): void { parent::setUp(); $this->withoutMiddleware(EnsurePlatformSession::class); $this->withoutVite(); } public function test_tip_is_applied_to_sale_total_on_create(): void { $owner = $this->owner(); $this->location($owner); $sale = app(PosSaleService::class)->createSale($owner, [ ['name' => 'Meal', 'unit_price_minor' => 10000, 'quantity' => 1], ], [ 'tip_minor' => 1500, 'currency' => 'GHS', ]); $this->assertSame(10000, $sale->subtotal_minor); $this->assertSame(1500, $sale->tip_minor); $this->assertSame(11500, $sale->total_minor); } public function test_digital_receipt_email_is_sent(): void { Mail::fake(); $owner = $this->owner(); $location = $this->location($owner); $sale = PosSale::create([ 'owner_ref' => $owner->public_id, 'location_id' => $location->id, 'reference' => 'POS-TESTRECEIPT1', 'status' => PosSale::STATUS_PAID, 'payment_method' => PosSale::METHOD_CASH, 'subtotal_minor' => 500, 'total_minor' => 500, 'currency' => 'GHS', 'paid_at' => now(), ]); $result = app(ReceiptEmailService::class)->send($sale, 'guest@example.com'); $this->assertTrue($result['ok']); Mail::assertSent(DigitalReceiptMail::class, function (DigitalReceiptMail $mail) use ($sale) { return $mail->sale->is($sale) && $mail->hasTo('guest@example.com'); }); $this->assertSame('guest@example.com', $sale->fresh()->customer_email); } public function test_customer_display_receipt_email_action_sends_mail(): void { Mail::fake(); $owner = $this->owner(); $location = $this->location($owner); $sale = PosSale::create([ 'owner_ref' => $owner->public_id, 'location_id' => $location->id, 'reference' => 'POS-TESTRECEIPT2', 'status' => PosSale::STATUS_PAID, 'payment_method' => PosSale::METHOD_CASH, 'subtotal_minor' => 800, 'total_minor' => 800, 'currency' => 'GHS', 'paid_at' => now(), ]); $display = app(CustomerDisplayService::class)->pushReceipt($location, $sale); $this->postJson(route('pos.customer-display.action', ['token' => $display->token]), [ 'type' => 'receipt_email', 'email' => 'buyer@example.com', ]) ->assertOk() ->assertJsonPath('email_sent', true); Mail::assertSent(DigitalReceiptMail::class); } public function test_settings_save_customer_promo_content(): void { Storage::fake('public'); $owner = $this->owner(); $this->location($owner); $this->actingAs($owner) ->put(route('pos.settings.update'), [ 'name' => 'Front counter', 'currency' => 'GHS', 'service_style' => 'retail', 'receipt_footer' => '', 'receipt_header' => 'Demo Shop', 'printer_paper_mm' => 80, 'customer_promo_headline' => 'Happy hour', 'customer_promo_body' => 'Buy one get one free until 6pm.', 'customer_promo_image' => UploadedFile::fake()->image('promo.jpg'), 'gateway_provider' => '', ]) ->assertRedirect(); $location = PosLocation::query()->first(); $this->assertSame('Happy hour', $location->customer_promo_headline); $this->assertSame('Buy one get one free until 6pm.', $location->customer_promo_body); $this->assertNotNull($location->customer_promo_image_path); $promo = $location->customerPromo(); $this->assertSame('Happy hour', $promo['headline']); $this->assertNotNull($promo['image_url']); $display = app(CustomerDisplayService::class)->ensureForLocation($location); $state = app(CustomerDisplayService::class)->publicState($display); $this->assertSame('Happy hour', $state['promo']['headline']); } public function test_operator_can_email_receipt_from_sale_page(): void { Mail::fake(); $owner = $this->owner(); $location = $this->location($owner); $sale = PosSale::create([ 'owner_ref' => $owner->public_id, 'location_id' => $location->id, 'reference' => 'POS-TESTRECEIPT3', 'status' => PosSale::STATUS_PAID, 'payment_method' => PosSale::METHOD_CASH, 'subtotal_minor' => 300, 'total_minor' => 300, 'currency' => 'GHS', 'paid_at' => now(), ]); $this->actingAs($owner) ->post(route('pos.sales.email-receipt', $sale), ['email' => 'print@example.com']) ->assertRedirect(); Mail::assertSent(DigitalReceiptMail::class); } }