I would like to hide a text field based on a date field on an access form. The use will enter a date in the field when they leave, but blank if they are current. I display two dates for years of service (current and after they leave).
Private Sub Form_Current()
If IsNull(DateEnd) Then
Me.YearsOfSeriviceEND.Visible = False
Else
Me.YearsOfSeriviceEND.Visible = True
End If
This does not hide the field, YearsOfSeriviceEND. I'm not sure if this is not working because the field is a date?
Dennis
Related
Is there any chance to add field "Inv. recpt date" to Payment block in Miro tcode so that the user could select "Inv. recpt date" instead of "Baseline Date". Is there any BAdi or BAPI?
There is no direct and straightforward way to add fields to MIRO payment tab, you can only add to details one (check LFDCB001 enhancement).
However you can change payment tab values on-the-fly to whatever you need via MRM_PAYMENT_TERMS BAdI. For changing baseline date in PAYMENT_TERMS_SET method put something like this:
DATA: h_drseg TYPE mmcr_drseg,
h_reindat TYPE RBKP-REINDAT.
LOOP AT ti_drseg INTO h_drseg WHERE selkz = 'X'.
SELECT SINGLE budat FROM ekbe INTO h_reindat WHERE
ebeln = h_drseg-ebeln AND
ebelp = h_drseg-ebelp AND
lfbnr = h_drseg-lfbnr AND
lfgja = h_drseg-lfgja AND
lfpos = h_drseg-lfpos AND
vgabe = '2'.
CHECK sy-subrc = 0.
e_zfbdt = h_reindat.
EXIT.
ENDLOOP.
Here h_reindat is an "Inv. recpt date" which is assigned to baseline date in runtime.
If you want anyway to make it visible in UI for manual entry, I recommend to stick to standard approach described here: How to activate Invoice Receipt Date in document header for any company
It will be put on the MIRO basic tab and then value is copied to baseline date on payment tab.
For your reference: SAP Note 1156325 - BAdIs in the Logistics Invoice Verification environment
So I have a couple forms. In the parent form, I collect information about a User and include a UserID field. Additionally in the parent form, there are several buttons that a data-enterer can click dictating several different categories.
When the data-enterer clicks on a category button, the engine opens a child UserCategory form. I've included logic in the On-Click event of the button (as well as the On-Open event of the child form) such that the UserID value is passed from the parent form record, and the CategoryID value is determined by the button clicked and is also passed to the child form. The combination of UserID and CategoryID is unique for the underlying UserCategory table in question and represents a key of the table, however, the primary key is another field -- UserCategoryID (which has a 1:1 relationship between the combination of UserID and CategoryID).
A requirement, then, is that if the form receives a combination of UserID and CategoryID that is already in the table, then the form should reference that record. However, the form will go ahead and create a new record when its given values that are already represented. I've encountered this problem before when creating related forms, and the problem arose because the table wasn't respecting the 1:1 relationship between the FK and the PK of the related table. In all cases, I was able to fix the problem by enforcing a 1:1 relationship using the Relationships Database Tool. However, in this scenario, a user can belong to multiple categories and a category can have multiple users -- in other words, the UserID field is 1:M and the CategoryID field is 1:M, but their combo is 1:1. I don't know if there's a way to enforce this relationship.
One potential solution I've thought of is to build a query in the On-Open event of a form. It will use the UserID and CategoryID to select the UserCategoryID from the table, which will then be fed into the field on the form. I've included my initial thoughts on the design of the query. Please excuse the syntax -- VBA beginner.
Any help is appreciated
EDIT -- Logic on the passer side:
Private Sub FLower_Click()
Dim catType As Integer
catType = 2
DoCmd.OpenForm "frm_RespondentUseCat", OpenArgs:=2
End Sub
Logic on the Passee side
Private Sub Form_Open(Cancel As Integer)
Dim catType As Integer
catType = Forms.frm_RespondentUseCat!OpenArgs
Dim userID As Integer
userID = Forms!Respondent.RespondentID.Value
Dim strSQL As String
strSQL = "SELECT * From RespondentUseCategories WHERE RespondentID = " & userID & " AND UseCategoryID = " & catType & ";"
Dim results As DAO.Recordset
Set results = CurrentDb.OpenRecordset(strSQL)
If results.RecordCount > 0 Then
Set Forms("frm_RespondentUseCat").Recordset = results
Else
Me.UseCategoryID.Value = catType
Me.RespondentID.Value = userID
End If
End Sub
Essentially the passer (i.e. the parent form with the button) will simply pass the category type reflecting what button was clicked. On the passee side, the form will execute some code on the event that it is opened. First it will collect the category type, then it will attempt to read the userID (RespondentID) value from the parent form (Respondent). Then it will use those two values to get the relevant record from the UserCategory table (RespondentUseCategories). If there is any data here, then we use that as the recordset for the form, and if not, we populate the userID and categoryID with the collected values and let the UserCateogryID autopopulated itself. This seems like the correct approach, however, when I tried the test-case where the record exists (e.g. an already encountered combo of User & Category IDS), the child form remains unpopulated. I'm guessing theres a bug in the VBA.
create a dual key on the UserCategory table using UserID and CategoryID as shown here:
https://www.access-programmers.co.uk/forums/threads/how-to-put-two-primary-keys-in-one-table.225908/
Now Access will throw an error if anyone finds a way to try and add a non unique combinations of UserID and CategoryID. Next using the designer I expect you will get something like:
note textboxes have been replaced with comboboxes and the UsersForm is all header because the subform shows the details. The Userform record source is Users & the subform record source is UserCategory. The form and subform are linked by UserID only. At this point access throws an error if someone trys to enter a non unique combination of user and category, but I don't want to be able to enter incorrect data so I came up with the following:
under the data properties of the UserCategorysForm set both allow dataentry and allow additions to no so the data enterer must use the buttons to add records then set the buttons to add a user/category combination if it doesn't exist and delete that combination if it does.
Private Sub cmbUserName_AfterUpdate()
Me.Filter = "UserID = " & Me.cmbUserName.Value
Me.FilterOn = True
End Sub
'TODO ADD CODE TO CHANGE BUTTON CAPTION BASED ON WHETHER BUTTON WILL ADD OR REMOVE CATEGORY
Private Sub cmdCommand_Click()
AddRemoveRecordFromUserCategoryTable 1
End Sub
Private Sub cmdScience_Click()
AddRemoveRecordFromUserCategoryTable 2
End Sub
Private Sub AddRemoveRecordFromUserCategoryTable(ID As Integer)
DoCmd.SetWarnings False
If IsNull(DLookup("UserCategoryID", "UserCategory", "UserID = " & Me.cmbUserName.Value & " AND CategoryID = " & ID)) Then
DoCmd.RunSQL ("INSERT INTO UserCategory (UserID, CategoryID) VALUES(" & Me.cmbUserName.Value & ", " & ID & ")")
Else
DoCmd.RunSQL ("DELETE * FROM UserCategory WHERE UserID = " & Me.cmbUserName.Value & " AND CategoryID = " & ID)
End If
DoCmd.SetWarnings True
Me.Refresh
End Sub
now the form checks to see if the user/category combination is already in the table before adding it and instead removes the record preventing duplicate combinations from being added. hitting command removes the record (not shown). hitting science adds a record.
I have two models a parent and the son contains two float fields
one of the values this calculates according to the other but when I change the father how can be my calculating function.
Here is my example:
class A(models.model):
trv_ids = fields.One2many(classB,id_A)
class B(models.model):
id_A = fields.Many2one(classA)
qtite = fields.float(default=0)
qtite1 = fields.float(default=0,compute=?????)
qtite1 gets the value of qtite when I change parent
as the example of cumulated amount becomes previous quantity the next month.
Thanks
If i understood right i think what you need is something like this:
#api.depends('id_A')
def _compute_qtie1(self):
for record in self:
record.qtite1 = record.qtite
qtite1 = fields.float(compute=_compute_qtie1, store=True)
The depends is what triggers (any time you change the id_A field in the record) the compute method, if you dont store it in the DB it will re-calculate every time you open a view that contains the record.
I'm making a module for reservations in Odoo 9 and one field of my model is populated based if it's reserved or no. Basically my model is:
class Reservation(models.Model):
....
room_id = fields.Many2one('reservation.room', string="Room")
I've defined an onchange function that return a domain to filter the room_ids that aren't reserved:
#api.onchange('date')
def _set_available_room(self):
.....
return {'domain': {'room_id': [('id', 'in', res)]}}
This works fine and when I set the date, the rooms are filtered ok. My problem is when I save a reservation and enter again to edit it. The room_id field show all values and only when I change the date the room_id is filtered.
I've tried using the domain attribute in the field definition like this, but it doesn't works:
room_id = fields.Many2one('reservation.room', string="Room", domain=lambda self: self._get_available_slots())
How can I filter this field on the load view using my function than search for available rooms?
I have a mails table which is my main tables for manipulating mails. I also have mails_sent and mails_dates which has FK connecting them with mails and contain data as follows mails_dates - a single mail could have more than one date set for sending so I have realtion 1:N where N are all the dates set from the user for the mail to be send and mails_sent - after a mail is sent a new record is added in this table with the id of the mail and the date it was sent. Because as I mentioned a mail could be sent more than once here the relation is also 1:N where N here represents the different dates when a mail was sent.
I need to show this info in a UI. First I had to show only the sending dates and I user this:
$this->db->select("mails.id, mails.subject, mails.dt_created, mails.groups");
$this->db->select("GROUP_CONCAT(DATE_FORMAT( mails_dates.dt_sending_date, '%d-%m-%Y')) AS sending_dates", FALSE );
$this->db->join('mails_dates','mails_dates.mail_id = mails.id', 'left');
$this->db->join('mails_sent','mails_sent.mail_id = mails.id', 'left');
$this->db->from('mails');
$this->db->group_by('mails.id');
$res = $this->db->get()->result_array();
return $res;
When I was using this everything was fine I was getting a string with all the dates in it. But the problem is when I try to get the dates when a mail was sent. I added one more select:
$this->db->select("GROUP_CONCAT(DATE_FORMAT( mails_sent.dt_sent, '%d-%m-%Y')) AS sent_dates", FALSE );
making my query looks like this:
$this->db->select("mails.id, mails.subject, mails.dt_created, mails.groups");
$this->db->select("GROUP_CONCAT(DATE_FORMAT( mails_sent.dt_sent, '%d-%m-%Y')) AS sent_dates", FALSE );
$this->db->select("GROUP_CONCAT(DATE_FORMAT( mails_dates.dt_sending_date, '%d-%m-%Y')) AS sending_dates", FALSE );
$this->db->join('mails_dates','mails_dates.mail_id = mails.id', 'left');
$this->db->join('mails_sent','mails_sent.mail_id = mails.id', 'left');
$this->db->from('mails');
$this->db->group_by('mails.id');
$res = $this->db->get()->result_array();
return $res;
But the problem is that If sending_dates contains let's say - 6 values, and sent_dates has only one I end up with a string containing 6 times the value of sent_dates. This is in production so I don't have a lot of records but the same happens with a query where I have 2 sending_dates and 1 record for sent_dates still I get 2 times the record from sent_dates.
How can I fix this?
Thanks
Leron
Ok, I found the solution, here it is:
$this->db->select("GROUP_CONCAT(DISTINCT(DATE_FORMAT(mails_sent.dt_sent, '%d-%m-%Y'))) AS sent_dates", FALSE );
In other words just use DISTINCT.