মুদ্রা / অর্থ পরিচালনার সর্বোত্তম পদ্ধতি কী?


323

আমি খুব বেসিক শপিং কার্ট সিস্টেমে কাজ করছি।

আমার কাছে একটি টেবিল itemsরয়েছে যার একটি কলাম priceরয়েছে integer

ইউরো এবং সেন্ট উভয়ই অন্তর্ভুক্ত এমন দামের জন্য আমার মতের মূল্য মূল্য প্রদর্শন করতে আমার সমস্যা হচ্ছে। রেল ফ্রেমওয়ার্কে মুদ্রা পরিচালনার ক্ষেত্রে আমি কী স্পষ্ট কিছু অনুভব করছি?


যদি কেউ ব্যবহার SQL, তারপর DECIMAL(19, 4) একটি জনপ্রিয় পছন্দ পরীক্ষা এই এছাড়াও পরীক্ষা এখানে সিদ্ধান্ত নিতে কত দশমিক ব্যবহারের স্থান, আশা সাহায্য করে বিশ্ব মুদ্রা বিন্যাস করা হয়।
শাইজুত

উত্তর:


495

আপনি সম্ভবত DECIMALআপনার ডাটাবেসের মধ্যে একটি প্রকার ব্যবহার করতে চাইবেন । আপনার মাইগ্রেশনে, এই জাতীয় কিছু করুন:

# precision is the total number of digits
# scale is the number of digits to the right of the decimal point
add_column :items, :price, :decimal, :precision => 8, :scale => 2

রেলগুলিতে, :decimalপ্রকারটি ফেরত দেওয়া হয় BigDecimal, যা মূল্য গণনার জন্য দুর্দান্ত।

আপনি যদি পূর্ণসংখ্যার ব্যবহারের জন্য জোর দিয়ে থাকেন, আপনাকে ম্যানুয়ালি BigDecimalসর্বত্র এবং সর্বত্র যে কোনও জায়গায় রূপান্তর করতে হবে যা সম্ভবত একটি ব্যথা হয়ে উঠবে।

এমসিএল দ্বারা নির্দেশিত হিসাবে, মূল্য মুদ্রণ করতে, ব্যবহার করুন:

number_to_currency(price, :unit => "€")
#=> €1,234.01

13
সংখ্যা_ টু_ক্রেন্সি সহায়ক, আরও তথ্য api.rubyonrails.org/class/ActionView/Helpers/…
mlibby

48
প্রকৃতপক্ষে, ক্রিয়াকলাপ_আস_ডোলারের সাথে একত্রে একটি পূর্ণসংখ্যার ব্যবহার করা অনেক বেশি নিরাপদ এবং সহজ। আপনি কি কখনও ভাসমান-পয়েন্ট তুলনা দ্বারা দংশিত হয়েছে? যদি তা না হয় তবে এটি আপনার প্রথম অভিজ্ঞতা হিসাবে তৈরি করবেন না। :) ক্রিয়া_স_ডোলারগুলির সাহায্যে আপনি 12.34 ফর্ম্যাটে স্টাফ রেখেছেন, এটি 1234 হিসাবে সংরক্ষণ করা হয়েছে এবং এটি 12.34 হিসাবে প্রকাশিত হবে।
সারা মেই

50
@ সরাহ মে: বিগডিসিমালস + দশমিক কলাম ফর্ম্যাট এটিকে একেবারে এড়িয়ে চলে।
মল্ফ

114
এই উত্তরটি অন্ধভাবে অনুলিপি না করা গুরুত্বপূর্ণ - যথার্থতা 8, স্কেল 2 আপনাকে সর্বোচ্চ 999,999.99 এর মান দেয় । আপনার যদি দশ লক্ষের বেশি সংখ্যার প্রয়োজন হয় তবে নির্ভুলতা বাড়ান!
জন কেয়ার্নস

