Changed initial_weight to be net weight, not gross weight
This commit is contained in:
@@ -145,7 +145,7 @@
|
|||||||
"used_length": "Used Length",
|
"used_length": "Used Length",
|
||||||
"remaining_length": "Remaining Length",
|
"remaining_length": "Remaining Length",
|
||||||
"initial_weight": "Initial Weight",
|
"initial_weight": "Initial Weight",
|
||||||
"empty_weight": "Empty Weight",
|
"spool_weight": "Empty Weight",
|
||||||
"location": "Location",
|
"location": "Location",
|
||||||
"lot_nr": "Lot Nr",
|
"lot_nr": "Lot Nr",
|
||||||
"first_used": "First Used",
|
"first_used": "First Used",
|
||||||
@@ -160,8 +160,8 @@
|
|||||||
"used_weight": "How much filament has been used from the spool. A new spool should have 0g used.",
|
"used_weight": "How much filament has been used from the spool. A new spool should have 0g used.",
|
||||||
"remaining_weight": "How much filament is left on the spool. For a new spool this should match the spool weight.",
|
"remaining_weight": "How much filament is left on the spool. For a new spool this should match the spool weight.",
|
||||||
"measured_weight": "How much the filament and spool weigh.",
|
"measured_weight": "How much the filament and spool weigh.",
|
||||||
"initial_weight": "The initial Total Weight of the filament and spool.",
|
"initial_weight": "The initial Weight of the filament (net weight)",
|
||||||
"empty_weight": "The weight of the spool when it is empty.",
|
"spool_weight": "The weight of the spool when it is empty.",
|
||||||
"location": "Where the spool is located if you have multiple locations where you store your spools.",
|
"location": "Where the spool is located if you have multiple locations where you store your spools.",
|
||||||
"lot_nr": "Manufacturer's lot number. Can be used to ensure a print has consistent color if multiple spools are used."
|
"lot_nr": "Manufacturer's lot number. Can be used to ensure a print has consistent color if multiple spools are used."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { Form, Input, DatePicker, Select, InputNumber, Radio, Divider, Button, T
|
|||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import TextArea from "antd/es/input/TextArea";
|
import TextArea from "antd/es/input/TextArea";
|
||||||
import { IFilament } from "../filaments/model";
|
import { IFilament } from "../filaments/model";
|
||||||
import { ISpool, ISpoolParsedExtras } from "./model";
|
import { ISpool, ISpoolParsedExtras, WeightToEnter } from "./model";
|
||||||
import { numberFormatter, numberParser } from "../../utils/parsing";
|
import { numberFormatter, numberParser } from "../../utils/parsing";
|
||||||
import { useSpoolmanLocations } from "../../components/otherModels";
|
import { useSpoolmanLocations } from "../../components/otherModels";
|
||||||
import { MinusOutlined, PlusOutlined } from "@ant-design/icons";
|
import { MinusOutlined, PlusOutlined } from "@ant-design/icons";
|
||||||
@@ -14,6 +14,7 @@ import { EntityType, useGetFields } from "../../utils/queryFields";
|
|||||||
import { ExtraFieldFormItem, StringifiedExtras } from "../../components/extraFields";
|
import { ExtraFieldFormItem, StringifiedExtras } from "../../components/extraFields";
|
||||||
import utc from "dayjs/plugin/utc";
|
import utc from "dayjs/plugin/utc";
|
||||||
import { getCurrencySymbol, useCurrency } from "../../utils/settings";
|
import { getCurrencySymbol, useCurrency } from "../../utils/settings";
|
||||||
|
import { ValueType } from "rc-input-number";
|
||||||
|
|
||||||
dayjs.extend(utc);
|
dayjs.extend(utc);
|
||||||
|
|
||||||
@@ -39,6 +40,9 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
|
|||||||
formProps.initialValues = {};
|
formProps.initialValues = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const initialWeightValue = Form.useWatch("initial_weight", form);
|
||||||
|
const spoolWeightValue = Form.useWatch("spool_weight", form);
|
||||||
|
|
||||||
if (props.mode === "clone") {
|
if (props.mode === "clone") {
|
||||||
// Clear out the values that we don't want to clone
|
// Clear out the values that we don't want to clone
|
||||||
formProps.initialValues.first_used = null;
|
formProps.initialValues.first_used = null;
|
||||||
@@ -121,19 +125,19 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
|
|||||||
return obj.value === newID;
|
return obj.value === newID;
|
||||||
});
|
});
|
||||||
|
|
||||||
const initial_weight = form.getFieldValue("initial_weight") as number ?? 0;
|
const initial_weight = initialWeightValue ?? 0;
|
||||||
const empty_weight = form.getFieldValue("empty_weight") as number ?? 0;
|
const spool_weight = spoolWeightValue ?? 0;
|
||||||
|
|
||||||
const newFilamentWeight = newSelectedFilament?.weight || 0;
|
const newFilamentWeight = newSelectedFilament?.weight || 0;
|
||||||
const newSpoolWeight = newSelectedFilament?.spool_weight || 0;
|
const newSpoolWeight = newSelectedFilament?.spool_weight || 0;
|
||||||
|
|
||||||
const currentCalculatedFilamentWeight = getTotalWeightFromFilament();
|
const currentCalculatedFilamentWeight = getTotalWeightFromFilament();
|
||||||
if ((initial_weight === 0 || initial_weight === currentCalculatedFilamentWeight) && newFilamentWeight > 0) {
|
if ((initial_weight === 0 || initial_weight === currentCalculatedFilamentWeight) && newFilamentWeight > 0) {
|
||||||
form.setFieldValue("initial_weight", newFilamentWeight + newSpoolWeight);
|
form.setFieldValue("initial_weight", newFilamentWeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((empty_weight === 0 || empty_weight === (selectedFilament?.spool_weight ?? 0)) && newSpoolWeight > 0) {
|
if ((spool_weight === 0 || spool_weight === (selectedFilament?.spool_weight ?? 0)) && newSpoolWeight > 0) {
|
||||||
form.setFieldValue("empty_weight", newSpoolWeight);
|
form.setFieldValue("spool_weight", newSpoolWeight);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -161,57 +165,34 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
|
|||||||
setQuantity(quantity - 1);
|
setQuantity(quantity - 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSpoolTotalWeight = (): number => {
|
const getSpoolWeight = (): number => {
|
||||||
const initial_weight = form.getFieldValue("initial_weight") as number;
|
return spoolWeightValue ?? (selectedFilament?.spool_weight ?? 0);
|
||||||
const empty_weight = form.getFieldValue("empty_weight") as number;
|
}
|
||||||
const spool_weight = empty_weight ?? selectedFilament?.spool_weight;
|
|
||||||
return initial_weight ?? (selectedFilament?.weight ?? 0) + spool_weight;
|
const getFilamentWeight = (): number => {
|
||||||
|
return initialWeightValue ?? (selectedFilament?.weight ?? 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getGrossWeight = (): number => {
|
||||||
|
const net_weight = getFilamentWeight();
|
||||||
|
const spool_weight = getSpoolWeight();
|
||||||
|
return net_weight + spool_weight;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTotalWeightFromFilament = (): number => {
|
const getTotalWeightFromFilament = (): number => {
|
||||||
return (selectedFilament?.weight ?? 0) + (selectedFilament?.spool_weight ?? 0);
|
return (selectedFilament?.weight ?? 0) + (selectedFilament?.spool_weight ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const getFilamentWeight = (): number => {
|
|
||||||
const initial_weight = form.getFieldValue("initial_weight") as number;
|
|
||||||
const empty_weight = form.getFieldValue("empty_weight") as number;
|
|
||||||
const spool_weight = empty_weight ?? selectedFilament?.spool_weight;
|
|
||||||
if (initial_weight) {
|
|
||||||
return initial_weight - (spool_weight ?? 0);
|
|
||||||
}
|
|
||||||
return selectedFilament?.weight ?? 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getMeasuredWeight = (): number => {
|
const getMeasuredWeight = (): number => {
|
||||||
const initial_weight = form.getFieldValue("initial_weight") as number;
|
const grossWeight = getGrossWeight();
|
||||||
|
|
||||||
if (initial_weight) {
|
return grossWeight - usedWeight;
|
||||||
return initial_weight - usedWeight;
|
|
||||||
}
|
|
||||||
const empty_weight = form.getFieldValue("empty_weight") as number;
|
|
||||||
const spool_weight = empty_weight ?? selectedFilament?.spool_weight;
|
|
||||||
|
|
||||||
if (selectedFilament?.weight && spool_weight) {
|
|
||||||
return selectedFilament?.weight - usedWeight + spool_weight;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getRemainingWeight = (): number => {
|
const getRemainingWeight = (): number => {
|
||||||
const initial_weight = form.getFieldValue("initial_weight") as number ?? 0;
|
const initial_weight = getFilamentWeight();
|
||||||
const empty_weight = form.getFieldValue("empty_weight") as number;
|
|
||||||
const spool_weight = empty_weight ?? selectedFilament?.spool_weight;
|
|
||||||
|
|
||||||
let remaining_weight = 0;
|
return initial_weight - usedWeight;
|
||||||
|
|
||||||
if (initial_weight === 0) {
|
|
||||||
remaining_weight = (selectedFilament?.weight ?? 0) - usedWeight;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
remaining_weight = initial_weight - spool_weight - usedWeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (remaining_weight >= 0) ? remaining_weight : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const isMeasuredWeightEnabled = (): boolean => {
|
const isMeasuredWeightEnabled = (): boolean => {
|
||||||
@@ -220,13 +201,13 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const empty_weight = form.getFieldValue("empty_weight") as number;
|
const spool_weight = spoolWeightValue;
|
||||||
|
|
||||||
return (empty_weight || selectedFilament?.spool_weight) ? true : false;
|
return (spool_weight || selectedFilament?.spool_weight) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isRemainingWeightEnabled = (): boolean => {
|
const isRemainingWeightEnabled = (): boolean => {
|
||||||
const initial_weight = form.getFieldValue("initial_weight") as number;
|
const initial_weight = initialWeightValue;
|
||||||
|
|
||||||
if (initial_weight) {
|
if (initial_weight) {
|
||||||
return true;
|
return true;
|
||||||
@@ -236,21 +217,21 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
|
|||||||
}
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (weightToEnter >= 3)
|
if (weightToEnter >= WeightToEnter.measured_weight)
|
||||||
{
|
{
|
||||||
if (!isMeasuredWeightEnabled()) {
|
if (!isMeasuredWeightEnabled()) {
|
||||||
setWeightToEnter(2);
|
setWeightToEnter(WeightToEnter.remaining_weight);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (weightToEnter >= 2)
|
if (weightToEnter >= WeightToEnter.remaining_weight)
|
||||||
{
|
{
|
||||||
if (!isRemainingWeightEnabled()) {
|
if (!isRemainingWeightEnabled()) {
|
||||||
setWeightToEnter(1);
|
setWeightToEnter(WeightToEnter.used_weight);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [selectedFilament, weightChange])
|
}, [selectedFilament])
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -359,13 +340,13 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<InputNumber addonAfter="g" precision={1}/>
|
<InputNumber addonAfter="g" precision={1} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("spool.fields.empty_weight")}
|
label={t("spool.fields.spool_weight")}
|
||||||
help={t("spool.fields_help.empty_weight")}
|
help={t("spool.fields_help.spool_weight")}
|
||||||
name={["empty_weight"]}
|
name={["spool_weight"]}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: false,
|
required: false,
|
||||||
@@ -386,14 +367,14 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
|
|||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
setWeightToEnter(value.target.value);
|
setWeightToEnter(value.target.value);
|
||||||
}}
|
}}
|
||||||
defaultValue={1}
|
defaultValue={WeightToEnter.used_weight}
|
||||||
value={weightToEnter}
|
value={weightToEnter}
|
||||||
>
|
>
|
||||||
<Radio.Button value={1}>{t("spool.fields.used_weight")}</Radio.Button>
|
<Radio.Button value={WeightToEnter.used_weight}>{t("spool.fields.used_weight")}</Radio.Button>
|
||||||
<Radio.Button value={2} disabled={!isRemainingWeightEnabled()}>
|
<Radio.Button value={WeightToEnter.remaining_weight} disabled={!isRemainingWeightEnabled()}>
|
||||||
{t("spool.fields.remaining_weight")}
|
{t("spool.fields.remaining_weight")}
|
||||||
</Radio.Button>
|
</Radio.Button>
|
||||||
<Radio.Button value={3} disabled={!isMeasuredWeightEnabled()}>
|
<Radio.Button value={WeightToEnter.measured_weight} disabled={!isMeasuredWeightEnabled()}>
|
||||||
{t("spool.fields.measured_weight")}
|
{t("spool.fields.measured_weight")}
|
||||||
</Radio.Button>
|
</Radio.Button>
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
@@ -406,7 +387,7 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
|
|||||||
precision={1}
|
precision={1}
|
||||||
formatter={numberFormatter}
|
formatter={numberFormatter}
|
||||||
parser={numberParser}
|
parser={numberParser}
|
||||||
disabled={weightToEnter != 1}
|
disabled={weightToEnter != WeightToEnter.used_weight}
|
||||||
value={usedWeight}
|
value={usedWeight}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
weightChange(value ?? 0);
|
weightChange(value ?? 0);
|
||||||
@@ -424,7 +405,7 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
|
|||||||
precision={1}
|
precision={1}
|
||||||
formatter={numberFormatter}
|
formatter={numberFormatter}
|
||||||
parser={numberParser}
|
parser={numberParser}
|
||||||
disabled={weightToEnter != 2}
|
disabled={weightToEnter != WeightToEnter.remaining_weight}
|
||||||
value={getRemainingWeight()}
|
value={getRemainingWeight()}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
weightChange(getFilamentWeight() - (value ?? 0));
|
weightChange(getFilamentWeight() - (value ?? 0));
|
||||||
@@ -442,10 +423,10 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
|
|||||||
precision={1}
|
precision={1}
|
||||||
formatter={numberFormatter}
|
formatter={numberFormatter}
|
||||||
parser={numberParser}
|
parser={numberParser}
|
||||||
disabled={weightToEnter != 3}
|
disabled={weightToEnter != WeightToEnter.measured_weight}
|
||||||
value={getMeasuredWeight()}
|
value={getMeasuredWeight()}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
const totalWeight = getSpoolTotalWeight();
|
const totalWeight = getGrossWeight();
|
||||||
weightChange(totalWeight - (value ?? 0));
|
weightChange(totalWeight - (value ?? 0));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ export const SpoolEdit: React.FC<IResourceComponentsProps> = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const initialWeightValue = Form.useWatch("initial_weight", form);
|
||||||
|
const spoolWeightValue = Form.useWatch("spool_weight", form);
|
||||||
// Get filament selection options
|
// Get filament selection options
|
||||||
const { queryResult } = useSelect<IFilament>({
|
const { queryResult } = useSelect<IFilament>({
|
||||||
resource: "filament",
|
resource: "filament",
|
||||||
@@ -101,19 +103,19 @@ export const SpoolEdit: React.FC<IResourceComponentsProps> = () => {
|
|||||||
return obj.value === newID;
|
return obj.value === newID;
|
||||||
});
|
});
|
||||||
|
|
||||||
const initial_weight = form.getFieldValue("initial_weight") as number ?? 0;
|
const initial_weight = initialWeightValue ?? 0;
|
||||||
const empty_weight = form.getFieldValue("empty_weight") as number ?? 0;
|
const spool_weight = spoolWeightValue ?? 0;
|
||||||
|
|
||||||
const newFilamentWeight = newSelectedFilament?.weight || 0;
|
const newFilamentWeight = newSelectedFilament?.weight || 0;
|
||||||
const newSpoolWeight = newSelectedFilament?.spool_weight || 0;
|
const newSpoolWeight = newSelectedFilament?.spool_weight || 0;
|
||||||
|
|
||||||
const currentCalculatedFilamentWeight = getTotalWeightFromFilament();
|
const currentCalculatedFilamentWeight = getTotalWeightFromFilament();
|
||||||
if ((initial_weight === 0 || initial_weight === currentCalculatedFilamentWeight) && newFilamentWeight > 0) {
|
if ((initial_weight === 0 || initial_weight === currentCalculatedFilamentWeight) && newFilamentWeight > 0) {
|
||||||
form.setFieldValue("initial_weight", newFilamentWeight + newSpoolWeight);
|
form.setFieldValue("initial_weight", newFilamentWeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((empty_weight === 0 || empty_weight === (selectedFilament?.spool_weight ?? 0)) && newSpoolWeight > 0) {
|
if ((spool_weight === 0 || spool_weight === (selectedFilament?.spool_weight ?? 0)) && newSpoolWeight > 0) {
|
||||||
form.setFieldValue("empty_weight", newSpoolWeight);
|
form.setFieldValue("spool_weight", newSpoolWeight);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -132,57 +134,34 @@ export const SpoolEdit: React.FC<IResourceComponentsProps> = () => {
|
|||||||
allLocations.push(newLocation.trim());
|
allLocations.push(newLocation.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
const getSpoolTotalWeight = (): number => {
|
const getSpoolWeight = (): number => {
|
||||||
const initial_weight = form.getFieldValue("initial_weight") as number;
|
return spoolWeightValue ?? (selectedFilament?.spool_weight ?? 0);
|
||||||
const empty_weight = form.getFieldValue("empty_weight") as number;
|
}
|
||||||
const spool_weight = empty_weight ?? selectedFilament?.spool_weight;
|
|
||||||
return initial_weight ?? (selectedFilament?.weight ?? 0) + spool_weight;
|
const getFilamentWeight = (): number => {
|
||||||
|
return initialWeightValue ?? (selectedFilament?.weight ?? 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getGrossWeight = (): number => {
|
||||||
|
const net_weight = getFilamentWeight();
|
||||||
|
const spool_weight = getSpoolWeight();
|
||||||
|
return net_weight + spool_weight;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTotalWeightFromFilament = (): number => {
|
const getTotalWeightFromFilament = (): number => {
|
||||||
return (selectedFilament?.weight ?? 0) + (selectedFilament?.spool_weight ?? 0);
|
return (selectedFilament?.weight ?? 0) + (selectedFilament?.spool_weight ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const getFilamentWeight = (): number => {
|
|
||||||
const initial_weight = form.getFieldValue("initial_weight") as number;
|
|
||||||
const empty_weight = form.getFieldValue("empty_weight") as number;
|
|
||||||
const spool_weight = empty_weight ?? selectedFilament?.spool_weight;
|
|
||||||
if (initial_weight) {
|
|
||||||
return initial_weight - (spool_weight ?? 0);
|
|
||||||
}
|
|
||||||
return selectedFilament?.weight ?? 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getMeasuredWeight = (): number => {
|
const getMeasuredWeight = (): number => {
|
||||||
const initial_weight = form.getFieldValue("initial_weight") as number;
|
const grossWeight = getGrossWeight();
|
||||||
|
|
||||||
if (initial_weight) {
|
return grossWeight - usedWeight;
|
||||||
return initial_weight - usedWeight;
|
|
||||||
}
|
|
||||||
const empty_weight = form.getFieldValue("empty_weight") as number;
|
|
||||||
const spool_weight = empty_weight ?? selectedFilament?.spool_weight;
|
|
||||||
|
|
||||||
if (selectedFilament?.weight && spool_weight) {
|
|
||||||
return selectedFilament?.weight - usedWeight + spool_weight;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getRemainingWeight = (): number => {
|
const getRemainingWeight = (): number => {
|
||||||
const initial_weight = form.getFieldValue("initial_weight") as number ?? 0;
|
const initial_weight = getFilamentWeight();
|
||||||
const empty_weight = form.getFieldValue("empty_weight") as number;
|
|
||||||
const spool_weight = empty_weight ?? selectedFilament?.spool_weight;
|
|
||||||
|
|
||||||
let remaining_weight = 0;
|
return initial_weight - usedWeight;
|
||||||
|
|
||||||
if (initial_weight === 0) {
|
|
||||||
remaining_weight = (selectedFilament?.weight ?? 0) - usedWeight;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
remaining_weight = initial_weight - spool_weight - usedWeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (remaining_weight >= 0) ? remaining_weight : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const isMeasuredWeightEnabled = (): boolean => {
|
const isMeasuredWeightEnabled = (): boolean => {
|
||||||
@@ -191,13 +170,13 @@ export const SpoolEdit: React.FC<IResourceComponentsProps> = () => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const empty_weight = form.getFieldValue("empty_weight") as number;
|
const spool_weight = spoolWeightValue;
|
||||||
|
|
||||||
return (empty_weight || selectedFilament?.spool_weight) ? true : false;
|
return (spool_weight || selectedFilament?.spool_weight) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isRemainingWeightEnabled = (): boolean => {
|
const isRemainingWeightEnabled = (): boolean => {
|
||||||
const initial_weight = form.getFieldValue("initial_weight") as number;
|
const initial_weight = initialWeightValue;
|
||||||
|
|
||||||
if (initial_weight) {
|
if (initial_weight) {
|
||||||
return true;
|
return true;
|
||||||
@@ -221,7 +200,7 @@ export const SpoolEdit: React.FC<IResourceComponentsProps> = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [selectedFilament, weightChange])
|
}, [selectedFilament])
|
||||||
|
|
||||||
const initialUsedWeight = formProps.initialValues?.used_weight || 0;
|
const initialUsedWeight = formProps.initialValues?.used_weight || 0;
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -342,9 +321,9 @@ export const SpoolEdit: React.FC<IResourceComponentsProps> = () => {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("spool.fields.empty_weight")}
|
label={t("spool.fields.spool_weight")}
|
||||||
help={t("spool.fields_help.empty_weight")}
|
help={t("spool.fields_help.spool_weight")}
|
||||||
name={["empty_weight"]}
|
name={["spool_weight"]}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: false,
|
required: false,
|
||||||
@@ -421,7 +400,7 @@ export const SpoolEdit: React.FC<IResourceComponentsProps> = () => {
|
|||||||
disabled={weightToEnter != WeightToEnter.measured_weight}
|
disabled={weightToEnter != WeightToEnter.measured_weight}
|
||||||
value={getMeasuredWeight()}
|
value={getMeasuredWeight()}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
const totalWeight = getSpoolTotalWeight();
|
const totalWeight = getGrossWeight();
|
||||||
weightChange(totalWeight - (value ?? 0));
|
weightChange(totalWeight - (value ?? 0));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export interface ISpool {
|
|||||||
filament: IFilament;
|
filament: IFilament;
|
||||||
price?: number;
|
price?: number;
|
||||||
initial_weight?: number;
|
initial_weight?: number;
|
||||||
empty_weight?: number;
|
spool_weight?: number;
|
||||||
remaining_weight?: number;
|
remaining_weight?: number;
|
||||||
used_weight: number;
|
used_weight: number;
|
||||||
remaining_length?: number;
|
remaining_length?: number;
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ def upgrade() -> None:
|
|||||||
"initial_weight",
|
"initial_weight",
|
||||||
sa.Float(),
|
sa.Float(),
|
||||||
nullable=True,
|
nullable=True,
|
||||||
comment="The initial total weight of the spool (gross weight).",
|
comment="The initial weight of the filament on the spool (net weight).",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
op.add_column(
|
op.add_column(
|
||||||
"spool",
|
"spool",
|
||||||
sa.Column("empty_weight", sa.Float(), nullable=True, comment="The weight of the empty spool (tare weight)."),
|
sa.Column("spool_weight", sa.Float(), nullable=True, comment="The weight of the empty spool (tare weight)."),
|
||||||
)
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
@@ -36,6 +36,6 @@ def upgrade() -> None:
|
|||||||
def downgrade() -> None:
|
def downgrade() -> None:
|
||||||
"""Perform the downgrade."""
|
"""Perform the downgrade."""
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_column("spool", "empty_weight")
|
op.drop_column("spool", "spool_weight")
|
||||||
op.drop_column("spool", "initial_weight")
|
op.drop_column("spool", "initial_weight")
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ def upgrade() -> None:
|
|||||||
nullable=False,
|
nullable=False,
|
||||||
),
|
),
|
||||||
sa.Column(
|
sa.Column(
|
||||||
"empty_weight",
|
"spool_weight",
|
||||||
sa.Float(),
|
sa.Float(),
|
||||||
nullable=False,
|
nullable=False,
|
||||||
),
|
),
|
||||||
@@ -48,13 +48,13 @@ def upgrade() -> None:
|
|||||||
.where(filament.c.id == spool.c.filament_id)
|
.where(filament.c.id == spool.c.filament_id)
|
||||||
.scalar_subquery()
|
.scalar_subquery()
|
||||||
)
|
)
|
||||||
empty_weight = sa.select(filament.c.spool_weight).where(filament.c.id == spool.c.filament_id).scalar_subquery()
|
spool_weight = sa.select(filament.c.spool_weight).where(filament.c.id == spool.c.filament_id).scalar_subquery()
|
||||||
|
|
||||||
set_initial_weight = sa.update(spool).values(initial_weight=initial_weight)
|
set_initial_weight = sa.update(spool).values(initial_weight=initial_weight)
|
||||||
op.execute(set_initial_weight)
|
op.execute(set_initial_weight)
|
||||||
|
|
||||||
set_empty_weight = sa.update(spool).values(empty_weight=empty_weight)
|
set_spool_weight = sa.update(spool).values(spool_weight=spool_weight)
|
||||||
op.execute(set_empty_weight)
|
op.execute(set_spool_weight)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -190,10 +190,10 @@ class Spool(BaseModel):
|
|||||||
initial_weight: Optional[float] = Field(
|
initial_weight: Optional[float] = Field(
|
||||||
default=None,
|
default=None,
|
||||||
ge=0,
|
ge=0,
|
||||||
description=("Initial weight of the filament and spool (gross weight)"),
|
description=("The initial weight, in grams, of the filament on the spool (net weight)."),
|
||||||
example=1246,
|
example=1246,
|
||||||
)
|
)
|
||||||
empty_weight: Optional[float] = Field(
|
spool_weight: Optional[float] = Field(
|
||||||
default=None,
|
default=None,
|
||||||
ge=0,
|
ge=0,
|
||||||
description=("Weight of an empty spool (tare weight)."),
|
description=("Weight of an empty spool (tare weight)."),
|
||||||
@@ -242,9 +242,7 @@ class Spool(BaseModel):
|
|||||||
remaining_length: Optional[float] = None
|
remaining_length: Optional[float] = None
|
||||||
|
|
||||||
if item.initial_weight is not None:
|
if item.initial_weight is not None:
|
||||||
filament_spool_weight = item.filament.spool_weight if item.filament.spool_weight is not None else 0
|
remaining_weight = max(item.initial_weight - item.used_weight, 0)
|
||||||
spool_weight = item.empty_weight if item.empty_weight is not None else filament_spool_weight
|
|
||||||
remaining_weight = max(item.initial_weight - spool_weight - item.used_weight, 0)
|
|
||||||
remaining_length = length_from_weight(
|
remaining_length = length_from_weight(
|
||||||
weight=remaining_weight,
|
weight=remaining_weight,
|
||||||
density=filament.density,
|
density=filament.density,
|
||||||
@@ -272,7 +270,7 @@ class Spool(BaseModel):
|
|||||||
filament=filament,
|
filament=filament,
|
||||||
price=item.price,
|
price=item.price,
|
||||||
initial_weight=item.initial_weight,
|
initial_weight=item.initial_weight,
|
||||||
empty_weight=item.empty_weight,
|
spool_weight=item.spool_weight,
|
||||||
used_weight=item.used_weight,
|
used_weight=item.used_weight,
|
||||||
used_length=used_length,
|
used_length=used_length,
|
||||||
remaining_weight=remaining_weight,
|
remaining_weight=remaining_weight,
|
||||||
|
|||||||
@@ -42,10 +42,10 @@ class SpoolParameters(BaseModel):
|
|||||||
)
|
)
|
||||||
initial_weight: Optional[float] = Field(
|
initial_weight: Optional[float] = Field(
|
||||||
ge=0,
|
ge=0,
|
||||||
description="The initial total weight of the filament and spool, in grams. (gross weight)",
|
description="The initial weight of the filament on the spool, in grams. (net weight)",
|
||||||
example=200,
|
example=200,
|
||||||
)
|
)
|
||||||
empty_weight: Optional[float] = Field(
|
spool_weight: Optional[float] = Field(
|
||||||
ge=0,
|
ge=0,
|
||||||
description="The weight of an empty spool, in grams. (tare weight)",
|
description="The weight of an empty spool, in grams. (tare weight)",
|
||||||
example=200,
|
example=200,
|
||||||
@@ -369,7 +369,7 @@ async def create( # noqa: ANN201
|
|||||||
filament_id=body.filament_id,
|
filament_id=body.filament_id,
|
||||||
price=body.price,
|
price=body.price,
|
||||||
initial_weight=body.initial_weight,
|
initial_weight=body.initial_weight,
|
||||||
empty_weight=body.empty_weight,
|
spool_weight=body.spool_weight,
|
||||||
remaining_weight=body.remaining_weight,
|
remaining_weight=body.remaining_weight,
|
||||||
used_weight=body.used_weight,
|
used_weight=body.used_weight,
|
||||||
first_used=body.first_used,
|
first_used=body.first_used,
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ class Spool(Base):
|
|||||||
filament_id: Mapped[int] = mapped_column(ForeignKey("filament.id"))
|
filament_id: Mapped[int] = mapped_column(ForeignKey("filament.id"))
|
||||||
filament: Mapped["Filament"] = relationship(back_populates="spools")
|
filament: Mapped["Filament"] = relationship(back_populates="spools")
|
||||||
initial_weight: Mapped[Optional[float]] = mapped_column()
|
initial_weight: Mapped[Optional[float]] = mapped_column()
|
||||||
empty_weight: Mapped[Optional[float]] = mapped_column()
|
spool_weight: Mapped[Optional[float]] = mapped_column()
|
||||||
used_weight: Mapped[float] = mapped_column()
|
used_weight: Mapped[float] = mapped_column()
|
||||||
location: Mapped[Optional[str]] = mapped_column(String(64))
|
location: Mapped[Optional[str]] = mapped_column(String(64))
|
||||||
lot_nr: Mapped[Optional[str]] = mapped_column(String(64))
|
lot_nr: Mapped[Optional[str]] = mapped_column(String(64))
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ async def create(
|
|||||||
filament_id: int,
|
filament_id: int,
|
||||||
remaining_weight: Optional[float] = None,
|
remaining_weight: Optional[float] = None,
|
||||||
initial_weight: Optional[float] = None,
|
initial_weight: Optional[float] = None,
|
||||||
empty_weight: Optional[float] = None,
|
spool_weight: Optional[float] = None,
|
||||||
used_weight: Optional[float] = None,
|
used_weight: Optional[float] = None,
|
||||||
first_used: Optional[datetime] = None,
|
first_used: Optional[datetime] = None,
|
||||||
last_used: Optional[datetime] = None,
|
last_used: Optional[datetime] = None,
|
||||||
@@ -50,13 +50,13 @@ async def create(
|
|||||||
"""Add a new spool to the database. Leave weight empty to assume full spool."""
|
"""Add a new spool to the database. Leave weight empty to assume full spool."""
|
||||||
filament_item = await filament.get_by_id(db, filament_id)
|
filament_item = await filament.get_by_id(db, filament_id)
|
||||||
|
|
||||||
# Set empty_weight to spool_weight if spool_weight is not null and empty_weight not provided
|
# Set spool_weight to spool_weight if spool_weight is not null and spool_weight not provided
|
||||||
if empty_weight is None and filament_item.spool_weight is not None:
|
if spool_weight is None and filament_item.spool_weight is not None:
|
||||||
empty_weight = filament_item.spool_weight
|
spool_weight = filament_item.spool_weight
|
||||||
|
|
||||||
# Calculate initial_weight if not provided
|
# Calculate initial_weight if not provided
|
||||||
if initial_weight is None and filament_item.weight is not None:
|
if initial_weight is None and filament_item.weight is not None:
|
||||||
initial_weight = filament_item.weight + (empty_weight if empty_weight is not None else 0)
|
initial_weight = filament_item.weight
|
||||||
|
|
||||||
if used_weight is None:
|
if used_weight is None:
|
||||||
if remaining_weight is not None:
|
if remaining_weight is not None:
|
||||||
@@ -65,7 +65,7 @@ async def create(
|
|||||||
"remaining_weight can only be used if the initial_weight is "
|
"remaining_weight can only be used if the initial_weight is "
|
||||||
"defined or the filament has a weight set.",
|
"defined or the filament has a weight set.",
|
||||||
)
|
)
|
||||||
used_weight = max(initial_weight - empty_weight - remaining_weight, 0)
|
used_weight = max(initial_weight - remaining_weight, 0)
|
||||||
else:
|
else:
|
||||||
used_weight = 0
|
used_weight = 0
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ async def create(
|
|||||||
filament=filament_item,
|
filament=filament_item,
|
||||||
registered=datetime.utcnow().replace(microsecond=0),
|
registered=datetime.utcnow().replace(microsecond=0),
|
||||||
initial_weight=initial_weight,
|
initial_weight=initial_weight,
|
||||||
empty_weight=empty_weight,
|
spool_weight=spool_weight,
|
||||||
used_weight=used_weight,
|
used_weight=used_weight,
|
||||||
price=price,
|
price=price,
|
||||||
first_used=first_used,
|
first_used=first_used,
|
||||||
@@ -166,7 +166,7 @@ async def find(
|
|||||||
for fieldstr, order in sort_by.items():
|
for fieldstr, order in sort_by.items():
|
||||||
sorts = []
|
sorts = []
|
||||||
if fieldstr in {"remaining_weight", "remaining_length"}:
|
if fieldstr in {"remaining_weight", "remaining_length"}:
|
||||||
sorts.append(models.Spool.initial_weight - models.Spool.empty_weight - models.Spool.used_weight)
|
sorts.append(models.Spool.initial_weight - models.Spool.spool_weight - models.Spool.used_weight)
|
||||||
elif fieldstr == "filament.combined_name":
|
elif fieldstr == "filament.combined_name":
|
||||||
sorts.append(models.Vendor.name)
|
sorts.append(models.Vendor.name)
|
||||||
sorts.append(models.Filament.name)
|
sorts.append(models.Filament.name)
|
||||||
@@ -198,15 +198,13 @@ async def update(
|
|||||||
if k == "filament_id":
|
if k == "filament_id":
|
||||||
spool.filament = await filament.get_by_id(db, v)
|
spool.filament = await filament.get_by_id(db, v)
|
||||||
# If there is no initial_weight, calculate it from the filament weight
|
# If there is no initial_weight, calculate it from the filament weight
|
||||||
if spool.initial_weight is None and spool.empty_weight is None and spool.filament.weight is not None:
|
if spool.initial_weight is None and spool.filament.weight is not None:
|
||||||
spool_weight = spool.empty_weight if spool.empty_weight is not None else 0
|
spool.initial_weight = spool.filament.weight
|
||||||
spool.initial_weight = spool.filament.weight + spool_weight
|
|
||||||
spool.empty_weight = spool_weight
|
|
||||||
|
|
||||||
elif k == "remaining_weight":
|
elif k == "remaining_weight":
|
||||||
if spool.initial_weight is None:
|
if spool.initial_weight is None:
|
||||||
raise ItemCreateError("remaining_weight can only be used if initial_weight is set.")
|
raise ItemCreateError("remaining_weight can only be used if initial_weight is set.")
|
||||||
spool.used_weight = max((spool.initial_weight - spool.empty_weight) - v, 0)
|
spool.used_weight = max(spool.initial_weight - v, 0)
|
||||||
elif isinstance(v, datetime):
|
elif isinstance(v, datetime):
|
||||||
setattr(spool, k, utc_timezone_naive(v))
|
setattr(spool, k, utc_timezone_naive(v))
|
||||||
elif k == "extra":
|
elif k == "extra":
|
||||||
@@ -343,7 +341,7 @@ async def measure(db: AsyncSession, spool_id: int, weight: float) -> models.Spoo
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
spool_result = await db.execute(
|
spool_result = await db.execute(
|
||||||
sqlalchemy.select(models.Spool.initial_weight, models.Spool.used_weight, models.Spool.empty_weight).where(
|
sqlalchemy.select(models.Spool.initial_weight, models.Spool.used_weight, models.Spool.spool_weight).where(
|
||||||
models.Spool.id == spool_id,
|
models.Spool.id == spool_id,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -354,8 +352,8 @@ async def measure(db: AsyncSession, spool_id: int, weight: float) -> models.Spoo
|
|||||||
raise SpoolMeasureError("Spool not found.") from exc
|
raise SpoolMeasureError("Spool not found.") from exc
|
||||||
|
|
||||||
initial_weight = spool_info[0]
|
initial_weight = spool_info[0]
|
||||||
empty_weight = spool_info[2]
|
spool_weight = spool_info[2]
|
||||||
if initial_weight is None or initial_weight == 0 or empty_weight is None or empty_weight == 0:
|
if initial_weight is None or initial_weight == 0 or spool_weight is None or spool_weight == 0:
|
||||||
# Get filament weight and spool_weight
|
# Get filament weight and spool_weight
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
sqlalchemy.select(models.Filament.weight, models.Filament.spool_weight)
|
sqlalchemy.select(models.Filament.weight, models.Filament.spool_weight)
|
||||||
@@ -367,17 +365,19 @@ async def measure(db: AsyncSession, spool_id: int, weight: float) -> models.Spoo
|
|||||||
except NoResultFound as exc:
|
except NoResultFound as exc:
|
||||||
raise ItemNotFoundError("Filament not found for spool.") from exc
|
raise ItemNotFoundError("Filament not found for spool.") from exc
|
||||||
|
|
||||||
if empty_weight is None or empty_weight == 0:
|
if spool_weight is None or spool_weight == 0:
|
||||||
empty_weight = filament_info[1]
|
spool_weight = filament_info[1]
|
||||||
|
|
||||||
if initial_weight is None or initial_weight == 0:
|
if initial_weight is None or initial_weight == 0:
|
||||||
initial_weight = (filament_info[0] if filament_info[0] is not None else 0) + empty_weight
|
initial_weight = filament_info[0] if filament_info[0] is not None else 0
|
||||||
|
|
||||||
if initial_weight is None or initial_weight == 0:
|
if initial_weight is None or initial_weight == 0:
|
||||||
raise SpoolMeasureError("Initial weight is not set.")
|
raise SpoolMeasureError("Initial weight is not set.")
|
||||||
|
|
||||||
|
initial_gross_weight = initial_weight + spool_weight
|
||||||
|
|
||||||
# Calculate the current gross weight (initial_weight - used_weight)
|
# Calculate the current gross weight (initial_weight - used_weight)
|
||||||
current_use = initial_weight - spool_info[1]
|
current_use = initial_gross_weight - spool_info[1]
|
||||||
|
|
||||||
# if the measurement is greater than the initial weight, raise an error
|
# if the measurement is greater than the initial weight, raise an error
|
||||||
if weight > current_use:
|
if weight > current_use:
|
||||||
@@ -387,8 +387,8 @@ async def measure(db: AsyncSession, spool_id: int, weight: float) -> models.Spoo
|
|||||||
weight_to_use = current_use - weight
|
weight_to_use = current_use - weight
|
||||||
|
|
||||||
# If the measured weight is less than the empty weight, use the rest of the spool
|
# If the measured weight is less than the empty weight, use the rest of the spool
|
||||||
if (initial_weight - weight_to_use) < empty_weight:
|
if (initial_gross_weight - weight_to_use) < spool_weight:
|
||||||
weight_to_use = current_use - empty_weight
|
weight_to_use = current_use - spool_weight
|
||||||
|
|
||||||
return await use_weight(db, spool_id, weight_to_use)
|
return await use_weight(db, spool_id, weight_to_use)
|
||||||
|
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ def test_add_spool_initial_weight(random_filament: dict[str, Any]):
|
|||||||
"""Test adding a spool to the database."""
|
"""Test adding a spool to the database."""
|
||||||
# Execute
|
# Execute
|
||||||
remaining_weight = 750
|
remaining_weight = 750
|
||||||
initial_weight = 1245
|
initial_weight = 1010
|
||||||
location = "The Pantry"
|
location = "The Pantry"
|
||||||
lot_nr = "123456789"
|
lot_nr = "123456789"
|
||||||
comment = "abcdefghåäö"
|
comment = "abcdefghåäö"
|
||||||
@@ -225,7 +225,7 @@ def test_add_spool_initial_weight(random_filament: dict[str, Any]):
|
|||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
|
|
||||||
# Verify
|
# Verify
|
||||||
used_weight = initial_weight - random_filament["spool_weight"] - remaining_weight
|
used_weight = initial_weight - remaining_weight
|
||||||
used_length = length_from_weight(
|
used_length = length_from_weight(
|
||||||
weight=used_weight,
|
weight=used_weight,
|
||||||
density=random_filament["density"],
|
density=random_filament["density"],
|
||||||
@@ -247,7 +247,7 @@ def test_add_spool_initial_weight(random_filament: dict[str, Any]):
|
|||||||
"last_used": "2023-01-02T11:00:00Z",
|
"last_used": "2023-01-02T11:00:00Z",
|
||||||
"filament": random_filament,
|
"filament": random_filament,
|
||||||
"initial_weight": pytest.approx(initial_weight),
|
"initial_weight": pytest.approx(initial_weight),
|
||||||
"empty_weight": pytest.approx(random_filament["spool_weight"]),
|
"spool_weight": pytest.approx(random_filament["spool_weight"]),
|
||||||
"remaining_weight": pytest.approx(remaining_weight),
|
"remaining_weight": pytest.approx(remaining_weight),
|
||||||
"used_weight": pytest.approx(used_weight),
|
"used_weight": pytest.approx(used_weight),
|
||||||
"remaining_length": pytest.approx(remaining_length),
|
"remaining_length": pytest.approx(remaining_length),
|
||||||
@@ -268,11 +268,11 @@ def test_add_spool_initial_weight(random_filament: dict[str, Any]):
|
|||||||
httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status()
|
httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status()
|
||||||
|
|
||||||
|
|
||||||
def test_add_spool_empty_weight(random_filament: dict[str, Any]):
|
def test_add_spool_spool_weight(random_filament: dict[str, Any]):
|
||||||
"""Test adding a spool to the database."""
|
"""Test adding a spool to the database."""
|
||||||
# Execute
|
# Execute
|
||||||
remaining_weight = 750
|
remaining_weight = 750
|
||||||
empty_weight = 200
|
spool_weight = 200
|
||||||
location = "The Pantry"
|
location = "The Pantry"
|
||||||
lot_nr = "123456789"
|
lot_nr = "123456789"
|
||||||
comment = "abcdefghåäö"
|
comment = "abcdefghåäö"
|
||||||
@@ -285,7 +285,7 @@ def test_add_spool_empty_weight(random_filament: dict[str, Any]):
|
|||||||
"last_used": "2023-01-02T11:00:00Z",
|
"last_used": "2023-01-02T11:00:00Z",
|
||||||
"filament_id": random_filament["id"],
|
"filament_id": random_filament["id"],
|
||||||
"remaining_weight": remaining_weight,
|
"remaining_weight": remaining_weight,
|
||||||
"empty_weight": empty_weight,
|
"spool_weight": spool_weight,
|
||||||
"location": location,
|
"location": location,
|
||||||
"lot_nr": lot_nr,
|
"lot_nr": lot_nr,
|
||||||
"comment": comment,
|
"comment": comment,
|
||||||
@@ -317,8 +317,8 @@ def test_add_spool_empty_weight(random_filament: dict[str, Any]):
|
|||||||
"first_used": "2023-01-02T11:00:00Z",
|
"first_used": "2023-01-02T11:00:00Z",
|
||||||
"last_used": "2023-01-02T11:00:00Z",
|
"last_used": "2023-01-02T11:00:00Z",
|
||||||
"filament": random_filament,
|
"filament": random_filament,
|
||||||
"initial_weight": pytest.approx(random_filament["weight"] + empty_weight),
|
"initial_weight": pytest.approx(random_filament["weight"]),
|
||||||
"empty_weight": pytest.approx(empty_weight),
|
"spool_weight": pytest.approx(spool_weight),
|
||||||
"remaining_weight": pytest.approx(remaining_weight),
|
"remaining_weight": pytest.approx(remaining_weight),
|
||||||
"used_weight": pytest.approx(used_weight),
|
"used_weight": pytest.approx(used_weight),
|
||||||
"remaining_length": pytest.approx(remaining_length),
|
"remaining_length": pytest.approx(remaining_length),
|
||||||
|
|||||||
@@ -83,8 +83,8 @@ def test_get_spool_default_weights(random_filament: dict[str, Any]):
|
|||||||
|
|
||||||
# Verify
|
# Verify
|
||||||
assert result_spool == spool
|
assert result_spool == spool
|
||||||
assert result_spool["initial_weight"] == pytest.approx(random_filament["weight"] + random_filament["spool_weight"])
|
assert result_spool["initial_weight"] == pytest.approx(random_filament["weight"])
|
||||||
assert result_spool["empty_weight"] == pytest.approx(random_filament["spool_weight"])
|
assert result_spool["spool_weight"] == pytest.approx(random_filament["spool_weight"])
|
||||||
|
|
||||||
# Clean up
|
# Clean up
|
||||||
httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status()
|
httpx.delete(f"{URL}/api/v1/spool/{spool['id']}").raise_for_status()
|
||||||
@@ -97,7 +97,7 @@ def test_get_spool_weights(random_filament: dict[str, Any]):
|
|||||||
last_used = "2023-01-02T00:00:00"
|
last_used = "2023-01-02T00:00:00"
|
||||||
remaining_weight = 750
|
remaining_weight = 750
|
||||||
initial_weight = 1255
|
initial_weight = 1255
|
||||||
empty_weight = 246
|
spool_weight = 246
|
||||||
location = "The Pantry"
|
location = "The Pantry"
|
||||||
lot_nr = "123456789"
|
lot_nr = "123456789"
|
||||||
comment = "abcdefghåäö"
|
comment = "abcdefghåäö"
|
||||||
@@ -111,7 +111,7 @@ def test_get_spool_weights(random_filament: dict[str, Any]):
|
|||||||
"filament_id": random_filament["id"],
|
"filament_id": random_filament["id"],
|
||||||
"remaining_weight": remaining_weight,
|
"remaining_weight": remaining_weight,
|
||||||
"initial_weight": initial_weight,
|
"initial_weight": initial_weight,
|
||||||
"empty_weight": empty_weight,
|
"spool_weight": spool_weight,
|
||||||
"location": location,
|
"location": location,
|
||||||
"lot_nr": lot_nr,
|
"lot_nr": lot_nr,
|
||||||
"comment": comment,
|
"comment": comment,
|
||||||
|
|||||||
@@ -9,21 +9,20 @@ import pytest
|
|||||||
from ..conftest import URL
|
from ..conftest import URL
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("measurement", [0, 0.05, -0.05, 1000])
|
@pytest.mark.parametrize("measurement", [246, 500, 600, 1000])
|
||||||
def test_measure_spool(random_filament: dict[str, Any], measurement: float):
|
def test_measure_spool(random_filament: dict[str, Any], measurement: float):
|
||||||
"""Test using a spool in the database."""
|
"""Test using a spool in the database."""
|
||||||
# Setup
|
# Setup
|
||||||
random_filament["weight"]
|
random_filament["weight"]
|
||||||
initial_weight = 1255
|
spool_weight = 246
|
||||||
empty_weight = 246
|
|
||||||
start_weight = 1000
|
start_weight = 1000
|
||||||
result = httpx.post(
|
result = httpx.post(
|
||||||
f"{URL}/api/v1/spool",
|
f"{URL}/api/v1/spool",
|
||||||
json={
|
json={
|
||||||
"filament_id": random_filament["id"],
|
"filament_id": random_filament["id"],
|
||||||
"remaining_weight": start_weight,
|
"remaining_weight": start_weight,
|
||||||
"initial_weight": initial_weight,
|
"initial_weight": start_weight,
|
||||||
"empty_weight": empty_weight,
|
"spool_weight": spool_weight,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
@@ -41,9 +40,9 @@ def test_measure_spool(random_filament: dict[str, Any], measurement: float):
|
|||||||
# Verify
|
# Verify
|
||||||
spool = result.json()
|
spool = result.json()
|
||||||
# remaining_weight should be clamped so it's never negative, but used_weight should not be clamped to the net weight
|
# remaining_weight should be clamped so it's never negative, but used_weight should not be clamped to the net weight
|
||||||
expected_use = min(initial_weight - measurement, initial_weight - empty_weight)
|
expected_use = min(start_weight - (measurement - spool_weight), start_weight)
|
||||||
assert spool["used_weight"] == pytest.approx(expected_use)
|
assert spool["used_weight"] == pytest.approx(expected_use)
|
||||||
expected_remaining = max(measurement - empty_weight, 0)
|
expected_remaining = max(measurement - spool_weight, 0)
|
||||||
assert spool["remaining_weight"] == pytest.approx(expected_remaining)
|
assert spool["remaining_weight"] == pytest.approx(expected_remaining)
|
||||||
# Verify that first_used has been updated
|
# Verify that first_used has been updated
|
||||||
diff = abs((datetime.now(tz=timezone.utc) - datetime.fromisoformat(spool["first_used"])).total_seconds())
|
diff = abs((datetime.now(tz=timezone.utc) - datetime.fromisoformat(spool["first_used"])).total_seconds())
|
||||||
@@ -62,16 +61,15 @@ def test_measure_spool_invalid(random_filament: dict[str, Any], measurement: flo
|
|||||||
"""Test using a spool in the database."""
|
"""Test using a spool in the database."""
|
||||||
# Setup
|
# Setup
|
||||||
random_filament["weight"]
|
random_filament["weight"]
|
||||||
initial_weight = 1255
|
spool_weight = 246
|
||||||
empty_weight = 246
|
|
||||||
start_weight = 1000
|
start_weight = 1000
|
||||||
result = httpx.post(
|
result = httpx.post(
|
||||||
f"{URL}/api/v1/spool",
|
f"{URL}/api/v1/spool",
|
||||||
json={
|
json={
|
||||||
"filament_id": random_filament["id"],
|
"filament_id": random_filament["id"],
|
||||||
"remaining_weight": start_weight,
|
"remaining_weight": start_weight,
|
||||||
"initial_weight": initial_weight,
|
"initial_weight": start_weight,
|
||||||
"empty_weight": empty_weight,
|
"spool_weight": spool_weight,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
@@ -96,17 +94,17 @@ def test_measure_spool_sequence(random_filament: dict[str, Any], measurements: l
|
|||||||
"""Test using a spool in the database."""
|
"""Test using a spool in the database."""
|
||||||
# Setup
|
# Setup
|
||||||
random_filament["weight"]
|
random_filament["weight"]
|
||||||
initial_weight = 1255
|
spool_weight = 246
|
||||||
|
start_weight = 1009
|
||||||
|
initial_weight = start_weight + spool_weight
|
||||||
current_weight = initial_weight
|
current_weight = initial_weight
|
||||||
empty_weight = 246
|
|
||||||
start_weight = 1000
|
|
||||||
result = httpx.post(
|
result = httpx.post(
|
||||||
f"{URL}/api/v1/spool",
|
f"{URL}/api/v1/spool",
|
||||||
json={
|
json={
|
||||||
"filament_id": random_filament["id"],
|
"filament_id": random_filament["id"],
|
||||||
"remaining_weight": start_weight,
|
"remaining_weight": start_weight,
|
||||||
"initial_weight": initial_weight,
|
"initial_weight": start_weight,
|
||||||
"empty_weight": empty_weight,
|
"spool_weight": spool_weight,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
@@ -126,9 +124,9 @@ def test_measure_spool_sequence(random_filament: dict[str, Any], measurements: l
|
|||||||
spool = result.json()
|
spool = result.json()
|
||||||
# remaining_weight should be clamped so it's never negative,
|
# remaining_weight should be clamped so it's never negative,
|
||||||
# but used_weight should not be clamped to the net weight
|
# but used_weight should not be clamped to the net weight
|
||||||
expected_use = min(initial_weight - m, initial_weight - empty_weight)
|
expected_use = min(initial_weight - m, initial_weight - spool_weight)
|
||||||
assert spool["used_weight"] == pytest.approx(expected_use)
|
assert spool["used_weight"] == pytest.approx(expected_use)
|
||||||
expected_remaining = max(m - empty_weight, 0)
|
expected_remaining = max(m - spool_weight, 0)
|
||||||
assert spool["remaining_weight"] == pytest.approx(expected_remaining)
|
assert spool["remaining_weight"] == pytest.approx(expected_remaining)
|
||||||
# Verify that first_used has been updated
|
# Verify that first_used has been updated
|
||||||
diff = abs((datetime.now(tz=timezone.utc) - datetime.fromisoformat(spool["first_used"])).total_seconds())
|
diff = abs((datetime.now(tz=timezone.utc) - datetime.fromisoformat(spool["first_used"])).total_seconds())
|
||||||
@@ -148,17 +146,17 @@ def test_measure_spool_sequence(random_filament: dict[str, Any], measurements: l
|
|||||||
def test_measure_spool_empty(random_empty_filament: dict[str, Any], measurements: list[float]):
|
def test_measure_spool_empty(random_empty_filament: dict[str, Any], measurements: list[float]):
|
||||||
"""Test using a spool in the database."""
|
"""Test using a spool in the database."""
|
||||||
# Setup
|
# Setup
|
||||||
initial_weight = 1255
|
spool_weight = 246
|
||||||
current_weight = initial_weight
|
|
||||||
empty_weight = 246
|
|
||||||
start_weight = 1000
|
start_weight = 1000
|
||||||
|
initial_weight = start_weight + spool_weight
|
||||||
|
current_weight = initial_weight
|
||||||
result = httpx.post(
|
result = httpx.post(
|
||||||
f"{URL}/api/v1/spool",
|
f"{URL}/api/v1/spool",
|
||||||
json={
|
json={
|
||||||
"filament_id": random_empty_filament["id"],
|
"filament_id": random_empty_filament["id"],
|
||||||
"remaining_weight": start_weight,
|
"remaining_weight": start_weight,
|
||||||
"initial_weight": initial_weight,
|
"initial_weight": start_weight,
|
||||||
"empty_weight": empty_weight,
|
"spool_weight": spool_weight,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
@@ -178,9 +176,9 @@ def test_measure_spool_empty(random_empty_filament: dict[str, Any], measurements
|
|||||||
spool = result.json()
|
spool = result.json()
|
||||||
# remaining_weight should be clamped so it's never negative,
|
# remaining_weight should be clamped so it's never negative,
|
||||||
# but used_weight should not be clamped to the net weight
|
# but used_weight should not be clamped to the net weight
|
||||||
expected_use = min(initial_weight - m, initial_weight - empty_weight)
|
expected_use = min(initial_weight - m, initial_weight - spool_weight)
|
||||||
assert spool["used_weight"] == pytest.approx(expected_use)
|
assert spool["used_weight"] == pytest.approx(expected_use)
|
||||||
expected_remaining = max(m - empty_weight, 0)
|
expected_remaining = max(m - spool_weight, 0)
|
||||||
assert spool["remaining_weight"] == pytest.approx(expected_remaining)
|
assert spool["remaining_weight"] == pytest.approx(expected_remaining)
|
||||||
# Verify that first_used has been updated
|
# Verify that first_used has been updated
|
||||||
diff = abs((datetime.now(tz=timezone.utc) - datetime.fromisoformat(spool["first_used"])).total_seconds())
|
diff = abs((datetime.now(tz=timezone.utc) - datetime.fromisoformat(spool["first_used"])).total_seconds())
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ def test_update_spool_weights(random_filament: dict[str, Any]):
|
|||||||
"filament_id": random_filament["id"],
|
"filament_id": random_filament["id"],
|
||||||
"remaining_weight": 1000,
|
"remaining_weight": 1000,
|
||||||
"initial_weight": 1255,
|
"initial_weight": 1255,
|
||||||
"empty_weight": 246,
|
"spool_weight": 246,
|
||||||
"location": "The Pantry",
|
"location": "The Pantry",
|
||||||
"lot_nr": "123456789",
|
"lot_nr": "123456789",
|
||||||
},
|
},
|
||||||
@@ -98,8 +98,8 @@ def test_update_spool_weights(random_filament: dict[str, Any]):
|
|||||||
first_used = "2023-01-01T12:00:00+02:00"
|
first_used = "2023-01-01T12:00:00+02:00"
|
||||||
last_used = "2023-01-02T12:00:00+02:00"
|
last_used = "2023-01-02T12:00:00+02:00"
|
||||||
remaining_weight = 750
|
remaining_weight = 750
|
||||||
initial_weight = 1250
|
initial_weight = 1005
|
||||||
empty_weight = 245
|
spool_weight = 245
|
||||||
location = "Living Room"
|
location = "Living Room"
|
||||||
lot_nr = "987654321"
|
lot_nr = "987654321"
|
||||||
comment = "abcdefghåäö"
|
comment = "abcdefghåäö"
|
||||||
@@ -117,13 +117,13 @@ def test_update_spool_weights(random_filament: dict[str, Any]):
|
|||||||
"archived": archived,
|
"archived": archived,
|
||||||
"price": price,
|
"price": price,
|
||||||
"initial_weight": initial_weight,
|
"initial_weight": initial_weight,
|
||||||
"empty_weight": empty_weight,
|
"spool_weight": spool_weight,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
result.raise_for_status()
|
result.raise_for_status()
|
||||||
|
|
||||||
# Verify
|
# Verify
|
||||||
used_weight = initial_weight - empty_weight - remaining_weight
|
used_weight = initial_weight - remaining_weight
|
||||||
used_length = length_from_weight(
|
used_length = length_from_weight(
|
||||||
weight=used_weight,
|
weight=used_weight,
|
||||||
density=random_filament["density"],
|
density=random_filament["density"],
|
||||||
@@ -139,7 +139,7 @@ def test_update_spool_weights(random_filament: dict[str, Any]):
|
|||||||
assert spool["first_used"] == "2023-01-01T10:00:00Z"
|
assert spool["first_used"] == "2023-01-01T10:00:00Z"
|
||||||
assert spool["last_used"] == "2023-01-02T10:00:00Z"
|
assert spool["last_used"] == "2023-01-02T10:00:00Z"
|
||||||
assert spool["initial_weight"] == pytest.approx(initial_weight)
|
assert spool["initial_weight"] == pytest.approx(initial_weight)
|
||||||
assert spool["empty_weight"] == pytest.approx(empty_weight)
|
assert spool["spool_weight"] == pytest.approx(spool_weight)
|
||||||
assert spool["remaining_weight"] == pytest.approx(remaining_weight)
|
assert spool["remaining_weight"] == pytest.approx(remaining_weight)
|
||||||
assert spool["used_weight"] == pytest.approx(used_weight)
|
assert spool["used_weight"] == pytest.approx(used_weight)
|
||||||
assert spool["remaining_length"] == pytest.approx(remaining_length)
|
assert spool["remaining_length"] == pytest.approx(remaining_length)
|
||||||
|
|||||||
Reference in New Issue
Block a user