How to get value of form field and past it to another form field - yii

I am developing HR system, I want to calculate how many days off the employee can take.
In the HR table I have three attributes.
1- start_date(when the employee starting to work in the company).
2- leavestaken(how many days off the employee took before).
3- leaves(the number of days available for the employee to take off) which equal to=(months between current date and start_date) * 2.5(beacuse each month give 2.5 days off) - leavestaken
third attribute is automated and not from the user, how I can get the first and second attributive values from field forms, use them in the calculation and save the result in the leaves attribute?
I'm using sql and this only for server side

Server side:
If your start_date is unix timestamp:
if ($model->load(Yii::$app->request->post())) {
n_month = (time() - $model->leaves) / (30 * 24 * 60 * 60);
$model->leaves = ceil(n_month * 2.5) - $model->leavestaken;
# code...
//ceil : Because one day off is not complete, Rounds a number down to the nearest integer
But if it's not unix, you can use the date_diff() method or ...
You can do this in the model file, in the beforeSave or beforeValidate method.
You can use JavaScript to calculate the client side.

My solution was
if ($model->load(Yii::$app->request->post()) ) {
$date = date('m/d/Y');
$datetime1 = date_create($date);
$datetime2 = date_create($model->start_date);
// calculates the difference between DateTime objects
$interval = $datetime2->diff($datetime1);
$n_month= $interval->m + 12*$interval->y;
$model->leaves = ceil($n_month * 2.5) - $model->leavestaken;
$model->save();

Related

Left Join with same table and group by is returning duplicated tuples with reverse order

I'm trying to query a database(not owned by me) that contains the following columns :
NumEpoca (epoch), Turma(class), Dia (day - indicates day of the week),
Hora (hour - each value indicates a 30mins time, a 3h class generate 6 tuples),
Disciplina (course), TipoAula (type of class, theoretical or practical),
Sala (classroom)
This is basically a class schedule, so for a given Class, in the same day of the week I can have in one week a practical class and in the other a theoretical class.
Now, I want to get for a given day, the minimum and max hour (so I can calculate the starting and ending hour of the class), but I also want to get the classrooms for them, and I don't know at priori, if it's going to be a theoretical or practical class.
Also, certain classes are only practical, and some are only theoretical, so I just want 1 classroom.
The query I'm doing, gives me basically everything but
LectureDetails(beginDate=2020-05-26 15:30:00, endDate=2020-05-26 18:30:00, classroom=L_H1/G.0.08)
LectureDetails(beginDate=2020-05-26 15:30:00, endDate=2020-05-26 18:30:00, classroom=G.0.08/L_H1)
as you can see here, I get the same class (that starts and ends at the same hour, for the 2 classrooms Teo and Pract. But I only need 1 tuple for that day and I'm getting L_H1/G.0.08 and G.0.08/L_H1.
"SELECT a1.Dia,MIN(a1.Hora),MAX(a1.Hora),a1.Sala, a2.Sala FROM Aulas as a1 LEFT JOIN Aulas as a2 " +
"on a1.Sala <> a2.Sala and a1.Disciplina = a2.Disciplina and a1.NumEpoca = a2.NumEpoca and a1.Turma = a2.Turma " +
"and a1.Dia= a2.Dia and a1.Hora = a2.Hora " +
"where NumEpoca = ? AND Turma = ? AND Disciplina=? GROUP BY a1.Dia,a1.Sala,a2.Sala"
Thanks in advance.
You could have eliminated the mis-ordered results by using a1.Sala < a2.Sala instead of the inequality.
But that's not really the approach you want anyway. Try something like this:
SELECT Dia, MIN(Hora), MAX(Hora),
MIN(Sala),
CASE WHEN MIN(Sala) = MAX(Sala) THEN NULL ELSE MAX(Sala) END
FROM Aulas
WHERE NumEpoca = ? AND Turma = ? AND Disciplina = ?
GROUP BY Dia

SQL | Match Shop cash with Bank Cash

! - I'm not looking for paid software which will do this job (as too expensive)
We have an issue with cash management to match the values.
I have two SQL Tables, let's call it SHOP_CASH and BANK_CASH
1) The matching should be happens based on ShopName-CashAmount-Date.
2) Here I faced two issues
The cash should be round up to nearest £50, ideally, 12 400 and 12 499 should round up to 12 450, OR this just IDEAL is a match based on cash difference which less than 50, dry to match different value if the difference is less than 50, match them, but here is the question how to match the value up.. this is just the stupid ideas))??? Hmmm...stuck.
Dates, the shop can cash up a few days later, so need to join based on cash-up date (for example 2018-10-26) with bank date RANGE 2018-10-26 to (+7 days) 2018-11-02
Currently, I do not understand the possible way (logical) of matching in this circumstance. Any logical path of calculation/joining will be extremely appreciated
TRY:
Let's say I can join two tables by SHOPNAME - Cool
Then I will try to join by date, which potentially will be:
SELECT * FROM SHOP_CASH AS SC
LEFT JOIN BANK_CASH AS BC
ON SC.SHOP_NAME_SC = BC.SHOP_NAME_BC
AND SC.DATE_SC = (ANY DATE FROM SC.DATE_SC TO SC.DATE_SC (+7 DAYS) = TO DATE_BC - not sure how)
AND FLOOR(SC.CASH_SC / 50) * 50 = FLOOR(BC_CASH_BC / 50) * 50
P.S. For this project will be using the Google Big Query.
This is my (temporary solution)
WITH MAIN AS(SELECT
CMS.Store_name AS STORE_NAME,
CMS.Date AS SHOP_DATE,
CMB.ENTRY_DATE AS BANK_DATE,
SUM(CMS.Cash) AS STORE_CASH,
SUM(CMB.AMOUNT) AS BANK_CASH
FROM `store_data` CMS
LEFT JOIN `bank_data` AS CMB
ON CMS.store_name = CMB.STRAIGHT_LOOKUP
AND FLOOR(CMS.Cash / 50) * 50 = FLOOR(CMB.AMOUNT / 50) * 50
AND CAST(FORMAT_DATE("%F",CMB.ENTRY_DATE) AS STRING) > CAST(FORMAT_DATE("%F",CMS.Date) AS STRING)
AND CAST(FORMAT_DATE("%F",CMB.ENTRY_DATE) AS STRING) <= CAST(FORMAT_DATE("%F",DATE_ADD(CMS.Date, INTERVAL 4 day)) AS STRING)
GROUP BY STORE_NAME,SHOP_DATE,BANK_DATE)
SELECT
MAIN2.*
FROM (
SELECT
ARRAY_AGG(MAIN ORDER BY MAIN.SHOP_DATE ASC LIMIT 1)[OFFSET(0)] AS MAIN2
FROM
MAIN AS MAIN
GROUP BY MAIN.SHOP_DATE, MAIN.STORE_CASH)
this is quite interesting case.
You haven't provided any sample data so I'm not able to test it, but this may work. Some modification may be required since not sure about date format. Let me know if there is an issue.
SELECT * FROM SHOP_CASH AS SC
LEFT JOIN BANK_CASH AS BC
ON SC.SHOP_NAME_SC = BC.SHOP_NAME_BC
AND SC.DATE_SC BETWEEN BC.DATE_BC AND DATE_ADD(BC.DATE_BC, DAY 7)
AND trunc(SC.CASH_SC, -2) + 50 = trunc(BC.CASH_BC,2) + 50

