2020 September Release

Basic App RoomPermanent link for this heading

The contract management app should allow managing contracts in contract shelves (app rooms). Settings can be defined in the app configuration. The fully-implemented basic example looks like that:

Object ModelPermanent link for this heading

First of all, the app itself is needed.

app.ducx-om

objmodel DEMOCONTRACTMGMT@111.100
{
  import COOATTREDIT@1.1;
  import COODESK@1.1;
  import COOSYSTEM@1.1;
  import COOTC@1.1001;

  instance App AppContractMgmt {
    symbol = SymbolAgreement;
    appdescriptionstr = {}
  }
}

In addition, define the following object model:

  • App Dashboard ContractDashboard (derived from AppDashboard)
    The dashboard is the central access point to your app. It provides a recently used list of contracts and a list of contract shelves (property dbapprooms).
  • App Configuration ContractConfiguration (derived from AppConfigurationRoom)
    The configuration can be used to define customizations and store settings. AppConfigurationRoom provides by default fields like Forms and Categories, Processes, Templates and so on.
  • App Room ContractShelf (derived from AppRoom)
    The room is used to store contracts and define access rights. AppRoom provides by default a Teamroom-like behavior.
  • Contract Contract (derived from CompoundObject)
    The contract metadata and documents can be stored in contract objects.

model.ducx-om

objmodel DEMOCONTRACTMGMT@111.100
{
  import COOATTREDIT@1.1;
  import COODESK@1.1;
  import COOMAPI@1.1;
  import COOSYSTEM@1.1;
  import FSCFOLIO@1.1001;
  import FSCTEAMROOM@1.1001;
  
  /**
   * The dashboard for contract management

   */

  class ContractDashboard : AppDashboard {
    compapps = AppContractMgmt;
    symbol = SymbolAgreement;
    // Shows recently used contracts, for more information see the
    // description after this example

    unique Contract[] cdrecentlyusedcontracts volatile(tx) readonly {
      get = AttrCdRecentlyUsedContractsGet;
      copy = NoOperation;
    }
    // Helper property for the recently used list
    unique RecentlyUsedElements[] cdrecentlyusedelements invisible {
      attractsearch = AttrSearchNotPossible;
      copy = NoOperation;
    }
  }
  
  /**
   * The configuration room for
the contract management
   */

  class ContractConfiguration : AppConfigurationRoom {
    compapps = AppContractMgmt;
    symbol = SymbolAgreement;
  }
  
  /**
   * The room containing all contracts

   */

  class ContractShelf : AppRoom {
    compapps = AppContractMgmt;
    symbol = SymbolRecordFilled;
    Contract[] cscontracts {
      child = true;
    }
  }
  
  /**
   *
The contract containing all documents and meta data
   */

  class Contract : CompoundObject {
    compapps = AppContractMgmt;
    symbol = SymbolBill;
    string ctpartner not null;
    string[] ctdescription;
    date ctstart;
    date ctend {
      validate = expression {
        !::value || !cooobj.ctstart || cooobj.ctstart <= ::value;
      }
    }
    ContentObject[] ctdocuments {
      child = true;
    }
    Address[] ctaddress;
    Telephone[] cttelephone;
    EmailInformation[] ctemailinformation;
  }
}

To calculate the “Recently Used” list of the dashboard following is needed (see also usecases.ducx-uc):

  • cdrecentlyusedelements is an invisible helper property that stores the recently used elements with time stamp.
  • The actions AddRecentlyUsedToAppDashboard and GetRecentlyUsedDisplayAttributes need to be overridden to provide the “recently used” functionality for contracts.
  • cdrecentlyusedcontracts shows the contracts based on the get action AttrCdRecentlyUsedContractsGet.
  • The get action AttrCdRecentlyUsedContractsGet returns contracts based on the timestamp.

User InterfacePermanent link for this heading

Define the following user interface:

  • The dashboard should show the last recently used list and the contract shelf list.
  • The configuration should inherit default pages and show the contract shelf list.
  • The contract shelf should show the contract list with defined columns.
  • The contract should show the documents in explore mode and the metadata when editing the contract.
  • Actions for creating a contract shelf or contract should be available to the user.

forms.ducx-ui

userinterface DEMOCONTRACTMGMT@111.100
{
  import COOATTREDIT@1.1;
  import COODESK@1.1;
  import COOSEARCH@1.1;
  import COOSYSTEM@1.1;
  import FSCTEAMROOM@1.1001;
  
  form FormContractDashboardExplore {
    inherit = false;
    formpage PageRecentlyUsedContracts {
      dataset { cdrecentlyusedcontracts; }
    }
    formpage PageDBContractShelves {
      dataset { dbapprooms; }
    }
  }
  
  form FormContractConfigurationExplore {
    inherit = true;
    formpage PageContractShelves {
      dataset { acapprooms; }
    }
  }
  
  form FormContractShelfExplore {
    inherit = false;
    formpage PageContracts {
      dataset { cscontracts; }
    }
  }
  
  form FromContract {
    formpage PageContract {
      dataset {
        Contract;
      }
      layout {
        row {
          objname {
            mustbedef = expression { true; }
          }
        }
        row { ctpartner; }
        row { ctdescription; }
        row {
          ctstart;
          ctend;
        }
        row { ctaddress; }
        row { cttelephone; }
        row { ctemailinformation; }
      }
    }
  }
  
  form FormContractExplore {
    inherit = false;
    formpage PageContractDocuments {
      dataset { ctdocuments; }
    }
  }
  
  forms for ContractDashboard {
     ExploreObject { FormContractDashboardExplore; }
  }
  
  forms for ContractConfiguration {
    ExploreObject { FormContractConfigurationExplore; }
  }
  
  forms for ContractShelf {
    ExploreObject { FormContractShelfExplore; }
  }
  
  forms for Contract {
    default, ObjectConstructor { FromContract; }
    ExploreObject { FormContractExplore; }
  }
  
  columns for ContractShelf {
    cscontracts {
      objname;
      ctpartner;
      ctstart;
      ctend;
    }
  }
  
  menus for ContractConfiguration {
    TaskPaneExpansion {
      target = [dashboard, acapprooms];
      MenuCreateContractShelf;
    }
  }

  menus for ContractDashboard {
    TaskPaneExpansion {
      target = [dashboard, dbapprooms];
      MenuCreateContractShelf;
    }
  }
  
  menus for ContractShelf {
    TaskPaneExpansion {
      MenuCreateContract;
    }
  }
}

