In Designer mode

 


So far, you simply added Accruals calculation register records, which stated that some calculations were required. However, you have not yet implemented these calculations.

Now it is time to describe the algorithms for various calculations types.

Since you will use the algorithms not only in Employee accrual documents, it is wise to store them in a separate common module.

  1. In Designer, open the posting event handler of the EmployeeAccruals document and add a call of the CalculateAccruals() procedure from the Calculations common module after the lines that record data to the Accruals register (listing 18.2).

    Listing 18.2. EmployeeAccruals document posting procedure

    Procedure Posting(Cancel, Mode)
        ...
        EndDo;
        //}}__REGISTER_REGISTERRECORDS_WIZARD
     
        // Writing register records
        RegisterRecords.Accruals.Write();
     
        // Getting the list of employees referenced in the document
        Query = New Query(
        "SELECT DISTINCT
        |    EmployeeAccrualsAccruals.Employee
        |FROM
        |    Document.EmployeeAccruals.Accruals AS EmployeeAccrualsAccruals
        |WHERE
        |    EmployeeAccrualsAccruals.Ref = &CurDocument");
     
        Query.SetParameter("CurDocument", Ref);
     
        // Generating employee list
        ValTable = Query.Execute().Unload();
        EmployeeArray = ValTable.UnloadColumn("Employee");
     
        // Calling the CalculateAccruals procedure from the common module
        Calculations.CalculateAccruals(RegisterRecords.Accruals,
            ChartsOfCalculationTypes.MainAccruals.Salary, EmployeeArray);
        RegisterRecords.Accruals.Write( , True);
        Calculations.CalculateAccruals(RegisterRecords.Accruals,
            ChartsOfCalculationTypes.MainAccruals.Bonus, EmployeeArray);
        RegisterRecords.Accruals.Write( , True);
     
    EndProcedure
    Note that the records generated by the document are first written to the register (RegisterRecords.Accruals.Write()) and then the register record set is passed to the CalculateAccruals() calculation procedure. You will create this procedure in the Calculations common module later in this tutorial.

    This procedure is called twice. The first call calculates primary records (Salary), while the second call calculates secondary ones (Bonus).

    The calculation procedure generates the resource values for the register based on the calculation algorithms described in the procedure and register data.

    Once the resources are calculated, the set of register records is rewritten without generating recalculation records (the second parameter in the Write() method is True).

    Before calling the procedure from the common module, a query generates a list of employees referenced in the document in order to pass it to the procedure.

    The CurDocument query parameter value is taken from the standard Ref document attribute. The query method Query.Execute().Unload() dumps the query result to a value table (the ValTable variable). Then the EmployeeArray is generated, it contains the Employee column from this value table.
  2. In the Common branch of the configuration tree, create a module named Calculations.
  3. For this module, select the Server call check box.

    This is required to make the export procedures and functions visible (fig. 18.14).


    Fig. 18.14. Common module properties
  4. Create a template for the CalculateAccruals() procedure (listing 18.3).

    Listing 18.3. CalculateAccruals() procedure template

    Procedure CalculateAccruals (RegisterRecordSet, RequiredCalculationType, EmployeeList) Export
     
        Recorder = RegisterRecordSet.Filter.Recorder.Value;
     
        // Calculating primary records
        If RequiredCalculationType = ChartsOfCalculationTypes.MainAccruals.Salary Then
     
        // Calculating secondary records
        ElsIf RequiredCalculationType = ChartsOfCalculationTypes.MainAccruals.Bonus Then
     
        EndIf;
     
    EndProcedure
    The accruals calculation algorithm varies for primary (Salary calculation type) and secondary (Bonus calculation type) records, and each of the algorithm parts is located in a branch of the If... clause.

    Calculation of primary records requires the schedule data of the calculation register, so let us add a query to the calculation register virtual table (CalculationRegister.Accruals.ScheduleData) to the first branch of the If... clause (listing 18.4).

    Listing 18.4. Modifying the CalculateAccruals() procedure

    Procedure CalculateAccruals (RegisterRecordSet, RequiredCalculationType, EmployeeList) Export
     
        Recorder = RegisterRecordSet.Filter.Recorder.Value;
     
        // Calculating primary records
        If RequiredCalculationType = ChartsOfCalculationTypes.MainAccruals.Salary Then
     
            Query = New Query;
            Query.Text = 
                "SELECT
                |    AccrualsScheduleData.ValueActionPeriod AS Normal,
                |    AccrualsScheduleData.ValueActualActionPeriod AS Actual,
                |    AccrualsScheduleData.LineNumber
                |FROM
                |    CalculationRegister.Accruals.ScheduleData(Recorder = &Recorder AND
                |    CalculationType = &CalculationType AND Employee IN (&EmployeeList))
                |    AS AccrualsScheduleData";
     
            Query.SetParameter("Recorder", Recorder);
            Query.SetParameter("CalculationType", RequiredCalculationType);
            Query.SetParameter("EmployeeList", EmployeeList);
     
            SelectionResult = Query.Execute().Select();
     
        // Calculating secondary records
        ElsIf RequiredCalculationType = ChartsOfCalculationTypes.MainAccruals.Bonus Then
     
        EndIf;
     
    EndProcedure
    The query selects schedule values for the action period and the actual action period from the calculation register schedule data virtual table. The virtual table parameters specify that the selection of schedule values is limited by recorder, calculation type, and employee list.
  5. Add the iteration through the record set passed to the procedure and the calculation of records based on the retrieved schedule data (listing 18.5).

    Listing 18.5. Adding the iteration through the record set and the calculation of primary records

    Procedure CalculateAccruals (RegisterRecordSet, RequiredCalculationType, EmployeeList) Export
     
        Recorder = RegisterRecordSet.Filter.Recorder.Value;
     
        // Calculating primary records
        If RequiredCalculationType = ChartsOfCalculationTypes.MainAccruals.Salary Then
            ...
            SelectionResult = Query.Execute().Select();
     
            For Each RegisterRecord In RegisterRecordSet Do
                StructureNumber = New Structure("LineNumber");
                StructureNumber.LineNumber = RegisterRecord.LineNumber;
                SelectionResult.Reset();
     
                If SelectionResult.FindNext(StructureNumber) Then
     
                    If SelectionResult.Normal = 0 Then
                        Message = New UserMessage;
                        Message.Text = "Calculation type: Salary. No working days in the specified period";
                        Message.Message();
                        RegisterRecord.Result = 0;
     
                    Else
     
                        // Calculating salary based on the actual period and the source data
                        RegisterRecord.Result = (RegisterRecord.SourceData / SelectionResult.Normal)
                            * SelectionResult.Actual;
                        Message = New UserMessage;
                        Message.Text = "Calculation completed: " + RegisterRecord.Recorder
                            + " – " + RegisterRecord.CalculationType
                            + " – " + RegisterRecord.Employee;
                        Message.Message();
     
                    EndIf;
     
                EndIf;
     
            EndDo;
     
        // Calculating secondary records
        ElsIf RequiredCalculationType = ChartsOfCalculationTypes.MainAccruals.Bonus Then
     
        EndIf;
     
    EndProcedure
    For each record of the calculation register record set, a line number is retrieved. The line number identifies an accrual for a specific employee, and this number is used to find the corresponding record in the query result selection.

    If a record with that line number is found in the query result, the calculation register record result is calculated. It is a salary accrual calculated by the following formula: the accrued amount (SourceData register field) is divided by the number of working days in the month (Normal) and the result is multiplied by the number of actual working days (Actual).
  6. Add a query script to the second branch of the If… clause (listing 18.6).

    This query is similar to the first one, with the following difference: the base values are retrieved from the calculation register virtual table (CalculationRegister.Accruals.AccrualBase).

    Listing 18.6. Adding the query script to the second clause branch

    Procedure CalculateAccruals (RegisterRecordSet, RequiredCalculationType, EmployeeList) Export
     
        Recorder = RegisterRecordSet.Filter.Recorder.Value;
     
        // Calculating primary records
        If RequiredCalculationType = ChartsOfCalculationTypes.MainAccruals.Salary Then
        
        ...
    
        // Calculating secondary records
        ElsIf RequiredCalculationType = ChartsOfCalculationTypes.MainAccruals.Bonus Then
     
            Query = New Query;
            Query.Text=
                "SELECT
                |    AccrualsBaseAccruals.ResultBase AS Base,
                |    AccrualsBaseAccruals.LineNumber AS LineNumber
                |FROM
                |    CalculationRegister.Accruals.BaseAccruals(&MainDimensions,
                |    &BaseDimensions, , Recorder = &Recorder AND
                |        CalculationType = &CalculationType AND
                |        Employee IN (&EmployeeList))
                |    AS AccrualsBaseAccruals";
     
            Dim = New Array(1);
            Dim[0]="Employee";
     
            Query.SetParameter("MainDimensions", Dim);
            Query.SetParameter("BaseDimensions", Dim);
            Query.SetParameter("Recorder", Recorder);
            Query.SetParameter("CalculationType", RequiredCalculationType);
            Query.SetParameter("EmployeeList", EmployeeList);
     
            SelectionResult = Query.Execute().Select();
     
        EndIf;
     
    EndProcedure
    The virtual query table parameters include not only recorder, calculation type, and employee list, which are familiar to you, but also the dimensions of the main and base registers. In this case it is a single Accruals register, and what you need is its Employee dimension.
  7. Add the iteration through the record set and the calculation of secondary records to the second If... clause (listing 18.7).

    Listing 18.7. Adding the iteration through the record set and the calculation of secondary records

    Procedure CalculateAccruals (RegisterRecordSet, RequiredCalculationType, EmployeeList) Export
     
        Recorder = RegisterRecordSet.Filter.Recorder.Value;
     
        // Calculating primary records
        If RequiredCalculationType = ChartsOfCalculationTypes.MainAccruals.Salary Then
        
        ...
     
        // Calculating secondary records
        ElsIf RequiredCalculationType = ChartsOfCalculationTypes.MainAccruals.Bonus Then
    
            ... 
     
            SelectionResult = Query.Execute().Select();
     
            For Each RegisterRecord In RegisterRecordSet Do
                StructureNumber = New Structure("LineNumber");
                StructureNumber.LineNumber = RegisterRecord.LineNumber;
                SelectionResult.Reset();
     
                If SelectionResult.FindNext(StructureNumber) Then
                    RegisterRecord.Result = SelectionResult.Base * (10/100);
                    Message = New UserMessage;
                    Message.Text="Calculation completed: " + RegisterRecord.Recorder
                        + " – " + RegisterRecord.CalculationType
                        + " – " + RegisterRecord.Employee;
                    Message.Message();
     
                EndIf;
     
            EndDo;
     
        EndIf;
     
    EndProcedure
    This script calculates the accrued bonus as 10% of the calculated salary.

Comments
0
Add comment