黄色い救急車を呼ばれるレベル

今日は、朝から乾燥機の電気の点検修理の予定だと思っていたんです。
朝、園に行くと、今日じゃないよと。
そろそろ黄い救急車を呼ばれるレベルです。
大丈夫か、俺。

空振りだったので、ジムニーの 1 ヶ月点検に行ってきました。
1,000km 走るのに 3 ヶ月くらいかかってます。
とりあえず、エンジンオイルを交換してもらいました。

それと、タイヤの件です。
まだまだ純正タイヤに山があるのでもったいないという思いが強いんですが、とりあえずということで、トランパス MT の値段を聞きに行きました。
谷町のアルペンの向かいに BEE LINE さんができていたので、そこに行ってきました。
結論から言うと、5 本(お尻に背負っているスペア)を交換すると、8 万弱、ということです。
そんなに高いの?
BEE LINE は安いと言う印象でしたが、これはダメですね。

組み替えの工賃、ということなんでしょうかね。
にしても、タイヤ組むのなんて、ガソリンスタンドのアルバイトでもできる程度のことで、多少の設備が必要なだけです。
真っ当に商売してもらいたいですね。

タイヤ交換 持ち込み、で調べたら、

松山市の持込タイヤ交換専門店(1本1,485円~)車検の速太郎 松山店

と出てきました。
まあ、2,000 円だとしても、やはり 1 万前後で交換できそうです。

格安のマッドタイヤ

マッドタイヤに交換するとなれば1本当たり大体1万円以上の出費は覚悟しなければなりません。それがトランパスM/Tなら1本1万円以下の出費に抑えることができる神タイヤです。

ネットショップの中には1本7,000円台で取り扱っているところもあります。国内タイヤメーカーのジムニー用マッドタイヤでこの価格は最安値です。

参考:195R16 104Q TRANPATH M/T – Google ショッピング

海外タイヤメーカーにも格安マッドタイヤはありますが、国内タイヤメーカー並の品質や信頼性を期待できるかは微妙なところです。あらゆる面で考えるとトランパスM/Tはコスパ最高タイヤなんです。

タイヤ自体、よく探してませんが、パッとみただけでも、8,000 円台で売られていますから。
探せば 7,000 円くらいのところもあるかもしれませんね。

あと、このサイズのタイヤを履くとなると、ノーマル 175 → 195 と 20mm 幅が増えるんですが、ホイルはそのままでいいのかなと思います。
ホイルも欲しいんですけど、どうせガリっとやるだろうし、先立つものないし、悩みどころです。

それはそうと、なんなんでしょうか、この数字は。
クッソ遅い軽四なんですけど、ミニよりも悪いですね。
4t ユニック、キャンター並ですよ、これ。
キャンターは軽油ですから燃料が安いので、ジムニーの方がよろしくない感じ。
黒だから、エアコンガンガンで燃費が悪化しているのでしょうか。。。

それで、輸出許可のために必要な書類作りをしていたんですが、Amazon や Walmart で買い込んだ生活用品は、インボイスがバラバラなので、ダウンロードして PDF に変換してまとめているのですが、単純作業なので、AppleScript で Safari を操作して自動化しているのです。
curl とか、wget で落とせたら、もっと早くて確実なんでしょうが、ログインが必要な先にあるので、Safari でやった方が楽かなと思ったわけです。

前回まではバナー広告とか、そういうのを CSS に細工して非表示にしてから PDF にして保存していたのですが、Walmart の画面デザインが変わって動作しなくなったので、ソースをダウンロードするスクリプトと PDF に変換するスクリプトを分けたんですが、ソースをダウンロードするスクリプトすら Walmart は、動かなくなりました。
Amazon とか他は問題ないんですけど。。。
さらに、手動で保存して PDF に変換する際に、もう無茶苦茶にレイアウトが崩れる(多分 CSS が引っ張ってこれてない)ので、使い物になりません。
大した量ではないので、手動でやりましたが、本当に不毛です。
なんとかならないもんでしょうかね。

月曜日までに書類は揃えないといけないので、ボチボチ頑張りたいと思います。

不良品撲滅!

FISKARS の砥石なんですけど、意外と不良率の高い商品なのです。

不良のパターンとしては、よくある順で、

  • 滑り止めが取れて数が足りずガタガタする
  • 砥石のカバーの爪が折れている
  • 砥石が入ってない

なんですが、輸送中の事故なら、箱の中に壊れた残骸とかありそうなものなんですが、箱に穴もなく残骸もない、っていうのが毎度のパターンです。

