I am trying to save money format in laravel 5.1.
Here is table price define:
$table->decimal(price,6,2);
For instance ; when 1.000,50 Turkish Liras saving to MySQL this format 1.00
How can solve this issue?
You can try defining your price like this
$table->decimal('price',9,3);
Where,
9 is the precision, ie 1234567.89 has a precision of 9
3 is the number of decimal places, ie 123456.789 has a scale of 3
In other words, if we use less decimal-places than 3, we can use remaining for real-number places.
You can refer to this link for about precision and scale of database
How do I interpret precision and scale of a number in a database?
I would suggest not using a float value to store currency as decimals, since floats don't act exactly as you would expect them to, due to the way they are stored in the system.
You would be much better off storing the value in "kuruş" (the subunit of Turkish Lira), as it will be much, much easier in the long run.
In other words, storing the lowest unit you think will be ever required, like storing Centi-meters instead of Meters (Centi is originally Greekish name for "0.01" number).
Secondly, if you're using Eloquent you can use mutators/accessors on the Model e.g.
public function getPriceAttribute($price)
{
return $price / 100;
}
public function setPriceAttribute($price)
{
$this->attributes['price'] = $price * 100;
}
That way you don't have to manually convert the price.
Update
If you're using Laravel 9 or above, you can use the new Attribute syntax instead:
use Illuminate\Database\Eloquent\Casts\Attribute;
protected function price(): Attribute
{
return Attribute::make(
get: fn ($price) => $price / 100,
set: fn ($price) => $price * 100,
);
}
Illuminate blueprints do not support money columns. AFAIK, the money column type itself is only supported in a couple of DBMSes.
What you can do is issue an ALTER TABLE statement to the database after the initial CREATE statement:
Schema::create('my_table', function(Blueprint $table) {
$table->decimal('my_money_column', 999, 2);
// ... the rest of the column definitions
});
DB::statement("
ALTER TABLE my_table ALTER COLUMN my_money_column
SET DATA TYPE MONEY;
");
Beware, though, as this will (probably) break cross-DBMS compatibility of your migration scripts.
Related
I am trying to create a EA in mql4, but in OrderSend function, when i use some value instead of zero it show ordersend error 130. Please help to solve this problem
Code line is
int order = OrderSend("XAUUSD",OP_SELL,0.01,Bid,3,Bid+20*0.01,tp,"",0,0,Red);
error number 130 means Invalid stops.
so that means there is a problem with the stops you set with the ordersend function.
I suggest you set it like that:
int order = OrderSend("XAUUSD",OP_SELL,0.01,Bid,3,Bid+20*Point,tp,"",0,0,Red);
so you could use Point instead of hard coding it.
and to check what is the error number means. I think you could refer to: https://book.mql4.com/appendix/errors
You should know that there exists a minimum Stop Loss Size (mSLS) given in pips. "mSLS" changes with the currency and broker. So, you need to put in the OnInit() procedure of your EA a variable to get it:
int mSLS = MarketInfo(symbol,MODE_STOPLEVEL);
The distance (in pips) from your Order Open Price (OOP) and the Stop-Loss Price (SLP) can not be smaller than mSLS value.
I will try to explain a general algorithm I use for opening orders in my EAs, and then apply the constrain on Stop-Loss level (at step 3):
Step 1. I introduce a flag (f) for the type of operation I will open, being:
f = 1 for Buy, and
f = -1 for Sell
You know that there are mql4 constants OP_SELL=1 and OP_BUY=0 (https://docs.mql4.com/constants/tradingconstants/orderproperties).
Once I have defined f, I set my operation type variable to
int OP_TYPE = int(0.5((1+f)*OP_BUY+(1-f)*OP_SELL));
that takes value OP_TYPE=OP_BUY when f=1, while OP_TYPE=OP_SELL when f=-1.
NOTE: Regarding the color of the orders I put them in an array
color COL[2]= {clrBlue,clrRed};
then, having OP_TYPE, I set
color COLOR=COL[OP_TYPE];
Step 2. Similarly, I set the Order Open Price as
double OOP = int(0.5*((1+f)*Ask+(1-f)*Bid));
which takes value OOP=Ask when f=1, while OOP=Bid when f=-1.
Step 3. Then, given my desired Stop Loss in pips (an external POSITIVE parameter of my EA, I named sl) I make sure that sl > SLS. In other words, I check
if (sl <= mSLS) // I set my sl as the minimum allowed
{
sl = 1 + mSLS;
}
Step 4. Then I calculate the Stop-Loss Price of the order as
double SLP = OOP - f * sl * Point;
Step 5. Given my desired Take Profit in pips (an external POSITIVE parameter of my EA, I named tp) I calculate the Take-Profit Price (TPP) of the order as
double TPP = OOP + f * tp * Point;
OBSERVATION: I can not affirm, but, according to mql4 documentation, the minimum distance rule between the stop-loss limit prices and the open price also applies to the take profit limit price. In this case, a "tp" check-up needs to be done, similar to that of the sl check-up, above. that is, before calculating TPP it must be executed the control lines below
if (tp <= mSLS) // I set my tp as the minimum allowed
{
tp = 1 + mSLS;
}
Step 5. I call for order opening with a given lot size (ls) and slippage (slip) on the operating currency pair (from where I get the Ask and Bid values)
float ls = 0.01;
int slip = 3; //(pips)
int order = OrderSend(Symbol(),OP_TYPE,ls,OOP,slip,SLP,TPP,"",0,0,COLOR);
Note that with these few lines it is easy to build a function that opens orders of any type under your command, in any currency pair you are operating, without receiving error message 130, passing to the function only 3 parameters: f, sl and tp.
It is worth including in the test phase of your EA a warning when the sl is corrected for being less than the allowed, this will allow you to increase its value so that it does not violate the stop-loss minimum value rule, while you have more control about the risk of its operations. Remember that the "sl" parameter defines how much you will lose if the order fails because the asset price ended up varying too much in the opposite direction to what was expected.
I hope I could help!
Whilst the other two answers are not necessarily wrong (and I will not go over the ground they have already covered), for completeness of answers, they fail to mention that for some brokers (specifically ECN brokers) you must open your order first, without setting a stop loss or take profit. Once the order is opened, use OrderModify() to set you stop loss and/or take profit.
I have a column that contain double value 42.2223. I want to truncate the last four digits of this particular column.
Can any one please provide hive UDF for this particular scenario?
If you want to truncate the last four digits and get an integer, you can use the built-in functions floor(double a) or ceiling(double a), depending on the the kind of rounding (upper or lower) that you want.
If you wanted your double to be truncated to d decimal places (and get a double, instead of an integer), you could use round(double a, int d).
EDITED
In order to round without truncating, you can use this
CAST((column * 100) AS int)/100
Wrote an UDF for the above question where we can specify number of characters it can be truncated
package com.hive.udf.truncate;
import java.math.BigDecimal;
import org.apache.hadoop.hive.ql.exec.UDF;
public class Trunc extends UDF {
public double evaluate(double input,int numberOfDecimals){
if ( input > 0) {
return new BigDecimal(String.valueOf(input)).setScale(numberOfDecimals, BigDecimal.ROUND_FLOOR).doubleValue();
}
else {
return new BigDecimal(String.valueOf(input)).setScale(numberOfDecimals, BigDecimal.ROUND_CEILING).doubleValue();
}
}
}
I am using Dentaku gem to solve little complex expressions like basic salary is 70% of Gross salary. As the formulas are user editable so I worked on dentaku.
When I write calculator = Dentaku::Calculator.new to initialize and then enter the command calculator.evaluate("60000*70%") then error comes like below:
Dentaku::ParseError: Dentaku::AST::Modulo requires numeric operands
from /Users/sulman/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/dentaku-2.0.8/lib/dentaku/ast/arithmetic.rb:11:in `initialize'
I have array is which formula is stored like: ["EarningItem-5","*","6","7","%"] where EarningItem-5 is an object and has value 60000
How can I resolve such expressions?
For this particular case you can use basic_salary = gross_salary * 0.7
Next you need to create the number field in your views which accepts 0..100 range. At last, set up the after_save callback and use this code:
model
after_create :percent_to_float
protected
def percent_to_float
self.percent = percent / 100.0
self.save
end
edit:
Of course, you can simply use this formula without any callbacks:
basic_salary = gross_salary / 100.0 * 70
where 70 is user defined value.
Dentaku does not appear to support "percent". Try this instead
calculator.evaluate('60000 * 0.7')
I am generating a unique and random alphanumeric string segment to represent certain links that will be generated by the users. For doing that I was approaching with "uuid" number to ensure it's uniqueness and randomness, but, as per my requirements the string shouldn't be more than 5 characters long. So I dropped that idea.
Then I decided to generate such a string using random function of ruby and current time stamp.
The code for my random string goes like this:-
temp=DateTime.now
temp=temp + rand(DateTime.now.to_i)
temp= hash.abs.to_s(36)
What I did is that I stored the current DateTime in a temp variable and then I generated a random number passing the current datetime as parameter. Then in the second line actually added current datetime and random number together to make a unique and random string.
Soon I found,while I was testing my application in two different machines and send the request at the same time, it generated the same string(Though it's rare) once after more than 100 trials.
Now I'm thinking that I should add one more parameter like mac address or client ip address before passing to_s(36) on temp variable. But can't figure out how to do it and even then whether it will be unique or nor...
Thanks....
SecureRandom in ruby uses process id (if available) and current time. You can use the urlsafe_base64(n= 16) class method to generate the sequence you need. According to your requirements I think this is your best bet.
Edit: After a bit of testing, I still think that this approach will generate non-unique keys. The way I solved this problem for barcode generation was:
barcode= barcode_sql_id_hash("#{sql_id}#{keyword}")
Here, your keyword can be time + pid.
If you are certain that you will never need more than a given M amount of unique values, and you don't need more than rudimentary protection against guessing the next generated id, you can use a Linear Congruentual Generator to generate your identificators. All you have to do is remember the last id generated, and use that to generate a new one using the following formula:
newid = (A * oldid + B) mod M
If 2³² distinct id values are enough to suit your needs, try:
def generate_id
if #lcg
#lcg = (1664525 * #lcg + 1013904223) % (2**32)
else
#lcg = rand(2**32) # Random seed
end
end
Now just pick a suitable set of characters to represent the id in as little as 6 character. Uppercase and lowercase letters should do the trick, since (26+26)^6 > 2^32:
ENCODE_CHARS = [*?a..?z, *?A..?Z]
def encode(n)
6.times.map { |i|
n, mod = n.divmod(ENCODE_CHARS.size)
ENCODE_CHARS[mod]
}.join
end
Example:
> 10.times { n = generate_id ; puts "%10d = %s" % [n, encode(n)] }
2574974483 = dyhjOg
3636751446 = QxyuDj
368621501 = bBGvYa
1689949688 = yuTgxe
1457610999 = NqzsRd
3936504298 = MPpusk
133820481 = PQLpsa
2956135596 = yvXpOh
3269402651 = VFUhFi
724653758 = knLfVb
Due to the nature of the LCG, the generated id will not repeat until all 2³² values have been used exactly once each.
There is no way you can generate a unique UUID with only five chars, with chars and numbers you have a basic space of around 56 chars, so there is a max of 56^5 combinations , aprox 551 million (Around 2^29).
If with this scheme you were about to generate 10.000 UUIDs (A very low number of UUIDs) you would have a probability of 1/5.000 of generating a collision.
When using crypto, the standard definition of a big enough space to avert collisions is around 2^80.
To put this into perspective, your algorithm would be better off if it generated just a random integer (a 32 bit uint is 2^32, 8 times the size you are proposing) which is clearly a bad idea.
I am storing a cost in my application. The cost is not formatted in the database. For example: 00.00 saves as 0, 1.00 saves as 1, and 40.50 saves as 40.5
I need to read these values from the database and convert them to strings for dollars and cents. For example: 0 --> cost_dollars = "00" & cost_cents = "00", 1 --> cost_dollars = "01" & cost_cents = "00", 40.5 --> cost_dollars = "40" & cost_cents = "50".
Is there an easy way to do this in ruby on rails? Or does someone have code that does this?
Thanks!
You can accomplish that with this little bit of Ruby code:
fmt = "%05.2f" % cost
cost_dollars, cost_cents = fmt.split '.'
If you're trying to format dollar values in a view, you should look at number_to_currency in ActionView::Helpers::NumberHelper.
>> bd = BigDecimal.new "5.75"
>> include ActionView::Helpers
>> number_to_currency(bd)
=> "$5.75"
As for breaking up the value into separate dollars and cents, my first question would be, "Why?" If you have a good reason, and you're dealing with decimals in your database, then you could do the following.
>> bd = BigDecimal.new "5.75"
>> "dollars:#{bd.truncate} cents:#{bd.modulo(1) * BigDecimal.new('100')}"
=> "dollars:5.0 cents:75.0"
number_to_currency is nice, but it can get expensive; you might want to roll your own if you need to call it a lot.
You should be aware that using a float to store currency can be problematic (and see) if you do a lot of calculations based on these values. One solution is to use integers for currency and count cents. This appears to be the approach used by the money plugin. Another solution is to use a decimal type in your migration, which should work out-of-the-box for modern versions of Rails (> 1.2):
add_column :items, :price, :decimal, :precision => 10, :scale => 2
(:scale is the number of places past the decimal, :precision is the total number of digits.) This will get you BigDecimal objects in Rails, which are a little harder to work with, but not too bad.
Both the integer and decimal approaches are a little slower than floating point. I'm using floats for currency in some places, because I know I won't need to do calculations on the values within Rails, only store and display them. But if you need accurate currency calculations, don't use floats.
Instead of storing as a decimal, store as an integral number of cents. So 1 dollar is stored as 100 in the database.
Alternatively, if you don't mind a bit of performance overhead, check for '.' in the database's value. If it exists, split on '.', and parse the pieces as integers.
sprintf is your friend here:
cost_dollars = sprintf('%02.f', cost)
cost_cents = sprintf('%.2f', cost)