Use CasesPermanent link for this heading

Define the following functionality:

  • The use cases for creating a contract shelf and a contract have to be implemented.
  • The recently used functionality of the dashboard has to be implemented.

usecases.ducx-uc

usecases DEMOCONTRACTMGMT@111.100
{
  import COOATTREDIT@1.1;
  import COODESK@1.1;
  import COOSYSTEM@1.1;
  import COOTC@1.1001;
  import FSCFOLIO@1.1001;
  import FSCTEAMROOM@1.1001;
  import FSCVAPP@1.1001;
  import FSCVENV@1.1001;
  
  /**
   * Menu usecase to create a new contract shelf

   */

  menu usecase CreateContractShelf direct {
    symbol = SymbolRecordFilled;
    variant ContractConfiguration {
      application {
        expression {
          ->CreateObjectApp(cooobj, sys_action, #acapprooms, , , , true,
                            , , false, #ContractShelf, , #ContractShelf.
                            GetAttributeString(cootx, #mlname), , false,
                            true);
        }
        apphints = {
          MH_NEEDSCURRENTVERSION,
          MH_CREATESOBJ
        }
      }
    }
    variant ContractDashboard {
      application {
        expression {
          AppConfigurationRoom config = cooobj.GetAppConfiguration();
          if (config.IsUsable(#ContractConfiguration)) {
            ->CreateObjectApp(config, sys_action, #acapprooms, , , , true,
                              , , false, #ContractShelf, , #ContractShelf.
                              GetAttributeString(cootx, #mlname), , false,
                              true);
          }
        }
        apphints = {
          MH_NEEDSCURRENTVERSION,
          MH_CREATESOBJ
        }
      }
    }
  }
  
  /**
   * Menu usecase to create a new contract

   */

  menu usecase CreateContract direct {
    symbol = SymbolAgreement;
    variant ContractShelf {
      application {
        expression {
          ->CreateObjectApp(cooobj, sys_action, #cscontracts, , , , true,
                            , , false, #Contract, , #Contract.
                            GetAttributeString(cootx, #mlname), , false,
                            true);
        }
        apphints = {
          MH_NEEDSCURRENTVERSION,
          MH_CREATESOBJ
        }
      }
    }
  }
  
  /**
   * Adds recently used contracts to the dashboard

   */

  override AddRecentlyUsedToAppDashboard {
    variant Contract {
      expression {
        if (!cooobj.objistemplate) {
          ContractDashboard dashboard =
             coouser.GetUserDashboardByApp(#AppContractMgmt);
          if (dashboard.IsUsable(#ContractDashboard)) {
            try new transaction {
              dashboard.UpdateRecentlyUsedObjects(#cdrecentlyusedelements,
                                                 #cdrecentlyusedcontracts,
                                                  cooobj);
            }
          }
        }
      }
    }
  }

  /**
   * Retrieves the attribute containing recently used objects in the dashboard

   */

  override GetRecentlyUsedDisplayAttributes {
    variant ContractDashboard {
      expression {
        attrdefs = #cdrecentlyusedcontracts;
      }
    }
  }
  
  /**
   * Calculate and sort the recently used contracts based on last usage

   */

  AttrCdRecentlyUsedContractsGet(parameters as AttrGetPrototype) {
    variant ContractDashboard {
      expression {
        RecentlyUsedElements[] recentlyused =
            coouser.Sort(cooobj.cdrecentlyusedelements, false,
                         #ruetimestamp, false);
        value = unique(recentlyused.rueobject)[IsUsable(#Contract) &&
                                               !objistemplate];
      }
    }
  }
}

CustomizationsPermanent link for this heading

Define the following customization:

  • If the configuration does not exist, it should be automatically created when the license for the app is granted.

customization.ducx-cu

customization DEMOCONTRACTMGMT@111.100
{
  import COOATTREDIT@1.1;
  import COOSYSTEM@1.1;
  import FSCTEAMROOM@1.1001;
  
  target default {
    /**
     * Automatically create a ContractConfiguration after the license
     *
for the app is granted
     */
    customize CPAutoCreateAppConfiguration<ContractConfiguration> {
      autocreate = true;
    }
  }
}

ResultPermanent link for this heading

Only the few steps depicted in the previous chapters are necessary to provide your own room for storing contracts. Load this example in your test environment and have a try.