markTestSkipped('FRAPPE_ERP_* env vars not set'); } $this->client = new FrappeHttpClient( HttpClient::create(), (string) $baseUrl, (string) $apiKey, (string) $apiSecret, ); $this->adapter = new FrappeErpAdapter($this->client, (string) $itemCode); } protected function tearDown(): void { if ('' !== $this->createdInvoiceName) { try { $this->client->put('/api/resource/Sales Invoice/'.$this->createdInvoiceName, ['docstatus' => 2]); $this->client->delete('/api/resource/Sales Invoice/'.$this->createdInvoiceName); } catch (\Throwable) { // best-effort cleanup } } } public function test_find_simon_kuehn_by_name_and_address(): void { $customerId = $this->adapter->findExistingCustomer( 'Simon Kühn', 'Kirchstr. 1', 'Karbach', '56281', ); $this->assertNotNull($customerId, 'Simon Kühn should exist in Frappe staging'); $this->assertStringStartsWith('Simon', $customerId); } public function test_unknown_person_is_not_found(): void { $customerId = $this->adapter->findExistingCustomer( 'Voldemort', 'Dunkle Gasse 1', 'Nirgendwo', '00000', ); $this->assertNull($customerId); } public function test_find_simon_and_create_invoice_for_1337(): void { $frappeId = $this->adapter->findExistingCustomer( 'Simon Kühn', 'Kirchstr. 1', 'Karbach', '56281', ); $this->assertNotNull($frappeId, 'Simon Kühn should exist in Frappe staging'); $simon = new Customer('Simon Kühn', 'simon.kuehn83@gmail.com', [ 'street' => 'Kirchstr. 1', 'city' => 'Karbach', 'zip' => '56281', ]); $simon->setFrappeCustomerId($frappeId); $article = new Article( new ArticleType('Laptop'), 'LAP-THINK-SIMON', 'INV-THINK-SIMON', 1, ArticleCondition::Good, ); $article->setManufacturer('Lenovo'); $article->setModelName('ThinkBook 14 G6 IRL'); $article->setModelNumber('21KG00NQGE'); $article->setSerialNumber('PNV09SJZ'); $article->setEbayTitle('Lenovo ThinkBook 14 G6 IRL — generalüberholt, läuft wie Butter'); $order = new Order( $article, $simon, new Platform('direct', 'Direktverkauf'), 'ORDER-SIMON-1337', '1337.00', new \DateTimeImmutable('2026-05-18'), ); $invoiceId = $this->adapter->createSalesInvoice($order); $this->assertNotEmpty($invoiceId); $this->createdInvoiceName = $invoiceId; // Verify the invoice actually exists in Frappe $response = $this->client->get('/api/resource/Sales Invoice/'.$invoiceId); $this->assertSame($invoiceId, $response['data']['name']); $this->assertEquals(1337.0, $response['data']['grand_total']); } }