LEFT JOIN include data

I have an application which handles school vacation. Unfortunately there are three kinds of different school vacations: Country wide, Federal State wide and City wide vacations. I store all the information in a table days, a table vacation_periods and a connection table slots:
days {
id:integer
date_value:date
}
slots {
id:integer
day_id:integer
vacation_period_id:integer
}
vacation_periods {
id:integer
starts_on:date
ends_on:date
name:string
country_id:integer
federal_state_id:integer
city_id:integer
}
I want to select all days within a specific time frame. Let's say Jan 1st of 2017 to Jan 31st of 2017. I can get those days with:
SELECT * FROM days WHERE date_value >= '2017-01-01' AND
date_value <= '2017-01-31';
But for my vacation calendar I don't just need the days but also the information which vacation_periods are within. Assuming I search for all vacation_periods which are in that time frame and which have
country_id == 1 or federal_state_id == 5 or city_id == 30
I've read about JOINS and LEFT JOINS which seem to be the solution to the problem. But I can't get everything together.
Is it possible to send one SQL request which returns all days within the requested time frame and the additional information if a vacation_period that fits the country_id == 1 or federal_state_id == 5 or city_id == 30 rule is connected via slots to each day. Including the name of that vacation_period?
If one request is not possible: Which is the quickest way to solve this within the database? How many requests? What kind of requests?
If possible I'd like to get a result in some kind of this form:
- date_value: "2017-01-01"
- date_value: "2017-01-02"
- date_value: "2017-01-03"
* vacation_period.id: 15
* vacation_period.name: "foobar"
- date_value: "2017-01-04"
* vacation_period.id: 15
* vacation_period.name: "foobar"
- date_value: "2017-01-05"
* vacation_period.id: 15
* vacation_period.name: "foobar"
- date_value: "2017-01-06"
- date_value: "2017-01-07"
...
The following query might give you the answer you are looking for:
SELECT * FROM days WHERE date_value >= '2017-01-01' AND date_value <='2017-01-31'
INNER JOIN slots ON days.id = slots.day_id
INNER JOIN vacation_periods ON vacation_periods.id = slots.vacation_period_id
I think you can get an unformatted version of what you want (that could be processed into a hierarchical output) with
CREATE TYPE vacation_authority AS ENUM
('COUNTY', 'FED-STATE', 'CITY');
/* not necessary, but cleans up the vacation_period table */
change to let vacation_period have only one id, and a new field authority of type vacation_authority. You can now make a primary key out of either the id field or (id, authority), depending on how the vacation data comes into the system.
SELECT date_value, vp.name, vp.id /* is the ID meaningful or arbitrary? */
FROM dates LEFT JOIN vacation_periods vp
WHERE date_value BETWEEN vp.starts_on AND vp.ends_on; -- inclusive range
Now if there are multiple holidays spanning a given date, this will be multiple records in the output. It's not clear what you want in this case.
None of the other answers was able to solve my problem but they let me to the solution so I'm grateful for them. Here's the solution:
SELECT days.date_value, slots.period_id, vacation_periods.name FROM days
LEFT OUTER JOIN slots ON (days.id = slots.day_id)
LEFT OUTER JOIN vacation_periods ON (slots.period_id = vacation_periods.id)
WHERE days.date_value >= '2017-01-05'
AND days.date_value <='2017-01-15'
AND (vacation_periods.id IS NULL
OR vacation_periods.country_id = 1
OR vacation_periods.federal_state_id = 5)
ORDER BY days.date_value;