それで、当然検品しているんですが、Amazon の場合は袋を作って包んでいたんですが、直送する場合には、かなり手間がかかるので省いていたんです。

プチプチ封筒に入れて送るのですから、もし事故があればわかると思うわけですよ。
ところが、それでも事故が起こったもんですから、念には念を入れて、袋に入れることにしたわけです。

ざっと寸法を測って注文したら。。。写真の有様です。
ピッタリすぎて、蓋ができません。。。

なんとも。

そんなこんなで、今日の出荷は 1 パレットのみでした。

納品のラベル作成スクリプトをちょっと更新してたら、出荷の締め切りは 18:30 なんですが、18:20 くらいになってしまいました。

それで、ダンボールの話になるんですが、輸送箱の重量やサイズを入力しないといけないのですが、これがものすごくかったるいのです。

写真の箱だと、9″ x 9″ x 7″ ってことがわかるんですが、入力フィールドが 3 つに分かれているし、cm なのでいちいち変換しないといけなくてかったるくて仕方ない。

実際、納品のデータを作るのに小一時間かかっていますし、ミスがあると送料で莫大な損が出ますので、ものすごくストレスなんです。

作業のやり方自体に詰めて、データはアップローできるようなので、自前のシステムを構築して行こうかと思います。
ローマは一日にして成らず。
コツコツ頑張らないと。。。

それと、輸出書類の件。
Save as PDF で保存しないことにはどうにもならないので、重い腰を上げて書き直しました。

まあ、世界狭いんですよね、Mac 界隈は。
木下さん、お世話になりました。

書いてある通りなんですが、要素をひたすら every UI element で調べまくる、これで解決です。

例えば画像の状態の場合、開いているウインドウが window 1, そこに印刷のモーダルダイアログが出てますが、これは sheet 1 of window 1 となります。

PDF の部分ですが、これは menu button "PDF" で、画面の状態にするにはクリックしないといけません。
クリックする click menu button "PDF" と、メニューが表示され、選択可能になります。
click menu item "Save as PDF" of menu of menu button "PDF"

そうすると、さらにモーダルダイアログが出てきて、保存場所を選択できるんですが、これは sheet 1 of window 1 になるんです。ややこしい。

ここでは keystroke "g" using {command down, shift down} すると、フルパスが入力できるようになるので、パスを keystroke で入力した後に Save ボタンをクリックしてやると、問題なく保存されます。
ただし、ファイルが存在するややこしいので、事前に保存先の PDF は掃除しておきます。

というわけで、every UI element で調べまくる、という気づきがあり、なんとか解決することができました。

一難去ってまた一難、今度は Walmart がサイトのデザインが変わって、レイアウトが崩れまくってます。。。
ボチボチ頑張ります。

Safari の Export as PDF と Print からの Save as PDF

大ハマりです。

輸出のためのインボイスをまとめているんですが、結構枚数があるので、半自動処理をしています。

これがかなり曲者というか、トリッキーというかなんですが、流れとしては、

  • 倉庫にある品物のうち、積み込むもののインボイス番号をピックアップする
  • インボイス番号から、Amazon 等での注文だと判明したもの(日用品, 例えば洗剤など)の invoice を Safari で表示, 一旦 HTML としてローカルに保存する
  • ローカルに保存した HTML のうち不要なものを CSS を細工して取り除く(ヘッダやふった、ロゴなど)
  • Export as PDF を使い PDF に変換して保存する
  • 各インボイス番号に基づきソートし、連番を振った上で、FPDF を使い 1 ファイルにまとめる

って感じなんです。

Amazon とか、まあその辺での小物の買い物は、次のような理由でものすごく数が多いので、いちいち人力でやっていたら、大変だし、ミスが起こります。
なので、自動化しているんですが。。。

  • 洗剤やケミカル類, おにゃー様のグッズなどは、Subscribe & Save という定期注文で、1 アイテムごとにインボイスができるため、10 アイテムを定期注文しているなら、10 件のインボイスが発生する
  • Subscribe & Save は、同じアイテムを 2 個買うと、1 件の定期注文とカウントされるけど、1 アイテムづつを 2 件定期注文すると、注文件数に下駄をはかせることができ、割引率がアップ
  • また、数が多いときは、数量変更だと、いちいち変更作業が必要だけど、全部ならスキップをワンクリックするだけで良いので楽

ぱっと見はうまく動いていたんです、ぱっと見は。

問題は、表題の通りなんですが、Export as PDF と Print からの Save as PDF の違いです。