22
আপনি যদি বিভিন্ন মুদ্রা পরিচালনা করছেন তবে অন্ধভাবে 2 স্কেল ব্যবহার না করাও গুরুত্বপূর্ণ - কিছু উত্তর-আফ্রিকান এবং আরব মুদ্রার মতো ওমানি রিয়াল বা তিউনিসিয়ান দিনার স্কেল 3 থাকে, সুতরাং যথাযথ 8 স্কেল 3 আরও উপযুক্ত ।
রিচার্টজ

117

এখানে একটি সূক্ষ্ম, সরল পদ্ধতির যা লাভ করে composed_of(অ্যাক্টিভেকর্ডের অংশ, ভ্যালুঅবজেক্ট প্যাটার্ন ব্যবহার করে) এবং মানি রত্ন

আপনার প্রয়োজন হবে

  • মানি মণি (সংস্করণ 4.1.0)
  • উদাহরণস্বরূপ একটি মডেল Product
  • integerউদাহরণস্বরূপ আপনার মডেল (এবং ডাটাবেস) এর একটি কলাম:price

আপনার product.rbফাইলে এটি লিখুন :

class Product > ActiveRecord::Base

  composed_of :price,
              :class_name => 'Money',
              :mapping => %w(price cents),
              :converter => Proc.new { |value| Money.new(value) }
  # ...

আপনি কি পাবেন:

  • কোনও অতিরিক্ত পরিবর্তন ছাড়াই আপনার সমস্ত ফর্ম ডলার এবং সেন্ট দেখায় তবে অভ্যন্তরীণ উপস্থাপনা এখনও কেবল সেন্ট is ফর্মগুলি "$ 12,034.95" এর মতো মান গ্রহণ করবে এবং এটি আপনার জন্য রূপান্তর করবে। আপনার মডেলের অতিরিক্ত হ্যান্ডলার বা গুণাবলী বা আপনার দৃষ্টিভঙ্গিতে সহায়কগুলি যুক্ত করার দরকার নেই।
  • product.price = "$12.00" স্বয়ংক্রিয়ভাবে মানি ক্লাসে রূপান্তরিত হয়
  • product.price.to_s দশমিক বিন্যাসিত নম্বর প্রদর্শন করে ("1234.00")
  • product.price.format মুদ্রার জন্য একটি সঠিকভাবে ফর্ম্যাট স্ট্রিং প্রদর্শন করে
  • আপনার যদি সেন্টগুলি প্রেরণের দরকার হয় (কোনও অর্থ প্রদানের প্রবেশদ্বারে যা পেনিগুলি চায়), product.price.cents.to_s
  • বিনামূল্যে মুদ্রা রূপান্তর

14
আমি এই পদ্ধতিকে ভালবাসি। তবে দয়া করে নোট করুন: নিশ্চিত করুন যে এই উদাহরণে 'দাম' এর জন্য আপনার স্থানান্তর নালাগুলি এবং ডিফল্টগুলিকে 0 এর মঞ্জুরি দেয় না যাতে আপনি এটি কেন কাজ করে না তা বের করার চেষ্টা করে পাগল হয়ে যান।
Cory

3
আমি যদি আপনার মুদ্রা রূপান্তরের প্রয়োজন না হয় তবে মানি_ক্লম রত্নটি ( শপাইফাই থেকে প্রাপ্ত) খুব সোজাভাবে ব্যবহার করার জন্য পেয়েছি ... অর্থের রত্নের চেয়ে সহজ, যদি আপনার প্রয়োজন হয় না need
টালাইরিক

7
মানি রত্ন ব্যবহার করে এমন সকলের জন্য এটি লক্ষ্য করা উচিত যে রেল কোর দলটি কাঠামো থেকে "কমপোজড_অফ" অবমূল্যায়ন এবং সরানোর বিষয়ে আলোচনা করছে। আমি সন্দেহ করি রত্নটি এটি হ্যান্ডেল করার জন্য আপডেট করা হবে, তবে আপনি যদি 4.0 রেলগুলি খুঁজছেন তবে আপনার এই সম্ভাবনাটি সম্পর্কে সচেতন হওয়া উচিত
পিয়ার অ্যালান

1
composed_of এখানে অপসারণ সম্পর্কে @ পিয়ারআল্লানের মন্তব্য সম্পর্কে সেই বিষয়ে আরও বিস্তারিত পাশাপাশি বিকল্প বাস্তবায়নও রয়েছে।
HerbCSO