Kettle Datedif month issue

I need to reproduce the kettle Datedif function in the R programming language. I need the 'datedif month' option. I thought reproducing would be pretty easy but I have some 'weird behaviour' in pentaho. As an example:
ID date_1 date_2 monthly_difference_kettle daydiff_mysql
15943 31/12/2013 28/07/2014 7 209
15943 31/12/2011 27/07/2012 6 209
So in pentaho kettle I used the formula-step and the function DATEDIF(date2,date1,"m"). As you can see when I calculate the daily difference in mysql I get for both records the same amount of days in difference (209), however, when the monthly difference is calculated via the formula step in pentaho kettle I get a different result in months (7 and 6 respectively). I don't understand how this is calculated...
Can anyone produce the source code for the 'DATEDIF months' function in pentaho? I would like to reproduce it in R so I get exactly the same results.
Thanks in advance,
best regards,
Not sure about mysql, but i think it is the same. In PostgreSQL date difference gives integer value (in days). It means both rows has total match in days.
Calculating month difference non trivial. What is month (28, 30, 31 day)? Shall we count if month is not full?
Documentation states If there is not a complete month between the dates, 0 will be returned
But according to source code easy to understand how calculated datedif:
Source code available via github https://github.com/pentaho/pentaho-reporting/blob/f7defbcfc0e8f48ad2b139fe9820445f052e0e78/libraries/libformula/src/main/java/org/pentaho/reporting/libraries/formula/function/datetime/DateDifFunction.java
private int addFieldLoop( final GregorianCalendar c, final GregorianCalendar target, final int field ) {
c.set( Calendar.MILLISECOND, 0 );
c.set( Calendar.SECOND, 0 );
c.set( Calendar.MINUTE, 0 );
c.set( Calendar.HOUR_OF_DAY, 0 );
target.set( Calendar.MILLISECOND, 0 );
target.set( Calendar.SECOND, 0 );
target.set( Calendar.MINUTE, 0 );
target.set( Calendar.HOUR_OF_DAY, 0 );
if ( c.getTimeInMillis() == target.getTimeInMillis() ) {
return 0;
}
int count = 0;
while ( true ) {
c.add( field, 1 );
if ( c.getTimeInMillis() > target.getTimeInMillis() ) {
return count;
}
count += 1;
}
}
Append 1 month to start date till it will become bigger then end date

