diff --git a/app/Http/Requests/AdjustQuantityRequest.php b/app/Http/Requests/AdjustQuantityRequest.php index f3ad5edc08..94c34d68b6 100644 --- a/app/Http/Requests/AdjustQuantityRequest.php +++ b/app/Http/Requests/AdjustQuantityRequest.php @@ -23,9 +23,12 @@ class AdjustQuantityRequest extends FormRequest { return [ // Signed delta: positive to replenish, negative to decrement. - // The trait rejects the actual below-in-use case; here we - // just guard against zero (nothing to do) and non-integer. - 'amount' => ['required', 'integer', 'not_in:0'], + // Zero is intentionally allowed so users can record an audit + // (physical count against the current DB qty). The trait + // writes a QuantityAdjust log entry with quantity=0 in that + // case without touching the on-hand column. The trait itself + // rejects the actual below-in-use case. + 'amount' => ['required', 'integer'], 'note' => ['required', 'string', 'max:65535'], 'order_number' => ['nullable', 'string', 'max:191'], // Optional receipt/invoice/PO scan. Attaches to the same diff --git a/app/Models/Traits/AdjustsQuantity.php b/app/Models/Traits/AdjustsQuantity.php index 0578449861..25cb1ad484 100644 --- a/app/Models/Traits/AdjustsQuantity.php +++ b/app/Models/Traits/AdjustsQuantity.php @@ -54,6 +54,11 @@ trait AdjustsQuantity * PHP-side read-modify-write). Wrapped in a transaction so the log * entry and the quantity change either both happen or both roll back. * + * A delta of zero is a valid audit-only submission: no qty change + * happens but the log entry still writes, so a user can record a + * physical count that confirms the DB value without also logging a + * spurious increment or decrement. + * * Rejects any adjustment that would leave the on-hand quantity below * the number of units currently in use — decrementing below what's * already checked out to users/assets would leave the DB inconsistent @@ -69,10 +74,6 @@ trait AdjustsQuantity */ public function adjustQuantity(int $delta, string $note, ?string $orderNumber = null, ?string $filename = null): void { - if ($delta === 0) { - return; - } - $column = $this->getAdjustableQuantityColumn(); $current = (int) ($this->{$column} ?? 0); $inUse = max(0, (int) $this->currentlyInUseCount()); @@ -91,12 +92,17 @@ trait AdjustsQuantity // {qty:{old,new}}) alongside our QuantityAdjust log. Keep // the in-memory attribute in sync so any downstream code // reading $this->qty after the call sees the new value. - $delta > 0 - ? $this->newQuery()->where('id', $this->id)->increment($column, $delta) - : $this->newQuery()->where('id', $this->id)->decrement($column, abs($delta)); - - $this->{$column} = (int) $this->{$column} + $delta; - $this->syncOriginalAttribute($column); + // Gate the actual UPDATE on delta !== 0 so audit-only + // submissions (delta = 0) skip the round-trip. + if ($delta > 0) { + $this->newQuery()->where('id', $this->id)->increment($column, $delta); + $this->{$column} = (int) $this->{$column} + $delta; + $this->syncOriginalAttribute($column); + } elseif ($delta < 0) { + $this->newQuery()->where('id', $this->id)->decrement($column, abs($delta)); + $this->{$column} = (int) $this->{$column} + $delta; + $this->syncOriginalAttribute($column); + } $log = new Actionlog; $log->item_type = static::class; diff --git a/resources/lang/en-US/general.php b/resources/lang/en-US/general.php index e088d01709..e556a296ca 100644 --- a/resources/lang/en-US/general.php +++ b/resources/lang/en-US/general.php @@ -16,7 +16,7 @@ return [ 'adjust_quantity' => 'Adjust Quantity', 'adjust_quantity_success' => 'Quantity adjusted successfully.', 'adjust_quantity_amount' => 'Amount to add or remove', - 'adjust_quantity_amount_help' => 'Positive to replenish (e.g. 5), negative to decrease (e.g. -3). Must not be zero.', + 'adjust_quantity_amount_help' => 'Positive to replenish (e.g. 5), negative to decrease (e.g. -3). Zero records an audit entry without changing the on-hand quantity.', 'adjust_quantity_note' => 'Reason / note', 'adjust_quantity_below_zero' => 'That adjustment would take the on-hand quantity below what is currently checked out.', 'adjusted_quantity' => 'adjusted quantity', diff --git a/resources/views/blade/modals/adjust-quantity.blade.php b/resources/views/blade/modals/adjust-quantity.blade.php index 86c6dc7774..ec68fa84e8 100644 --- a/resources/views/blade/modals/adjust-quantity.blade.php +++ b/resources/views/blade/modals/adjust-quantity.blade.php @@ -21,8 +21,11 @@ {{-- min is populated by snipeit.js when the modal opens (–available). The browser stepper then refuses to go below and the built-in - constraint-validation message surfaces if a user types past it. --}} - + constraint-validation message surfaces if a user types past it. + Zero is a valid input: it produces an audit-only QuantityAdjust + log entry with no qty change so users can record a physical + count against the current DB value. --}} +

{{ trans('general.adjust_quantity_amount_help') }}

diff --git a/resources/views/layouts/default.blade.php b/resources/views/layouts/default.blade.php index e4b39ee19b..aef03d8c65 100644 --- a/resources/views/layouts/default.blade.php +++ b/resources/views/layouts/default.blade.php @@ -1138,17 +1138,6 @@ return param.test(value); }, '{{ trans('validation.generic.invalid_value_in_field') }}'); - // Opt-in via data-rule-not-zero="true" on any numeric input. - // Used by the adjust-quantity modal: the server-side rule is - // not_in:0 (zero delta = nothing to adjust), and HTML5 has no - // native way to exclude a single value from a numeric range. - $.validator.addMethod('notZero', function (value, element) { - if (this.optional(element)) { - return true; - } - return parseFloat(value) !== 0; - }, '{{ trans('general.adjust_quantity_amount_help') }}'); - // Generic radio-toggles-required-select handler. Any form pattern // where a radio group hides/shows sibling