3
এছাড়াও, এটি রেল-মানি মণি ব্যবহার করে সত্যই পুনরায় প্রত্যাশা ।
fotanus

25

দশমিক প্রকার ব্যবহার করা মুদ্রা পরিচালনা করার জন্য সাধারণ অনুশীলন। এখানে "রেলগুলির সাথে চতুর ওয়েব ডেভলপমেন্ট" থেকে একটি সাধারণ উদাহরণ দেওয়া হয়েছে

add_column :products, :price, :decimal, :precision => 8, :scale => 2 

এটি আপনাকে -999,999.99 থেকে 999,999.99 পর্যন্ত দামগুলি পরিচালনা করতে দেয় আপনি
নিজের আইটেমগুলিতেও কোনও বৈধতা অন্তর্ভুক্ত করতে চাইতে পারেন

def validate 
  errors.add(:price, "should be at least 0.01") if price.nil? || price < 0.01 
end 

আপনার মান মানসিকভাবে পরীক্ষা করতে।


1
এই সমাধান আপনাকে এসকিউএল যোগ এবং বন্ধুদের ব্যবহার করতে সক্ষম করে।
ল্যারি কে

4
আপনি সম্ভবত এটি করতে পারেন: বৈধতা: দাম,: উপস্থিতি => সত্য,: সংখ্যাগততা => {: বৃহত্তর_থান => 0}
গ্যালাক্সি

9

আপনি যদি পোস্টগ্রিস ব্যবহার করছেন (এবং যেহেতু আমরা এখন 2017 এ আছি) আপনি তাদের :moneyকলামের ধরণটি চেষ্টা করে দেখতে পারেন।

add_column :products, :price, :money, default: 0

7

অর্থ-রেল রত্ন ব্যবহার করুন । এটি আপনার মডেলটিতে খুব সুন্দরভাবে অর্থ এবং মুদ্রা পরিচালনা করে এবং আপনার মূল্যগুলি ফর্ম্যাট করতে সহায়তার একগুচ্ছ রয়েছে।


হ্যাঁ, আমি এটির সাথে একমত সাধারণত, আমি এটিকে সেন্ট (পূর্ণসংখ্যা) হিসাবে সংরক্ষণ করে এবং মেমরির মধ্যে ডেটা হ্যান্ডল করার জন্য অর্থ হিসাবে অর্থ বা অর্থের (অর্থ-রেল) রত্ন ব্যবহার করে অর্থ পরিচালনা করি। এটি পূর্ণসংখ্যার সাথে পরিচালনা করা those দুষ্টু গোলাকার ত্রুটিগুলি রোধ করে। উদাহরণস্বরূপ 0.2 * 3 => 0.600000000000000001 এটি অবশ্যই কাজ করে যদি আপনার এক শতাংশের ভগ্নাংশের প্রয়োজন হয় না।
চাদ এম

আপনি যদি রেল ব্যবহার করে থাকেন তবে এটি খুব সুন্দর। এটি ফেলে দিন এবং দশমিক কলাম সহ সমস্যাগুলি নিয়ে চিন্তা করবেন না। : আপনি একটি দৃশ্য সঙ্গে এই ব্যবহার করেন, তাহলে এই উত্তরটি পাশাপাশি সহায়ক হতে পারে stackoverflow.com/questions/18898947/...
mooreds

6

আরআর বিকাশের কিছু উচ্চাকাঙ্ক্ষী জুনিয়র / নতুনদের জন্য সমস্ত উত্তরগুলির একটি সামান্য আপডেট এবং একটি সামঞ্জস্য যা অবশ্যই এখানে কিছু ব্যাখ্যার জন্য আসবে।

অর্থ দিয়ে কাজ করা

:decimal@ মল্ফের পরামর্শ অনুসারে ডিবিতে অর্থ সঞ্চয় করতে ব্যবহার করুন (এবং অর্থের সাথে কাজ করার সময় আমার সংস্থা সোনার মান হিসাবে কী ব্যবহার করে)।

# precision is the total number of digits
# scale is the number of digits to the right of the decimal point
add_column :items, :price, :decimal, precision: 8, scale: 2

কয়েকটি পয়েন্ট:

  • :decimalহিসাবে ব্যবহার করা যেতে যাচ্ছে BigDecimalযা বিষয় অনেক solves।

  • precisionscaleআপনি উপস্থাপন করছেন তার উপর নির্ভর করে এবং সামঞ্জস্য করা উচিত

    • আপনি যদি পেমেন্ট গ্রহণ এবং প্রেরণে কাজ করেন precision: 8এবং scale: 2আপনাকে 999,999.99সর্বোচ্চ পরিমাণ হিসাবে দেয় যা 90% ক্ষেত্রে জরিমানা।

    • আপনার যদি কোনও সম্পত্তি বা বিরল গাড়ির মূল্য উপস্থাপন করতে হয় তবে আপনার উচ্চতর ব্যবহার করা উচিত precision

    • যদি আপনি স্থানাঙ্ক (দ্রাঘিমাংশ এবং অক্ষাংশ) নিয়ে কাজ করেন তবে অবশ্যই আপনার উচ্চতর প্রয়োজন হবে scale

মাইগ্রেশন কীভাবে তৈরি করা যায়

উপরের বিষয়বস্তু সহ স্থানান্তর তৈরি করতে, টার্মিনালটিতে চালান:

bin/rails g migration AddPriceToItems price:decimal{8-2}

অথবা

bin/rails g migration AddPriceToItems 'price:decimal{5,2}'

হিসাবে এই ব্লগ পোস্টে ব্যাখ্যা ।

মুদ্রার বিন্যাস

চুম্বন অতিরিক্ত লাইব্রেরি বিদায় এবং ব্যবহার বিল্ট ইন সাহায্যকারী। number_to_currency@ মল্ফ এবং @ ফ্যাকুন্ডোফারিয়াস প্রস্তাবিত হিসাবে ব্যবহার করুন ।

সাথে খেলতে number_to_currencyপাগল কনসোলে সাহায্যকারী, একটি কল পাঠাতে ActiveSupportএর NumberHelperসাহায্যকারী অ্যাক্সেস করার জন্য বর্গ।

উদাহরণ স্বরূপ:

ActiveSupport::NumberHelper.number_to_currency(2_500_000.61, unit: '€', precision: 2, separator: ',', delimiter: '', format: "%n%u")

নিম্নলিখিত আউটপুট দেয়

2500000,61

অন্যান্য পরীক্ষা করে দেখুন optionsএর number_to_currency সাহায্যকারী।

কোথায় রাখব

আপনি এটিকে অ্যাপ্লিকেশন সহায়কতে রাখতে পারেন এবং এটি কোনও পরিমাণের জন্য দর্শনের অভ্যন্তরে ব্যবহার করতে পারেন।

module ApplicationHelper    
  def format_currency(amount)
    number_to_currency(amount, unit: '€', precision: 2, separator: ',', delimiter: '', format: "%n%u")
  end
end

অথবা আপনি এটিকে Itemমডেলটিতে একটি উদাহরণ পদ্ধতি হিসাবে রাখতে পারেন এবং যেখানে দামটি বিন্যাস করতে হবে সেদিকে ফোন করতে পারেন (ভিউ বা সহায়তাকারীদের ক্ষেত্রে)।

class Item < ActiveRecord::Base
  def format_price
    number_to_currency(price, unit: '€', precision: 2, separator: ',', delimiter: '', format: "%n%u")
  end
end

এবং, আমি কীভাবে number_to_currencyএকটি কনট্রোলারের অভ্যন্তরটি ব্যবহার করি তার একটি উদাহরণ ( negative_formatবিকল্পটি লক্ষ্য করুন , অর্থ ফেরতের প্রতিনিধিত্ব করতে ব্যবহৃত হবে)

def refund_information
  amount_formatted = 
    ActionController::Base.helpers.number_to_currency(@refund.amount, negative_format: '(%u%n)')
  {
    # ...
    amount_formatted: amount_formatted,
    # ...
  }
