Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[4947][ADD] purchase_stock_price_variance #107

Open
wants to merge 11 commits into
base: 16.0
Choose a base branch
from

Conversation

AungKoKoLin1997
Copy link
Contributor

@AungKoKoLin1997 AungKoKoLin1997 changed the title [4947][ADD] purchase_inventory_valuation_price_check [4947][ADD] purchase_inventory_price_check Feb 14, 2025
@AungKoKoLin1997 AungKoKoLin1997 changed the title [4947][ADD] purchase_inventory_price_check [4947][ADD] inventory_price_check Feb 14, 2025
@AungKoKoLin1997 AungKoKoLin1997 marked this pull request as ready for review February 14, 2025 03:08
Copy link
Member

@yostashiro yostashiro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partial review.

inventory_price_check doesn't seem to follow the normal naming convention. How about purchase_stock_price_variance as the module name?

Comment on lines 10 to 15
price_discrepancy_threshold_type = fields.Selection(
[("percentage", "Percentage"), ("fixed", "Fixed Value"), ("ignore", "Ignore")]
)
price_discrepancy_threshold_value = fields.Float(
help="Threshold value for price discrepancy warnings."
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make it like this:

Suggested change
price_discrepancy_threshold_type = fields.Selection(
[("percentage", "Percentage"), ("fixed", "Fixed Value"), ("ignore", "Ignore")]
)
price_discrepancy_threshold_value = fields.Float(
help="Threshold value for price discrepancy warnings."
)
price_variance_threshold_percent = fields.Float(help="Maximum variance (in percent) allowable between the product's standard price and purchase receipt unit price.")
price_variance_threshold_amount = fields.Float(help="Maximum allowable variance (in monetary amount, based on company currency) between the product's standard price and the purchase receipt unit price.")

The idea is to allow both types of thresholds. Hitting either one should trigger an error.

class Stockpick(models.Model):
_inherit = "stock.picking"

allow_price_inconsistency = fields.Boolean(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
allow_price_inconsistency = fields.Boolean(
bypass_price_variance_check = fields.Boolean(

for pick in self:
if pick.picking_type_id.code != "incoming":
continue
if pick.sudo().allow_price_inconsistency:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why sudo() here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This field is only allowed for some group and we will get access right error if the user is not in this group.

product = move.product_id
threshold_type = (
product.price_discrepancy_threshold_type
or pick.company_id.price_discrepancy_threshold_type
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Values from the company should be kept in variables outside the loop.

@AungKoKoLin1997 AungKoKoLin1997 changed the title [4947][ADD] inventory_price_check [4947][ADD] purchase_stock_price_variance Feb 17, 2025
Copy link
Member

@yostashiro yostashiro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partial review.

bypass_price_variance_check = fields.Boolean(
copy=False,
tracking=True,
groups="purchase_stock_price_variance.group_bypass_price_variance_check",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be better to extend write() to check if the user belongs to this group? I think this group assignment to the field is too rigid.

product.price_variance_threshold_amount
or global_price_variance_threshold_amount
)
received_price = move.price_unit
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be safer this way to update the cost based on the current exchange rate.

Suggested change
received_price = move.price_unit
received_price = move._get_price_unit()

continue
if pick.sudo().bypass_price_variance_check:
continue
for move in pick.move_ids_without_package:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason for not using pick.move_ids?

Comment on lines 27 to 28
if pick.picking_type_id.code != "incoming":
continue
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please check if adding conditions using _is_in() and _is_dropshipped() for each stock move record is more appropriate instead of this?

Copy link
Contributor Author

@AungKoKoLin1997 AungKoKoLin1997 Feb 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I checked the odoo source code, checking picking_type_id.code is used in stock._is_in() and _is_dropshipped() is introduced in stock_account and used them. In our module, stock_account is part of dependency because we use purchase_stock as a dependency. So, I think using _is_in() and _is_dropshipped() is more appropriate.

Comment on lines 10 to 12
<field name="price_variance_threshold_percent" />
<field name="price_variance_threshold_amount" />
<field name="bypass_price_variance_check" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<field name="price_variance_threshold_percent" />
<field name="price_variance_threshold_amount" />
<field name="bypass_price_variance_check" />
<field name="bypass_price_variance_check" />
<field name="price_variance_threshold_percent" />
<field name="price_variance_threshold_amount" />

and make the threshold fields invisible when bypass_price_variance_check is true.

@AungKoKoLin1997
Copy link
Contributor Author

I did bypass_price_variance_check to be True as a default for two reasons. First is to avoid the test cases failed of other module because the default threshold values are 0.0(it means there should be no variance) and reduce the work for the user to disable the check for all product and to set up the threshold value for the products that is needed to use for threshold check.

):
raise UserError(
_(
f"Price discrepancy detected for {product.name}: "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
f"Price discrepancy detected for {product.name}: "
f"Price variance exceeding a threshold detected for {product.name}: "

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please tidy the steps (with numbers, perhaps) and "correct" the line breaks.

Comment on lines 1 to 2
This module checks for variance between the receipt price and the product's
standard price at the time of validation.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This module checks for variance between the receipt price and the product's
standard price at the time of validation.
This module checks the variance between the purchase price and the product's
standard price at the time of receipt picking validation and displays an error if the
variance exceeds a given threshold.

Comment on lines 1 to 6
A warning message will be displayed during validation if the variance
between the receipt price and the standard price exceeds the threshold.

Selecting 'Bypass Price Variance Check' allows users to bypass this error,
and it is only visible to members of the 'Bypass Price Variance Check'
group.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A warning message will be displayed during validation if the variance
between the receipt price and the standard price exceeds the threshold.
Selecting 'Bypass Price Variance Check' allows users to bypass this error,
and it is only visible to members of the 'Bypass Price Variance Check'
group.
An error message will be displayed during validation if the variance
between the purchase price and the standard price exceeds a threshold.
Selecting 'Bypass Price Variance Check' in the receipt picking allows users
to bypass this error. Only members of the 'Bypass Price Variance Check'
group can update this field.

self.env.company.price_variance_threshold_amount
)
for pick in self:
if pick.sudo().bypass_price_variance_check:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if pick.sudo().bypass_price_variance_check:
if pick.bypass_price_variance_check:

@yostashiro
Copy link
Member

I did bypass_price_variance_check to be True as a default for two reasons. First is to avoid the test cases failed of other module because the default threshold values are 0.0(it means there should be no variance) and reduce the work for the user to disable the check for all product and to set up the threshold value for the products that is needed to use for threshold check.

@AungKoKoLin1997 Sorry, missed this comment. I think the default of the product should be false, and have another field in res.config.settings to enable the feature.

Copy link
Member

@yostashiro yostashiro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review.

if (
percentage_difference > threshold_percent
or amount_difference > threshold_amount
):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AungKoKoLin1997
I'm doing the functional test.
Currently, two problems arise.

  1. The initial threshold value is 0, so if the variance check is set to true and other thresholds are not changed, all products will not be able to be received.
  2. Both percentage and fixed values ​​are used for variance, making it difficult to continue adjusting those values.

When I consulted Tashiro-san, he said that when it was 0, it would be best to avoid using that threshold.
I thought so too.

I think it's a good idea to separate the process by threshold to see if they're using that value, and if they're using them, check if they're above the threshold.
What do you think?

Copy link
Member

@yostashiro yostashiro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nobuQuartile Please remove the pre-commit noise from other modules.

Comment on lines 66 to 67
threshold_percent != 0 and percentage_difference > threshold_percent
) or (threshold_amount != 0 and amount_difference > threshold_amount):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
threshold_percent != 0 and percentage_difference > threshold_percent
) or (threshold_amount != 0 and amount_difference > threshold_amount):
threshold_percent and percentage_difference > threshold_percent
) or (threshold_amount and amount_difference > threshold_amount):

price_variance_threshold_amount = fields.Float(
help="Maximum allowable variance (in monetary amount, based on company currency)"
" between the product's standard price and the purchase receipt unit price."
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make sure that the values are positive here.

Suggested change
)
)
@api.constrains("price_variance_threshold_percent", "price_variance_threshold_amount")
def _check_price_variance_threshold(self):
for rec in self:
if rec.price_variance_threshold_percent < 0 or rec.price_variance_threshold_amount < 0:
raise ValidationError(_("The threshold values cannot be negative."))

<div class="o_setting_right_pane">
<label for="price_variance_threshold_percent" />
<div class="text-muted">
Maximum variance (in percent) allowable between the product's standard price and purchase receipt unit price.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Maximum variance (in percent) allowable between the product's standard price and purchase receipt unit price.
Maximum variance (in percent) allowable between the product's standard price and purchase receipt unit price.
Keeping it at zero means that this threshold will not be checked.

Please apply the same adjustments to all the relevant places.

</div>
<div class="content-group">
<div class="mt16">
<field name="price_variance_threshold_percent" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure this is the correct way to put it. Please check it yourself, and do the same for all the relevant fields.

Suggested change
<field name="price_variance_threshold_percent" />
<field name="price_variance_threshold_percent" /><span> %</span>

@nobuQuartile
Copy link

@AungKoKoLin1997 @yostashiro
Global values ​​cannot be ignored for each threshold at the product level and cannot be allowed.

Current Product Variant Options
The initial value is set to 0

  • Set a value at the product level (+)
  • Disable the variant at the product level for a specific threshold (Not possible)
  • Use the global value (0)

Option1
When using numeric types, the only way to divide other than 0 and plus is negative.

  • Disable the variant at the product level for a specific threshold (-)

Option2

  • Set a value at the product level (+)
  • Disable the variant at the product level for a specific threshold (0)
  • Use the global value (-)

Option3
Create a new boolean for each threshold at the product level.

  • Set a value at the product level (+)
  • Disable the variant at the product level for a specific threshold (0)
  • Use the global value (New boolean)

I think Option3 is better.
What do you think?

@nobuQuartile
Copy link

We decided not to change the code.

Current Product Variant Options
The initial value is set to 0

Set a value at the product level (+)
Disable the variant at the product level for a specific threshold (Large value that is not typical)
Use the global value (0)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants