Refactor ProductSku and PartSku models to enforce required fields for overrideCost, overridePrice, and related properties. Update visibility logic for cost and price fields based on overrides, ensuring consistent data handling across components. Adjust NewProductSku and ProductInfo components to utilize updated default values and improve user experience.
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good

This commit is contained in:
Tom Butcher 2026-06-21 21:19:49 +01:00
parent 6cd0dca365
commit 4501f9936f
4 changed files with 201 additions and 124 deletions

View File

@ -8,7 +8,11 @@ const NewProductSku = ({ onOk, reset, defaultValues }) => {
<NewObjectForm
type='productSku'
reset={reset}
defaultValues={defaultValues}
defaultValues={{
overrideCost: false,
overridePrice: false,
...defaultValues
}}
>
{({ handleSubmit, submitLoading, objectData, formValid }) => {
const steps = [
@ -50,51 +54,18 @@ const NewProductSku = ({ onOk, reset, defaultValues }) => {
<ObjectInfo
type='productSku'
column={1}
labelWidth={100}
labelWidth={120}
visibleProperties={{
overrideCost: true,
cost: true,
costTaxRate: true,
costWithTax: true,
overridePrice: true,
priceMode: true,
price: true,
margin: true,
priceTaxRate: true,
priceWithTax: true,
priceMode: true
}}
required={true}
bordered={false}
isEditing={true}
objectData={objectData}
/>
)
},
{
title: 'Parts',
key: 'parts',
content: (
<ObjectInfo
type='productSku'
column={1}
labelWidth={100}
visibleProperties={{
_id: false,
createdAt: false,
updatedAt: false,
barcode: false,
product: false,
name: false,
description: false,
priceMode: false,
cost: false,
costWithTax: false,
costTaxRate: false,
price: false,
priceWithTax: false,
margin: false,
amount: false,
priceTaxRate: false,
vendor: false
priceWithTax: true
}}
bordered={false}
isEditing={true}
@ -131,9 +102,10 @@ const NewProductSku = ({ onOk, reset, defaultValues }) => {
createdAt: false,
updatedAt: false,
_id: false,
_reference: false
_reference: false,
parts: false
}}
labelWidth={100}
labelWidth={120}
bordered={false}
isEditing={false}
objectData={objectData}

View File

@ -197,7 +197,7 @@ const ProductInfo = () => {
}}
reset={newProductSkuOpen}
defaultValues={{
product: productId ? { _id: productId } : undefined
product: objectFormState?.objectData || undefined
}}
/>
</Modal>

View File

@ -75,7 +75,17 @@ export const PartSku = {
'createdAt',
'updatedAt'
],
filters: ['_id', 'barcode', 'part', 'part._id', 'name', 'cost', 'costWithTax', 'price', 'priceWithTax'],
filters: [
'_id',
'barcode',
'part',
'part._id',
'name',
'cost',
'costWithTax',
'price',
'priceWithTax'
],
sorters: [
'barcode',
'part',
@ -152,54 +162,44 @@ export const PartSku = {
type: 'text',
columnWidth: 200
},
{
name: 'priceMode',
label: 'Price Mode',
required: false,
type: 'priceMode',
columnWidth: 150
},
{
name: 'overrideCost',
label: 'Override Cost',
required: false,
required: true,
type: 'bool',
value: (objectData) => objectData?.overrideCost ?? false,
columnWidth: 150
},
{
name: 'overridePrice',
label: 'Override Price',
required: false,
type: 'bool',
value: (objectData) => objectData?.overridePrice ?? false,
columnWidth: 150
},
{
name: 'cost',
label: 'Cost',
required: false,
required: true,
type: 'number',
prefix: '£',
min: 0,
step: 0.01,
disabled: (objectData) => !objectData?.overrideCost,
visible: (objectData) => {
return objectData?.overrideCost
},
value: (objectData) =>
objectData?.overrideCost ? objectData?.cost : undefined,
objectData?.overrideCost ? objectData?.cost : objectData?.part?.cost,
columnWidth: 100
},
{
name: 'costWithTax',
label: 'Cost w/ Tax',
required: false,
required: true,
readOnly: true,
type: 'number',
prefix: '£',
min: 0,
step: 0.01,
disabled: (objectData) => !objectData?.overrideCost,
visible: (objectData) => {
return objectData?.overrideCost
},
value: (objectData) => {
if (!objectData?.overrideCost) return undefined
if (!objectData?.overrideCost)
return objectData?.part?.costWithTax || undefined
const cost = objectData?.cost
const taxRate = objectData?.costTaxRate
if (!cost) return 0
@ -215,28 +215,58 @@ export const PartSku = {
{
name: 'costTaxRate',
label: 'Cost Tax Rate',
required: false,
required: true,
type: 'object',
objectType: 'taxRate',
showHyperlink: true,
disabled: (objectData) => !objectData?.overrideCost,
visible: (objectData) => {
return objectData?.overrideCost
},
value: (objectData) =>
objectData?.overrideCost ? objectData?.costTaxRate : undefined,
objectData?.overrideCost
? objectData?.costTaxRate
: objectData?.part?.costTaxRate,
columnWidth: 150
},
{
name: 'overridePrice',
label: 'Override Price',
required: true,
type: 'bool',
columnWidth: 150
},
{
name: 'priceMode',
label: 'Price Mode',
required: true,
visible: (objectData) => {
return objectData?.overridePrice
},
value: (objectData) => {
return objectData?.overridePrice
? objectData?.priceMode
: objectData?.part?.priceMode
},
type: 'priceMode',
columnWidth: 150
},
{
name: 'price',
label: 'Price',
required: false,
required: true,
type: 'number',
prefix: '£',
min: 0,
step: 0.1,
disabled: (objectData) => !objectData?.overridePrice,
fixedNumber: 2,
visible: (objectData) => {
return objectData?.overridePrice
},
readOnly: (objectData) =>
objectData?.overridePrice && objectData?.priceMode == 'margin',
value: (objectData) => {
if (!objectData?.overridePrice) return undefined
if (!objectData?.overridePrice)
return objectData?.part?.price || undefined
const priceMode = objectData?.priceMode ?? objectData?.part?.priceMode
const cost = objectData?.overrideCost
? objectData?.cost
@ -248,7 +278,7 @@ export const PartSku = {
margin !== null &&
cost != null
) {
return (cost * (1 + margin / 100)).toFixed(2) || undefined
return cost * (1 + margin / 100) || undefined
}
return objectData?.price
},
@ -257,15 +287,18 @@ export const PartSku = {
{
name: 'priceWithTax',
label: 'Price w/ Tax',
required: false,
required: true,
readOnly: true,
type: 'number',
prefix: '£',
min: 0,
step: 0.01,
disabled: (objectData) => !objectData?.overridePrice,
visible: (objectData) => {
return objectData?.overridePrice
},
value: (objectData) => {
if (!objectData?.overridePrice) return undefined
if (!objectData?.overridePrice)
return objectData.part?.priceWithTax || undefined
let price
const priceMode = objectData?.priceMode ?? objectData?.part?.priceMode
const cost = objectData?.overrideCost
@ -292,28 +325,51 @@ export const PartSku = {
{
name: 'margin',
label: 'Margin',
required: false,
required: true,
type: 'number',
disabled: (objectData) =>
!objectData?.overridePrice || objectData?.priceMode == 'amount',
visible: (objectData) => {
return objectData?.overridePrice
},
readOnly: (objectData) => {
const priceMode = objectData?.priceMode ?? objectData?.part?.priceMode
return priceMode == 'amount'
},
suffix: '%',
min: 0,
max: 100,
step: 0.01,
value: (objectData) =>
objectData?.overridePrice ? objectData?.margin : undefined,
value: (objectData) => {
if (!objectData?.overridePrice)
return objectData?.part?.margin || undefined
const priceMode = objectData?.priceMode ?? objectData?.part?.priceMode
const cost = objectData?.overrideCost
? objectData?.cost
: objectData?.part?.cost
if (priceMode == 'amount') {
const price = objectData?.price
if (price != null && cost != null) {
return Number(((price / cost - 1) * 100).toFixed(2)) || undefined
}
return undefined
}
return objectData?.margin ?? objectData?.part?.margin
},
columnWidth: 85
},
{
name: 'priceTaxRate',
label: 'Price Tax Rate',
required: false,
required: true,
type: 'object',
objectType: 'taxRate',
showHyperlink: true,
disabled: (objectData) => !objectData?.overridePrice,
visible: (objectData) => {
return objectData?.overridePrice
},
value: (objectData) =>
objectData?.overridePrice ? objectData?.priceTaxRate : undefined,
objectData?.overridePrice
? objectData?.priceTaxRate
: objectData?.part?.priceTaxRate,
columnWidth: 150
}
]

View File

@ -163,54 +163,45 @@ export const ProductSku = {
type: 'text',
columnWidth: 200
},
{
name: 'priceMode',
label: 'Price Mode',
required: false,
type: 'priceMode',
columnWidth: 150
},
{
name: 'overrideCost',
label: 'Override Cost',
required: false,
required: true,
type: 'bool',
value: (objectData) => objectData?.overrideCost ?? false,
columnWidth: 150
},
{
name: 'overridePrice',
label: 'Override Price',
required: false,
type: 'bool',
value: (objectData) => objectData?.overridePrice ?? false,
columnWidth: 150
},
{
name: 'cost',
label: 'Cost',
required: false,
required: true,
type: 'number',
prefix: '£',
min: 0,
step: 0.01,
disabled: (objectData) => !objectData?.overrideCost,
visible: (objectData) => {
return objectData?.overrideCost
},
value: (objectData) =>
objectData?.overrideCost ? objectData?.cost : undefined,
objectData?.overrideCost
? objectData?.cost
: objectData?.product?.cost,
columnWidth: 100
},
{
name: 'costWithTax',
label: 'Cost w/ Tax',
required: false,
required: true,
readOnly: true,
type: 'number',
prefix: '£',
min: 0,
step: 0.01,
disabled: (objectData) => !objectData?.overrideCost,
visible: (objectData) => {
return objectData?.overrideCost
},
value: (objectData) => {
if (!objectData?.overrideCost) return undefined
if (!objectData?.overrideCost)
return objectData?.product?.costWithTax || undefined
const cost = objectData?.cost
const taxRate = objectData?.costTaxRate
if (!cost) return 0
@ -226,28 +217,58 @@ export const ProductSku = {
{
name: 'costTaxRate',
label: 'Cost Tax Rate',
required: false,
required: true,
type: 'object',
objectType: 'taxRate',
showHyperlink: true,
disabled: (objectData) => !objectData?.overrideCost,
visible: (objectData) => {
return objectData?.overrideCost
},
value: (objectData) =>
objectData?.overrideCost ? objectData?.costTaxRate : undefined,
objectData?.overrideCost
? objectData?.costTaxRate
: objectData?.product?.costTaxRate,
columnWidth: 150
},
{
name: 'overridePrice',
label: 'Override Price',
required: true,
type: 'bool',
columnWidth: 150
},
{
name: 'priceMode',
label: 'Price Mode',
required: true,
visible: (objectData) => {
return objectData?.overridePrice
},
value: (objectData) => {
return objectData?.overridePrice
? objectData?.priceMode
: objectData?.product?.priceMode
},
type: 'priceMode',
columnWidth: 150
},
{
name: 'price',
label: 'Price',
required: false,
required: true,
type: 'number',
prefix: '£',
min: 0,
step: 0.1,
disabled: (objectData) => !objectData?.overridePrice,
fixedNumber: 2,
visible: (objectData) => {
return objectData?.overridePrice
},
readOnly: (objectData) =>
objectData?.overridePrice && objectData?.priceMode == 'margin',
value: (objectData) => {
if (!objectData?.overridePrice) return undefined
if (!objectData?.overridePrice)
return objectData?.product?.price || undefined
const priceMode =
objectData?.priceMode ?? objectData?.product?.priceMode
const cost = objectData?.overrideCost
@ -260,7 +281,7 @@ export const ProductSku = {
margin !== null &&
cost != null
) {
return (cost * (1 + margin / 100)).toFixed(2) || undefined
return cost * (1 + margin / 100) || undefined
}
return objectData?.price
},
@ -269,15 +290,18 @@ export const ProductSku = {
{
name: 'priceWithTax',
label: 'Price w/ Tax',
required: false,
required: true,
readOnly: true,
type: 'number',
prefix: '£',
min: 0,
step: 0.01,
disabled: (objectData) => !objectData?.overridePrice,
visible: (objectData) => {
return objectData?.overridePrice
},
value: (objectData) => {
if (!objectData?.overridePrice) return undefined
if (!objectData?.overridePrice)
return objectData.product?.priceWithTax || undefined
let price
const priceMode =
objectData?.priceMode ?? objectData?.product?.priceMode
@ -305,28 +329,53 @@ export const ProductSku = {
{
name: 'margin',
label: 'Margin',
required: false,
required: true,
type: 'number',
disabled: (objectData) =>
!objectData?.overridePrice || objectData?.priceMode == 'amount',
visible: (objectData) => {
return objectData?.overridePrice
},
readOnly: (objectData) => {
const priceMode =
objectData?.priceMode ?? objectData?.product?.priceMode
return priceMode == 'amount'
},
suffix: '%',
min: 0,
max: 100,
step: 0.01,
value: (objectData) =>
objectData?.overridePrice ? objectData?.margin : undefined,
value: (objectData) => {
if (!objectData?.overridePrice)
return objectData?.product?.margin || undefined
const priceMode =
objectData?.priceMode ?? objectData?.product?.priceMode
const cost = objectData?.overrideCost
? objectData?.cost
: objectData?.product?.cost
if (priceMode == 'amount') {
const price = objectData?.price
if (price != null && cost != null) {
return Number(((price / cost - 1) * 100).toFixed(2)) || undefined
}
return undefined
}
return objectData?.margin ?? objectData?.product?.margin
},
columnWidth: 85
},
{
name: 'priceTaxRate',
label: 'Price Tax Rate',
required: false,
required: true,
type: 'object',
objectType: 'taxRate',
showHyperlink: true,
disabled: (objectData) => !objectData?.overridePrice,
visible: (objectData) => {
return objectData?.overridePrice
},
value: (objectData) =>
objectData?.overridePrice ? objectData?.priceTaxRate : undefined,
objectData?.overridePrice
? objectData?.priceTaxRate
: objectData?.product?.priceTaxRate,
columnWidth: 150
},
{