=====
apply
=====

.. py:method:: apply(self, connection=None, params=None, safe=False):

**domain**: server

**language**: python

**class** :doc:`Item class </refs/server/item_api>`

Description
===========

Writes all updated, inserted, and deleted records from the item dataset to the 
database.

The ``apply`` method

* checks whether the item is a detail, and if it is, returns (the master saves the
  details changes)

* checks whether the item is in edit or insert 
  :doc:`state <at_item_state>`
  , and if so, posts the record
  
* checks if the change log has changes, and if not, returns

* triggers the ``on_before_apply`` event handler if one is defined for the item 
  
* if ``connection`` parameter is ``None`` the task 
  :doc:`connect </refs/server/task/m_connect>` method is called to get a connection
  from task connection pool

* if ``on_apply`` event handler of the task is defined, executes it

* if 
  :doc:`on_apply </refs/server/item/on_apply>`
  event handler is defined for the item, executes it
  
* generates and executes SQL query to write changes to the database using the 
  connection

* if ``connection`` parameter was not specified, commits changes to the database and
  returns connection to the connection pool
  
* after writing changes to the database, updates the change log and the item dataset
  - updates primary key values of new records

* triggers the ``on_after_apply`` event handler if one is defined for the item 
  
Parameters
----------

* ``connection`` - if this parameter is specified the appication uses it to 
  execute sql query that it generates (it doesn't commit changes and doesn't
  close the connection), otherwise it procures a connection from the task connection 
  pool that will be returned to the pool after changes are commited.

* ``params`` - use the parameter to pass some user defined options to be used in
  the 
  :doc:`on_apply <on_apply>`
  event handler. This parameter must be an object of key-value pairs
  
* ``safe`` - if set to ``True``, the method checks if the user that called the
  method has a right to create, edit or delete records in the item's database 
  table (if such operation is going to be performed) and, if not, raises 
  an exception. The default value is ``False``.
  See 
  :doc:`Roles </admin/roles>`
  

Examples
========

In the second example below, the changes are saved in one transaction.

.. code-block:: py

  def change_invoice_date(item, item_id):
      inv = item.copy()
      cust = item.task.customers.copy()
      inv.set_where(id=item_id)
      inv.open()
      if inv.record_count():
          now = datetime.datetime.now()
          cust.set_where(id=inv.customer.value)
          cust.open()
  
          inv.edit()
          inv.invoice_datetime.value = now
          inv.post()
          inv.apply()
          
          cust.edit()
          cust.last_action_date.value = now
          cust.post()
          cust.apply()

.. code-block:: py

  def change_invoice_date(item, item_id):
      con = item.task.connect()
      try:
          inv = item.copy()
          cust = item.task.customers.copy()
          inv.set_where(id=item_id)
          inv.open()
          if inv.record_count():
              now = datetime.datetime.now()
              cust.set_where(id=inv.customer.value)
              cust.open()
  
              inv.edit()
              inv.invoice_datetime.value = now
              inv.post()
              inv.apply(con)
              
              cust.edit()
              cust.last_action_date.value = now
              cust.post()
              cust.apply(con)
      finally:
          con.commit()
          con.close()    

See also
========

:doc:`Modifying datasets </programming/data/modifying_datasets>`