本当は、Print からの Save as PDF で PDF に変換したかったんですが、プリントダイアログの操作をしないといけなくて、この部分が不安定だったんで、それを省略できる Export as PDF で処理していました。

このところずっとこれで問題なく動いていたんですが、出来上がった PDF の用紙サイズがおかしなことになっているのです。
インスペクタで見ると、Paper size: 40.19 x 23.32cm となっています。
これを A4 サイズにすると、横 210mm x縦 297mm なので、右半分が欠落してしまいます。

当たり前ですが、Print からの Save as PDF の場合、用紙サイズの設定ができるので、このような問題は起こりません。

で、なんで一旦 HTML で保存をするのか、というと、Amazon の側が当然セキュリティのため、暗号通信になっているので、wget だとかそこらへんでゴニョゴニョできそうになかったため、です。

次に HTML から PDF の変換を、それこそ FPDF でやれよ、って話ですが、JavaScript やら CSS でゴニョゴニョしているため、レイアウトが崩れすぎて使い物にならなかったため、です。
Acrobat を使ったらできるんだろうか。。。持ってないけど。

しかしまあ、個人事業者の方で、こういう税金を払う時に提出しないといけないインボイス類って、どうやってるんでしょうかね。

というわけで、丸一日かかっても解決できませんでしたので、今回は人力で Print からの Save as PDF での変換作業で凌ぎたいと思います。

それはそうと、次の Lodge 製品の仕入れの件なんですが、今まではバラバラというか、一個一個の荷物として倉庫に搬入してもらい、それをこちらで輸出用の梱包にまとめていたんです。
ただ、この方法だと輸送コストが嵩む上、紛失や破損、あとそれらの管理のコストもかなりかかるし、Lodge 製品もある程度売れるようになってきたので、量をまとめて注文をしようかなと思うわけです。

それで、担当者が知らない単語がでてきたのですが、

ということのようです。

  • MOQ Minimum Order Quantity 最低注文数
  • SPQ Standard Packing Quantity 最小発注単位
  • SNP Standard Number of Package 標準の梱包の数=「出荷梱包単位」

さて、SNP ですが、例えば Lodge の製品で言えば、L8SK3 などは複数枚, たしか 3 枚で 1 つの箱に入っているんです。
その場合、SNP = 3 なのかなと思うわけです。
ただ、その箱が本当に最終の箱か、とも思うんですが、基本的にある程度の大きさがあり、当然に、鉄なので重たいので、3 枚入りの箱を、さらに大きな箱で梱包するのかという疑問なんですが、以前紹介した Lodge の工場での生産風景で、出荷時にパレットにはい付けして、ストレッチフィルムで梱包している様子が見て取れますが、このパレット 1 枚、これも SNP といえば、SNP じゃないの、って話です。
さらに言えば、パレットにきれいに積みつけられる数、1 段のですよ、これも SNP といえば SNP ではないかと。

うちの標準の梱包サイズで言えば、L8SK3 は LCC3 と共通の箱を使い、1 箱 5 枚で再梱包しています。
再梱包する理由は、L8SK3 には外箱がないため、Amazon で保管されている際に、

  • 1 アイテムがどこまでか範囲をはっきりさせるため
  • 商品を保護するため

1 アイテムごとに箱に入れるか、ビニール袋等で個別に梱包し、FBA ラベルを貼り付けることを求められるためです。

厳密に言えば、この作業はメーカーバーコードで納品すれば省略できますが、手間暇かけて丁寧に検品して、丁寧に梱包してこそ差別化できる わけでし、値段とその部分でしか差別化はできませんから、ここが自分の唯一の仕事と言っても過言ではありません。

で、箱の寸法ですが、B4-80 と同じくらいなんですが、長さ 375 × 幅 265mm(内寸)なので、400 x 300 といったところです。

写真は、保管のために倉庫内で積んである様子で、棒積みになっています。
この後、輸送のために、交互の煉瓦積みに積みなおししましたが。

要するに保管時には、ダンボールの強度を優先して、劣化を避けるために低く積んでおくわけです。
輸送の際には、特にこの箱は輸送専用で、Amazon に到着したら破棄されて、お客様にお届けするものではないので、到着まで持てば良いので、荷崩れせず、かつ、スペース効率の良い積み方に切り替える、というわけです。
写真の量で 3 x 3 で 9 箱、入り数が 5 ですから、一箱 15 キロはないですが、一つ 5 pounds なので、10kg ちょっとですね。なので、1 段で 100kg くらいです。
4 段積めば、一番下の段には 30kg 以上乗っているのですから、小学生くらいの子供が踏み台に使っているようなものです。
なので、ちゃんと考えないと、すぐに箱がダメになってしまうんです。
箱は 100 円近くしますので、パレット一つあたり、梱包の材料代だけで何千円もかかっているんです。