Mean time to Failure calculation in DAX

I am trying to calculate the mean time to failure for each asset in a job table. At the moment I calculate as follows;
Previous ID = CALCULATE(MAX('JobTrackDB Job'[JobId]),FILTER('JobTrackDB Job','JobTrackDB Job'[AssetDescriptionID]=EARLIER('JobTrackDB Job'[AssetDescriptionID]) && 'JobTrackDB Job'[JobId]<EARLIER('JobTrackDB Job'[JobId])))
Then I bring back the last finish time for the current job when the JobStatus is 7 (closed);
Finish Time = CALCULATE(MAX('JobTrackDB JobDetail'[FinishTime]),'JobTrackDB JobDetail'[JobId],'JobTrackDB JobDetail'[JobStatus]=7)
Then I bring back the previous jobs finish time where the JobType is 1 (Response rather than comparing it to maintenance calls);
Previous Finish = CALCULATE(MAX('JobTrackDB Job'[Finish Time]),FILTER('JobTrackDB Job','JobTrackDB Job'[AssetDescriptionID]=EARLIER('JobTrackDB Job'[AssetDescriptionID]) && 'JobTrackDB Job'[Finish Time]<EARLIER('JobTrackDB Job'[Finish Time]) && EARLIER('JobTrackDB Job'[JobTypeID])=1))
Then I calculate the Time between failure where I also disregard erroneous values;
Time between failure = IF([Previous Finish]=BLANK(),BLANK(),IF('JobTrackDB Job'[Date Logged]-[Previous Finish]<0,BLANK(),'JobTrackDB Job'[Date Logged]-[Previous Finish]))
Issue is that sometimes the calculation uses previous maintenance jobs even though I specified JobTypeID = 1 in the filter. Also, the current calculation does not take into account the time from the start of records to the first job for that asset and also from the last job till today. I am scratching my head trying to figure it out.
Any ideas???
Thanks,
Brent
Some base measures:
MaxJobID := MAX( Job[JobID] )
MaxLogDate := MAX ( Job[Date Logged] )
MaxFinishTime := MAX (JobDetail[Finish Time])
Intermediate calculations:
ClosedFinishTime := CALCULATE ( [MaxFinishTime], Job[Status] = 7 )
AssetPreviousJobID := CALCULATE (
[MaxJobID],
FILTER(
ALLEXCEPT(Job, Table1[AssetDescriptionID]),
Job[JobId] < MAX(Table1[JobID])
)
)
PreviousFinishTime: = CALCULATE ( [ClosedFinishTime],
FILTER(
ALLEXCEPT(Job, Job[AssetDescriptionID]),
Job[JobId] < MAX(Job[JobID])
&& Job[JobType] = 1
)
)
FailureTime := IF (
ISBLANK([PreviousFinishTime]),
0,
( [MaxLogDate]-[PreviousFinishTime] )
)
This should at least get you started. If you want to set some sort of "first day", you can replace the 0 in the FailureTime with a calc like MaxLogDate - [OverallFirstDate], which could be a calculated measure or a constant.
For something that hasn't failed, you'd want to use an entirely different measure since this one is based on lookback only. Something like [Days Since Last Failure] which would just be (basically) TODAY() - [ClosedFinishTime]