end

5

ব্যবহার (সংশোধিত (প্রদত্ত) Railscast লিংক) ভার্চুয়াল গুণাবলী আপনি একটি পূর্ণসংখ্যা কলামে আপনার price_in_cents সংরক্ষণ এবং একটি গেটার এবং সেটার যেমন আপনার পণ্যের মডেল একটি ভার্চুয়াল অ্যাট্রিবিউট price_in_dollars যোগ করতে পারেন।

# Add a price_in_cents integer column
$ rails g migration add_price_in_cents_to_products price_in_cents:integer

# Use virtual attributes in your Product model
# app/models/product.rb

def price_in_dollars
  price_in_cents.to_d/100 if price_in_cents
end

def price_in_dollars=(dollars)
  self.price_in_cents = dollars.to_d*100 if dollars.present?
end

উত্স: রেলকাস্টস # 016: ভার্চুয়াল বৈশিষ্ট্য : ভার্চুয়াল বৈশিষ্ট্যগুলি ফর্ম ক্ষেত্রগুলি যুক্ত করার একটি পরিষ্কার উপায় যা সরাসরি ডেটাবেজে মানচিত্র দেয় না। এখানে আমি কীভাবে বৈধতা, সমিতিগুলি এবং আরও কীভাবে পরিচালনা করব তা দেখাই।


1
এটি
200.0


2

যদি কেউ সিকুয়েল ব্যবহার করে থাকে তবে মাইগ্রেশনটি দেখতে এরকম কিছু দেখতে পাবে:

add_column :products, :price, "decimal(8,2)"

সিকুয়েল কোনওভাবে উপেক্ষা করে: যথার্থতা এবং: স্কেল

(সিকুয়েল সংস্করণ: সিক্যুয়াল (3.39.0, 3.38.0))


2

আমার অন্তর্নিহিত API গুলি সমস্ত অর্থ উপস্থাপনের জন্য সেন্ট ব্যবহার করছিল এবং আমি এটি পরিবর্তন করতে চাইনি। না আমি প্রচুর পরিমাণে অর্থ নিয়ে কাজ করছিলাম। সুতরাং আমি এটি একটি সহায়ক পদ্ধতিতে রেখেছি:

sprintf("%03d", amount).insert(-3, ".")

এটি পূর্ণসংখ্যাকে কমপক্ষে তিনটি অঙ্কের সাথে স্ট্রিংয়ে রূপান্তর করে (প্রয়োজনে নেতৃস্থানীয় জিরো যুক্ত করে), তারপরে শেষ দুটি অঙ্কের আগে দশমিক পয়েন্ট সন্নিবেশ করে, কখনই ব্যবহার করে না Float। সেখান থেকে আপনি যে কোনও মুদ্রার প্রতীক আপনার ব্যবহারের ক্ষেত্রে উপযুক্ত তা যুক্ত করতে পারেন।

এটি অবশ্যই দ্রুত এবং নোংরা, তবে কখনও কখনও এটি ঠিক আছে!


বিশ্বাস করতে পারে না কেউ আপনাকে উঁচু করে তুলেছে। এই একমাত্র জিনিস যা আমার অর্থের অবজেক্টটিকে সুন্দরভাবে একটি ফর্মের মধ্যে আনতে কাজ করেছিল যাতে কোনও এপিআই এটি নিতে পারে। (দশমিক)
কোড-মনকি

2

আমি এটি এইভাবে ব্যবহার করছি:

number_to_currency(amount, unit: '€', precision: 2, format: "%u %n")

অবশ্যই মুদ্রার প্রতীক, নির্ভুলতা, ফর্ম্যাট এবং তাই প্রতিটি মুদ্রার উপর নির্ভর করে।


1

আপনি কয়েকটি বিকল্প number_to_currency(এখানে স্ট্যান্ডার্ড রেলস 4 ভিউ সহায়ক) পাস করতে পারেন :

number_to_currency(12.0, :precision => 2)
# => "$12.00"

যেমনটি ডিলান মার্কো পোস্ট করেছেন


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.