もちろん、LCC3 のように積み上げても、製品全体で重量を受け止めることができ、ダンボールが痛まない場合、また、LCC3 の場合、普通の茶色の箱と、カラー印刷の化粧箱とバリエーションがあるんですが、カラー印刷はコートされているのか、とてもとても滑りやすいため、そもそも棒積みで何段か積んだら、リフトが止まっただけで前方に滑り落ちかねないので、こういうものはシュリンクフィルムを軽く巻きつけておくと、フィルム同士が接すると滑り止めにもなるので、輸送ラベルからの保護も兼ねて、シュリンクフィルムを巻くようにしています。

えらく話が脱線しましたが、アメリカのパレットは、40″ x 48″ なので、1,000 x 1,200mm といったところなので、LCC 3 の箱なら、煉瓦積みで 300 x 400 が 4 個 x 1 列、400 x 300 が 3 個 x 2 列で、10 個/段, ということになるんじゃないかなと思うわけです。

ただ、最初から色々と細かくいいすぎるのもアレかと思うわけで、向こうも素人ではないというよりも、こちらよりも経験も知識もあるだろうから、まずはやってみて、問題が出たら煮詰めていけばいいんじゃないかなと思います。
まあ、結構、自分のやり方に固執して、それ以外はできない、という人もいるというか、そういう人の方が多いんで、問題が出ても解決できないってのは往々にしてあるパターンだったりもするんですが。

案ずるより産むが易しともいうし、とにかくやってみようと思います。

STORES の管理画面がリニューアルされた件

雑貨屋 Hearth & Home 暖炉家(暖炉屋) は STORES という個人のお店用のサービスを使って営業しています。

こういうサイトを一から作るのはそれなりに手間隙がかかるわけで、売れるかどうかもわからない状態で、コストを掛けることはできないし、拙速に行こうということで、サービスが始まった当初に登録して、1 年くらいは開店休業状態だったんですが、2 年ほど前から、本格的に活動を始めたわけです。

ヤフオクも手数料が跳ね上がったので、今までどおりの価格では出品できなくなったのと、簡単取引の仕組みが導入されたたため、すべての出品を一度終了していたのですが、自動出品機能も STORES のほうが変更になったので機能しなくなっていたので、雨で外の仕事ができないので、ごそごそとプログラムを書き直しました。

ほとんど備忘録ですが、JavaScript で変数の汚染の問題があったんですが、とりあえず、無名関数を使って対処するようにしました。

(function(){
    l = [];
    e = document.querySelectorAll('p.quantities_variation_title');
    if (e) {
        for (i = 0; i < e.length; ++i) {
            l.push(e[i].textContent);
        }
    }
    return l.join(';;');
})();

それはそうと、いろいろ調べ物をしていて、今頃知ったんですが、JXA といって、Mac の操作が JavaScript からできるようになっているようです。

Illustrator とかも、JavaScript で自動化できるようですし、Safari 自体も、コンテンツを JavaScript で外部から云々すれば、クロスサイトでの処理も、上の join のようなブサイクなことをしなくても済むので、かなりコーディングが楽になりそうです。

勉強してみようと思いますが、その前に、Raspberry Pi、届いているんですが、micro SD のアダプタがないこと、HDMI で繋がるディスプレイがないこと、この 2 点でテンションが下がって、放置プレイ中です。

忘れるほうが早い年代になってきましたので、忘れないうちにこっちにも時間を割いていこうと思います。

画像形式を変換するコマンド

最近本当に忘れっぽくて困ります。

さて、本日のお題は、表題のとおりなんですが、STORES.jp に出品している商品をベースとして、ヤフー店にも、商品を転送?しているわけですが、スクリプトがエラーになりました。

まあ、商品の登録時に気をつけておけばいいことではあるんですが、この調子だといつまでも覚えてないと思うので、また同じ轍を踏むのは確実です。

というわけで、スクリプト自体を書き換えました。

エラーの原因は、いくつかあって、STORES の方は、JPEG 以外にも、PNG などの形式が OK なんですが、ヤフー店は、JPEG か GIF ということになっているためです。

それ以前に、スクリプト自体が JPEG である前提でした。

set myNumImages to do JavaScript "document.querySelectorAll('li>img[src*=hearthandhome]').length"
if myNumImages > 3 then set myNumImages to 3

