diff --git a/inventory.json b/inventory.json index fa282d5..e73e48b 100644 --- a/inventory.json +++ b/inventory.json @@ -448,5 +448,6 @@ "quantityUnit": "caps", "orderDate": "2024-02-03", "numBottles": 1 - } + }, + {"orderDate":"2014-02-04T23:00:00.000Z","name":"Ashwagandha","quantity":120,"quantityUnits":"caps","servingUnit":"mg","numUnitsInServing":300,"numBottles":1},{"orderDate":"2014-02-04T23:00:00.000Z","name":"Crucera-SGS","quantity":60,"quantityUnits":"caps","servingUnit":"caps","numUnitsInServing":1,"numBottles":1},{"orderDate":"2014-02-04T23:00:00.000Z","name":"High Absorption CoQ10 with BioPerine","quantity":120,"quantityUnits":"caps","servingUnit":"mg","numUnitsInServing":100,"numBottles":1},{"orderDate":"2014-02-04T23:00:00.000Z","name":"Ultimate Omega","quantity":640,"quantityUnits":"mg per Soft Gel","servingUnit":"mg","numUnitsInServing":1280,"numBottles":1},{"orderDate":"2014-02-04T23:00:00.000Z","name":"Genistein from Sophora Japonica","quantity":60,"quantityUnits":"caps","servingUnit":"mg","numUnitsInServing":125,"numBottles":1},{"orderDate":"2014-02-04T23:00:00.000Z","name":"Ginger Root","quantity":100,"quantityUnits":"caps","servingUnit":"mg","numUnitsInServing":550,"numBottles":1},{"orderDate":"2014-02-04T23:00:00.000Z","name":"Glucosamine Sulfate","quantity":240,"quantityUnits":"caps","servingUnit":"mg","numUnitsInServing":750,"numBottles":1},{"orderDate":"2014-02-04T23:00:00.000Z","name":"Glycine","quantity":250,"quantityUnits":"caps","servingUnit":"mg","numUnitsInServing":1000,"numBottles":1},{"orderDate":"2014-02-04T23:00:00.000Z","name":"Liquid Iodine Plus","quantity":59,"quantityUnits":"ml","servingUnit":"ml","numUnitsInServing":0.126,"numBottles":1},{"orderDate":"2014-02-04T23:00:00.000Z","name":"Super K","quantity":90,"quantityUnits":"caps","servingUnit":"mcg","numUnitsInServing":1500,"numBottles":1},{"orderDate":"2014-02-04T23:00:00.000Z","name":"Lithium","quantity":100,"quantityUnits":"caps","servingUnit":"mcg","numUnitsInServing":1000,"numBottles":1},{"orderDate":"2014-02-04T23:00:00.000Z","name":"Hyaluronic Acid","quantity":30,"quantityUnits":"caps","servingUnit":"mg","numUnitsInServing":200,"numBottles":1} ] diff --git a/scrape_iherb_orders.js b/scrape_iherb_orders.js index 6804f01..5fed8c3 100644 --- a/scrape_iherb_orders.js +++ b/scrape_iherb_orders.js @@ -1,4 +1,4 @@ -const getOrderElements = () => Array.from(document.querySelectorAll(".order-details-box")) +let getOrderElements = () => Array.from(document.querySelectorAll(".order-details-box")) function getDateOfOrder(orderEl) { return Date.parse( @@ -11,7 +11,7 @@ function getDateOfOrder(orderEl) { ); } -const getSupps = orderEl => Array.from(orderEl.children[1].children[0].children); +let getSupps = orderEl => Array.from(orderEl.children[1].children[0].children); SERVINGS_LOOKUP = { "Liquid D-3 & MK-7": { @@ -20,7 +20,7 @@ SERVINGS_LOOKUP = { }, "Crucera-SGS": { numUnitsInServing: 1, - servingUnit: "cap", + servingUnit: "caps", }, "Creatine": { numUnitsInServing: 5, @@ -32,7 +32,7 @@ SERVINGS_LOOKUP = { }, "Magnesium Taurate": { numUnitsInServing: 1, - servingUnit: "cap", + servingUnit: "caps", }, "High Absorption Magnesium Glycinate 350": { numUnitsInServing: 350, @@ -40,15 +40,15 @@ SERVINGS_LOOKUP = { }, "Iron Bisglycinate": { numUnitsInServing: 1, - servingUnit: "cap", + servingUnit: "caps", }, "Extend-Release Magnesium": { numUnitsInServing: 1, - servingUnit: "cap", + servingUnit: "caps", }, "Lutein & Zeaxanthin": { numUnitsInServing: 1, - servingUnit: "cap", + servingUnit: "caps", }, "Aged Garlic Extract": { numUnitsInServing: 600, @@ -62,9 +62,17 @@ SERVINGS_LOOKUP = { numUnitsInServing: .25, servingUnit: "ml", }, + "Glycine": { + numUnitsInServing: 1000, + servingUnit: "mg", + }, + "Super K": { + numUnitsInServing: 1500, + servingUnit: "mcg", + }, }; -const getNumBottles = orderEl => parseInt(orderEl +let getNumBottles = orderEl => parseInt(orderEl .children[1] .children[0] .children[0] @@ -73,7 +81,7 @@ const getNumBottles = orderEl => parseInt(orderEl .innerText .split("Qty: ").slice(-1)[0]); -const SKIP_THESE = [ +let SKIP_THESE = [ "Organic Brown Mustard", "Sunflower Lecithin", "Premium Whole Flaxseed", @@ -150,11 +158,16 @@ function makeSuppObj(sup) { } -function main(orderCutoffHuman) { - const orderCutoff = Date.parse(orderCutoffHuman); - const orderEls = getOrderElements() - .filter(el => !el.innerText.includes("Cancelled")) - .filter(el => getDateOfOrder(el) > orderCutoff) +function main(orderCutoffHuman, getFirst) { + let orderEls; + if (!getFirst) { + const orderCutoff = Date.parse(orderCutoffHuman); + orderEls = getOrderElements() + .filter(el => !el.innerText.includes("Cancelled")) + .filter(el => getDateOfOrder(el) > orderCutoff) + } else { + orderEls = [getOrderElements()[0]]; + } let suppEls = []; for (const orderEl of orderEls) { suppEls = suppEls.concat(getSupps(orderEl)); @@ -163,4 +176,4 @@ function main(orderCutoffHuman) { return suppEls.map(suppEl => makeSuppObj(suppEl)).filter(res => res != null); } -console.log(JSON.stringify(main("January 04, 2024"))); +console.log(JSON.stringify(main(null, true))); diff --git a/src/sup/cli.py b/src/sup/cli.py index d1da8a6..743d67c 100644 --- a/src/sup/cli.py +++ b/src/sup/cli.py @@ -82,7 +82,12 @@ def get_num_winter_days_starting(num_days: int, starting: dt.date) -> int: @app.command() def status(): - """check if there's enough inventory for the next fill-up; if not, what to order?""" + """ + check if there's enough inventory for the next fill-up; if not, what to order? + + TODO: this doesn't seem to sense pending orders which have been added to inventory.json + maybe because the delivery date is in the present/future? + """ validate_matches() config = load_config() @@ -107,29 +112,32 @@ def status(): qty_needed = sup_inst * num_days_of_inventory_needed try: - inv = inventory[sup_inst.name] + inv = inventory[sup_inst.name.lower()] except KeyError: + print(f"no hit for key '{sup_inst.name}'") qty_of_inventory = 0 - else: - qty_of_inventory = get_qty_inventory(sup_inst, inv, next_fill_date) + needs.append((sup_inst.name, 0, float('inf'))) + continue + + qty_of_inventory = get_qty_inventory(sup_inst, inv, next_fill_date) + print(sup_inst.name, int(qty_of_inventory / inv["numUnitsInServing"])) net_need = int(qty_needed - qty_of_inventory) if net_need > 0: - if qty_of_inventory == 0: - num_bottles_needed = 1 - else: - if sup_inst.name == "magnesium slow release": - print(f"{net_need=}") - print(f"{inv['numUnitsInServing']=}") - print(f"{inv['quantity']=}") - num_units_needed = net_need / inv["numUnitsInServing"] # type: ignore - num_bottles_needed = int(math.ceil(num_units_needed / inv["quantity"])) # type: ignore + num_units_needed = net_need / inv["numUnitsInServing"] # type: ignore + num_bottles_needed = int(math.ceil(num_units_needed / inv["quantity"])) # type: ignore needs.append((sup_inst.name, int(num_units_needed), num_bottles_needed)) + if needs: + print() print(f"The next fill-up is on {next_fill_date}, and you won't have enough of:") + print() for name, units_needed, num_bottles in needs: bottle = "bottle" if num_bottles == 1 else "bottles" - print(f"{name} (need {units_needed} units, which is {num_bottles} {bottle})") + print( + f"{name} (need {units_needed} units, which is {num_bottles} {bottle})" + ) + print() @app.command() diff --git a/src/sup/main.py b/src/sup/main.py index ba95d79..8a66ae3 100644 --- a/src/sup/main.py +++ b/src/sup/main.py @@ -62,6 +62,5 @@ class Supp: def quantity_per_day(self) -> float: return ( sum([self.morning, self.lunch, self.dinner, self.bedtime]) - * 7 - / self.days_per_week + * self.days_per_week / 7 ) diff --git a/supps.toml b/supps.toml index 03ecbf7..b639912 100644 --- a/supps.toml +++ b/supps.toml @@ -65,7 +65,7 @@ units = "iu" winter_only = true [[supps]] -name = "DHEA" +name = "dhea" morning = 25 [[supps]] @@ -75,9 +75,8 @@ days_per_week = 3 [[supps]] name = "EPA/DHA" -morning = 2 -dinner = 1 -units = "caps" +morning = 1280 +dinner = 640 [[supps]] name = "garlic" @@ -108,8 +107,8 @@ morning = 300 [[supps]] name = "iodine" -morning = 125 -units = "mcg" +morning = 0.126 +units = "ml" [[supps]] name = "iron" @@ -122,7 +121,7 @@ units="mcg" [[supps]] name = "k2-mk7" -morning = 600 +morning = 300 # it's actually 600 but I get half of it from the d-3 + mk7 drops + the Super K units = "mcg" [[supps]] @@ -140,7 +139,8 @@ dinner = 500 [[supps]] name = "lithium orotate" -morning = 1 +morning = 1000 +units = "mcg" [[supps]] name = "lycopene" @@ -169,7 +169,7 @@ morning = 1700 units = "mcg" [[supps]] -name = "NAC" +name = "nac" morning = 1800 dinner = 1800 @@ -214,4 +214,5 @@ B-50 = "b complex" "Vitamin K2, MK-4 (Menatetrenone)" = "k2-mk4" "Super K" = "k1" "Ultimate Omega, Lemon" = "epa/dha" - +"Ultimate Omega" = "epa/dha" +"Lithium" = "lithium orotate"