内製を支援するビジネスに再挑戦
会社を作った当初はそれを目指していたけど、しっくり来るツールがないのと色んな出会いがあってその方向性はトーンダウンしたが、内製を支援する方向に舵を切ろうと思う。PoCが増えてきたのもある。内製出来る規模のシステムを育てていくのが楽しかったし。
コーポレート・エンジニアリングは、内製が基本だと思う。もちろんSaaS・PaaSはあるだろうけど、結局それらをつなげていかねばならないし、そこに特化出来るように業務を変えていくことになりそう。色んなPaaS・開発ツールを触っては試してみたけれど、自分の中でどうやって組み合わせて行きていけばいいか、ピンときていない。
自分の中で再評価しているのがFileMaker。これ、もしかしてすげーやつなんじゃっていう気持ちがどんどん出てきた。明日から、自分で作った販売管理の仕組みをコイツで作ってみて、やれるところまでやってみようと思います。
Accelerate Corporate Engineering.
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 !!
SQLAlchemy 101って本が日本語であれば、1万円でも買います。
追記 2019.12.28
そんなことしなくても、relationship関数のlazyキーワードに、joinedって入れたらそれだけで良いっぽい
# これでJOIN時にFetchしてくれるからN+1にならへん user = relationship("User", lazy="joined")
レッツゴーFlutter
展示会運営のアプリをAndroid・iOSで各々ネイティブで作って運営しているが、やっぱりワンソースでいい感じにやりたい...2つ同じもの作るのは単純に辛い。メンテナンス・コストが単純に倍になるのがだるい。1から勉強したってのもあるけど、フルコミットでリリースできるまで半年近くかかった。
利用しているライブラリの最新化、OSバージョンアップに伴って廃止/非推奨になったコードのメンテ、ルックアンドフィールの変更に伴うメンテ(今回のダークモードみたいなやつ)、テストコードのメンテ、ビルドシステム(Carthage / Gradle)のメンテ... Webアプリのほうが楽かも。UIのロジックとビジネスロジックの切り分けも気をつけないとすぐ肥大化するし。
Flutterが Android/ iOS のクロスプラットフォーム開発の本命だと思われるので、こいつを勉強してなんとかワンソースで頑張りたいンゴ... Google Waveのようなことにはならんやろ。頼むで。
雑貨製造業向けの販売管理システムをリリースしました
Windowsフォーム→WPFに刷新して、空いた時間でコツコツ作っていた販売管理システムを、8月にリリースしました。他社利用も始まっており、後には戻れない〜。
技術的な話
フロントはWPF、バックエンドはPythonで、HTTPSでJSONのやり取りを行っています。
MVVMフレームワークに、Prism7.2を採用しています。PythonはFlask/SQLAlchemyで、Nginx+Gunicornのリバースプロキシ入り環境をDockerでコンテナ化してます。
WPFを選んだ理由は以下の通りです。Electronだと無理な要件が多かったため。
- グリッドのセル入力やセルのフォーカス制御など、グリッドの操作性の高さが必要だった
- 画面を切り替えても入力中データがローカルに残るため、利便性が高かった
- 帳票のダイレクト印刷が必要だった
- キーイベントの実装が簡単
機能的な話
物売りの商売で一番面倒で重要になるのは「残管理」です。
- 取置の残管理
- 出荷残管理(先納期、分納、納入待ち)
- 注文残(入荷分から出荷する)の管理
- 入荷の残管理(発注分の入荷予定の管理)
- 在庫の管理
この辺がいい感じに連動していている販売管理システムは、あまりないと思います。
販売管理システムの切り替えをご検討の方でこの記事をご覧の方が万が一おられましたら、下記の会社フォームまでお問い合わせを頂ければ。僕が代表なので。デモ版のご案内をさせて頂きます。
CASE-WHENでWhere句を動的に組み立てる
Flask with Vue.js
やっと話が見てきた。
Javascript弱者だったため、Vue.js や Vue-cli 並びにJavascriptの開発環境とか、色んなことがつながるまで少し時間がかかった。
Vue.js のコンポーネント化にはCLIが必要
拡張子がvueのファイルにHTML/CSS/Javascriptをまとめてコンポーネント化し、そいつをimport して使うみたいなやり方をするには、ビルドが必要になる。ここでいうビルドはブラウザが理解できる形で変換をかけること。ScssファイルがCSSファイルに変換されるようなアレだ。
Javascriptの言語仕様がPythonやJava等に比べて色々足りていないのを、パッケージマネージャやビルドツールを使って頑張っているのだなぁ。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日だから、通常の年度でいいから別段なにもしなくてよい。
検証した
かんぺき。シカクいアタマをマルくしないと、生きていけない。
縦持ちの場合はこういう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とか使ってそっちで集計して、画面に出すってのもありかも〜