set myPath to do shell script "echo ~/Pictures/STORES/" & myItemId
try
    do shell script "mkdir " & myPath
end try
do shell script "open " & myPath

repeat with myImageIndex from myNumImages to 1 by -1
    set myImageFileName to do JavaScript "document.querySelectorAll('li>img[ng-src*=hearthandhome]')[" & myImageIndex - 1 & "].src.replace(/^.+[/]|_100x100/g,'')"
    
    set myImagePath to myPath & "/" & myImageIndex & ".jepg"
    set myImageURL to "https://f.stores.jp/_files/hearthandhome/" & myImageFileName
    
    do shell script "/sw/bin/wget --no-check-certificate " & myImageURL & " -O " & myImagePath
    
    if myImageFileName ends with ".jpeg" is false then
        do shell script "sips -s format jpeg " & myImagePath
    end if
end repeat

やっつけなので汚いですが、とりあえず動きました。

今度の改築で、自動的に png があると jpeg に変換されるので、その画像にすげ替えれば、次からは問題ないかと。

えらく振りが長くてすみません。

肝心のコマンドですが、sips です。

sips コマンドは、記憶が確かなら海上忍氏の 連載記事 で知ったと思うんですけど、あれ、344 回も続いたんですね。

当該記事は、こちら です。

2003/12/05 の記事でしたので、かれこれ 12 年ほど前ですか。
まあ、よく覚えていたというべきか、それともやっぱり耄碌したと考えるべきか。

というか、OS X になってからもうそんなに経つんですかね。
そういえば、Preview Release は嫁さんと新宿新南口の高島屋に買いに行ったような記憶があります。
Cheater のリリースは 2001 年だったのようですから、子供が生まれる前ですね。
いやはや、長生きしたものです。

今更ながら JavaScript で半角 → 全角

まあ、半角・全角という表現がアレなのはおいておいてください。

最近、郵送にクリックポストという手段を使うのですが、ヤマトのメール便に似た感じのサービスで、A4 サイズ、3cm までの厚みのものが安価に送れます。

ウェブで送り先などを入力して、ラベルを作成するんですが、ある程度の数になると、それが結構面倒臭いんですよね。

需要があるのか、さっぱりわかりませんが、重松は住所録ソフトは筆まめを使っているんですが、その筆まめの住所データーをいちいち Windows と Mac とを切り替えながらコピペするのも面倒くさいので、自動化しました。

その時、住所は半角があってはいけないので、変換する必要があるんですが、以前は、Script Managaer を使って変換していたんですけど、もう OSAX がどっかに行ってしまっているし、JavaScript でやることにしました。

以下のページを参考にしました。

tell application "Finder"
    set myText to the clipboard
end tell

tell application "Safari"
    set myClickPostDocument to 0
    
    set myNumOfDocuments to count every document
    repeat with myDocumentNum from 1 to myNumOfDocuments
        set theDocumentTitle to do JavaScript "document.title" in document myDocumentNum
        if theDocumentTitle contains "新規発送" then
            set myClickPostDocument to myDocumentNum
            exit repeat
        end if
    end repeat
    
    if myClickPostDocument is 0 then
        say "click post document was not found"
        return
    end if
    
    tell application "Finder" to set myClip to the clipboard
    set buf to AppleScript's text item delimiters
    set AppleScript's text item delimiters to " "
    set myData to every text item of myClip
    set AppleScript's text item delimiters to buf
        
    set myName to item 4 of myData
    set myZip to item 67 of myData
    set myAddr to item 68 of myData
    if 0 < (length of (item 69 of myData)) then set myAddr to myAddr & item 69 of myData
    
    tell document myClickPostDocument
        do JavaScript "
document.querySelector('div.edit_panel input[name$=id39]').value='おふだ';
document.querySelector('div.edit_panel input[name$=no_missive]').checked=true;
document.querySelector('div.edit_panel input[name$=checked_pack_size]').checked=true;

myZip = '" & myZip & "';

document.querySelector('div.edit_panel input[name$=zip1]').value = myZip.substr(0,3);
document.querySelector('div.edit_panel input[name$=zip2]').value = myZip.substr(4,4);

myAddr = '" & myAddr & "'.replace(/[!-~]/g, function(s) {
    return String.fromCharCode(s.charCodeAt(0) + 0xFEE0);
});
myAddr = myAddr.replace(/^愛媛県/,'');
document.querySelector('div.edit_panel textarea[name$=receiver_address]').value = myAddr;

myName = '" & myName & "';
document.querySelector('div.edit_panel input[name$=receiver_name]').value = myName;
"
    end tell
end tell