Module: Controllers::PriceEditable
- Extended by:
- ActiveSupport::Concern
- Included in:
- OrdersController
- Defined in:
- app/concerns/controllers/price_editable.rb
Overview
ActiveSupport::Concern mixin: price editable.
Instance Method Summary collapse
-
#price_edit ⇒ void
Renders the price-editing form for the context object.
-
#price_update ⇒ void
Applies submitted unit price edits to the context object's line items.
Instance Method Details
#price_edit ⇒ void
This method returns an undefined value.
Renders the price-editing form for the context object.
Only CO and ST order types support price editing; anything else is
redirected back to the object with an error flash.
18 19 20 21 22 23 24 25 26 27 |
# File 'app/concerns/controllers/price_editable.rb', line 18 def price_edit load_context :edit_prices, @context_object if %w[CO ST].include?(@context_object.order_type) render 'price_editable/price_edit' else flash[:error] = "#{@context_object.class.name} must be a CO or ST to allow price editing" redirect_to polymorphic_url(@context_object) end end |
#price_update ⇒ void
This method returns an undefined value.
Applies submitted unit price edits to the context object's line items.
Validates every submitted row first (discounted price, MSRP, optional
taxable amount); kit components and blank/invalid rows are skipped with
per-line and base errors. On success, assigns the new values, saves with
+do_not_set_totals+ so coupon recalculation does not wipe manual edits,
then refreshes header totals via +perform_db_total+.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'app/concerns/controllers/price_editable.rb', line 38 def price_update load_context :edit_prices, @context_object line_item_payload = params[:line_item] unless line_item_payload.respond_to?(:each) flash[:error] = 'No line item prices were submitted.' return render 'price_editable/price_edit' end applications = [] line_item_payload.each do |line_item_id, values| next if values.blank? attrs = price_edit_line_item_attrs(values) discounted_raw = attrs['discounted_price'].to_s.strip price_raw = attrs['price'].to_s.strip line_item = @context_object.line_items.find { |li| li.id == line_item_id.to_i } next unless line_item # Kit components carry no price of their own — the kit parent owns it. The # form renders them read-only; guard the action too so a crafted payload # can't set one (see LineItem#enforce_zero_price_on_kit_component). next if line_item.kit_component? next if discounted_raw.blank? || price_raw.blank? new_taxable_raw = attrs['taxable_amount'].to_s.strip label = price_edit_line_item_label(line_item) row_invalid = false discounted_value = price_edit_parse_decimal(discounted_raw) if discounted_value.nil? line_item.errors.add(:discounted_price, 'is not a valid number') @context_object.errors.add(:base, "#{label}: unit discounted price is not a valid number") row_invalid = true end price_value = price_edit_parse_decimal(price_raw) if price_value.nil? line_item.errors.add(:price, 'is not a valid number') @context_object.errors.add(:base, "#{label}: unit MSRP is not a valid number") row_invalid = true end new_taxable_amount = nil if new_taxable_raw.present? tax_value = price_edit_parse_decimal(new_taxable_raw) if tax_value.nil? line_item.errors.add(:taxable_amount, 'is not a valid number') @context_object.errors.add(:base, "#{label}: unit taxable amount is not a valid number") row_invalid = true else new_taxable_amount = tax_value end end next if row_invalid applications << { line_item: line_item, discounted_price: discounted_value, price: price_value, taxable_amount: new_taxable_amount, tax_only: attrs['tax_only'].to_s == '1' } end if @context_object.errors.any? render 'price_editable/price_edit' return end applications.each do |app| li = app[:line_item] li.discounted_price = app[:discounted_price] li.price = app[:price] li.taxable_amount = app[:taxable_amount] li.tax_only = app[:tax_only] end if applications.any? # Saving with force_total_reset triggers set_totals → calculate_discounts, and # Coupon::ItemizableDiscountCalculator resets every line with discounted_price = price # (MSRP), wiping manual edits. Skip that path for this action only, then refresh # header totals via the same SQL used after a normal total reset. @context_object.do_not_set_totals = true if @context_object.respond_to?(:do_not_set_totals=) if @context_object.save @context_object.do_not_set_totals = false if @context_object.respond_to?(:do_not_set_totals=) @context_object.perform_db_total if @context_object.respond_to?(:perform_db_total) @context_object.reload redirect_to polymorphic_url(@context_object) else @context_object.do_not_set_totals = false if @context_object.respond_to?(:do_not_set_totals=) flash[:error] = @context_object.errors..to_sentence.presence || 'Could not save price changes.' render 'price_editable/price_edit' end else flash[:error] = 'No prices were updated. Enter both unit discounted price and unit MSRP for each line you change.' render 'price_editable/price_edit' end end |