"""Mapping classes for the DMD database
"""
from dmd import common
from sqlalchemy.orm import declarative_base
from sqlalchemy import (
    Column,
    Integer,
    String,
    Float,
    BigInteger,
    SmallInteger,
    ForeignKey,
    Date
)
from sqlalchemy.orm import relationship
from datetime import datetime

Base = declarative_base()


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def parse_date(date_str):
    """Parse a date string into a python datetime object
    """
    try:
        return datetime.strptime(date_str, "%Y-%m-%d")
    except TypeError:
        return None


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class FileInfo(Base):
    """A representation of the ``file_info`` table.

    Parameters
    ----------
    file_info_id : `int`
        auto-incremented index
    file_type : `str`
        The type of the file, there are a number of options. For the zipfiles
        it will be ``zip`` or ``bonus_zip``. For the XML files with will be
        either ``lookup``, ``ingredient``, ``vmp``, ``vmp``, ``vmpp``, ``amp``,
        ``ampp``.
    file_basename : `str`
        The file name without the path.
    file_version : `str`
        The file version extracted from the file name.
    file_date : `datetime.datetime`
        The file date extracted from the file name.

    Notes
    -----
    This is not a DM+D table and is added by the build script.
    """
    __tablename__ = 'file_info'

    file_info_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="auto-incremented index"
    )
    file_type = Column(
        String(255), nullable=False,
        doc="The type of the file, there are a number of options. For the zip"
        "files it will be ``zip`` or ``bonus_zip``. For the XML files with "
        "will be either ``lookup``, ``ingredient``, ``vmp``, ``vmp``, "
        "``vmpp``, ``amp``, ``ampp``."
    )
    file_basename = Column(
        String(255), nullable=False, doc="The file name without the path."
    )
    file_version = Column(
        String(255), nullable=False,
        doc="The file version extracted from the file name."
    )
    file_date = Column(
        Date, nullable=False,
        doc="The file date extracted from the file name."
    )

    # -------------------------------------------------------------------------#
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpCombPackInd(Base):
    """A representation of the ``lkp_comb_pack_ind`` table. This holds data
    from the XML node ``LOOKUP.COMBINATION_PACK_IND``.

    Parameters
    ----------
    comb_pack_ind_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file.
    comb_pack_ind_desc : `str`
        The combination pack description.

    Notes
    -----
    The combination pack indicator table, this contains code descriptions for
    actual medicinal product pack (AMPP) and virtual medicinal product pack
    (VMPP) combination indicator.
    """
    __tablename__ = 'lkp_comb_pack_ind'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'COMBINATION_PACK_IND'
    XML_MAPPINGS = dict(
        CD=('comb_pack_ind_cd', int),
        DESC=('comb_pack_ind_desc', str),
    )

    comb_pack_ind_cd = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file."
    )
    comb_pack_ind_desc = Column(
        String(60), nullable=False,
        doc="The combination pack description."
    )

    # -------------------------------------------------------------------------#
    vmp_pack_comb_pack_ind = relationship(
        'VirtMedProdPack',
        back_populates='comb_pack_ind'
    )
    ampp_comb_pack_ind = relationship(
        'ActMedProdPack',
        back_populates='comb_pack_ind'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpCombProdInd(Base):
    """A representation of the ``lkp_comb_prod_ind`` table. This holds data
    from the XML node ``LOOKUP.COMBINATION_PROD_IND``.

    Parameters
    ----------
    comb_prod_ind_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file.
    comb_prod_ind_desc : `str`
        The combination product description.

    Notes
    -----
    The combination product indicator table, this contains code descriptions
    for actual medicinal product (AMP) and virtual medicinal product (VMP)
    combination indicator.
    """
    __tablename__ = 'lkp_comb_prod_ind'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'COMBINATION_PROD_IND'
    XML_MAPPINGS = dict(
        CD=('comb_prod_ind_cd', int),
        DESC=('comb_prod_ind_desc', str),
    )

    comb_prod_ind_cd = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file."
    )
    comb_prod_ind_desc = Column(
        String(255), nullable=False,
        doc="The combination product description."
    )

    # -------------------------------------------------------------------------#
    vmp_comb_prod_ind = relationship(
        "VirtMedProd",
        back_populates='comb_prod_ind'
    )
    amp_comb_prod_ind = relationship(
        "ActMedProd",
        back_populates='comb_prod_ind'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpBasisOfName(Base):
    """A representation of the ``lkp_basis_of_name`` table. This holds data
    from the XML node ``LOOKUP.BASIS_OF_NAME``.

    Parameters
    ----------
    basis_name_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file.
    basis_name_desc : `str`
        The basis of name description.

    Notes
    -----
    Code descriptions for virtual medicinal product (VMP) name basis.
    """
    __tablename__ = 'lkp_basis_of_name'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'BASIS_OF_NAME'
    XML_MAPPINGS = dict(
        CD=('basis_name_cd', int),
        DESC=('basis_name_desc', str),
    )

    basis_name_cd = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file."
    )
    basis_name_desc = Column(
        String(150), nullable=False,
        doc="The basis of name description."
    )

    # -------------------------------------------------------------------------#
    virt_med_prod = relationship(
        'VirtMedProd',
        primaryjoin="LkpBasisOfName.basis_name_cd == "
        "VirtMedProd.basis_name_cd",
        back_populates='basis_name'
    )
    virt_med_prod_prev = relationship(
        'VirtMedProd',
        primaryjoin="LkpBasisOfName.basis_name_cd == "
        "VirtMedProd.basis_name_cd_prev",
        back_populates='basis_name_prev'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpNameChangeReason(Base):
    """A representation of the ``lkp_name_change_reason`` table. This holds
    data from the XML node ``LOOKUP.NAMECHANGE_REASON``.

    Parameters
    ----------
    name_change_reason_id : `int`
        The primary key, this is added by the build script and not the original
        primary key in the XML file. This is due to the original key starting
        at 0 and causing issues with MySQL auto-increment and SQLAchemy. For
        the original key see the ``_cd`` suffixed column.
    name_change_reason_cd : `int`
        A unique key, this column represents the primary key in the original
        XML file however because it incremented from 0 a surrogate primary key
        was created in the ``_id`` suffixed column.
    name_change_reason_desc : `str`
        The name change reason description.

    Notes
    -----
    Code descriptions for virtual medicinal product (VMP) name change reason.
    """
    __tablename__ = 'lkp_name_change_reason'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'NAMECHANGE_REASON'
    XML_MAPPINGS = dict(
        CD=('name_change_reason_cd', int),
        DESC=('name_change_reason_desc', str),
    )

    name_change_reason_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, this is added by the build script and not the"
        " original primary key in the XML file. This is due to the original "
        "key starting at 0 and causing issues with MySQL auto-increment and"
        " SQLAchemy. For the original key see the ``_cd`` suffixed column."
    )
    name_change_reason_cd = Column(
        Integer, nullable=False, unique=True,
        doc="A unique key, this column represents the primary key in the "
        "original XML file however because it incremented from 0 a surrogate "
        "primary key was created in the ``_id`` suffixed column."
    )
    name_change_reason_desc = Column(
        String(255), nullable=False,
        doc="The name change reason description."
    )

    # -------------------------------------------------------------------------#
    virt_med_prod = relationship(
        "VirtMedProd",
        back_populates='name_change_reason'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpVirtualProdPresStatus(Base):
    """A representation of the ``lkp_virtual_prod_pres_status`` table. This
    holds data from the XML node ``LOOKUP.VIRTUAL_PRODUCT_PRES_STATUS``.

    Parameters
    ----------
    pres_status_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file.
    pres_status_desc : `str`
        The virtual medicinal product prescribing status description.

    Notes
    -----
    Code descriptions for virtual medicinal product (VMP) prescribing status.
    """
    __tablename__ = 'lkp_virtual_prod_pres_status'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'VIRTUAL_PRODUCT_PRES_STATUS'
    XML_MAPPINGS = dict(
        CD=('pres_status_cd', int),
        DESC=('pres_status_desc', str),
    )

    pres_status_cd = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file."
    )
    pres_status_desc = Column(
        String(255), nullable=False,
        doc="The virtual medicinal product prescribing status description."
    )

    # -------------------------------------------------------------------------#
    virt_med_prod = relationship(
        "VirtMedProd",
        back_populates='pres_status'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpControlDrugCat(Base):
    """A representation of the ``lkp_control_drug_cat`` table. This holds data
    from the XML node ``LOOKUP.CONTROL_DRUG_CATEGORY``.

    Parameters
    ----------
    cont_drug_cat_id : `int`
        The primary key, this is added by the build script and not the original
        primary key in the XML file. This is due to the original key starting
        at 0 and causing issues with MySQL auto-increment and SQLAchemy. For
        the original key see the ``_cd`` suffixed column.
    cont_drug_cat_cd : `int`
        A unique key, this column represents the primary key in the original
        XML file however because it incremented from 0 a surrogate primary key
        was created in the ``_id`` suffixed column.
    cont_drug_cat_desc : `str`
        The controlled drug category description.

    Notes
    -----
    Code descriptions for the virtual medicinal product (VMP) controlled drug
    information.
    """
    __tablename__ = 'lkp_control_drug_cat'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'CONTROL_DRUG_CATEGORY'
    XML_MAPPINGS = dict(
        CD=('cont_drug_cat_cd', int),
        DESC=('cont_drug_cat_desc', str),
    )

    cont_drug_cat_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, this is added by the build script and not the"
        " original primary key in the XML file. This is due to the original "
        "key starting at 0 and causing issues with MySQL auto-increment and"
        " SQLAchemy. For the original key see the ``_cd`` suffixed column."
    )
    cont_drug_cat_cd = Column(
        Integer, nullable=False, unique=True,
        doc="A unique key, this column represents the primary key in the "
        "original XML file however because it incremented from 0 a surrogate "
        "primary key was created in the ``_id`` suffixed column."
    )
    cont_drug_cat_desc = Column(
        String(255), nullable=False,
        doc="The controlled drug category description."
    )

    # -------------------------------------------------------------------------#
    cont_drug_info = relationship(
        'ContDrugInfo',
        primaryjoin="LkpControlDrugCat.cont_drug_cat_cd == "
        "ContDrugInfo.cont_drug_cat_cd",
        back_populates='cont_drug_cat'
    )
    cont_drug_info_prev = relationship(
        'ContDrugInfo',
        primaryjoin="LkpControlDrugCat.cont_drug_cat_cd == "
        "ContDrugInfo.cont_drug_cat_cd_prev",
        back_populates='cont_drug_cat_prev'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpLicenceAuth(Base):
    """A representation of the ``lkp_licence_auth`` table. This holds data from
    the XML node ``LOOKUP.LICENSING_AUTHORITY``.

    Parameters
    ----------
    lic_auth_id : `int`
        The primary key, this is added by the build script and not the original
        primary key in the XML file. This is due to the original key starting
        at 0 and causing issues with MySQL auto-increment and SQLAchemy. For
        the original key see the ``_cd`` suffixed column.
    lic_auth_cd : `int`
        A unique key, this column represents the primary key in the original
        XML file however because it incremented from 0 a surrogate primary key
        was created in the ``_id`` suffixed column.
    lic_auth_desc : `str`
        The licensing authority description.

    Notes
    -----
    Code descriptions the actual medicinal product (AMP) licensing authority.
    """
    __tablename__ = 'lkp_licence_auth'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'LICENSING_AUTHORITY'
    XML_MAPPINGS = dict(
        CD=('lic_auth_cd', int),
        DESC=('lic_auth_desc', str),
    )

    lic_auth_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, this is added by the build script and not the"
        " original primary key in the XML file. This is due to the original "
        "key starting at 0 and causing issues with MySQL auto-increment and"
        " SQLAchemy. For the original key see the ``_cd`` suffixed column."
    )
    lic_auth_cd = Column(
        Integer, nullable=False, unique=True,
        doc="A unique key, this column represents the primary key in the "
        "original XML file however because it incremented from 0 a surrogate "
        "primary key was created in the ``_id`` suffixed column."
    )
    lic_auth_desc = Column(
        String(255), nullable=False,
        doc="The licensing authority description."
    )

    # -------------------------------------------------------------------------#
    act_med_prod = relationship(
        'ActMedProd',
        primaryjoin="LkpLicenceAuth.lic_auth_cd == ActMedProd.lic_auth_cd",
        back_populates='lic_auth'
    )
    act_med_prod_prev = relationship(
        'ActMedProd',
        primaryjoin="LkpLicenceAuth.lic_auth_cd == ActMedProd.lic_auth_cd_prev",
        back_populates='lic_auth_prev'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpUnitMeasure(Base):
    """A representation of the ``lkp_unit_measure`` table. This holds data from
    the XML node ``LOOKUP.UNIT_OF_MEASURE``.

    Parameters
    ----------
    unit_meas_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file. Apparently it is a SNOMED code up to 18 digits long.
    unit_meas_cd_date : `datetime.datetime`
        The date the code is applicable from.
    unit_meas_cd_prev : `int`
        Previous code, up to 18 digits.
    unit_meas_desc : `str`
        The unit of measure description.

    Notes
    -----
    Code descriptions for units of measure. This maps back into many tables:
    ``virt_med_prod``, ``virt_prod_ing``, ``virt_med_prod_pack``,
    ``act_prod_ing``, ``virt_med_prod_map``.
    """
    __tablename__ = 'lkp_unit_measure'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'UNIT_OF_MEASURE'
    XML_MAPPINGS = dict(
        CD=('unit_meas_cd', int),
        CDDT=('unit_meas_cd_date', parse_date),
        CDPREV=('unit_meas_cd_prev', int),
        DESC=('unit_meas_desc', str),
    )
    unit_meas_cd = Column(
        BigInteger, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file. Apparently it is a SNOMED code up to 18"
        " digits long."
    )
    unit_meas_cd_date = Column(
        Date, nullable=True,
        doc="The date the code is applicable from."
    )
    unit_meas_cd_prev = Column(
        BigInteger, nullable=True,
        doc="Previous code, up to 18 digits."
    )
    unit_meas_desc = Column(
        String(255), nullable=False,
        doc="The unit of measure description."
    )

    # -------------------------------------------------------------------------#
    virt_med_prod = relationship(
        'VirtMedProd',
        primaryjoin="LkpUnitMeasure.unit_meas_cd == VirtMedProd.unit_meas_cd",
        back_populates='unit_meas'
    )
    virt_med_prod_ud = relationship(
        'VirtMedProd',
        primaryjoin="LkpUnitMeasure.unit_meas_cd == VirtMedProd.unit_meas_ud_cd",
        back_populates='unit_meas_ud'
    )
    virt_prod_ing_num = relationship(
        'VirtProdIng',
        primaryjoin="LkpUnitMeasure.unit_meas_cd == VirtProdIng.stren_value_num_unit_meas_cd",
        back_populates='stren_value_num_unit_meas'
    )
    virt_prod_ing_den = relationship(
        'VirtProdIng',
        primaryjoin="LkpUnitMeasure.unit_meas_cd == VirtProdIng.stren_value_den_unit_meas_cd",
        back_populates='stren_value_den_unit_meas'
    )
    virt_med_prod_pack = relationship(
        'VirtMedProdPack',
        back_populates='unit_meas'
    )
    act_prod_ing = relationship(
        'ActProdIng',
        back_populates='unit_meas'
    )
    virt_med_prod_map = relationship(
        'VirtMedProdMap',
        back_populates='unit_meas'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpForm(Base):
    """A representation of the ``lkp_form`` table. This holds data from the XML
    node ``LOOKUP.FORM``.

    Parameters
    ----------
    form_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file. This is a SNOMED code up to a maximum of 18 digits.
    form_cd_date : `datetime.datetime`
        Date the code is applicable from.
    form_cd_prev : `int`
        Previous form code, upto 18 digits.
    form_desc : `str`
        The form code description.

    Notes
    -----
    Code descriptions for formulations (Form). Links to the ``drug_form``
    table.
    """
    __tablename__ = 'lkp_form'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'FORM'
    XML_MAPPINGS = dict(
        CD=('form_cd', int),
        CDDT=('form_cd_date', parse_date),
        CDPREV=('form_cd_prev', int),
        DESC=('form_desc', str),
    )

    form_cd = Column(
        BigInteger, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file. This is a SNOMED code up to a maximum of"
        " 18 digits."
    )
    form_cd_date = Column(
        Date, nullable=True,
        doc="Date the code is applicable from."
    )
    form_cd_prev = Column(
        BigInteger, nullable=True,
        doc="Previous form code, upto 18 digits."
    )
    form_desc = Column(
        String(60), nullable=False,
        doc="The form code description."
    )

    # -------------------------------------------------------------------------#
    drug_form = relationship(
        'DrugForm',
        back_populates='form'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpOntFormRoute(Base):
    """A representation of the ``lkp_ont_form_route`` table. This holds data
    from the XML node ``LOOKUP.ONT_FORM_ROUTE``.

    Parameters
    ----------
    ont_form_route_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file.
    ont_form_route_desc : `str`
        The ontology form route description.

    Notes
    -----
    Code descriptions for ontology form route (virtual medicinal product (VMP)
    Form & Route) combinations.
    """
    __tablename__ = 'lkp_ont_form_route'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'ONT_FORM_ROUTE'
    XML_MAPPINGS = dict(
        CD=('ont_form_route_cd', int),
        DESC=('ont_form_route_desc', str),
    )

    ont_form_route_cd = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file."
    )
    ont_form_route_desc = Column(
        String(60), nullable=False,
        doc="The ontology form route description."
    )

    # -------------------------------------------------------------------------#
    ont_drug_form = relationship(
        'OntDrugForm',
        back_populates='ont_form_route'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpRoute(Base):
    """A representation of the ``lkp_route`` table. This holds data from the
    XML node ``LOOKUP.ROUTE``.

    Parameters
    ----------
    route_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file. This is a SNOMED code up to a maximum of 18 digits.
    route_cd_date : `datetime.datetime`
        The date the code is applicable from.
    route_cd_prev : `int`
        The previous route of administration code (max 18 digits).
    route_desc : `str`
        The route of administration description.

    Notes
    -----
    Code descriptions for routes of administration. This links to two tables:
    ``drug_route`` and ``licenced_route``.
    """
    __tablename__ = 'lkp_route'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'ROUTE'
    XML_MAPPINGS = dict(
        CD=('route_cd', int),
        CDDT=('route_cd_date', parse_date),
        CDPREV=('route_cd_prev', int),
        DESC=('route_desc', str),
    )

    route_cd = Column(
        BigInteger, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file. This is a SNOMED code up to a maximum of"
        " 18 digits."
    )
    route_cd_date = Column(
        Date, nullable=True,
        doc="The date the code is applicable from."
    )
    route_cd_prev = Column(
        BigInteger, nullable=True,
        doc="The previous route of administration code (max 18 digits)."
    )
    route_desc = Column(
        String(60), nullable=False,
        doc="The route of administration description."
    )

    # -------------------------------------------------------------------------#
    drug_route = relationship(
        'DrugRoute',
        back_populates='route'
    )
    licenced_route = relationship(
        'LicencedRoute',
        back_populates='route'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpDrugTariffCat(Base):
    """A representation of the ``lkp_drug_tariff_cat`` table. This holds data
    from the XML node ``LOOKUP.DT_PAYMENT_CATEGORY``.

    Parameters
    ----------
    drug_tariff_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file.
    drug_tariff_desc : `str`
        The drug tariff pay category description.

    Notes
    -----
    Code descriptions for Drug Tariff categories. This links to
    ``drug_tariff_info``.
    """
    __tablename__ = 'lkp_drug_tariff_cat'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'DT_PAYMENT_CATEGORY'
    XML_MAPPINGS = dict(
        CD=('drug_tariff_cd', int),
        DESC=('drug_tariff_desc', str),
    )

    drug_tariff_cd = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file."
    )
    drug_tariff_desc = Column(
        String(60), nullable=False,
        doc="The drug tariff pay category description."
    )

    # -------------------------------------------------------------------------#
    drug_tariff_info = relationship(
        'DrugTariffInfo',
        back_populates='drug_tariff_cat'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpSupplier(Base):
    """A representation of the ``lkp_supplier`` table. This holds data from the
    XML node ``LOOKUP.SUPPLIER``.

    Parameters
    ----------
    supplier_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file. This is a SNOMED code up to a maximum of 18 digits.
    supplier_cd_date : `datetime.datetime`
        The date the code is applicable from.
    supplier_cd_prev : `int`
        Previous code, max of 18 digits.
    supplier_invalid : `int`
        Is the code invalid?
    supplier_desc : `str`
        The supplier description.

    Notes
    -----
    Code descriptions for suppliers. Links to ``act_med_prod``.
    """
    __tablename__ = 'lkp_supplier'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'SUPPLIER'
    XML_MAPPINGS = dict(
        CD=('supplier_cd', int),
        CDDT=('supplier_cd_date', parse_date),
        CDPREV=('supplier_cd_prev', int),
        INVALID=('supplier_invalid', int),
        DESC=('supplier_desc', str),
    )

    supplier_cd = Column(
        BigInteger, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file. This is a SNOMED code up to a maximum of"
        " 18 digits."
    )
    supplier_cd_date = Column(
        Date, nullable=True,
        doc="The date the code is applicable from."
    )
    supplier_cd_prev = Column(
        BigInteger, nullable=True,
        doc="Previous code, max of 18 digits."
    )
    supplier_invalid = Column(
        SmallInteger, nullable=True,
        doc="Is the code invalid?"
    )
    supplier_desc = Column(
        String(80), nullable=False,
        doc="The supplier description."
    )

    # -------------------------------------------------------------------------#
    act_med_prod = relationship(
        'ActMedProd',
        back_populates='supplier'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpFlavour(Base):
    """A representation of the ``lkp_flavour`` table. This holds data from the
    XML node ``LOOKUP.FLAVOUR``.

    Parameters
    ----------
    flav_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file.
    flav_desc : `str`
        The flavour description.

    Notes
    -----
    Code descriptions for flavours. Links to the ``act_med_prod`` table.
    """
    __tablename__ = 'lkp_flavour'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'FLAVOUR'
    XML_MAPPINGS = dict(
        CD=('flav_cd', int),
        DESC=('flav_desc', str),
    )

    flav_cd = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file."
    )
    flav_desc = Column(
        String(60), nullable=False,
        doc="The flavour description."
    )

    # -------------------------------------------------------------------------#
    act_med_prod = relationship(
        'ActMedProd',
        back_populates='flavour'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpColour(Base):
    """A representation of the ``lkp_colour`` table. This holds data from the
    XML node ``LOOKUP.COLOUR``.

    Parameters
    ----------
    col_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file.
    col_desc : `str`
        The colour description.

    Notes
    -----
    Code descriptions for colours. Links to appliance product info
    (``app_prod_info``) table.
    """
    __tablename__ = 'lkp_colour'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'COLOUR'
    XML_MAPPINGS = dict(
        CD=('colour_cd', int),
        DESC=('colour_desc', str),
    )

    colour_cd = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file."
    )
    colour_desc = Column(
        String(60), nullable=False,
        doc="The colour description."
    )

    # -------------------------------------------------------------------------#
    app_prod_info = relationship(
        'AppProdInfo',
        back_populates='colour'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpBasisStrength(Base):
    """A representation of the ``lkp_basis_strength`` table. This holds data
    from the XML node ``LOOKUP.BASIS_OF_STRNTH``.

    Parameters
    ----------
    basis_strength_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file.
    basis_strength_desc : `str`
        The basis of strength description.

    Notes
    -----
    The codes and descriptions for the basis of strength. Links to the
    ``virt_prod_ing`` table.
    """
    __tablename__ = 'lkp_basis_strength'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'BASIS_OF_STRNTH'
    XML_MAPPINGS = dict(
        CD=('basis_strength_cd', int),
        DESC=('basis_strength_desc', str),
    )

    basis_strength_cd = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file."
    )
    basis_strength_desc = Column(
        String(150), nullable=False,
        doc="The basis of strength description."
    )

    # -------------------------------------------------------------------------#
    virt_prod_ing = relationship(
        'VirtProdIng',
        back_populates='basis_strength'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpReimbStatus(Base):
    """A representation of the ``lkp_reimb_status`` table. This holds data from
    the XML node ``LOOKUP.REIMBURSEMENT_STATUS``.

    Parameters
    ----------
    reimb_status_id : `int`
        The primary key, this is added by the build script and not the original
        primary key in the XML file. This is due to the original key starting
        at 0 and causing issues with MySQL auto-increment and SQLAchemy. For
        the original key see the ``_cd`` suffixed column.
    reimb_status_cd : `int`
        A unique key, this column represents the primary key in the original
        XML file however because it incremented from 0 a surrogate primary key
        was created in the ``_id`` suffixed column.
    reimb_status_desc : `str`
        The reimbursement status description.

    Notes
    -----
    Codes to the reimbursement status. Links to the appliance pack info
    (``app_pack_info``) table.
    """
    __tablename__ = 'lkp_reimb_status'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'REIMBURSEMENT_STATUS'
    XML_MAPPINGS = dict(
        CD=('reimb_status_cd', int),
        DESC=('reimb_status_desc', str),
    )

    reimb_status_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, this is added by the build script and not the"
        " original primary key in the XML file. This is due to the original "
        "key starting at 0 and causing issues with MySQL auto-increment and"
        " SQLAchemy. For the original key see the ``_cd`` suffixed column."
    )
    reimb_status_cd = Column(
        Integer, nullable=False, unique=True,
        doc="A unique key, this column represents the primary key in the "
        "original XML file however because it incremented from 0 a surrogate "
        "primary key was created in the ``_id`` suffixed column."
    )
    reimb_status_desc = Column(
        String(60), nullable=False,
        doc="The reimbursement status description."
    )

    # -------------------------------------------------------------------------#
    app_pack_info = relationship(
        'AppPackInfo',
        primaryjoin="LkpReimbStatus.reimb_status_cd == "
        "AppPackInfo.reimb_status_cd",
        back_populates='reimb_status'
    )
    app_pack_info_prev = relationship(
        'AppPackInfo',
        primaryjoin="LkpReimbStatus.reimb_status_cd == "
        "AppPackInfo.reimb_status_cd_prev",
        back_populates='reimb_status_prev'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpSpecialCont(Base):
    """A representation of the ``lkp_special_cont`` table. This holds data from
    the XML node ``LOOKUP.SPEC_CONT``.

    Parameters
    ----------
    special_cont_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file.
    special_cont_desc : `str`
        The special container description.

    Notes
    -----
    Code descriptions for special container indicator. Links to reimbursement
    information (``reimb_info``) table.
    """
    __tablename__ = 'lkp_special_cont'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'SPEC_CONT'
    XML_MAPPINGS = dict(
        CD=('special_cont_cd', int),
        DESC=('special_cont_desc', str),
    )

    special_cont_cd = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file."
    )
    special_cont_desc = Column(
        String(60), nullable=False,
        doc="The special container description."
    )

    # -------------------------------------------------------------------------#
    reimb_info = relationship(
        'ReimbInfo',
        back_populates='special_cont'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpDnd(Base):
    """A representation of the ``lkp_dnd`` table. This holds data from the XML
    node ``LOOKUP.DND``.

    Parameters
    ----------
    dnd_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file.
    dnd_desc : `str`
        The discount not deducted description.

    Notes
    -----
    Code descriptions for Discount Not Deducted indicator. Links to the
    reimbursement information (``reimb_info``) table.
    """
    __tablename__ = 'lkp_dnd'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'DND'
    XML_MAPPINGS = dict(
        CD=('dnd_cd', int),
        DESC=('dnd_desc', str),
    )

    dnd_cd = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file."
    )
    dnd_desc = Column(
        String(60), nullable=False,
        doc="The discount not deducted description."
    )

    # -------------------------------------------------------------------------#
    reimb_info = relationship(
        'ReimbInfo',
        back_populates='dnd'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpVirtMedProdNa(Base):
    """A representation of the ``lkp_virt_prod_non_avail`` table. This holds
    data from the XML node ``LOOKUP.VIRTUAL_PRODUCT_NON_AVAIL``.

    Parameters
    ----------
    virt_med_prod_na_id : `int`
        The primary key, this is added by the build script and not the original
        primary key in the XML file. This is due to the original key starting
        at 0 and causing issues with MySQL auto-increment and SQLAchemy. For
        the original key see the ``_cd`` suffixed column.
    virt_med_prod_na_cd : `int`
        A unique key, this column represents the primary key in the original
        XML file however because it incremented from 0 a surrogate primary key
        was created in the ``_id`` suffixed column.
    virt_med_prod_na_desc : `str`
        The VMP non availability description.

    Notes
    -----
    VMP non availability of VMP status codes. I am not sure if this are
    non-available codes vmps or non available statis codes!? Links to virtual
    medicinal product (``virt_med_prod``) table.
    """
    __tablename__ = 'lkp_virt_prod_non_avail'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'VIRTUAL_PRODUCT_NON_AVAIL'
    XML_MAPPINGS = dict(
        CD=('virt_med_prod_na_cd', int),
        DESC=('virt_med_prod_na_desc', str),
    )

    virt_med_prod_na_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, this is added by the build script and not the"
        " original primary key in the XML file. This is due to the original "
        "key starting at 0 and causing issues with MySQL auto-increment and"
        " SQLAchemy. For the original key see the ``_cd`` suffixed column."
    )
    virt_med_prod_na_cd = Column(
        Integer, nullable=False, unique=True,
        doc="A unique key, this column represents the primary key in the "
        "original XML file however because it incremented from 0 a surrogate "
        "primary key was created in the ``_id`` suffixed column."
    )
    virt_med_prod_na_desc = Column(
        String(60), nullable=False,
        doc="The VMP non availability description."
    )

    # -------------------------------------------------------------------------#
    virt_med_prod = relationship(
        "VirtMedProd",
        back_populates='virt_med_prod_na'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpDisconInd(Base):
    """A representation of the ``lkp_discon_ind`` table. This holds data from
    the XML node ``LOOKUP.DISCONTINUED_IND``.

    Parameters
    ----------
    discon_ind_id : `int`
        The primary key, this is added by the build script and not the original
        primary key in the XML file. This is due to the original key starting
        at 0 and causing issues with MySQL auto-increment and SQLAchemy. For
        the original key see the ``_cd`` suffixed column.
    discon_ind_cd : `int`
        A unique key, this column represents the primary key in the original
        XML file however because it incremented from 0 a surrogate primary key
        was created in the ``_id`` suffixed column.
    discon_ind_desc : `str`
        The discontinued indicator description.

    Notes
    -----
    Code descriptions for discontinued indicator. This links to actual
    medicinal product pack (``act_med_prod_pack``) table.
    """
    __tablename__ = 'lkp_discon_ind'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'DISCONTINUED_IND'
    XML_MAPPINGS = dict(
        CD=('discon_ind_cd', int),
        DESC=('discon_ind_desc', str),
    )

    discon_ind_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, this is added by the build script and not the"
        " original primary key in the XML file. This is due to the original "
        "key starting at 0 and causing issues with MySQL auto-increment and"
        " SQLAchemy. For the original key see the ``_cd`` suffixed column."
    )
    discon_ind_cd = Column(
        Integer, nullable=False, unique=True,
        doc="A unique key, this column represents the primary key in the "
        "original XML file however because it incremented from 0 a surrogate "
        "primary key was created in the ``_id`` suffixed column."
    )
    discon_ind_desc = Column(
        String(60), nullable=False,
        doc="The discontinued indicator description."
    )

    # -------------------------------------------------------------------------#
    act_med_prod_pack = relationship(
        'ActMedProdPack',
        back_populates='discon_ind'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpDoseFormInd(Base):
    """A representation of the ``lkp_dose_form_ind`` table. This holds data
    from the XML node ``LOOKUP.DF_INDICATOR``.

    Parameters
    ----------
    dose_form_ind_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file.
    dose_form_ind_desc : `str`
        The dose form indicator description.

    Notes
    -----
    Code descriptions for Dose form indicator. Links to the virtual medicinal
    product (``virt_med_prod``) table.
    """
    __tablename__ = 'lkp_dose_form_ind'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'DF_INDICATOR'
    XML_MAPPINGS = dict(
        CD=('dose_form_ind_cd', int),
        DESC=('dose_form_ind_desc', str),
    )

    dose_form_ind_cd = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file."
    )
    dose_form_ind_desc = Column(
        String(20), nullable=False,
        doc="The dose form indicator description."
    )

    # -------------------------------------------------------------------------#
    virt_med_prod = relationship(
        'VirtMedProd',
        back_populates='dose_form_ind'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpBasisPrice(Base):
    """A representation of the ``lkp_basis_price`` table. This holds data from
    the XML node ``LOOKUP.PRICE_BASIS``.

    Parameters
    ----------
    basis_price_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file.
    basis_price_desc : `str`
        The basis of price description.

    Notes
    -----
    Code descriptions for basis of actual medicinal product pack (AMPP) price.
    This links to the medicinal product price (``med_prod_price``) table.
    """
    __tablename__ = 'lkp_basis_price'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'PRICE_BASIS'
    XML_MAPPINGS = dict(
        CD=('basis_price_cd', int),
        DESC=('basis_price_desc', str),
    )

    basis_price_cd = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file."
    )
    basis_price_desc = Column(
        String(60), nullable=False,
        doc="The basis of price description."
    )

    # -------------------------------------------------------------------------#
    med_prod_price = relationship(
        'MedProdPrice',
        back_populates='basis_price'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpLegalCat(Base):
    """
    Notes
    -----
    Code descriptions for legal category of the actual medicinal product pack
    (AMPP). This links to actual medicinal product pack (``act_med_prod_pack``)
    table.
    """
    __tablename__ = 'lkp_legal_cat'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'LEGAL_CATEGORY'
    XML_MAPPINGS = dict(
        CD=('legal_cat_cd', int),
        DESC=('legal_cat_desc', str),
    )

    legal_cat_cd = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file."
    )
    legal_cat_desc = Column(
        String(60), nullable=False,
        doc="The legal category description."
    )

    # -------------------------------------------------------------------------#
    act_med_prod_pack = relationship(
        'ActMedProdPack',
        back_populates='legal_cat'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpAvailRestict(Base):
    """A representation of the ``lkp_avail_restrict`` table. This holds data
    from the XML node ``LOOKUP.AVAILABILITY_RESTRICTION``.

    Parameters
    ----------
    avail_restrict_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file.
    avail_restrict_desc : `str`
        The availability restriction description.

    Notes
    -----
    Code descriptions for availability restriction of the actual medicinal
    product (AMP). This links to actual medicinal product (``act_med_prod``)
    table.
    """
    __tablename__ = 'lkp_avail_restrict'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'AVAILABILITY_RESTRICTION'
    XML_MAPPINGS = dict(
        CD=('avail_restrict_cd', int),
        DESC=('avail_restrict_desc', str),
    )

    avail_restrict_cd = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file."
    )
    avail_restrict_desc = Column(
        String(60), nullable=False,
        doc="The availability restriction description."
    )

    # -------------------------------------------------------------------------#
    act_med_prod = relationship(
        'ActMedProd',
        back_populates='avail_restrict'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LkpLicAuthChange(Base):
    """A representation of the ``lkp_lic_auth_change`` table. This holds data
    from the XML node ``LOOKUP.LICENSING_AUTHORITY_CHANGE_REASON``.

    Parameters
    ----------
    lic_auth_change_cd : `int`
        The primary key, whilst this is set as an auto-increment but is sourced
        from the XML file.
    lic_auth_change_desc : `str`
        The licensing authority reason for change description.

    Notes
    -----
    Code descriptions for licensing authority reason for change. This links to
    actual medicinal product (``act_med_prod``) table.
    """
    __tablename__ = 'lkp_lic_auth_change'
    XML_ROOT = 'LOOKUP'
    XML_NODE = 'LICENSING_AUTHORITY_CHANGE_REASON'
    XML_MAPPINGS = dict(
        CD=('lic_auth_change_cd', int),
        DESC=('lic_auth_change_desc', str),
    )

    lic_auth_change_cd = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key, whilst this is set as an auto-increment but is"
        " sourced from the XML file."
    )
    lic_auth_change_desc = Column(
        String(60), nullable=False,
        doc="The licensing authority reason for change description."
    )

    # -------------------------------------------------------------------------#
    act_med_prod = relationship(
        'ActMedProd',
        back_populates='lic_auth_change'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class VirtTherMoiet(Base):
    """A representation of the ``virt_ther_moiet`` table. This holds data from
    the XML node ``VIRTUAL_THERAPEUTIC_MOIETIES.VTM``.

    Parameters
    ----------
    vtm_id : `int`
        Virtual therapeutic moiety identifier (SNOMED Code). Up to a maximum of
        18 integers.
    vtm_invalid : `int`
        Invalidity flag. If set to 1 indicates this is an invalid entry in
        file. 1 integer only.
    vtm_name : `str`
        Virtual therapeutic moiety name.
    vtm_abbrev : `str`
        Virtual therapeutic moiety abbreviated name.
    vtm_id_prev : `int`
        Previous virtual therapeutic moiety identifier (SNOMED Code). Up to a
        maximum of 18 integers.
    vtm_id_date : `datetime.datetime`
        The date the virtual therapeutic moiety identifier became valid.
    virt_med_prod : `dmd.orm.VirtMedProd`
        The relationship link back to the virtual medicinal product table.

    Notes
    -----
    Descriptions pf virtual therapeutic moieties. These can be thought of as
    the drug without any dosage information. This links to the virtual
    medicinal products (``virt_med_prod``) table.
    """
    __tablename__ = 'virt_ther_moiet'

    XML_ROOT = 'VIRTUAL_THERAPEUTIC_MOIETIES'
    XML_NODE = 'VTM'
    XML_MAPPINGS = dict(
        VTMID=('vtm_id', int),
        INVALID=('vtm_invalid', int),
        NM=('vtm_name', str),
        ABBREVNM=('vtm_abbrev', str),
        VTMIDPREV=('vtm_id_prev', str),
        VTMIDDT=('vtm_id_date', parse_date),
    )

    vtm_id = Column(
        BigInteger, nullable=False, primary_key=True,
        doc="Virtual therapeutic moiety identifier (SNOMED Code). Up to a "
        "maximum of 18 integers."
    )
    vtm_invalid = Column(
        SmallInteger, nullable=True,
        doc="Invalidity flag. If set to 1 indicates this is an invalid entry "
        "in file. 1 integer only."
    )
    vtm_name = Column(
        String(255), nullable=True,
        doc="Virtual therapeutic moiety name."
    )
    vtm_abbrev = Column(
        String(60), nullable=True,
        doc="Virtual therapeutic moiety abbreviated name."
    )
    vtm_id_prev = Column(
        BigInteger, nullable=True,
        doc="Previous virtual therapeutic moiety identifier (SNOMED Code). Up "
        "to a maximum of 18 integers."
    )
    vtm_id_date = Column(
        Date, nullable=True,
        doc="The date the virtual therapeutic moiety identifier became valid."
    )

    # -------------------------------------------------------------------------#
    virt_med_prod = relationship(
        'VirtMedProd',
        back_populates='virt_ther_moiet',
        doc="The relationship link back to the virtual medicinal product "
        "table."
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class Ingredient(Base):
    """A representation of the ``ingredient`` table. This holds data from the
    XML node ``INGREDIENT_SUBSTANCES.ING``.

    Parameters
    ----------
    ingredient_id : `int`
        Ingredient substance identifier (SNOMED Code). Up to a maximum of 18
        integers.
    ingredient_id_date : `datetime.datetime`
        The date the ingredient substance identifier became valid.
    ingredient_id_prev : `int`
        Previous ingredient substance identifier (SNOMED Code). Up to a maximum
        of 18 integers.
    ingredient_invalid : `int`
        Invalidity flag. If set to 1 indicates this is an invalid entry in
        file. 1 integer only.
    ingredient_name : `str`
        The ingredient substance name
    virt_prod_ing : `dmd.orm.VirtProdIng`
        The relationship link back to the virtual product ingredient table.
    """
    __tablename__ = 'ingredient'

    XML_ROOT = 'INGREDIENT_SUBSTANCES'
    XML_NODE = 'ING'
    XML_MAPPINGS = dict(
        ISID=('ingredient_id', int),
        ISIDDT=('ingredient_id_date', parse_date),
        ISIDPREV=('ingredient_id_prev', int),
        INVALID=('ingredient_invalid', int),
        NM=('ingredient_name', str)
    )

    ingredient_id = Column(
        BigInteger, nullable=False, primary_key=True,
        doc="Ingredient substance identifier (SNOMED Code). Up to a "
        "maximum of 18 integers."
    )
    ingredient_id_date = Column(
        Date, nullable=True,
        doc="The date the ingredient substance identifier became valid."
    )
    ingredient_id_prev = Column(
        BigInteger, nullable=True,
        doc="Previous ingredient substance identifier (SNOMED Code). Up "
        "to a maximum of 18 integers."
    )
    ingredient_invalid = Column(
        SmallInteger, nullable=True,
        doc="Invalidity flag. If set to 1 indicates this is an invalid entry "
        "in file. 1 integer only."
    )
    ingredient_name = Column(
        String(255), nullable=True,
        doc="The ingredient substance name"
    )

    # -------------------------------------------------------------------------#
    virt_prod_ing = relationship(
        'VirtProdIng',
        back_populates='ingredient',
        doc="The relationship link back to the virtual product ingredient "
        "table."
    )
    # -------------------------------------------------------------------------#
    act_prod_ing = relationship(
        'ActProdIng',
        back_populates='ingredient',
        doc="The relationship link back to the actual medicinal product "
        "ingredient table. These seem to be the non-active formulation "
        "ingredients"
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class VirtMedProd(Base):
    """A representation of the ``virt_med_prod`` table. This holds data from
    the XML node ``VIRTUAL_MED_PRODUCTS.VMPS``.

    Parameters
    ----------
    vmp_id : `int`
        Virtual medical product identifier (SNOMED Code). Up to a maximum of 18
        integers.
    vmp_id_date : `datetime.datetime`
        The date when the virtual medicinal product identifier became valid.
    vmp_id_prev : `int`
        Previous VMP identifier (SNOMED Code). Up to a maximum of 18 integers.
    vtm_id : `int`
        Virtual therapeutic moiety identifier (SNOMED Code). Up to a maximum of
        18 integers.
    vmp_invalid : `int`
        Invalidity flag. If set to 1 indicates this is an invalid entry in
        file. 1 integer only.
    vmp_name : `str`
        The virtual medical product name.
    vmp_name_abbrev : `str`
        The abbreviated virtual medical product name.
    vmp_name_date : `datetime.datetime`
        The date the VMP name became valid.
    vmp_name_prev : `str`
        The previous virtual medical product name.
    basis_name_cd : `int`
        The basis of name code.
    basis_name_cd_prev : `int`
        The previous basis of name code.
    name_change_reason_cd : `int`
        The reason for name change code.
    comb_prod_ind_cd : `int`
        The combination product indicator code.
    pres_status_cd : `int`
        The VMP prescribing status.
    sugar_free : `int`
        The sugar free indicator.
    gluten_free : `int`
        The gluten free indicator.
    pres_free : `int`
        The preservative free indicator.
    cfc_free : `int`
        The CFC free indicator.
    virt_med_prod_na_cd : `int`
        The non-availability indicator code.
    virt_med_prod_na_date : `datetime.datetime`
        The non-availability status date.
    dose_form_ind_cd : `int`
        The dose form indicator code.
    unit_dose_form_size : `float`
        Unit dose form size - a numerical value relating to size of entity.
        This will only be present if the unit dose form attribute is discrete.
        Up to a maximum of 10 digits and 3 decimal places.
    unit_meas_cd : `int`
        Unit dose form units - unit of measure code relating to the size. This
        will only be present if the unit dose form attribute is discrete.
        Narrative can be located in lookup file under tag <UNIT_OF_MEASURE> Up
        to a maximum of 18 digits.
    unit_meas_ud_cd : `int`
        Unit dose unit of measure - unit of measure code relating to a
        description of the entity that can be handled. This will only be
        present if the Unit dose form attribute is discrete. Narrative can be
        located in lookup file under tag <UNIT_OF_MEASURE>.

    Notes
    -----
    The virtual medicinal products table contains generic forms of drugs and is
    linked to the virtual therapeutic moiety table as well as other lookup
    tables.
    """
    __tablename__ = 'virt_med_prod'

    XML_ROOT = 'VIRTUAL_MED_PRODUCTS'
    XML_NODE = 'VMPS'
    XML_MAPPINGS = dict(
        VPID=('vmp_id', int),
        VPIDDT=('vmp_id_date', parse_date),
        VPIDPREV=('vmp_id_prev', int),
        VTMID=('vtm_id', int),
        INVALID=('vmp_invalid', int),
        NM=('vmp_name', str),
        ABBREVNM=('vmp_name_abbrev', str),
        NMDT=('vmp_name_date', parse_date),
        NMPREV=('vmp_name_prev', str),
        BASISCD=('basis_name_cd', int),
        BASIS_PREVCD=('basis_name_cd_prev', int),
        NMCHANGECD=('name_change_reason_cd', int),
        COMBPRODCD=('comb_prod_ind_cd', int),
        PRES_STATCD=('pres_status_cd', int),
        SUG_F=('sugar_free', int),
        GLU_F=('gluten_free', int),
        PRES_F=('pres_free', int),
        CFC_F=('cfc_free', int),
        NON_AVAILCD=('virt_med_prod_na_cd', int),
        NON_AVAILDT=('virt_med_prod_na_date', parse_date),
        DF_INDCD=('dose_form_ind_cd', int),
        UDFS=('unit_dose_form_size', float),
        UDFS_UOMCD=('unit_meas_cd', int),
        UNIT_DOSE_UOMCD=('unit_meas_ud_cd', int)
    )
    vmp_id = Column(
        BigInteger, nullable=False, primary_key=True,
        doc="Virtual medical product identifier (SNOMED Code). Up to a "
        "maximum of 18 integers."
    )
    vmp_id_date = Column(
        Date, nullable=True,
        doc="The date when the virtual medicinal product identifier"
        " became valid."
    )
    vmp_id_prev = Column(
        BigInteger, nullable=True,
        doc="Previous VMP identifier (SNOMED Code). Up to a "
        "maximum of 18 integers."
    )
    vtm_id = Column(
        BigInteger, ForeignKey('virt_ther_moiet.vtm_id'),
        nullable=True,
        doc="Virtual therapeutic moiety identifier (SNOMED Code). Up to a "
        "maximum of 18 integers."
    )
    vmp_invalid = Column(
        SmallInteger, nullable=False, default=0,
        doc="Invalidity flag. If set to 1 indicates this is an invalid entry "
        "in file. 1 integer only."
    )
    vmp_name = Column(
        String(255), nullable=False,
        doc="The virtual medical product name."
    )
    vmp_name_abbrev = Column(
        String(60), nullable=True,
        doc="The abbreviated virtual medical product name."
    )
    vmp_name_date = Column(
        Date, nullable=True,
        doc="The date the VMP name became valid."
    )
    vmp_name_prev = Column(
        String(255), nullable=True,
        doc="The previous virtual medical product name."
    )
    basis_name_cd = Column(
        Integer, ForeignKey('lkp_basis_of_name.basis_name_cd'),
        nullable=False,
        doc="The basis of name code."
    )
    basis_name_cd_prev = Column(
        Integer, ForeignKey('lkp_basis_of_name.basis_name_cd'),
        nullable=True,
        doc="The previous basis of name code."
    )
    name_change_reason_cd = Column(
        Integer, ForeignKey('lkp_name_change_reason.name_change_reason_cd'),
        nullable=True,
        doc="The reason for name change code."
    )
    comb_prod_ind_cd = Column(
        Integer, ForeignKey('lkp_comb_prod_ind.comb_prod_ind_cd'),
        nullable=True,
        doc="The combination product indicator code."
    )
    pres_status_cd = Column(
        Integer, ForeignKey('lkp_virtual_prod_pres_status.pres_status_cd'),
        nullable=False,
        doc="The VMP prescribing status."
    )
    sugar_free = Column(
        SmallInteger, nullable=True,
        doc="The sugar free indicator."
    )
    gluten_free = Column(
        SmallInteger, nullable=True,
        doc="The gluten free indicator."
    )
    pres_free = Column(
        SmallInteger, nullable=True,
        doc="The preservative free indicator."
    )
    cfc_free = Column(
        SmallInteger, nullable=True,
        doc="The CFC free indicator."
    )
    virt_med_prod_na_cd = Column(
        Integer, ForeignKey('lkp_virt_prod_non_avail.virt_med_prod_na_cd'),
        nullable=True,
        doc="The non-availability indicator code."
    )
    virt_med_prod_na_date = Column(
        Date, nullable=True,
        doc="The non-availability status date."
    )
    dose_form_ind_cd = Column(
        Integer, ForeignKey('lkp_dose_form_ind.dose_form_ind_cd'),
        nullable=True,
        doc="The dose form indicator code."
    )
    unit_dose_form_size = Column(
        Float, nullable=True,
        doc="Unit dose form size - a numerical value relating to size of "
        "entity. This will only be present if the unit dose form attribute is"
        " discrete. Up to a maximum of 10 digits and 3 decimal places."
    )
    unit_meas_cd = Column(
        BigInteger, ForeignKey('lkp_unit_measure.unit_meas_cd'),
        nullable=True,
        doc="Unit dose form units - unit of measure code relating to the size."
        " This will only be present if the unit dose form attribute is "
        "discrete. Narrative can be located in lookup file under tag "
        "<UNIT_OF_MEASURE> Up to a maximum of 18 digits."
    )
    unit_meas_ud_cd = Column(
        BigInteger, ForeignKey('lkp_unit_measure.unit_meas_cd'),
        nullable=True,
        doc="Unit dose unit of measure - unit of measure code relating to a"
        " description of the entity that can be handled. This will only be "
        "present if the Unit dose form attribute is discrete. Narrative can "
        "be located in lookup file under tag <UNIT_OF_MEASURE>."
    )

    # -------------------------------------------------------------------------#
    virt_ther_moiet = relationship(
        VirtTherMoiet,
        back_populates='virt_med_prod'
    )
    basis_name = relationship(
        LkpBasisOfName,
        foreign_keys=[basis_name_cd],
        back_populates='virt_med_prod'
    )
    basis_name_prev = relationship(
        LkpBasisOfName,
        foreign_keys=[basis_name_cd_prev],
        back_populates='virt_med_prod_prev'
    )
    name_change_reason = relationship(
        LkpNameChangeReason,
        back_populates='virt_med_prod'
    )
    comb_prod_ind = relationship(
        LkpCombProdInd,
        back_populates='vmp_comb_prod_ind'
    )
    pres_status = relationship(
        LkpVirtualProdPresStatus,
        back_populates='virt_med_prod'
    )
    virt_med_prod_na = relationship(
        LkpVirtMedProdNa,
        back_populates='virt_med_prod'
    )
    unit_meas = relationship(
        LkpUnitMeasure,
        foreign_keys=[unit_meas_cd],
        back_populates='virt_med_prod'
    )
    unit_meas_ud = relationship(
        LkpUnitMeasure,
        foreign_keys=[unit_meas_ud_cd],
        back_populates='virt_med_prod_ud'
    )
    virt_med_prod_pack = relationship(
        'VirtMedProdPack',
        back_populates='virt_med_prod'
    )
    act_med_prod = relationship(
        'ActMedProd',
        back_populates='virt_med_prod'
    )
    virt_med_prod_map = relationship(
        'VirtMedProdMap',
        back_populates='virt_med_prod'
    )
    ont_drug_form = relationship(
        'OntDrugForm',
        back_populates='virt_med_prod'
    )
    cont_drug_info = relationship(
        'ContDrugInfo',
        back_populates='virt_med_prod'
    )
    drug_form = relationship(
        'DrugForm',
        back_populates='virt_med_prod'
    )
    drug_route = relationship(
        'DrugRoute',
        back_populates='virt_med_prod'
    )
    virt_prod_ing = relationship(
        'VirtProdIng',
        back_populates='virt_med_prod'
    )
    dose_form_ind = relationship(
        LkpDoseFormInd,
        back_populates='virt_med_prod'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class VirtProdIng(Base):
    """A representation of the ``virt_prod_ing`` table. This holds data from
    the XML node ``VIRTUAL_MED_PRODUCTS.VIRTUAL_PRODUCT_INGREDIENT``.

    Parameters
    ----------
    vpi_id : `int`
        The virtual product ingredient ID, this is the primary key and is NOT
        derived from the XML file. I think it is required as there is a many-
        to-one relationship between ingredients and products (although not 100%
        sure).
    vmp_id : `int`
        The virtual medicinal product ID. This is derived from the XML file and
        is a maximum of 18 digits.
    vmp_ingredient_id : `int`
        Ingredient substance identifier (SNOMED Code). Up to a maximum of 18
        integers.
    basis_strength_cd : `int`
        The basis of pharmaceutical strength code.
    basis_strength_sub_id : `int`
        Virtual therapeutic moiety identifier (SNOMED Code). Up to a maximum of
        18 integers.
    stren_value_num : `float`
        Strength value numerator - value of numerator element of strength up to
        a maximum of 10 digits and 3 decimal places.
    stren_value_num_unit_meas_cd : `int`
        Strength value numerator unit - numerator value of strength unit of
        measure code. Up to a maximum of 18 digits.
    stren_value_den : `float`
        Strength value denominator - value of denominator element of strength.
        Up to a maximum of 10 digits and 3 decimal places.
    stren_value_den_unit_meas_cd : `int`
        Strength value denominator unit denominator value of strength unit of
        measure code. Up to a maximum of 18 digits.

    Notes
    -----
    The virtual product ingredients table contains the ingredients associated
    with virtual medicinal products.
    """
    __tablename__ = 'virt_prod_ing'

    XML_ROOT = 'VIRTUAL_MED_PRODUCTS'
    XML_NODE = 'VIRTUAL_PRODUCT_INGREDIENT'
    XML_MAPPINGS = dict(
        VPID=('vmp_id', int),
        ISID=('vmp_ingredient_id', int),
        BASIS_STRNTCD=('basis_strength_cd', int),
        BS_SUBID=('basis_strength_sub_id', int),
        STRNT_NMRTR_VAL=('stren_value_num', float),
        STRNT_NMRTR_UOMCD=('stren_value_num_unit_meas_cd', int),
        STRNT_DNMTR_VAL=('stren_value_den', float),
        STRNT_DNMTR_UOMCD=('stren_value_den_unit_meas_cd', int)
    )
    vpi_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The virtual product ingredient ID, this is the primary key and is"
        " NOT derived from the XML file. I think it is required as there is "
        "a many-to-one relationship between ingredients and products (although"
        " not 100% sure)."
    )
    vmp_id = Column(
        BigInteger, ForeignKey('virt_med_prod.vmp_id'),
        nullable=False,
        doc="The virtual medicinal product ID. This is derived from the XML"
        " file and is a maximum of 18 digits."
    )
    vmp_ingredient_id = Column(
        BigInteger, ForeignKey('ingredient.ingredient_id'),
        nullable=False,
        doc="Ingredient substance identifier (SNOMED Code). Up to a "
        "maximum of 18 integers."
    )
    basis_strength_cd = Column(
        Integer, ForeignKey('lkp_basis_strength.basis_strength_cd'),
        nullable=True,
        doc="The basis of pharmaceutical strength code."
    )
    # TODO: check this should not be referencing a lookup table
    #  I think this should map back to ingredients
    basis_strength_sub_id = Column(
        BigInteger, nullable=True,
        doc="Virtual therapeutic moiety identifier (SNOMED Code). Up to a "
        "maximum of 18 integers."
    )
    stren_value_num = Column(
        Float, nullable=True,
        doc="Strength value numerator - value of numerator element of strength"
        " up to a maximum of 10 digits and 3 decimal places."
    )
    stren_value_num_unit_meas_cd = Column(
        BigInteger, ForeignKey('lkp_unit_measure.unit_meas_cd'),
        nullable=True,
        doc="Strength value numerator unit - numerator value of strength "
        "unit of measure code. Up to a maximum of 18 digits."
    )
    stren_value_den = Column(
        Float, nullable=True,
        doc="Strength value denominator - value of denominator element of "
        "strength. Up to a maximum of 10 digits and 3 decimal places."
    )
    stren_value_den_unit_meas_cd = Column(
        BigInteger, ForeignKey('lkp_unit_measure.unit_meas_cd'),
        nullable=True,
        doc="Strength value denominator unit denominator value of strength "
        "unit of measure code. Up to a maximum of 18 digits."
    )

    # -------------------------------------------------------------------------#
    ingredient = relationship(
        Ingredient,
        back_populates='virt_prod_ing'
    )
    basis_strength = relationship(
        LkpBasisStrength,
        back_populates='virt_prod_ing'
    )
    stren_value_num_unit_meas = relationship(
        LkpUnitMeasure,
        foreign_keys=[stren_value_num_unit_meas_cd],
        back_populates='virt_prod_ing_num'
    )
    stren_value_den_unit_meas = relationship(
        LkpUnitMeasure,
        foreign_keys=[stren_value_den_unit_meas_cd],
        back_populates='virt_prod_ing_den'
    )
    virt_med_prod = relationship(
        VirtMedProd,
        back_populates='virt_prod_ing'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class OntDrugForm(Base):
    """A representation of the ``ont_drug_form`` table. This holds data from
    the XML node ``VIRTUAL_MED_PRODUCTS.ONT_DRUG_FORM``.

    Parameters
    ----------
    odf_id : `int`
        The primary key - this is not part of the XML file.
    vmp_id : `int`
        Virtual medicinal product identifier (as above in VMP tag). Up to a
        maximum of 18 digits.
    ont_form_route_cd : `int`
        Virtual medicinal product form & route code. Up to 4 digits (the XML
        file says always 4 characters but the XML schema is integer!?).

    Notes
    -----
    Ontology form & route information associated with each virtual medicinal
    product.
    """
    __tablename__ = 'ont_drug_form'

    XML_ROOT = 'VIRTUAL_MED_PRODUCTS'
    XML_NODE = 'ONT_DRUG_FORM'
    XML_MAPPINGS = dict(
        VPID=('vmp_id', int),
        FORMCD=('ont_form_route_cd', int),
    )

    odf_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key - this is not part of the XML file."
    )
    vmp_id = Column(
        BigInteger, ForeignKey('virt_med_prod.vmp_id'),
        nullable=False,
        doc="Virtual medicinal product identifier (as above in VMP tag)"
        ". Up to a maximum of 18 digits."
    )
    ont_form_route_cd = Column(
        Integer, ForeignKey('lkp_ont_form_route.ont_form_route_cd'),
        nullable=False,
        doc="Virtual medicinal product form & route code. Up to 4 digits (the"
        " XML file says always 4 characters but the XML schema is integer!?)."
    )

    # -------------------------------------------------------------------------#
    virt_med_prod = relationship(
        VirtMedProd,
        back_populates='ont_drug_form'
    )
    ont_form_route = relationship(
        LkpOntFormRoute,
        back_populates='ont_drug_form'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class DrugForm(Base):
    """A representation of the ``drug_form`` table. This holds data from the
    XML node ``VIRTUAL_MED_PRODUCTS.DRUG_FORM``.

    Parameters
    ----------
    df_id : `int`
        The primary key - this is not part of the XML file.
    vmp_id : `int`
        Virtual medicinal product identifier (as above in VMP tag). Up to a
        maximum of 18 digits.
    form_cd : `int`
        Formulation code.

    Notes
    -----
    Formulation or form associated with each virtual medicinal product.
    """
    __tablename__ = 'drug_form'

    XML_ROOT = 'VIRTUAL_MED_PRODUCTS'
    XML_NODE = 'DRUG_FORM'
    XML_MAPPINGS = dict(
        VPID=('vmp_id', int),
        FORMCD=('form_cd', int),
    )

    df_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key - this is not part of the XML file."
    )
    vmp_id = Column(
        BigInteger, ForeignKey('virt_med_prod.vmp_id'),
        nullable=False,
        doc="Virtual medicinal product identifier (as above in VMP tag)"
        ". Up to a maximum of 18 digits."
    )
    form_cd = Column(
        BigInteger, ForeignKey('lkp_form.form_cd'),
        nullable=False,
        doc="Formulation code."
    )

    # -------------------------------------------------------------------------#
    form = relationship(
        LkpForm,
        back_populates='drug_form'
    )
    virt_med_prod = relationship(
        VirtMedProd,
        back_populates='drug_form'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class DrugRoute(Base):
    """A representation of the ``drug_route`` table. This holds data from the
    XML node ``VIRTUAL_MED_PRODUCTS.DRUG_ROUTE``.

    Parameters
    ----------
    dr_id : `int`
        The primary key - this is not part of the XML file.
    vmp_id : `int`
        Virtual medicinal product identifier (as above in VMP tag). Up to a
        maximum of 18 digits.
    route_cd : `int`
        Route (of administration?) code.

    Notes
    -----
    Route (of administration?) associated with each virtual medicinal product.
    """
    __tablename__ = 'drug_route'

    XML_ROOT = 'VIRTUAL_MED_PRODUCTS'
    XML_NODE = 'DRUG_ROUTE'
    XML_MAPPINGS = dict(
        VPID=('vmp_id', int),
        ROUTECD=('route_cd', int),
    )
    dr_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key - this is not part of the XML file."
    )
    vmp_id = Column(
        BigInteger, ForeignKey('virt_med_prod.vmp_id'),
        nullable=False,
        doc="Virtual medicinal product identifier (as above in VMP tag)"
        ". Up to a maximum of 18 digits."
    )
    route_cd = Column(
        BigInteger, ForeignKey('lkp_route.route_cd'),
        nullable=False,
        doc="Route (of administration?) code."
    )

    # -------------------------------------------------------------------------#
    route = relationship(
        LkpRoute,
        back_populates='drug_route'
    )
    virt_med_prod = relationship(
        VirtMedProd,
        back_populates='drug_route'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class ContDrugInfo(Base):
    """A representation of the ``cont_drug_info`` table. This holds data from
    the XML node ``VIRTUAL_MED_PRODUCTS.CONTROL_DRUG_INFO``.

    Parameters
    ----------
    cdi_id : `int`
        The primary key - this is not part of the XML file.
    vmp_id : `int`
        Virtual medicinal product identifier (as above in VMP tag). Up to a
        maximum of 18 digits.
    cont_drug_cat_cd : `int`
        The controlled drug category code.
    cont_drug_date : `datetime.datetime`
        Controlled drug applicable date.
    cont_drug_cat_cd_prev : `int`
        Previous control drug information. Controlled drug category prior to
        change date.

    Notes
    -----
    Controlled drug information associated with each virtual medicinal product.
    """
    __tablename__ = 'cont_drug_info'

    XML_ROOT = 'VIRTUAL_MED_PRODUCTS'
    XML_NODE = 'CONTROL_DRUG_INFO'
    XML_MAPPINGS = dict(
        VPID=('vmp_id', int),
        CATCD=('cont_drug_cat_cd', int),
        CATDT=('cont_drug_date', parse_date),
        CAT_PREVCD=('cont_drug_cat_cd_prev', int),
    )

    cdi_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key - this is not part of the XML file."
    )
    vmp_id = Column(
        BigInteger, ForeignKey('virt_med_prod.vmp_id'),
        nullable=False,
        doc="Virtual medicinal product identifier (as above in VMP tag)"
        ". Up to a maximum of 18 digits."
    )
    cont_drug_cat_cd = Column(
        Integer, ForeignKey('lkp_control_drug_cat.cont_drug_cat_cd'),
        nullable=False,
        doc="The controlled drug category code."
    )
    cont_drug_date = Column(
        Date, nullable=True,
        doc="Controlled drug applicable date."
    )
    cont_drug_cat_cd_prev = Column(
        Integer, ForeignKey('lkp_control_drug_cat.cont_drug_cat_cd'),
        nullable=True,
        doc="Previous control drug information. Controlled drug category prior"
        " to change date."
    )

    # -------------------------------------------------------------------------#
    virt_med_prod = relationship(
        VirtMedProd,
        back_populates='cont_drug_info'
    )
    cont_drug_cat = relationship(
        LkpControlDrugCat,
        foreign_keys=[cont_drug_cat_cd],
        back_populates='cont_drug_info'
    )
    cont_drug_cat_prev = relationship(
        LkpControlDrugCat,
        foreign_keys=[cont_drug_cat_cd_prev],
        back_populates='cont_drug_info_prev'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class VirtMedProdPack(Base):
    """A representation of the ``virt_med_prod_pack`` table. This holds data
    from the XML node ``VIRTUAL_MED_PRODUCT_PACK.VMPP``.

    Parameters
    ----------
    vmp_pack_id : `int`
        Virtual medicinal product pack identifier (SNOMED Code). Up to a
        maximum of 18 digits.
    vmp_pack_invalid : `int`
        Invalidity flag. If set to 1 indicates this is an invalid entry in
        file. 1 integer only.
    vmp_pack_name : `str`
        The virtual medicinal product pack name.
    vmp_pack_name_abrv : `str`
        The abbreviated virtual medicinal product pack name. Not in the XML
        documentation so not sure on correct field size.
    vmp_id : `int`
        Virtual medicinal product identifier (as above in VMP tag). Up to a
        maximum of 18 digits.
    quant_val : `float`
        Quantity value up to a maximum of 10 digits and 2 decimal places.
    quant_unit_meas_cd : `int`
        Quantity value unit of measure code. Up to a maximum of 18 digits.
    comb_pack_ind_cd : `int`
        Combination pack indicator code. Up to 4 digits.

    Notes
    -----
    The virtual medicinal product packs associated with each virtual medicinal
    product.
    """
    __tablename__ = 'virt_med_prod_pack'

    XML_ROOT = 'VIRTUAL_MED_PRODUCT_PACK'
    XML_NODE = 'VMPP'
    XML_MAPPINGS = dict(
        VPPID=('vmp_pack_id', int),
        INVALID=('vmp_pack_invalid', int),
        NM=('vmp_pack_name', str),
        ABBREVNM=('vmp_pack_name_abrv', str),
        VPID=('vmp_id', int),
        QTYVAL=('quant_val', float),
        QTY_UOMCD=('quant_unit_meas_cd', int),
        COMBPACKCD=('comb_pack_ind_cd', int)
    )
    vmp_pack_id = Column(
        BigInteger, nullable=False, primary_key=True,
        doc="Virtual medicinal product pack identifier (SNOMED Code). Up to a"
        " maximum of 18 digits."
    )
    vmp_pack_invalid = Column(
        Integer, nullable=True,
        doc="Invalidity flag. If set to 1 indicates this is an invalid entry "
        "in file. 1 integer only."
    )
    vmp_pack_name = Column(
        String(420), nullable=False,
        doc="The virtual medicinal product pack name."
    )
    vmp_pack_name_abrv = Column(
        String(255), nullable=True,
        doc="The abbreviated virtual medicinal product pack name. Not in"
        " the XML documentation so not sure on correct field size."
    )
    vmp_id = Column(
        BigInteger, ForeignKey('virt_med_prod.vmp_id'),
        nullable=False,
        doc="Virtual medicinal product identifier (as above in VMP tag)"
        ". Up to a maximum of 18 digits."
    )
    quant_val = Column(
        Float, nullable=True,
        doc="Quantity value up to a maximum of 10 digits and 2 decimal places."
    )
    quant_unit_meas_cd = Column(
        BigInteger, ForeignKey('lkp_unit_measure.unit_meas_cd'),
        nullable=True,
        doc="Quantity value unit of measure code. Up to a maximum of 18"
        " digits."
    )
    comb_pack_ind_cd = Column(
        Integer, ForeignKey('lkp_comb_pack_ind.comb_pack_ind_cd'),
        nullable=True,
        doc="Combination pack indicator code. Up to 4 digits."
    )

    # -------------------------------------------------------------------------#
    unit_meas = relationship(
        LkpUnitMeasure,
        back_populates='virt_med_prod_pack'
    )
    comb_pack_ind = relationship(
        LkpCombPackInd,
        back_populates='vmp_pack_comb_pack_ind'
    )
    virt_med_prod = relationship(
        VirtMedProd,
        back_populates='virt_med_prod_pack'
    )
    comb_pack_parent = relationship(
        'VmppCombContent',
        primaryjoin="VirtMedProdPack.vmp_pack_id == "
        "VmppCombContent.vmp_pack_parent_id",
        back_populates='vmp_pack_parent'
    )
    comb_pack_child = relationship(
        'VmppCombContent',
        primaryjoin="VirtMedProdPack.vmp_pack_id == "
        "VmppCombContent.vmp_pack_child_id",
        back_populates='vmp_pack_child'
    )
    act_med_prod_pack = relationship(
        'ActMedProdPack',
        back_populates='virt_med_prod_pack'
    )
    drug_tariff_info = relationship(
        'DrugTariffInfo',
        back_populates='virt_med_prod_pack'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class DrugTariffInfo(Base):
    """A representation of the ``drug_tariff_info`` table. This holds data from
    the XML node ``VIRTUAL_MED_PRODUCT_PACK.DRUG_TARIFF_INFO``.

    Parameters
    ----------
    dti_id : `int`
        The primary key - this is not part of the XML file.
    vmp_pack_id : `int`
        Virtual medicinal product pack identifier (SNOMED Code). Up to a
        maximum of 18 digits.
    drug_tariff_cd : `int`
        Drug tariff payment category code.
    drug_tariff_price : `int`
        Drug tariff price.
    drug_tariff_date : `datetime.datetime`
        The date that the drug tariff price is valid from.
    drug_tariff_price_prev : `int`
        The drug tariff price before the ``drug_tariff_date``.

    Notes
    -----
    Drug tariff information for virtual medicinal product packs.
    """
    __tablename__ = 'drug_tariff_info'

    XML_ROOT = 'VIRTUAL_MED_PRODUCT_PACK'
    XML_NODE = 'DRUG_TARIFF_INFO'
    XML_MAPPINGS = dict(
        VPPID=('vmp_pack_id', int),
        PAY_CATCD=('drug_tariff_cd', int),
        PRICE=('drug_tariff_price', int),
        DT=('drug_tariff_date', parse_date),
        PREVPRICE=('drug_tariff_price_prev', int)
    )

    dti_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key - this is not part of the XML file."
    )
    vmp_pack_id = Column(
        BigInteger,  ForeignKey('virt_med_prod_pack.vmp_pack_id'),
        nullable=False,
        doc="Virtual medicinal product pack identifier (SNOMED Code). Up to a"
        " maximum of 18 digits."
    )
    drug_tariff_cd = Column(
        Integer, ForeignKey('lkp_drug_tariff_cat.drug_tariff_cd'),
        nullable=False,
        doc="Drug tariff payment category code."
    )
    drug_tariff_price = Column(
        Integer, nullable=True,
        doc="Drug tariff price."
    )
    drug_tariff_date = Column(
        Date, nullable=True,
        doc="The date that the drug tariff price is valid from."
    )
    drug_tariff_price_prev = Column(
        Integer, nullable=True,
        doc="The drug tariff price before the ``drug_tariff_date``."
    )

    # -------------------------------------------------------------------------#
    drug_tariff_cat = relationship(
        LkpDrugTariffCat,
        back_populates='drug_tariff_info'
    )
    virt_med_prod_pack = relationship(
        VirtMedProdPack,
        back_populates='drug_tariff_info'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class VmppCombContent(Base):
    """A representation of the ``vmp_pack_comb_content`` table. This holds data
    from the XML node ``VIRTUAL_MED_PRODUCT_PACK.COMB_CONTENT``.

    Parameters
    ----------
    vmp_pack_comb_pack_id : `int`
        The primary key - this is not part of the XML file.
    vmp_pack_parent_id : `int`
        The parent virtual medicinal product pack identifier (SNOMED Code). Up
        to maximum of 18 digits.
    vmp_pack_child_id : `int`
        The child virtual medicinal product pack identifier (SNOMED Code). Up
        to maximum of 18 digits.

    Notes
    -----
    Combination pack content for virtual medicinal product packs.
    """
    __tablename__ = 'vmp_pack_comb_content'

    XML_ROOT = 'VIRTUAL_MED_PRODUCT_PACK'
    XML_NODE = 'COMB_CONTENT'
    XML_MAPPINGS = dict(
        PRNTVPPID=('vmp_pack_parent_id', int),
        CHLDVPPID=('vmp_pack_child_id', int)
    )

    vmp_pack_comb_pack_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key - this is not part of the XML file."
    )
    vmp_pack_parent_id = Column(
        BigInteger, ForeignKey('virt_med_prod_pack.vmp_pack_id'),
        nullable=False,
        doc="The parent virtual medicinal product pack identifier "
        "(SNOMED Code). Up to maximum of 18 digits."
    )
    vmp_pack_child_id = Column(
        BigInteger, ForeignKey('virt_med_prod_pack.vmp_pack_id'),
        nullable=False,
        doc="The child virtual medicinal product pack identifier "
        "(SNOMED Code). Up to maximum of 18 digits."
    )

    # -------------------------------------------------------------------------#
    vmp_pack_parent = relationship(
        VirtMedProdPack,
        foreign_keys=[vmp_pack_parent_id],
        back_populates='comb_pack_parent'
    )
    vmp_pack_child = relationship(
        VirtMedProdPack,
        foreign_keys=[vmp_pack_child_id],
        back_populates='comb_pack_child'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class ActMedProd(Base):
    """A representation of the ``act_med_prod`` table. This holds data from the
    XML node ``ACTUAL_MEDICINAL_PRODUCTS.AMPS``.

    Parameters
    ----------
    amp_id : `int`
        Actual medicinal product identifier (as above in VMP tag). Up to a
        maximum of 18 digits.
    amp_invalid : `int`
        Invalidity flag. If set to 1 indicates this is an invalid entry in
        file. 1 integer only.
    vmp_id : `int`
        Virtual medicinal product identifier (as above in VMP tag). Up to a
        maximum of 18 digits.
    amp_name : `str`
        Actual medicinal product name.
    amp_name_abbrev : `str`
        Abbreviated actual medicinal product name.
    amp_desc : `str`
        Actual medicinal product description.
    amp_name_date : `datetime.datetime`
        Date when the actual medicinal product name became applicable.
    amp_name_prev : `str`
        Previous actual medicinal product name.
    supplier_cd : `int`
        Actual medicinal product supplied code.
    lic_auth_cd : `int`
        Actual medicinal product licensing authority code.
    lic_auth_cd_prev : `int`
        Previous actual medicinal product licensing authority code.
    lic_auth_change_cd : `int`
        Code for the reason for change of licensing authority.
    lic_auth_change_date : `datetime.datetime`
        Date of change of licensing authority.
    comb_prod_ind_cd : `int`
        Combination product indicator code.
    flav_cd : `int`
        Flavour code.
    ema : `int`
        EMA additional monitoring indicator.
    parallel_imp : `int`
        Parallel import indicator.
    avail_restrict_cd : `int`
        Restrictions on availability code.

    Notes
    -----
    Actual medicinal products. These are non-generic branded medicines.
    """
    __tablename__ = 'act_med_prod'

    XML_ROOT = 'ACTUAL_MEDICINAL_PRODUCTS'
    XML_NODE = 'AMPS'
    XML_MAPPINGS = dict(
        APID=('amp_id', int),
        INVALID=('amp_invalid', int),
        VPID=('vmp_id', int),
        NM=('amp_name', str),
        ABBREVNM=('amp_name_abbrev', str),
        DESC=('amp_desc', str),
        NMDT=('amp_name_date', parse_date),
        NM_PREV=('amp_name_prev', str),
        SUPPCD=('supplier_cd', int),
        LIC_AUTHCD=('lic_auth_cd', int),
        LIC_AUTH_PREVCD=('lic_auth_cd_prev', int),
        LIC_AUTHCHANGECD=('lic_auth_change_cd', int),
        LIC_AUTHCHANGEDT=('lic_auth_change_date', parse_date),
        COMBPRODCD=('comb_prod_ind_cd', int),
        FLAVOURCD=('flav_cd', int),
        EMA=('ema', int),
        PARALLEL_IMPORT=('parallel_imp', int),
        AVAIL_RESTRICTCD=('avail_restrict_cd', int),
    )

    amp_id = Column(
        BigInteger, nullable=False, primary_key=True,
        doc="Actual medicinal product identifier (as above in VMP tag)"
        ". Up to a maximum of 18 digits."
    )
    amp_invalid = Column(
        SmallInteger, nullable=True,
        doc="Invalidity flag. If set to 1 indicates this is an invalid entry "
        "in file. 1 integer only."
    )
    vmp_id = Column(
        BigInteger,  ForeignKey('virt_med_prod.vmp_id'),
        nullable=False,
        doc="Virtual medicinal product identifier (as above in VMP tag)"
        ". Up to a maximum of 18 digits."
    )
    amp_name = Column(
        String(255), nullable=False,
        doc="Actual medicinal product name."
    )
    amp_name_abbrev = Column(
        String(60), nullable=True,
        doc="Abbreviated actual medicinal product name."
    )
    amp_desc = Column(
        String(700), nullable=False,
        doc="Actual medicinal product description."
    )
    amp_name_date = Column(
        Date, nullable=True,
        doc="Date when the actual medicinal product name became applicable."
    )
    amp_name_prev = Column(
        String(255), nullable=True,
        doc="Previous actual medicinal product name."
    )
    supplier_cd = Column(
        BigInteger, ForeignKey('lkp_supplier.supplier_cd'),
        nullable=False,
        doc="Actual medicinal product supplied code."
    )
    lic_auth_cd = Column(
        Integer, ForeignKey('lkp_licence_auth.lic_auth_cd'),
        nullable=False,
        doc="Actual medicinal product licensing authority code."
    )
    lic_auth_cd_prev = Column(
        Integer, ForeignKey('lkp_licence_auth.lic_auth_cd'),
        nullable=True,
        doc="Previous actual medicinal product licensing authority code."
    )
    lic_auth_change_cd = Column(
        Integer, ForeignKey('lkp_lic_auth_change.lic_auth_change_cd'),
        nullable=True,
        doc="Code for the reason for change of licensing authority."
    )
    lic_auth_change_date = Column(
        Date, nullable=True,
        doc="Date of change of licensing authority."
    )
    comb_prod_ind_cd = Column(
        Integer, ForeignKey('lkp_comb_prod_ind.comb_prod_ind_cd'),
        nullable=True,
        doc="Combination product indicator code."
    )
    flav_cd = Column(
        Integer, ForeignKey('lkp_flavour.flav_cd'),
        nullable=True,
        doc="Flavour code."
    )
    ema = Column(
        SmallInteger, nullable=True,
        doc="EMA additional monitoring indicator."
    )
    parallel_imp = Column(
        SmallInteger, nullable=True,
        doc="Parallel import indicator."
    )
    avail_restrict_cd = Column(
        Integer, ForeignKey('lkp_avail_restrict.avail_restrict_cd'),
        nullable=False,
        doc="Restrictions on availability code."
    )

    # -------------------------------------------------------------------------#
    virt_med_prod = relationship(
        VirtMedProd,
        back_populates='act_med_prod'
    )
    supplier = relationship(
        LkpSupplier,
        back_populates='act_med_prod'
    )
    lic_auth = relationship(
        LkpLicenceAuth,
        foreign_keys=[lic_auth_cd],
        back_populates='act_med_prod'
    )
    lic_auth_prev = relationship(
        LkpLicenceAuth,
        foreign_keys=[lic_auth_cd_prev],
        back_populates='act_med_prod_prev'
    )
    lic_auth_change = relationship(
        LkpLicAuthChange,
        back_populates='act_med_prod'
    )
    comb_prod_ind = relationship(
        LkpCombProdInd,
        back_populates='amp_comb_prod_ind'
    )
    flavour = relationship(
        LkpFlavour,
        back_populates='act_med_prod'
    )
    avail_restrict = relationship(
        LkpAvailRestict,
        back_populates='act_med_prod'
    )
    act_prod_ing = relationship(
        'ActProdIng',
        back_populates='act_med_prod'
    )
    licenced_route = relationship(
        'LicencedRoute',
        back_populates='act_med_prod'
    )
    app_prod_info = relationship(
        'AppProdInfo',
        back_populates='act_med_prod'
    )
    act_med_prod_pack = relationship(
        'ActMedProdPack',
        back_populates='act_med_prod'
    )
    act_med_prod_map = relationship(
        'ActMedProdMap',
        back_populates='act_med_prod'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class ActProdIng(Base):
    """A representation of the ``act_prod_ing`` table. This holds data from the
    XML node ``ACTUAL_MEDICINAL_PRODUCTS.AP_INGREDIENT``.

    Parameters
    ----------
    api_id : `int`
        The primary key - this is not part of the XML file.
    amp_id : `int`
        Actual medicinal product identifier (as above in VMP tag). Up to a
        maximum of 18 digits.
    amp_ingredient_id : `int`
        Ingredient substance identifier (SNOMED Code). Up to a maximum of 18
        integers.
    strength : `float`
        Pharmaceutical strength numerical value - strength value. Up to a
        maximum of 10 digits and 3 decimal places.
    unit_meas_cd : `int`
        Pharmaceutical strength unit measure code.

    Notes
    -----
    Actual medicinal product ingredients.
    """
    __tablename__ = 'act_prod_ing'

    XML_ROOT = 'ACTUAL_MEDICINAL_PRODUCTS'
    XML_NODE = 'AP_INGREDIENT'
    XML_MAPPINGS = dict(
        APID=('amp_id', int),
        ISID=('amp_ingredient_id', int),
        STRNTH=('strength', float),
        UOMCD=('unit_meas_cd', int),
    )
    api_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key - this is not part of the XML file."
    )
    amp_id = Column(
        BigInteger, ForeignKey('act_med_prod.amp_id'),
        nullable=False,
        doc="Actual medicinal product identifier (as above in VMP tag)"
        ". Up to a maximum of 18 digits."
    )
    amp_ingredient_id = Column(
        BigInteger, ForeignKey('ingredient.ingredient_id'), nullable=False,
        doc="Ingredient substance identifier (SNOMED Code). Up to a "
        "maximum of 18 integers."
    )
    strength = Column(
        Float, nullable=True,
        doc="Pharmaceutical strength numerical value - strength value. Up to a"
        " maximum of 10 digits and 3 decimal places."
    )
    unit_meas_cd = Column(
        BigInteger, ForeignKey('lkp_unit_measure.unit_meas_cd'),
        nullable=True,
        doc="Pharmaceutical strength unit measure code."
    )

    # -------------------------------------------------------------------------#
    act_med_prod = relationship(
        ActMedProd,
        back_populates='act_prod_ing'
    )
    unit_meas = relationship(
        LkpUnitMeasure,
        back_populates='act_prod_ing'
    )
    ingredient = relationship(
        Ingredient,
        back_populates='act_prod_ing'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class LicencedRoute(Base):
    """A representation of the ``licenced_route`` table. This holds data from
    the XML node ``ACTUAL_MEDICINAL_PRODUCTS.LICENSED_ROUTE``.

    Parameters
    ----------
    lr_id : `int`
        The primary key - this is not part of the XML file.
    amp_id : `int`
        Actual medicinal product identifier (as above in VMP tag). Up to a
        maximum of 18 digits.
    lr_rt_cd : `int`
        Licensed route code.

    Notes
    -----
    Licensed route for actual medicinal products.
    """
    __tablename__ = 'licenced_route'

    XML_ROOT = 'ACTUAL_MEDICINAL_PRODUCTS'
    XML_NODE = 'LICENSED_ROUTE'
    XML_MAPPINGS = dict(
        APID=('amp_id', int),
        ROUTECD=('lr_rt_cd', int)
    )
    lr_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key - this is not part of the XML file."
    )
    amp_id = Column(
        BigInteger, ForeignKey('act_med_prod.amp_id'),
        nullable=False,
        doc="Actual medicinal product identifier (as above in VMP tag)"
        ". Up to a maximum of 18 digits."
    )
    lr_rt_cd = Column(
        BigInteger, ForeignKey('lkp_route.route_cd'),
        nullable=False,
        doc="Licensed route code."
    )

    # -------------------------------------------------------------------------#
    act_med_prod = relationship(
        ActMedProd,
        back_populates='licenced_route'
    )
    route = relationship(
        LkpRoute,
        back_populates='licenced_route'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class AppProdInfo(Base):
    """A representation of the ``app_prod_info`` table. This holds data from
    the XML node ``ACTUAL_MEDICINAL_PRODUCTS.AP_INFORMATION``.

    Parameters
    ----------
    app_id : `int`
        The primary key - this is not part of the XML file.
    amp_id : `int`
        Actual medicinal product identifier (as above in VMP tag). Up to a
        maximum of 18 digits.
    size_weight : `str`
        Size/weight.
    colour_cd : `int`
        The colour code.
    prod_order_no : `str`
        The product order number.

    Notes
    -----
    The appliance product information.
    """
    __tablename__ = 'app_prod_info'

    XML_ROOT = 'ACTUAL_MEDICINAL_PRODUCTS'
    XML_NODE = 'AP_INFORMATION'
    XML_MAPPINGS = dict(
        APID=('amp_id', int),
        SZ_WEIGHT=('size_weight', str),
        COLOURCD=('colour_cd', int),
        PROD_ORDER_NO=('prod_order_no', str),
    )

    app_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key - this is not part of the XML file."
    )
    amp_id = Column(
        BigInteger, ForeignKey('act_med_prod.amp_id'),
        nullable=False,
        doc="Actual medicinal product identifier (as above in VMP tag)"
        ". Up to a maximum of 18 digits."
    )
    size_weight = Column(
        String(100), nullable=True,
        doc="Size/weight."
    )
    colour_cd = Column(
        Integer, ForeignKey('lkp_colour.colour_cd'),
        nullable=True,
        doc="The colour code."
    )
    prod_order_no = Column(
        String(20), nullable=True,
        doc="The product order number."
    )

    # -------------------------------------------------------------------------#
    act_med_prod = relationship(
        ActMedProd,
        back_populates='app_prod_info'
    )
    colour = relationship(
        LkpColour,
        back_populates='app_prod_info'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class ActMedProdPack(Base):
    """A representation of the ``act_med_prod_pack`` table. This holds data
    from the XML node ``ACTUAL_MEDICINAL_PROD_PACKS.AMPPS``.

    Parameters
    ----------
    amp_pack_id : `int`
        Actual medicinal product pack identifier (SNOMED Code), up to a maximum
        of 18 digits.
    amp_pack_invalid : `int`
        Invalidity flag. If set to 1 indicates this is an invalid entry in
        file. 1 integer only.
    amp_pack_name : `str`
        Actual medicinal product pack description.
    amp_pack_name_abrv : `str`
        Abbreviated actual medicinal product pack description.
    vmp_pack_id : `int`
        Virtual medicinal product pack identifier (SNOMED Code). Up to a
        maximum of 18 digits.
    amp_id : `int`
        Actual medicinal product identifier (as above in VMP tag). Up to a
        maximum of 18 digits.
    comb_pack_ind_cd : `int`
        Combination pack indicator code.
    legal_cat_cd : `int`
        Legal category code.
    sub_pack_info : `str`
        Sub-pack information.
    discon_ind_cd : `int`
        Discontinued flag code.
    discon_ind_date : `datetime.datetime`
        Discontinued flag change date.

    Notes
    -----
    The actual medicinal product pack. Links back to actual medicinal product
    and virtual medicinal product pack.
    """
    __tablename__ = 'act_med_prod_pack'

    XML_ROOT = 'ACTUAL_MEDICINAL_PROD_PACKS'
    XML_NODE = 'AMPPS'
    XML_MAPPINGS = dict(
        APPID=('amp_pack_id', int),
        INVALID=('amp_pack_invalid', int),
        NM=('amp_pack_name', str),
        ABBREVNM=('amp_pack_name_abrv', str),
        VPPID=('vmp_pack_id', int),
        APID=('amp_id', int),
        COMBPACKCD=('comb_pack_ind_cd', int),
        LEGAL_CATCD=('legal_cat_cd', int),
        SUBP=('sub_pack_info', str),
        DISCCD=('discon_ind_cd', int),
        DISCDT=('discon_ind_date', parse_date),
    )
    amp_pack_id = Column(
        BigInteger, nullable=False, primary_key=True,
        doc="Actual medicinal product pack identifier (SNOMED Code), up to a"
        " maximum of 18 digits."
    )
    amp_pack_invalid = Column(
        SmallInteger, nullable=True,
        doc="Invalidity flag. If set to 1 indicates this is an invalid entry "
        "in file. 1 integer only."
    )
    amp_pack_name = Column(
        String(774), nullable=False,
        doc="Actual medicinal product pack description."
    )
    amp_pack_name_abrv = Column(
        String(60), nullable=True,
        doc="Abbreviated actual medicinal product pack description."
    )
    vmp_pack_id = Column(
        BigInteger, ForeignKey('virt_med_prod_pack.vmp_pack_id'),
        nullable=False,
        doc="Virtual medicinal product pack identifier (SNOMED Code). Up to a"
        " maximum of 18 digits."
    )
    amp_id = Column(
        BigInteger, ForeignKey('act_med_prod.amp_id'),
        nullable=False,
        doc="Actual medicinal product identifier (as above in VMP tag)"
        ". Up to a maximum of 18 digits."
    )
    comb_pack_ind_cd = Column(
        Integer, ForeignKey('lkp_comb_pack_ind.comb_pack_ind_cd'),
        nullable=True,
        doc="Combination pack indicator code."
    )
    legal_cat_cd = Column(
        Integer, ForeignKey('lkp_legal_cat.legal_cat_cd'),
        nullable=False,
        doc="Legal category code."
    )
    sub_pack_info = Column(
        String(30), nullable=True,
        doc="Sub-pack information."
    )
    discon_ind_cd = Column(
        Integer, ForeignKey('lkp_discon_ind.discon_ind_cd'),
        nullable=True,
        doc="Discontinued flag code."
    )
    discon_ind_date = Column(
        Date, nullable=True,
        doc="Discontinued flag change date."
    )

    # -------------------------------------------------------------------------#
    virt_med_prod_pack = relationship(
        VirtMedProdPack,
        back_populates='act_med_prod_pack'
    )
    act_med_prod = relationship(
        ActMedProd,
        back_populates='act_med_prod_pack'
    )
    comb_pack_ind = relationship(
        LkpCombPackInd,
        back_populates='ampp_comb_pack_ind'
    )
    legal_cat = relationship(
        LkpLegalCat,
        back_populates='act_med_prod_pack'
    )
    discon_ind = relationship(
        LkpDisconInd,
        back_populates='act_med_prod_pack'
    )
    app_pack_info = relationship(
        'AppPackInfo',
        back_populates='act_med_prod_pack'
    )
    drug_pres_info = relationship(
        'DrugPresInfo',
        back_populates='act_med_prod_pack'
    )
    med_prod_price = relationship(
        'MedProdPrice',
        back_populates='act_med_prod_pack'
    )
    reimb_info = relationship(
        'ReimbInfo',
        back_populates='act_med_prod_pack'
    )
    comb_pack_parent = relationship(
        'AmppCombPackContent',
        primaryjoin="ActMedProdPack.amp_pack_id == "
        "AmppCombPackContent.amp_pack_parent_id",
        back_populates='amp_pack_parent'
    )
    comb_pack_child = relationship(
        'AmppCombPackContent',
        primaryjoin="ActMedProdPack.amp_pack_id == "
        "AmppCombPackContent.amp_pack_child_id",
        back_populates='amp_pack_child'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class AppPackInfo(Base):
    """A representation of the ``app_pack_info`` table. This holds data from
    the XML node ``ACTUAL_MEDICINAL_PROD_PACKS.APPLIANCE_PACK_INFO``.

    Parameters
    ----------
    app_pack_info_id : `int`
        The primary key - this is not part of the XML file.
    amp_pack_id : `int`
        Actual medicinal product pack identifier (SNOMED Code), up to a maximum
        of 18 digits.
    reimb_status_cd : `int`
        Appliance reimbursement status code.
    reimb_status_date : `datetime.datetime`
        Date appliance reimbursement status code becomes effective.
    reimb_status_cd_prev : `int`
        Previous appliance reimbursement status code.
    pack_order_no : `str`
        Pack order number - order number of pack within drug tariff. Up to a
        maximum of 20 characters.

    Notes
    -----
    Appliance pack information.
    """
    __tablename__ = 'app_pack_info'

    XML_ROOT = 'ACTUAL_MEDICINAL_PROD_PACKS'
    XML_NODE = 'APPLIANCE_PACK_INFO'
    XML_MAPPINGS = dict(
        APPID=('amp_pack_id', int),
        REIMB_STATCD=('reimb_status_cd', int),
        REIMB_STATDT=('reimb_status_date', parse_date),
        REIMB_STATPREVCD=('reimb_status_cd_prev', int),
        PACK_ORDER_NO=('pack_order_no', str)
    )

    app_pack_info_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key - this is not part of the XML file."
    )
    amp_pack_id = Column(
        BigInteger, ForeignKey('act_med_prod_pack.amp_pack_id'),
        nullable=False,
        doc="Actual medicinal product pack identifier (SNOMED Code), up to a"
        " maximum of 18 digits."
    )
    reimb_status_cd = Column(
        Integer, ForeignKey('lkp_reimb_status.reimb_status_cd'),
        nullable=False,
        doc="Appliance reimbursement status code."
    )
    reimb_status_date = Column(
        Date, nullable=True,
        doc="Date appliance reimbursement status code becomes effective."
    )
    reimb_status_cd_prev = Column(
        Integer, ForeignKey('lkp_reimb_status.reimb_status_cd'),
        nullable=True,
        doc="Previous appliance reimbursement status code."
    )
    # TODO: Link to drug tariff?
    pack_order_no = Column(
        String(20), nullable=True,
        doc="Pack order number - order number of pack within drug tariff. Up "
        "to a maximum of 20 characters."
    )

    # -------------------------------------------------------------------------#
    act_med_prod_pack = relationship(
        ActMedProdPack,
        back_populates='app_pack_info'
    )
    reimb_status = relationship(
        LkpReimbStatus,
        foreign_keys=[reimb_status_cd],
        back_populates='app_pack_info'
    )
    reimb_status_prev = relationship(
        LkpReimbStatus,
        foreign_keys=[reimb_status_cd_prev],
        back_populates='app_pack_info_prev'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class DrugPresInfo(Base):
    """A representation of the ``drug_pres_info`` table. This holds data from
    the XML node ``ACTUAL_MEDICINAL_PROD_PACKS.DRUG_PRODUCT_PRESCRIB_INFO``.

    Parameters
    ----------
    dpi_id : `int`
        The primary key - this is not part of the XML file.
    amp_pack_id : `int`
        Actual medicinal product pack identifier (SNOMED Code), up to a maximum
        of 18 digits.
    schedule_two : `int`
        Schedule two indicator.
    acbs : `int`
        ACBS indicator.
    personal_admin : `int`
        Personally administered indicator.
    fp_ten : `int`
        FP10 MDA prescription indicator.
    schedule_one : `int`
        Schedule one indicator.
    hospital : `int`
        Hospital indicator.
    nurse : `int`
        Nurse formulary indicator.
    nurse_ext : `int`
        Nurse extended formulary indicator.
    dental : `int`
        Dental formulary indicator.

    Notes
    -----
    Drug product prescribing information. Links to actual medicinal product
    pack table.
    """
    __tablename__ = 'drug_pres_info'

    XML_ROOT = 'ACTUAL_MEDICINAL_PROD_PACKS'
    XML_NODE = 'DRUG_PRODUCT_PRESCRIB_INFO'
    XML_MAPPINGS = dict(
        APPID=('amp_pack_id', int),
        SCHED_2=('schedule_two', int),
        ACBS=('acbs', int),
        PADM=('personal_admin', int),
        FP10_MDA=('fp_ten', int),
        SCHED_1=('schedule_one', int),
        HOSP=('hospital', int),
        NURSE_F=('nurse', int),
        ENURSE_F=('nurse_ext', int),
        DENT_F=('dental', int)
    )
    dpi_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key - this is not part of the XML file."
    )
    amp_pack_id = Column(
        BigInteger, ForeignKey('act_med_prod_pack.amp_pack_id'),
        nullable=False,
        doc="Actual medicinal product pack identifier (SNOMED Code), up to a"
        " maximum of 18 digits."
    )
    schedule_two = Column(
        SmallInteger, nullable=True,
        doc="Schedule two indicator."
    )
    acbs = Column(
        SmallInteger, nullable=True,
        doc="ACBS indicator."
    )
    personal_admin = Column(
        SmallInteger, nullable=True,
        doc="Personally administered indicator."
    )
    fp_ten = Column(
        SmallInteger, nullable=True,
        doc="FP10 MDA prescription indicator."
    )
    schedule_one = Column(
        SmallInteger, nullable=True,
        doc="Schedule one indicator."
    )
    hospital = Column(
        SmallInteger, nullable=True,
        doc="Hospital indicator."
    )
    nurse = Column(
        SmallInteger, nullable=True,
        doc="Nurse formulary indicator."
    )
    nurse_ext = Column(
        SmallInteger, nullable=True,
        doc="Nurse extended formulary indicator."
    )
    dental = Column(
        SmallInteger, nullable=True,
        doc="Dental formulary indicator."
    )

    # -------------------------------------------------------------------------#
    act_med_prod_pack = relationship(
        ActMedProdPack,
        back_populates='drug_pres_info'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class MedProdPrice(Base):
    """A representation of the ``med_prod_price`` table. This holds data from
    the XML node ``ACTUAL_MEDICINAL_PROD_PACKS.MEDICINAL_PRODUCT_PRICE``.

    Parameters
    ----------
    mpp_id : `int`
        The primary key - this is not part of the XML file.
    amp_pack_id : `int`
        Actual medicinal product pack identifier (SNOMED Code), up to a maximum
        of 18 digits.
    price : `int`
        Actual medicinal product pack price.
    price_date : `datetime.datetime`
        Date of price validity.
    price_prev : `int`
        Previous actual medicinal product pack price.
    basis_price_cd : `int`
        Basis of price code.

    Notes
    -----
    Actual medicinal product pack price.
    """
    __tablename__ = 'med_prod_price'

    XML_ROOT = 'ACTUAL_MEDICINAL_PROD_PACKS'
    XML_NODE = 'MEDICINAL_PRODUCT_PRICE'
    XML_MAPPINGS = dict(
        APPID=('amp_pack_id', int),
        PRICE=('price', int),
        PRICEDT=('price_date', parse_date),
        PRICE_PREV=('price_prev', int),
        PRICE_BASISCD=('basis_price_cd', int)
    )

    mpp_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key - this is not part of the XML file."
    )
    amp_pack_id = Column(
        BigInteger, ForeignKey('act_med_prod_pack.amp_pack_id'),
        nullable=False,
        doc="Actual medicinal product pack identifier (SNOMED Code), up to a"
        " maximum of 18 digits."
    )
    price = Column(
        Integer, nullable=True,
        doc="Actual medicinal product pack price."
    )
    price_date = Column(
        Date, nullable=True,
        doc="Date of price validity."
    )
    price_prev = Column(
        Integer, nullable=True,
        doc="Previous actual medicinal product pack price."
    )
    basis_price_cd = Column(
        Integer, ForeignKey('lkp_basis_price.basis_price_cd'),
        nullable=False,
        doc="Basis of price code."
    )

    # -------------------------------------------------------------------------#
    act_med_prod_pack = relationship(
        ActMedProdPack,
        back_populates='med_prod_price'
    )
    basis_price = relationship(
        LkpBasisPrice,
        back_populates='med_prod_price'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class ReimbInfo(Base):
    """A representation of the ``reimb_info`` table. This holds data from the
    XML node ``ACTUAL_MEDICINAL_PROD_PACKS.REIMBURSEMENT_INFO``.

    Parameters
    ----------
    ri_id : `int`
        The primary key - this is not part of the XML file.
    amp_pack_id : `int`
        Actual medicinal product pack identifier (SNOMED Code), up to a maximum
        of 18 digits.
    pres_charges : `int`
        Prescription charges.
    disp_fees : `int`
        Dispensing fees.
    broken_bulk : `int`
        Broken bulk indicator.
    ltd_stab : `int`
        The Drug Tariff no longer identifies products for this purpose.
        Therefore this indicator is no longer populated in dm+d. The data field
        will persist but remains blank.
    calendar_pack : `int`
        Calendar pack indicator.
    special_cont_cd : `int`
        Special container indicator code.
    dnd_cd : `int`
        Discount not deducted indicator code.
    fp_three_four_d : `int`
        FP34D prescription item indicator.

    Notes
    -----
    Actual medicinal product pack reimbursement information.
    """
    __tablename__ = 'reimb_info'

    XML_ROOT = 'ACTUAL_MEDICINAL_PROD_PACKS'
    XML_NODE = 'REIMBURSEMENT_INFO'
    XML_MAPPINGS = dict(
        APPID=('amp_pack_id', int),
        PX_CHRGS=('pres_charges', int),
        DISP_FEES=('disp_fees', int),
        BB=('broken_bulk', int),
        LTD_STAB=('ltd_stab', int),
        CAL_PACK=('calendar_pack', int),
        SPEC_CONTCD=('special_cont_cd', int),
        DND=('dnd_cd', int),
        FP34D=('fp_three_four_d', int)
    )

    ri_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key - this is not part of the XML file."
    )
    amp_pack_id = Column(
        BigInteger, ForeignKey('act_med_prod_pack.amp_pack_id'),
        nullable=False,
        doc="Actual medicinal product pack identifier (SNOMED Code), up to a"
        " maximum of 18 digits."
    )
    pres_charges = Column(
        Integer, nullable=True,
        doc="Prescription charges."
    )
    disp_fees = Column(
        Integer, nullable=True,
        doc="Dispensing fees."
    )
    broken_bulk = Column(
        SmallInteger, nullable=True,
        doc="Broken bulk indicator."
    )
    ltd_stab = Column(
        Integer, nullable=True,
        doc="The Drug Tariff no longer identifies products for this purpose."
        " Therefore this indicator is no longer populated in dm+d. The data"
        " field will persist but remains blank."
    )
    calendar_pack = Column(
        SmallInteger, nullable=True,
        doc="Calendar pack indicator."
    )
    special_cont_cd = Column(
        Integer, ForeignKey('lkp_special_cont.special_cont_cd'),
        nullable=True,
        doc="Special container indicator code."
    )
    dnd_cd = Column(
        Integer, ForeignKey('lkp_dnd.dnd_cd'),
        nullable=True,
        doc="Discount not deducted indicator code."
    )
    fp_three_four_d = Column(
        SmallInteger, nullable=True,
        doc="FP34D prescription item indicator."
    )

    # -------------------------------------------------------------------------#
    act_med_prod_pack = relationship(
        ActMedProdPack,
        back_populates='reimb_info'
    )
    special_cont = relationship(
        LkpSpecialCont,
        back_populates='reimb_info'
    )
    dnd = relationship(
        LkpDnd,
        back_populates='reimb_info'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class AmppCombPackContent(Base):
    """A representation of the ``ampp_comb_pack_content`` table. This holds
    data from the XML node ``ACTUAL_MEDICINAL_PROD_PACKS.COMB_CONTENT``.

    Parameters
    ----------
    ampp_comb_pack_id : `int`
        The primary key - this is not part of the XML file.
    amp_pack_parent_id : `int`
        Actual medicinal product combination pack content parent ID.
    amp_pack_child_id : `int`
        Actual medicinal product combination pack content child ID.

    Notes
    -----
    Actual medicinal product combination pack content.
    """
    __tablename__ = 'ampp_comb_pack_content'

    XML_ROOT = 'ACTUAL_MEDICINAL_PROD_PACKS'
    XML_NODE = 'COMB_CONTENT'
    XML_MAPPINGS = dict(
        PRNTAPPID=('amp_pack_parent_id', int),
        CHLDAPPID=('amp_pack_child_id', int)
    )

    ampp_comb_pack_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key - this is not part of the XML file."
    )
    amp_pack_parent_id = Column(
        BigInteger, ForeignKey('act_med_prod_pack.amp_pack_id'),
        nullable=False,
        doc="Actual medicinal product combination pack content parent ID."
    )
    amp_pack_child_id = Column(
        BigInteger, ForeignKey('act_med_prod_pack.amp_pack_id'),
        nullable=False,
        doc="Actual medicinal product combination pack content child ID."
    )

    # -------------------------------------------------------------------------#
    amp_pack_parent = relationship(
        ActMedProdPack,
        foreign_keys=[amp_pack_parent_id],
        back_populates='comb_pack_parent'
    )
    amp_pack_child = relationship(
        ActMedProdPack,
        foreign_keys=[amp_pack_child_id],
        back_populates='comb_pack_child'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class VirtMedProdMap(Base):
    """A representation of the ``virt_med_prod_map`` table. This holds data
    from the XML node ``BNF_DETAILS.VMPS``.

    Parameters
    ----------
    vmpm_id : `int`
        The primary key - this is not part of the XML file.
    vmp_id : `int`
        Virtual medicinal product identifier (as above in VMP tag). Up to a
        maximum of 18 digits.
    bnf : `int`
        The British National Formulary (BNF) chapter mapping.
    atc : `str`
        The Anatomic Therapeutic Chemical (ATC) code mapping.
    ddd : `float`
        The defined daily dose.
    ddd_unit_meas_cd : `int`
        The drug daily dose unit of measure.

    Notes
    -----
    The virtual medicinal product mappings.
    """
    __tablename__ = 'virt_med_prod_map'

    XML_ROOT = 'BNF_DETAILS'
    XML_NODE = 'VMPS'
    XML_MAPPINGS = dict(
        VPID=('vmp_id', int),
        BNF=('bnf', int),
        ATC=('atc', str),
        DDD=('ddd', float),
        DDD_UOMCD=('ddd_unit_meas_cd', int),
    )

    vmpm_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key - this is not part of the XML file."
    )
    vmp_id = Column(
        BigInteger, ForeignKey('virt_med_prod.vmp_id'),
        nullable=False,
        doc="Virtual medicinal product identifier (as above in VMP tag)"
        ". Up to a maximum of 18 digits."
    )
    bnf = Column(
        Integer, nullable=True,
        doc="The British National Formulary (BNF) chapter mapping."
    )
    atc = Column(
        String(255), nullable=True,
        doc="The Anatomic Therapeutic Chemical (ATC) code mapping."
    )
    ddd = Column(
        Float, nullable=True,
        doc="The defined daily dose."
    )
    ddd_unit_meas_cd = Column(
        BigInteger, ForeignKey('lkp_unit_measure.unit_meas_cd'),
        nullable=True,
        doc="The drug daily dose unit of measure."
    )

    # -------------------------------------------------------------------------#
    virt_med_prod = relationship(
        VirtMedProd,
        back_populates='virt_med_prod_map'
    )
    unit_meas = relationship(
        LkpUnitMeasure,
        back_populates='virt_med_prod_map'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
class ActMedProdMap(Base):
    """A representation of the ``act_med_prod_map`` table. This holds data from
    the XML node ``BNF_DETAILS.AMPS``.

    Parameters
    ----------
    ampm_id : `int`
        The primary key - this is not part of the XML file.
    amp_id : `int`
        Actual medicinal product identifier (as above in VMP tag). Up to a
        maximum of 18 digits.
    bnf : `int`
        The British National Formulary (BNF) chapter mapping.

    Notes
    -----
    The actual medicinal product mappings.
    """
    __tablename__ = 'act_med_prod_map'

    XML_ROOT = 'BNF_DETAILS'
    XML_NODE = 'AMPS'
    XML_MAPPINGS = dict(
        APID=('amp_id', int),
        BNF=('bnf', int)
    )

    ampm_id = Column(
        Integer, nullable=False, primary_key=True,
        doc="The primary key - this is not part of the XML file."
    )
    amp_id = Column(
        BigInteger, ForeignKey('act_med_prod.amp_id'),
        nullable=False,
        doc="Actual medicinal product identifier (as above in VMP tag)"
        ". Up to a maximum of 18 digits."
    )
    bnf = Column(
        Integer, nullable=True,
        doc="The British National Formulary (BNF) chapter mapping."
    )

    # -------------------------------------------------------------------------#
    act_med_prod = relationship(
        ActMedProd,
        back_populates='act_med_prod_map'
    )
    # -------------------------------------------------------------------------#

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    def __repr__(self):
        return common.print_orm_obj(self)


# #############################################################################
# ####################### MAPPINGS INTO THE ORM CLASSES #######################
# #############################################################################


LOOKUP_MAPPINGS = dict(
    COMBINATION_PACK_IND=LkpCombPackInd,
    COMBINATION_PROD_IND=LkpCombProdInd,
    BASIS_OF_NAME=LkpBasisOfName,
    NAMECHANGE_REASON=LkpNameChangeReason,
    VIRTUAL_PRODUCT_PRES_STATUS=LkpVirtualProdPresStatus,
    CONTROL_DRUG_CATEGORY=LkpControlDrugCat,
    LICENSING_AUTHORITY=LkpLicenceAuth,
    UNIT_OF_MEASURE=LkpUnitMeasure,
    FORM=LkpForm,
    ONT_FORM_ROUTE=LkpOntFormRoute,
    ROUTE=LkpRoute,
    DT_PAYMENT_CATEGORY=LkpDrugTariffCat,
    SUPPLIER=LkpSupplier,
    FLAVOUR=LkpFlavour,
    COLOUR=LkpColour,
    BASIS_OF_STRNTH=LkpBasisStrength,
    REIMBURSEMENT_STATUS=LkpReimbStatus,
    SPEC_CONT=LkpSpecialCont,
    DND=LkpDnd,
    VIRTUAL_PRODUCT_NON_AVAIL=LkpVirtMedProdNa,
    DISCONTINUED_IND=LkpDisconInd,
    DF_INDICATOR=LkpDoseFormInd,
    PRICE_BASIS=LkpBasisPrice,
    LEGAL_CATEGORY=LkpLegalCat,
    AVAILABILITY_RESTRICTION=LkpAvailRestict,
    LICENSING_AUTHORITY_CHANGE_REASON=LkpLicAuthChange
)
"""Mappings from XML element section names into SQLAlchemy ORM Lookup
classes (`dict`)
"""

VTM_MAPPINGS = dict(
    VIRTUAL_THERAPEUTIC_MOIETIES=VirtTherMoiet,
)
"""Mappings from XML element section names into SQLAlchemy ORM VTM
classes (`dict`)
"""

IS_MAPPINGS = dict(
    INGREDIENT_SUBSTANCES=Ingredient,
)
"""Mappings from XML element section names into SQLAlchemy ORM VTM
classes (`dict`)
"""

VMP_MAPPINGS = dict(
    VMPS=VirtMedProd,
    VIRTUAL_PRODUCT_INGREDIENT=VirtProdIng,
    ONT_DRUG_FORM=OntDrugForm,
    DRUG_FORM=DrugForm,
    DRUG_ROUTE=DrugRoute,
    CONTROL_DRUG_INFO=ContDrugInfo
)
"""Mappings from XML element section names into SQLAlchemy ORM VMP
classes (`dict`)
"""

VMPP_MAPPINGS = dict(
    VMPPS=VirtMedProdPack,
    DRUG_TARIFF_INFO=DrugTariffInfo,
    COMB_CONTENT=VmppCombContent
)
"""Mappings from XML element section names into SQLAlchemy ORM VMPP
classes (`dict`)
"""

AMP_MAPPINGS = dict(
    AMPS=ActMedProd,
    AP_INGREDIENT=ActProdIng,
    LICENSED_ROUTE=LicencedRoute,
    AP_INFORMATION=AppProdInfo
)
"""Mappings from XML element section names into SQLAlchemy ORM AMP
classes (`dict`)
"""

AMPP_MAPPINGS = dict(
    AMPPS=ActMedProdPack,
    APPLIANCE_PACK_INFO=AppPackInfo,
    DRUG_PRODUCT_PRESCRIB_INFO=DrugPresInfo,
    MEDICINAL_PRODUCT_PRICE=MedProdPrice,
    REIMBURSEMENT_INFO=ReimbInfo,
    COMB_CONTENT=AmppCombPackContent
)
"""Mappings from XML element section names into SQLAlchemy ORM AMPP
classes (`dict`)
"""

BNF_MAPPINGS = dict(
    VMPS=VirtMedProdMap,
    AMPS=ActMedProdMap
)
"""Mappings from XML element section names into SQLAlchemy ORM BNF
classes (`dict`)
"""

MAPPINGS = dict(
    lookup=LOOKUP_MAPPINGS,
    vtm=VTM_MAPPINGS,
    ingredient=IS_MAPPINGS,
    vmp=VMP_MAPPINGS,
    vmpp=VMPP_MAPPINGS,
    amp=AMP_MAPPINGS,
    ampp=AMPP_MAPPINGS,
    bnf=BNF_MAPPINGS
)
"""Master mappings table the keys are XML file types and the values are
individual mappings into ORM classes (`dict`)
"""
