[DigiKey]複数のBOMファイルをまとめて、うまくbulk discountを活かしつつ一括で発注をかける

   2020/04/06

DigiKeyでは、BOMファイルから必要な部品をリストアップして自動的にカートに入れてくれる機能がある。
基板によっては100種類くらいの部品を使うこともあるから、この機能はマジで便利。
一つ一つ部品を検索してカートに入れていくとか正気の沙汰じゃねぇからな。

で、こいつはさらにbulk discountの提案も同時に行ってくれる。
これがまた便利で、何も考えなくても注文が安くなるように(しかももっと部品が手に入るように)仕向けてくれる。

例えば、とある集合抵抗を20個注文しようとしたとする。しかしこの部品には25個のbulk discountがあったようで、25個注文することを勧めてくる。こちらの方が安く、しかも5個多く部品が手に入る。

ただ、この機能をフルに活用するには、注文する部品が一つのBOMファイルにまとまっている必要がある。
例えば、CRCW0603100KJNEACというチップ抵抗をそれぞれ45個、30個要求するBOMファイルA,Bがあったとし、同時に発注をかけたい場合を考える。

CRCW0603100KJNEACの料金体系

二つのBOMファイルの部品を同時に注文するためには、それぞれのファイルごとにカートに入れる作業をしないといけない。
この時、まずファイルAを処理しようとすると、この抵抗を100個で注文することを勧められる(45個だと144円だが、100個だと132円に下がるため)。
ここでは、まだBで追加するからと提案を無視しておく。
次にファイルBを処理する。特に提案は表示されず、そのまま30個カートに入る。
結果、CRCW0603100KJNEACは75個の注文になっており、これは100個注文するより高くなってしまっている(カートからはbulk discountの画面を表示できない)。

じゃあAを処理するときに提案を受け入れ、抵抗100個をカートに入れたとすると、最終的にカートには130個の注文が入ってしまう。そんなにいらない。
この状態からカート内で部品数を調整するのは困難を極める作業である(必要な部品がそもそも多いのか、それとも余分に入ってしまっているのか、すべて手で計算しなおさなければならない)。

そもそも部品の種類やBOMファイルの数が多いと、「この部品はさっき提案を受けなかったから今回は受け入れて、こっちの部品はこのBOMファイルにしかないから提案を受け入れて...」とかやってられない。

BOMファイルをマージする機能が用意されていたら良かったが、そんなものはない。
ということで、うまいことBOMファイルをマージして、bulk discountを最大限活かせるような注文用BOMファイルをPythonで生成することにした。

import csv
import sys

args = sys.argv
unique_label = ""
quantity_label = ""
order_bom = {}

'''
Usage: python merge_bom.py [unique_label] [quantity_label] file.csv ...

unique_label: CSV label name for ID of a part
quantity_label: CSV label name for quantity
path to csv: Path to CSV files. You can set multiple CSVs.

e.g., python merge_bom.py DistributorPartNumber Quantity file1.bom.scv file2.bom.csv file3.bom.csv
'''
if __name__ == '__main__':
  unique_label = args[1]
  quantity_label = args[2]

  # Collect data of items
  for csv_path in args[3:]:
    with open(csv_path, encoding='utf-8-sig') as f:
      print("Scanning " + csv_path + "...")
      reader = csv.DictReader(f)
      for row in reader:
        try:
          # print(row)
          # print(row[unique_label])
          if row[unique_label] in order_bom:
            order_bom[row[unique_label]][quantity_label] += int(row[quantity_label])
          else:
            order_bom[row[unique_label]] = row
            order_bom[row[unique_label]][quantity_label] = int(row[quantity_label]) # str to int
        except ValueError:
          print("Invalid fieldnames: " + row)

  tmp_part_id = list(order_bom.keys())[0]
  header = order_bom[tmp_part_id].keys()
  # print("header: " + ','.join(list(header)))

  # generate bom for ordering
  print("Generating order.bom.csv...")
  with open("./order.bom.csv", "w") as f:
    writer = csv.DictWriter(f, header)
    writer.writeheader()
    for row in order_bom.values():
      writer.writerow(row)

  print("Done!")

Python3.x系で動く。

例えば、以下のようなBOMファイルがあったとする。

DistributorPartNumber,Quantity
CRCW0603100KJNEAC, 45
RESISTOR, 50
DistributorPartNumber,Quantity
CRCW0603100KJNEAC, 30
CAPACITOR, 50

で、以下のコマンドを叩くと、下のようなcsvファイルが生成される。

$ python3 merge_bom.py DistributorPartNumber Quantity A.bom.csv B.bom.csv
DistributorPartNumber,Quantity
CRCW0603100KJNEAC,75
RESISTOR,50
CAPACITOR,50

CSVを一つにまとめたおかげで、CRCW0603100KJNEACは75個の注文になり、BOM Managerは「100個買え」という最適な提案をしてくれるはずである。

タイトルとURLをコピーしました

この記事へのコメントはこちら

メールアドレスは公開されませんのでご安心ください。
また、* が付いている欄は必須項目となりますので、必ずご記入をお願いします。

内容に問題なければ、下記の「コメント送信」ボタンを押してください。

3 × 4 =

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください