Wanneer we in ons dagelijks werk iets tegenkomen dat "eigenlijk handmatig blijven doen is best vermoeiend", is het inmiddels normaal geworden om snel een klein systeem in Claude Code in te bouwen!
Dit keer hadden we precies zo'n geval, en de aanleiding was dat ons bedrijf zijn kapitaal verhoogde.
Ons boekjaar begint in februari, en we voerden de kapitaalverhoging ook in februari door. Omdat we ons kapitaal hebben verhoogd, zagen we ons genoodzaakt om ook onze inkoopprocedures ten opzichte van externe partners en samenwerkingsbedrijven beter in te richten dan ooit tevoren.
Dit raakt wat men noemt de subcontractorwet, een gebied dat vanaf januari 2026 onder de huidige regelgeving als de "wet passende handel" bekend staat. Als inkoper moet je meer gaan doen: duidelijk aangeven wat je inkoopt, inkoopstukken aanmaken en bewaren, betalingstermijnen vastleggen, enzovoort.
Uiteraard gaat het niet alleen maar om "we moeten dit doen omdat de wet het verplicht"!
Als je externe partners inschakelt, is het voor beide partijen—zowel de inkoper als de leverancier—belangrijk dat je duidelijk vastlegt wat je inkoopt, hoeveel het kost, wanneer, en hoe het zich verhoudt tot offertes. (Klinkt logisch, toch?)
Dit was geen functie die in onze boekhoudingssoftware zat.
We gebruiken MoneyForward-tools (hieronder afgekort als Manefo) voor boekhouding, offertes en facturen.
Dit werkt prima voor dagelijkse boekhouding- en facturatietaken, maar wat we deze keer wilden doen was iets anders.
Een offertePDF van een externe partner als basis gebruiken om een PO-PDF van Liberogic aan te maken
Manefo heeft niet echt de juiste functionaliteit voor wat we ervan nodig hebben, en het lijkt zonde om een service alleen daarvoor in te schakelen.
Als het handmatig zou moeten,
- Het formaat van de PO opstellen
- De offertegegevens handmatig overnemen in het PO-formaat terwijl je naar de offerte kijkt
- De orderdatum invullen
- Het offertenummer overnemen
- De regelitems overnemen
- De inhoud verifiëren, inclusief totaalbedrag en dergelijke
- De bestandsnaam aanpassen
- Overige, overige…
Het is lastig, toch? Deze taken nemen toe… daarom hebben we besloten het te bouwen.
In minder dan een uur praktisch bruikbaar met Claude Code
De timing was ook goed.
Het begint van februari, de kapitaalverhoging in februari, en de release van Claude Code samenvallend met integratie in ons team.
Intern liep al een hackathon-achtige flow waarbij we Claude Code gebruikten voor bedrijfsverbeteringen, kleine interne apps, en zelf bedachte ideeën konden implementeren.
Van eenvoudige specificatieverduidelijking tot instructies voor Claude Code, inclusief fijne aanpassingen…
In minder dan een uur hebben we het tot een praktisch bruikbaar niveau kunnen brengen.
Het is niet zo dat alles voltooid is door AI in te zetten, maar met goed uitgewerkte prompts is het snel en handig!
Desktopapplicatie voltooid
Een eenvoudig hulpmiddel voor het genereren van inkooporders dat op vrijwel elk besturingssysteem draait.
Sleep een offerte-PDF naar de speciale .app en een Python-script wordt uitgevoerd, dat de inhoud van de offerte-PDF leest en een inkooporder-PDF in dezelfde map genereert.
Na afronding stuurt het een macOS-melding en opent de gegenereerde inkooporder-PDF automatisch.
De structuur ziet er als volgt uit.
~/Desktop/発注書生成/
見積書をドロップ→発注書生成.app
_lib/
generate_purchase_order.py
liberogic_logo.png
liberogic_seal.png
purchase_order_counter.jsonOmdat we willen dat ook medewerkers uit de administratie en beheer dit kunnen gebruiken zonder de terminal te openen, gebruiken we een AppleScript-droplet als ingang en voeren we de daadwerkelijke PDF-generering uit met Python.
In wezen is het een desktopapplicatie waarmee je een offerte-PDF kunt slepen en neerzetten om een inkooporder-PDF te krijgen. Omdat het zonder terminal kan worden gebruikt, is het gemakkelijk hanteerbaar voor administratieve taken binnen het bedrijf.
Het uiterlijk van de inkooporder-PDF volgt het formaat van onze factuur- en offerte-PDF's.
In het opmerkingengedeelte hebben we de volgende tekst opgenomen.
Deze inkooporder is hiermee formeel. We plaatsen deze order op basis van offertenummer XXX.
We hebben het inkoopordernummer in het volgende formaat bepaald.
{bedrijfsafkorting} inkooporder {YYYY}{MM}{3-cijferige serienummer}
Als het bijvoorbeeld de eerste inkooporder in februari 2026 voor een bepaald bedrijf is,
○○ Inkooporder 202602001
ziet er als volgt uit.
De volgnummers per bedrijf en per maand worden beheerd in purchase_order_counter.json, en de inkooporder wordt automatisch 5 werkdagen na de datum van de offerte gegenereerd. (Dit is voorlopig alleen, hoor! We zullen dit later onder toezicht aanpassen!)
We gebruiken Python's jpholiday om niet alleen weekends maar ook Japanse feestdagen uit te sluiten.
Een beetje lastig onderdeel
De offerte waarop de inkooporder is gebaseerd, komt van externe partners of samenwerkingsbedrijven, dus het format verschilt per bedrijf.
We kunnen niet zomaar zeggen 'de bedrijfsnaam staat op deze coördinaat' of 'het totaalbedrag staat op deze positie' — het is veel complexer dan dat.
Uiteindelijk gebruiken we reguliere expressies om flexibel informatie zoals leveranciersnaam, adres, telefoonnummer, offertenummer, offertedatum, onderwerp, regelitems, subtotaal, btw en totaal uit te pakken. We behandelen bedrijven met 'Co., Ltd.' (御中) als ons eigen bedrijf en de rest als leveranciers. Plus al die veel voorkomende PDF-problemen: wanneer je tekst uit een PDF extraheert, informatie die visueel gescheiden lijkt, kan in tekstvorm aan elkaar kleven.
In sommige gevallen dringt gebouwnaam of verdiepingnummer door in het onderwerp. Daarom filteren we onnodige adresinformatie eruit op basis van trefwoorden zoals 'gebouw' of 'verdieping'.
AI of niet, dit soort zaken zijn gewone PDF-verwerkingsproblemen.
De prompt die we aan Claude Code hebben gegeven
In plaats van vaag verzoeken is het zuiniger met tokens om zo specifiek mogelijk te zijn: mappenstructuur, verwerkingsstroom, layout, nummering regels, werkdagberekening, PDF-extractievelden enzovoort.
Laat Claude ook een voorbeeld-PDF lezen!
以下の条件で、見積書PDFを発注書PDFに自動変換するツールをmacOS向けに作ってください。
## 環境
- macOS / Python3(pip可)
- フォント:`~/Library/Fonts/NotoSansJP-Regular.ttf` / `NotoSansJP-Bold.ttf`
## フォルダ構成
`~/Desktop/発注書生成/
見積書をドロップ→発注書生成.app
_lib/
generate_purchase_order.py
liberogic_logo.png
liberogic_seal.png
purchase_order_counter.json`
## 処理フロー
1. `.app` に見積書PDFをドラッグ&ドロップ
2. Pythonスクリプトを実行し発注書PDFを生成
3. 完了通知(macOS通知)を出して発注書PDFを自動で開く
4. 発注書PDFは見積書と同じフォルダに保存
## 発注書の仕様
出力フォーマットは添付のMoneyForward形式のPDFに合わせること。
このPDFから以下を抽出して使う:
- ロゴ画像
- 押印画像
- レイアウト座標
- 列幅
- 余白
- フォントサイズ
## 自社情報
リベロジック株式会社
登録番号:T2010401081132
〒108-0073 東京都港区三田1-3-37 板金会館2F
TEL: 03-6809-4366 / FAX: 03-6809-4367
## 発注書番号
- 形式:`{会社略称}様 発注書{YYYY}{MM}{3桁連番}`
- 会社別・月別の連番を `purchase_order_counter.json` で管理
- 出力ファイル名もこの発注書番号に揃える
## 発注日
- 見積書の日付から5営業日後
- 土日と日本の祝日を除外する
## 見積書からの情報抽出
- どんな会社のフォーマットでも対応できる柔軟な正規表現で抽出
- 抽出項目:ベンダー名・住所・TEL、見積書番号、見積日、件名、明細、小計・消費税・合計
- ベンダー判定:「御中」の付いた会社=自社、それ以外=発注先
- 件名に住所の建物名が混入するケースに対応
## 発注書レイアウト
- タイトル「発注書」中央大文字
- 左:発注先の社名・住所・TEL
- 右:自社情報+ロゴ+押印+発注書番号・発注日・見積書番号・見積日
- 件名・発注金額を大きく表示
- 明細テーブル:品目/単価/数量/単位/価格
- 交互グレー背景
- 最低8行
- 合計エリア:小計・消費税・合計のみ
- 備考欄を枠付きで表示
- ページ番号なしHet is eigenlijk slechts een eenvoudige specificatie, maar in plaats van 'maak het gewoon mooi' is het belangrijk om bedrijfsbeperkingen en een zo concreet mogelijke eindafbeelding door te geven.
Uiteindelijk, het lezen van een ander formaat kan mislukken, dus we moeten Claude nog harder laten werken, maar het gaat toch sneller, dus dat is prima.
(De externe medewerkers en samenwerkingspartners die ons bedrijf inhuurt, komen niet eens aan twee cijfers, dus het is eigenlijk niet zo belangrijk!)
Juist omdat het handig is, let je ook op de veiligheid
Aan de andere kant moet je bij het gebruik van AI-ontwikkelingshulp niet alleen op het gemak letten, maar ook op veiligheidskwesties.
Terwijl je Claude Code instrueert en werkt, worden er verschillende bewerkingen op de lokale omgeving uitgevoerd.
- ~/Desktop へのファイル読み書き
- ~/Library/Services/ へのアクセス検討
- pip install によるPythonライブラリの追加
- osacompile によるAppleScriptアプリの生成
- ~/Library/Fonts/ にあるフォントファイルの読み取りDit is dit keer niet echt een groot verhaal, maar gezien we AI uitvoeringsrechten op de lokale omgeving geven, is het inderdaad eng 😨
Bij het delegeren van terminalhandelingen en bestandshandelingen, kunnen onbedoeld bestanden worden aangemaakt, overschreven of verwijderd, dus
- Controleer wat je toestaat!
- Maak een back-up!
- Controleer verschillen voor git-beheerde items!
- Scheid werkfolders!
zijn essentiële basismaatregelen. Als u dit gebruikt in ontwikkelingswerkzaamheden, kan het beter zijn om het .env-bestand via 1password in te laden. Het is wat omslachtig, maar dit maakt echt een verschil. (door onze CTO)
Aan de andere kant, als het alleen in de lokale omgeving wordt gebruikt zoals in dit geval, is het risico relatief beperkt. De impact via het netwerk naar buiten is gering, en in de meeste gevallen blijft het beperkt tot 'in het ergste geval alleen invloed op mijn eigen omgeving'.
Er zijn nog veel meer aandachtspunten, maar 'snel bouwen' en 'veilig gebruiken' zijn verschillende kwesties. Bij het uitvoeren van ontwikkeling met AI moet u de uitvoeringsrechten / bestandsbeheer / externe bibliotheken / gegevensverwerking controleren terwijl u vordert!
Toekomstig: medewerkers delen en Supabase-integratie
Nu even ter zake: wat we deze keer hebben gemaakt is een eenvoudig inkoopordergeneratietool dat in de lokale omgeving werkt.
In het eerste stadium gebruikten we purchase_order_counter.json om opeenvolgende nummers per bedrijf en per maand te beheren, maar als we erover nadenken om dit in de toekomst met medewerkers te delen, zullen alleen lokale JSON-bestanden voor het beheer van opeenvolgende nummers ongetwijfeld problemen veroorzaken zoals dubbele inkoopordernummers.
Daarom willen we tegels per bedrijf en per maand aan de Supabase-kant toevoegen, zodat meerdere personen dit kunnen gebruiken zonder overlappende nummers, en we willen ook de geschiedenis van uitgegeven inkooporders / inkooppartners / offertenummers / inkoopbedragen / inkoopdata / PDF-opslaglocaties enz. implementeren!
CEO en tegelijkertijd altijd medewerker. Iemand die graag nieuwe technologieën begrijpt, zich verheugt in momenten waarop dingen handiger worden, en zich volledig in het praktijkwerk kan verdiepen. Enthousiast over toekomstige technologie en voortdurend op zoek naar nieuwe ervaringen, ongeacht de leeftijd.
Morimoto
Projectmanager / Director / Oprichter in 2007