Life is Really Short, Have Your Life!!

ござ先輩の主に技術的なメモ

SQLAlchemyのLazyLoadとEagerLoad

SQLAlchemyには、カラムを指定できるwith_entitiesという関数がある。

こいつを指定してクエリを組み立てるときは、joinによって指定されたテーブルの中身を、予めもってきてくれるようだ。AlchemyのDebug=Trueで確認した。

 db.session.query(Item).join(Category).with_entities(
    Item.id,
   Category.name
  ).all() 

だけど、もちろんbackrefの指定にもよるけれど、カラムをな~んにも指定しない場合は、lazyloadになる。該当のプロパティにアクセスされたと同時に、SQLが走る。

 rs = db.session.query(Item).join(Category).all()
 for v in rs:
    print(rs.category.name) # この度にSQLが走るっぽい

それは困るぜってときは、予めoption関数でjoinした時にもってこいやっていう指定ができる。

 rs = db.session.query(Item).options(joinedload(Item.category)).all()
 for v in rs:
    print(rs.category.name) # DO NOT N+1 !!

docs.sqlalchemy.org

SQLAlchemy 101って本が日本語であれば、1万円でも買います。

レッツゴーFlutter

展示会運営のアプリをAndroidiOSで各々ネイティブで作って運営しているが、やっぱりワンソースでいい感じにやりたい...2つ同じもの作るのは単純に辛い。メンテナンス・コストが単純に倍になるのがだるい。1から勉強したってのもあるけど、フルコミットでリリースできるまで半年近くかかった。

利用しているライブラリの最新化、OSバージョンアップに伴って廃止/非推奨になったコードのメンテ、ルックアンドフィールの変更に伴うメンテ(今回のダークモードみたいなやつ)、テストコードのメンテ、ビルドシステム(Carthage / Gradle)のメンテ... Webアプリのほうが楽かも。UIのロジックとビジネスロジックの切り分けも気をつけないとすぐ肥大化するし。

Flutterが Android/ iOSクロスプラットフォーム開発の本命だと思われるので、こいつを勉強してなんとかワンソースで頑張りたいンゴ... Google Waveのようなことにはならんやろ。頼むで。

雑貨製造業向けの販売管理システムをリリースしました

Windowsフォーム→WPFに刷新して、空いた時間でコツコツ作っていた販売管理システムを、8月にリリースしました。他社利用も始まっており、後には戻れない〜。

f:id:gothedistance:20190910090631p:plain
f:id:gothedistance:20190910090647p:plain

技術的な話

フロントはWPF、バックエンドはPythonで、HTTPSJSONのやり取りを行っています。

MVVMフレームワークに、Prism7.2を採用しています。PythonはFlask/SQLAlchemyで、Nginx+Gunicornのリバースプロキシ入り環境をDockerでコンテナ化してます。

WPFを選んだ理由は以下の通りです。Electronだと無理な要件が多かったため。

  • グリッドのセル入力やセルのフォーカス制御など、グリッドの操作性の高さが必要だった
  • 画面を切り替えても入力中データがローカルに残るため、利便性が高かった
  • 帳票のダイレクト印刷が必要だった
  • キーイベントの実装が簡単

Windowsフォームの開発である程度の知見があったので、そのままWPFにしました。

機能的な話

物売りの商売で一番面倒で重要になるのは「残管理」です。

  • 取置の残管理
  • 出荷残管理(先納期、分納、納入待ち)
  • 注文残(入荷分から出荷する)の管理
  • 入荷の残管理(発注分の入荷予定の管理)
  • 在庫の管理

この辺がいい感じに連動していている販売管理システムは、あまりないと思います。

販売管理システムの切り替えをご検討の方でこの記事をご覧の方が万が一おられましたら、下記の会社フォームまでお問い合わせを頂ければ。僕が代表なので。デモ版のご案内をさせて頂きます。

お問い合わせ - (株) クオリティスタート 〜 IT企画・ITプロジェクト支援の会社です

CASE-WHENでWhere句を動的に組み立てる

kuniku.hatenadiary.jp

日付で挟む時に、解約日があれば開始日〜解約日、なければ開始日〜終了日で挟みたいという事を実現するのに、ビューを作る必要があった。

CASE-WHEN、幅が広い。

WHERE
  startdate >= curdate()
AND
  curdate() <= 
  (
  CASE
      WHEN cancelDate IS NULL THEN endDate
      ELSE cancelDate
  END
  ) 

Flask with Vue.js

やっと話が見てきた。

qiita.com

Javascript弱者だったため、Vue.js や Vue-cli 並びにJavascriptの開発環境とか、色んなことがつながるまで少し時間がかかった。

Vue.js のコンポーネント化にはCLIが必要

拡張子がvueのファイルにHTML/CSS/Javascriptをまとめてコンポーネント化し、そいつをimport して使うみたいなやり方をするには、ビルドが必要になる。ここでいうビルドはブラウザが理解できる形で変換をかけること。ScssファイルがCSSファイルに変換されるようなアレだ。

Javascriptの言語仕様がPythonJava等に比べて色々足りていないのを、パッケージマネージャやビルドツールを使って頑張っているのだなぁ。JSのビルドには内部的にJSを使っているため、Node.jsベースのパッケージマネージャであるnpmがあるわけやな。

Flask連携

Flask側は大したことやる必要なくて、ポイントはテンプレートフォルダと静的なファイルを置くフォルダをビルドされた環境に合わせるだけ。あとは、その内容をFlaskがレンダリングするというだけの話。

Vue.jsでSPA化したものをPWAで画像関係をキャッシュしてより高速にしたいものだ。

決算期で集計する場合は、決算月だけマイナスすればいい

3月決算の会社の場合、4月〜翌月3月までが1年という単位になる。これをCASE句でまとめるのはツライ。同じ年度であることさえわかればGroupByできる。

4月1日〜翌3月31日を1年としたいなら、現在の日付から3ヶ月マイナスすればやっていける。

2018年1月〜3月から3ヶ月引くと、2017年10月〜12月になるから、2017年。
2018年4月〜12月は、2018年1月〜9月になるから、2018年。
2019年1月〜3月は、2018年10月〜12月になるから、2018年。
2019年4月以降は・・・2019年!

12月決算以外は、決算月の数値だけNヶ月さかのぼるだけ良い。12月決算は1月1日〜12月31日だから、通常の年度でいいから別段なにもしなくてよい。

検証した

かんぺき。シカクいアタマをマルくしないと、生きていけない。

f:id:gothedistance:20190307172654p:plain

縦持ちの場合はこういうSQLになる

3月決算の場合です。3という固定値をプレースホルダーにすれば、どの決算月でもおk!

SELECT
	date_format(e.billdate, '%Y年%m月'),
	e.subtotal
FROM
	earnings AS e
GROUP BY
	YEAR(e.billdate - INTERVAL (3 % 12) MONTH),
	MONTH(e.billdate)
ORDER BY
	date_format(e.billdate,'%Y%m' )

横持ち(つまり、12ヶ月分のカラムを並べる)の場合は、CASE-WHENで頑張るしか無いな・・・

SELECT
	CASE
		WHEN MONTH(e.billdate) = 4 THEN e.subtotal
		ELSE 0
	END AS '4',
	CASE
		WHEN MONTH(e.billdate) = 5 THEN e.subtotal
		ELSE 0
	END AS '5',
	CASE
		WHEN MONTH(e.billdate) = 5 THEN e.subtotal
		ELSE 0
	END AS '6' -- 以下略
FROM
	earnings AS e
GROUP BY
	YEAR(e.billdate - INTERVAL (3 % 12) MONTH),
	MONTH(e.billdate)
ORDER BY
	date_format(e.billdate,'%Y%m' )

横持ちについては、縦で取得してPythonならPandasとか使ってそっちで集計して、画面に出すってのもありかも〜

PWAを覚えるぞ

販売管理システムのデスクトップアプリは、ほぼ出来上がってきた。日常業務をこなすには問題なく、あとは管理業務としての分析・帳票出力・権限管理などが控えているが、4月から試験導入予定。

次の課題がスマホアプリ。主要の販売管理システムはクラサバなので、そもそも外に出れなかったりする。クラウド対応みたいな所もあるだろうけど、ブラウザでレスポンシブになるんでみたいな所しかないと思う。作るのは、顧客との販売チャネルとしてのスマホアプリ。カタログ配信、プッシュ通知、ネット注文(予約も可能)、請求、注残の管理・・・みたいなのがいい感じ出来るもの。ECのようなもんね、簡単に言えば。お客さんが注文してくれて販売管理システムに連動して請求までできれば、最強。

僕が知る限り、雑貨の小売店の現場にはPCを置いてあることが少ない。本部バイヤーがいる所はまだしも、PC開いてカタログ開いてぺちぺちとキーボードを叩いて注文する時間も手間もかけられない。スマホならできるし、商品のバーコード読んだら商品詳細ページに飛ばすとか、やりたいよね。

このアプリをネイティブで作ったら死ぬ(iOS/Androidを各々作ったらすげー頑張っても半年かかる)ので、PWAで作る。デバイスが必要なのカメラだけだし。SNS連携とか一切いらないし。1ヶ月あれば、だいたいの実装はできそうな気がする。見えていないのはキャッシュのさせ方。動的なクエリのついたURLとか、商品データJSONとか、そういうのをオフラインでキャッシュさせたい。適切なタイミングで更新も必要だし。そのあたりが見えてくれば、あとは単なるWebアプリだし。イケそう。

やっていき。