Skip to main content

Notifications

Finance | Project Operations, Human Resources, ...
Suggested answer

Split timesheet based on project id

(0) ShareShare
ReportReport
Posted on by 20

Hi,

I want to split timesheet based on the project id before submitting timesheet to workflow in d365 f&o

Suppose I have timesheet with 3 lines out of those 2 lines with same project id and 3rd line with different project then based on the different project id it will create new timesheet for line 3 and existing timesheet will same with 2 lines which is having same project id. 3rd line Data should copy from existing timesheet and both timesheet needs to automatically submitted to workflow.

Can you please suggest where to write the code before submitting timesheet to workflow.

  • Suggested answer
    Sonali Mane Profile Picture
    Sonali Mane 20 on at
    RE: Split timesheet based on project id

    Hi ,

    Splitting is fine & its creating two new timesheet with proper lines only posting done together for splitted lines. 3rd line never get posted as posting for 3rd line is already done in Line 2

    /// 
    [ExtensionOf(classStr(TsWorkflowActionManager))]
    final class ADNTsWorkflowActionManager_Extension
    {
    
        /// 
        /// submitToWorkflow
        /// 
        /// _args
        ///  returns boolean value
        public boolean submitToWorkflow(Args _args)
        {
            next submitToWorkflow (_args);
    
            TSTimesheetTrans tsTimeSheetTrans;
            TSTimesheetLineWeek tsTimesheetLineWeek;
            TSTimesheetTable    tsTimesheetTable,newTimesheetTable;
            ProjPeriodLine      projPeriodLine;
            ProjPeriodTimesheetWeek projPeriodTimesheetWeek;
            TsTimesheetLog  tstimeSheetLog;
            TSTimesheetNbr      tsTimesheetNbr;
            ProjId  firstProjId,currentProjId;
            TSTimesheetLine tsTimesheetLine,tsTimesheetLineBuff,tsTimesheetLinelocal,origtimesheetLineDelete;
            //boolean         result = true;
    
            if(projparameters::find().ADNSplitTimesheetOnProjId && !canceledAction)
            {
                Common callerRecord = _args.record();
                tsTimesheetTable = callerRecord as TSTimesheetTable;
    
                select firstonly projId from tsTimesheetLine
                    where tsTimesheetLine.TimesheetNbr == tsTimesheetTable.TimesheetNbr;
    
                firstProjId = tsTimesheetLine.ProjId;
    
                while select tsTimesheetLineBuff group by tsTimesheetLineBuff.ProjId
                    where tsTimesheetLineBuff.ProjId != firstProjId &&
                        tsTimesheetLineBuff.TimesheetNbr == tsTimesheetTable.TimesheetNbr
                {
                    projPeriodLine = TSTimesheetTable::getValidResourcePeriod(tsTimesheetTable.Resource);
    
                    if (this &&
                            TSTimesheetTable::checkMaxTimesheets(projPeriodLine.PeriodFrom, tsTimesheetTable.Resource, true))
                    {
                        if (projPeriodLine.RecId != 0)
                        {
                            newTimesheetTable.TimesheetNbr ="";
                            newTimesheetTable.initValue();
                            newTimesheetTable.Resource = tsTimesheetTable.Resource;
                            newTimesheetTable.ProjPeriodId = projPeriodLine.PeriodId;
                            newTimesheetTable.PeriodFrom = projPeriodLine.PeriodFrom;
                            newTimesheetTable.PeriodTo = projPeriodLine.PeriodTo;
                            projPeriodTimesheetWeek = ProjPeriodTimesheetWeek::findFromPeriod(projPeriodLine.PeriodId);
                            if (projPeriodTimesheetWeek.RecId == 0)
                            {
                                warning("@SYS338882");
                            }
                            else
                            {
                                newTimesheetTable.ProjPeriodTimesheetWeek = projPeriodTimesheetWeek.RecId;
                            }
                            //ttsBegin;
                            newTimesheetTable.insert();
                            //ttscommit;
                            tsTimesheetNbr = newTimesheetTable.TimesheetNbr;
    
                            if (newTimesheetTable.RecId != 0)
                            {
                                if (ProjParameters::find().TimesheetAuditTrail)
                                {
                                    TSTimesheetTableLog::createTableLog(newTimesheetTable, '', TsTimesheetChangeType::Create);
                                }
    
                                this.preLineInserts(newTimesheetTable);
    
                                currentProjId = tsTimesheetLineBuff.ProjId;
    
                                while select * from tsTimesheetLinelocal
                                    where tsTimesheetLinelocal.ProjId == currentProjId
                                    && tsTimesheetLinelocal.TimesheetNbr == tsTimesheetTable.TimesheetNbr
                                    && tsTimesheetLinelocal.ProjId != firstProjId
                                {
                                    this.createTimesheetLine(tsTimesheetNbr,tsTimesheetLinelocal);
    
                                    delete_from origtimesheetLineDelete
                                        where origtimesheetLineDelete.RecId ==  tsTimesheetLinelocal.RecId;
    
                                }
                                this.postLineInserts(newTimesheetTable, true);
    
                                //ttscommit;
    
                                ttsbegin;
                                newTimesheetTable.selectForUpdate(true);
    
                                if (newTimesheetTable.RecId && newTimesheetTable.ApprovalStatus == TSAppStatus::Create)
                                {
                                    // submitting to workflow;
                                    Workflow::activateFromWorkflowType(workFlowTypeStr(TSDocumentTemplate),
                                        newTimesheetTable.RecId,
                                        "@ADN:AutoSubmitToWF",
                                        false,
                                        curUserid());
                                }
                                this.updateStatusToInReview(newTimesheetTable, false);
                                ttscommit;
                                
                            }
                        }
                        else
                        {
                            throw error("@Timesheet:Timesheet_Not_Created");
                        }
                    }
                }
            }
            return true;
            //return next submitToWorkflow (_args);
            
        }
    
        /// 
        /// Create TimesheetLine
        /// 
        /// _timesheetNbr
        /// _timesheetLine
        public void createTimesheetLine(TSTimesheetNbr  _timesheetNbr, TSTimesheetLine _timesheetLine)
        {
            TSTimesheetLine newTimesheetLine = this.initFromTsTimesheetLine(_timesheetNbr, _timesheetLine);
    
            if (newTimesheetLine.validateWrite() && newTimesheetLine.ProjPeriodTimesheetWeek != 0)
            {
                newTimesheetLine.insert();
    
                this.loadFromLine(newTimesheetLine, _timesheetLine);
            }
        }
    
        /// 
        /// Create TSTimesheetLineWeek record
        /// 
        /// _tsTimesheetLineNew
        /// _tsTimesheetLineOld
        public  void loadFromLine(TSTimesheetLine _tsTimesheetLineNew, TSTimesheetLine _tsTimesheetLineOld)
        {
            TSTimesheetLineWeek lineWeek, lineWeekOld;
    
            while select lineWeekOld
                where lineWeekOld.TimesheetNbr == _tsTimesheetLineOld.TimesheetNbr
                        && lineWeekOld.linenum == _tsTimesheetLineOld.LineNum
                        && lineWeekOld.tstimesheetLine  == _tsTimesheetLineOld.RecId
            {
                lineWeek.clear();
                buf2Buf(lineWeekOld, lineWeek);
    
                lineWeek.TimesheetNbr =  _tsTimesheetLineNew.TimesheetNbr;
                lineWeek.LineNum         = _tsTimesheetLineNew.LineNum;
                lineWeek.tsTimesheetLine = _tsTimesheetLineNew.RecId;
    
                lineWeek.insert();
            }
    
        }
    
        /// 
        /// Init from timesheetLine Value
        /// 
        /// _timesheetNbr
        /// _timesheetLine
        /// TSTimesheetLine
        public TSTimesheetLine initFromTsTimesheetLine(TSTimesheetNbr _timesheetNbr, TSTimesheetLine _timesheetLine)
        {
            TSTimesheetLine  newTimesheetLine;
            TSTimesheetTable targetTimesheet = TSTimesheetTable::find(_timesheetNbr);
    
            RefRecId getTimesheetWeekRecId(RefRecId sourceWeekId)
            {
                ProjPeriodTimesheetWeek sourcePeriodTimesheetWeek;
                ProjPeriodTimesheetWeek targetPeriodTimesheetWeek;
                TSTimesheetTable sourceTimesheet = TSTimesheetTable::find(_timesheetLine.TimesheetNbr);
                int counter = 0, counter2 = 0;
                RefRecId retval = 0;
    
                while select RecId from sourcePeriodTimesheetWeek
                    order by sourcePeriodTimesheetWeek.PeriodFrom
                    where sourcePeriodTimesheetWeek.PeriodId   == sourceTimesheet.ProjPeriodId
                       && sourcePeriodTimesheetWeek.PeriodFrom >= sourceTimesheet.PeriodFrom
                       && sourcePeriodTimesheetWeek.PeriodTo   <= sourceTimesheet.PeriodTo
    
                {
                    if (sourcePeriodTimesheetWeek.RecId == sourceWeekId)
                    {
                        break;
                    }
                    counter  ;
                }
    
                while select RecId from targetPeriodTimesheetWeek
                    order by targetPeriodTimesheetWeek.PeriodFrom
                    where targetPeriodTimesheetWeek.PeriodId   == targetTimesheet.ProjPeriodId
                       && targetPeriodTimesheetWeek.PeriodFrom >= targetTimesheet.PeriodFrom
                       && targetPeriodTimesheetWeek.PeriodTo   <= targetTimesheet.PeriodTo
    
                {
                    // always set the last PeriodWeek
                    // if the source Period has more weeks than target, then the timesheet lines will be set
                    // to whatever is the last week of the target period
                    retval = targetPeriodTimesheetWeek.RecId;
    
                    if (counter == counter2)
                    {
                        retval = targetPeriodTimesheetWeek.RecId;
                        break;
                    }
                    counter2  ;
                }
    
                return retval;
            }
    
            newTimesheetLine.TimesheetNbr               = _timesheetNbr;
            newTimesheetLine.ApprovalStatus             = TSAppStatus::Create;
            newTimesheetLine.LineNum                    = _timesheetLine.LineNum;
            newTimesheetLine.Resource                   = targetTimesheet.Resource;
            newTimesheetLine.ProjId                     = _timesheetLine.ProjId;
            newTimesheetLine.ActivityNumber             = _timesheetLine.ActivityNumber;
            newTimesheetLine.CategoryId                 = _timesheetLine.CategoryId;
            newTimesheetLine.LinePropertyId             = _timesheetLine.LinePropertyId;
            newTimesheetLine.WrkCtrId                   = _timesheetLine.WrkCtrId;
            newTimesheetLine.CurrencyCode               = _timesheetLine.CurrencyCode;
            newTimesheetLine.DefaultDimension           = _timesheetLine.DefaultDimension;
            newTimesheetLine.TaxGroupId                 = _timesheetLine.TaxGroupId;
            newTimesheetLine.TaxItemGroup               = _timesheetLine.TaxItemGroup;
            newTimesheetLine.ProjectDataAreaId          = _timesheetLine.ProjectDataAreaId;
            newTimesheetLine.ProjCompanySalesCurrency   = _timesheetLine.ProjCompanySalesCurrency;
            newTimesheetLine.setNextLineNum(_timesheetNbr);
            newTimesheetLine.ProjPeriodTimesheetWeek    = getTimesheetWeekRecId(_timesheetLine.ProjPeriodTimesheetWeek);
            return newTimesheetLine;
        }
    
        /// 
        /// Init from timesheetLine Value
        /// 
        /// _isNew
        public void postLineInserts(
            TSTimesheetTable _tsTimesheetTable,
            boolean          _isNew)
        {
            TsTimesheetTableLog tsTimesheetTableLog;
    
            if (ProjParameters::find().TimesheetAuditTrail)
            {
                TsTimesheetLog      tsTimesheetLog;
                // if the timesheet is new we need to use the existing table log created in insert
                if (_isNew)
                {
                    select firstOnly tsTimesheetTableLog where
                        tsTimesheetTableLog.TimesheetNbr == _tsTimesheetTable.TimesheetNbr;
                }
                else
                {
                    tsTimesheetTableLog = TsTimesheetTableLog::createTableLog(_tsTimesheetTable, '', TsTimesheetChangeType::Update);
                }
                tsTimesheetLog.logPostLineInserts(tsTimesheetTableLog);
            }
        }
    
        /// 
        /// update Status To InReview when submitted to workflow
        /// 
        /// tsTimesheetTable
        /// isLineItemApprovalConfigured
        public void updateStatusToInReview(TSTimesheetTable tsTimesheetTable, boolean isLineItemApprovalConfigured)
        {
            TSTimesheetLine tsTimesheetLine;
            TSTimesheetTrans tsTrans;
    
            if (tsTimesheetTable.ApprovalStatus != TSAppStatus::Pending)
            {
                if (!TSStateChangeManager::validateStatusChange(tsTimesheetTable.ApprovalStatus, TSAppStatus::Pending))
                {
                    throw error(strFmt("@SYS108515",tsTimesheetTable.ApprovalStatus, TSAppStatus::Pending));
                }
    
                tsTimesheetTable.ApprovalStatus = TSAppStatus::Pending;
                ttsbegin;
                tsTimesheetTable.doUpdate();
                ttscommit;
            }
    
            if (!isLineItemApprovalConfigured)
            {
                // The status change is unrelated to other data changes and should not require any row-by-row processing.
                tsTimesheetLine.skipDataMethods(true);
                tsTrans.skipDataMethods(true);
    
                tsTimesheetLine.skipDatabaseLog(true);
                tsTrans.skipDatabaseLog(true);
    
                tsTimesheetLine.skipEvents(true);
                tsTrans.skipEvents(true);
    
                update_recordset tsTimesheetLine setting ApprovalStatus = TSAppStatus::Pending where tsTimesheetLine.TimesheetNbr == tsTimesheetTable.TimesheetNbr;
                update_recordset tsTrans setting ApprovalStatus = TSAppStatus::Pending where tsTrans.TimesheetNbr == tsTimesheetTable.TimesheetNbr;
            }
        }
    
        /// 
        /// preLineInserts
        /// 
        /// _timesheetTable
        Public void preLineInserts(TSTimesheetTable _timesheetTable)
        {
            TsTimesheetLog tsTimesheetLog;
            if (ProjParameters::find().TimesheetAuditTrail)
            {
                tsTimesheetLog = new TsTimesheetLog();
                tsTimesheetLog.preLineInserts(_timesheetTable);
            }
        }
    
    }

  • Suggested answer
    Anton Venter Profile Picture
    Anton Venter 19,493 Super User 2025 Season 1 on at
    RE: Split timesheet based on project id

    Hi Sonali,

    From what I can see your code is creating only one extra timesheet and not a new timesheet for the timesheet lines for every project.

    I suggest to create a separate function to create a timesheet record and the timesheet lines for each project.

    Can you insert your code as formatted text? It makes it a lot easier to read.

  • Suggested answer
    Sonali Mane Profile Picture
    Sonali Mane 20 on at
    RE: Split timesheet based on project id

    Hi,

    I have created extension of TsWorkflowActionManager to split timesheet. below is my code.

    I have created Timesheet with 3 lines.
    Line 1 with project id: SE03-000033_001

    Line 2 with project id: SE03-000075_002

    Line 3 with project id: SE03-000004_003

    As per my code I am splitting timesheet based on project Id. Line 1 remains same in Original Timesheet. For Line 2 & Line 3 I am creating new timesheet with lines using x++ code & submitting automatically to workflow. 

    But when I am creating 3 lines with different Project id so posting of original line i.e. 1st line is fine as per standard. But 2nd & 3rd line which submitted automatically to workflow by my custom code comes under single Voucher transaction.

    For 2nd & 3rd line transaction posted in line no 2. For line 3 there is no transaction. May I know the reason Why transaction comes under in same voucher transaction and not per project wise or timesheet wise.

    Below is my code.

    [ExtensionOf(classStr(TsWorkflowActionManager))]
    final class ADNTsWorkflowActionManager_Extension
    {

    currentProjId = tsTimesheetLineBuff.ProjId;

    public boolean submitToWorkflow(Args _args)
    {
    //next submitToWorkflow (_args);

    TSTimesheetTable tsTimesheetTable,newTimesheetTable;
    ProjPeriodLine projPeriodLine;
    ProjPeriodTimesheetWeek projPeriodTimesheetWeek;
    TsTimesheetLog tstimeSheetLog;
    TSTimesheetNbr tsTimesheetNbr;
    ProjId firstProjId,currentProjId;
    TSTimesheetLine tsTimesheetLine,tsTimesheetLineBuff,tsTimesheetLinelocal,origtimesheetLineDelete;
    //boolean result = true;

    if(projparameters::find().ADNSplitTimesheetOnProjId && !canceledAction)
    {
    Common callerRecord = _args.record();
    tsTimesheetTable = callerRecord as TSTimesheetTable;

    select firstonly projId from tsTimesheetLine
    where tsTimesheetLine.TimesheetNbr == tsTimesheetTable.TimesheetNbr;

    firstProjId = tsTimesheetLine.ProjId;

    while select tsTimesheetLineBuff group by tsTimesheetLineBuff.ProjId
    where tsTimesheetLineBuff.ProjId != firstProjId &&
    tsTimesheetLineBuff.TimesheetNbr == tsTimesheetTable.TimesheetNbr
    {
    projPeriodLine = TSTimesheetTable::getValidResourcePeriod(tsTimesheetTable.Resource);

    if (this &&
    TSTimesheetTable::checkMaxTimesheets(projPeriodLine.PeriodFrom, tsTimesheetTable.Resource, true))
    {
    if (projPeriodLine.RecId != 0)
    {
    newTimesheetTable.TimesheetNbr ="";
    newTimesheetTable.initValue();
    newTimesheetTable.Resource = tsTimesheetTable.Resource;
    newTimesheetTable.ProjPeriodId = projPeriodLine.PeriodId;
    newTimesheetTable.PeriodFrom = projPeriodLine.PeriodFrom;
    newTimesheetTable.PeriodTo = projPeriodLine.PeriodTo;
    projPeriodTimesheetWeek = ProjPeriodTimesheetWeek::findFromPeriod(projPeriodLine.PeriodId);
    if (projPeriodTimesheetWeek.RecId == 0)
    {
    warning("@SYS338882");
    }
    else
    {
    newTimesheetTable.ProjPeriodTimesheetWeek = projPeriodTimesheetWeek.RecId;
    }
    ttsBegin;
    newTimesheetTable.insert();
    //ttscommit;
    tsTimesheetNbr = newTimesheetTable.TimesheetNbr;

    if (newTimesheetTable.RecId != 0)
    {
    if (ProjParameters::find().TimesheetAuditTrail)
    {
    TSTimesheetTableLog::createTableLog(newTimesheetTable, '', TsTimesheetChangeType::Create);
    }

    if (ProjParameters::find().TimesheetAuditTrail)
    {
    tsTimesheetLog = new TsTimesheetLog();
    tsTimesheetLog.preLineInserts(newTimesheetTable);
    }

    while select * from tsTimesheetLinelocal
    where tsTimesheetLinelocal.ProjId == currentProjId
    && tsTimesheetLinelocal.TimesheetNbr == tsTimesheetTable.TimesheetNbr
    && tsTimesheetLinelocal.ProjId != firstProjId
    {
    this.createTimesheetLine(tsTimesheetNbr,tsTimesheetLinelocal);

    delete_from origtimesheetLineDelete
    where origtimesheetLineDelete.RecId == tsTimesheetLinelocal.RecId;
    }
    this.postLineInserts(newTimesheetTable, true);

    if (newTimesheetTable.RecId
    && newTimesheetTable.ApprovalStatus == TSAppStatus::Create)
    {
    // submitting to workflow;
    Workflow::activateFromWorkflowType(
    workFlowTypeStr(TSDocumentTemplate),
    newTimesheetTable.RecId,
    "@ADN:AutoSubmitToWF",
    false,
    curUserid());
    }
    ttscommit;
    }
    }
    else
    {
    throw error("@Timesheet:Timesheet_Not_Created");
    }
    }
    }
    }
    return next submitToWorkflow (_args);;
    }

    /// <summary>
    /// Create TimesheetLine
    /// </summary>
    /// <param name = "_timesheetNbr">_timesheetNbr</param>
    /// <param name = "_timesheetLine">_timesheetLine</param>
    public void createTimesheetLine(TSTimesheetNbr _timesheetNbr, TSTimesheetLine _timesheetLine)
    {
    TSTimesheetLine newTimesheetLine = this.initFromTsTimesheetLine(_timesheetNbr, _timesheetLine);

    if (newTimesheetLine.validateWrite() && newTimesheetLine.ProjPeriodTimesheetWeek != 0)
    {
    newTimesheetLine.insert();

    this.adnloadFromLine(newTimesheetLine, _timesheetLine);
    }
    }

    /// <summary>
    /// Create TSTimesheetLineWeek record
    /// </summary>
    /// <param name = "_tsTimesheetLineNew">_tsTimesheetLineNew</param>
    /// <param name = "_tsTimesheetLineOld">_tsTimesheetLineOld</param>
    public void adnloadFromLine(TSTimesheetLine _tsTimesheetLineNew, TSTimesheetLine _tsTimesheetLineOld)
    {
    TSTimesheetLineWeek lineWeek, lineWeekOld;

    while select lineWeekOld
    where lineWeekOld.TimesheetNbr == _tsTimesheetLineOld.TimesheetNbr
    && lineWeekOld.linenum == _tsTimesheetLineOld.LineNum
    && lineWeekOld.tstimesheetLine == _tsTimesheetLineOld.RecId
    {
    lineWeek.clear();
    buf2Buf(lineWeekOld, lineWeek);

    lineWeek.TimesheetNbr = _tsTimesheetLineNew.TimesheetNbr;
    lineWeek.LineNum = _tsTimesheetLineNew.LineNum;
    lineWeek.tsTimesheetLine = _tsTimesheetLineNew.RecId;

    lineWeek.insert();
    }

    }

    /// <summary>
    /// Init from timesheetLine Value
    /// </summary>
    /// <param name = "_timesheetNbr">_timesheetNbr</param>
    /// <param name = "_timesheetLine">_timesheetLine</param>
    /// <returns>TSTimesheetLine</returns>
    public TSTimesheetLine initFromTsTimesheetLine(TSTimesheetNbr _timesheetNbr, TSTimesheetLine _timesheetLine)
    {
    TSTimesheetLine newTimesheetLine;
    TSTimesheetTable targetTimesheet = TSTimesheetTable::find(_timesheetNbr);

    RefRecId getTimesheetWeekRecId(RefRecId sourceWeekId)
    {
    ProjPeriodTimesheetWeek sourcePeriodTimesheetWeek;
    ProjPeriodTimesheetWeek targetPeriodTimesheetWeek;
    TSTimesheetTable sourceTimesheet = TSTimesheetTable::find(_timesheetLine.TimesheetNbr);
    int counter = 0, counter2 = 0;
    RefRecId retval = 0;

    while select RecId from sourcePeriodTimesheetWeek
    order by sourcePeriodTimesheetWeek.PeriodFrom
    where sourcePeriodTimesheetWeek.PeriodId == sourceTimesheet.ProjPeriodId
    && sourcePeriodTimesheetWeek.PeriodFrom >= sourceTimesheet.PeriodFrom
    && sourcePeriodTimesheetWeek.PeriodTo <= sourceTimesheet.PeriodTo

    {
    if (sourcePeriodTimesheetWeek.RecId == sourceWeekId)
    {
    break;
    }
    counter++;
    }

    while select RecId from targetPeriodTimesheetWeek
    order by targetPeriodTimesheetWeek.PeriodFrom
    where targetPeriodTimesheetWeek.PeriodId == targetTimesheet.ProjPeriodId
    && targetPeriodTimesheetWeek.PeriodFrom >= targetTimesheet.PeriodFrom
    && targetPeriodTimesheetWeek.PeriodTo <= targetTimesheet.PeriodTo

    {
    // always set the last PeriodWeek
    // if the source Period has more weeks than target, then the timesheet lines will be set
    // to whatever is the last week of the target period
    retval = targetPeriodTimesheetWeek.RecId;

    if (counter == counter2)
    {
    retval = targetPeriodTimesheetWeek.RecId;
    break;
    }
    counter2++;
    }

    return retval;
    }

    newTimesheetLine.TimesheetNbr = _timesheetNbr;
    newTimesheetLine.ApprovalStatus = TSAppStatus::Create;
    newTimesheetLine.LineNum = _timesheetLine.LineNum;
    newTimesheetLine.Resource = targetTimesheet.Resource;
    newTimesheetLine.ProjId = _timesheetLine.ProjId;
    newTimesheetLine.ActivityNumber = _timesheetLine.ActivityNumber;
    newTimesheetLine.CategoryId = _timesheetLine.CategoryId;
    newTimesheetLine.LinePropertyId = _timesheetLine.LinePropertyId;
    newTimesheetLine.WrkCtrId = _timesheetLine.WrkCtrId;
    newTimesheetLine.CurrencyCode = _timesheetLine.CurrencyCode;
    newTimesheetLine.DefaultDimension = _timesheetLine.DefaultDimension;
    newTimesheetLine.TaxGroupId = _timesheetLine.TaxGroupId;
    newTimesheetLine.TaxItemGroup = _timesheetLine.TaxItemGroup;
    newTimesheetLine.ProjectDataAreaId = _timesheetLine.ProjectDataAreaId;
    newTimesheetLine.ProjCompanySalesCurrency = _timesheetLine.ProjCompanySalesCurrency;
    newTimesheetLine.setNextLineNum(_timesheetNbr);
    newTimesheetLine.ProjPeriodTimesheetWeek = getTimesheetWeekRecId(_timesheetLine.ProjPeriodTimesheetWeek);
    return newTimesheetLine;
    }

    /// <summary>
    /// Init from timesheetLine Value
    /// </summary>
    /// <param name = "_tsTimesheetTable>_tsTimesheetTable</param>
    /// <param name = "_isNew">_isNew</param>
    public void postLineInserts(
    TSTimesheetTable _tsTimesheetTable,
    boolean _isNew)
    {
    TsTimesheetTableLog tsTimesheetTableLog;

    if (ProjParameters::find().TimesheetAuditTrail)
    {
    TsTimesheetLog tsTimesheetLog;
    // if the timesheet is new we need to use the existing table log created in insert
    if (_isNew)
    {
    select firstOnly tsTimesheetTableLog where
    tsTimesheetTableLog.TimesheetNbr == _tsTimesheetTable.TimesheetNbr;
    }
    else
    {
    tsTimesheetTableLog = TsTimesheetTableLog::createTableLog(_tsTimesheetTable, '', TsTimesheetChangeType::Update);
    }
    tsTimesheetLog.logPostLineInserts(tsTimesheetTableLog);
    }
    }
    }

  • Sonali Mane Profile Picture
    Sonali Mane 20 on at
    RE: Split timesheet based on project id

    Hi Gaurangkumar,

    We have suggested this option but customer don't want to change the current process & needs this automation of splitting timesheet based on project ids before submitting timesheet to workflow.

  • Suggested answer
    Gaurangkumar Jani Profile Picture
    Gaurangkumar Jani 4,511 User Group Leader on at
    RE: Split timesheet based on project id

    HI Sonali Mane

    I can understand the situation and delay of dependent tasks due to non approval of other project line.

    If I have to resolve this issue, Instead of doing this development, I would ask my user to created timesheet in per project instead of combining timesheet.

    Please let us know if this helps.

    Thanks,

  • Sonali Mane Profile Picture
    Sonali Mane 20 on at
    RE: Split timesheet based on project id

    Thanks for your reply Anton!

    Timesheet lines are approved by the project manager or line manager Lines in the timesheet are not posted to the projects before all lines in the timesheet are approved. This makes a project dependent on other project approvals from other project managers which may delay invoicing, estimates and cost follow-up.

    For that reason, timesheets will automatically be split on project id, meaning that one timesheet only contains one project id. Dependencies to other project managers approval will then disappear.

  • Suggested answer
    Anton Venter Profile Picture
    Anton Venter 19,493 Super User 2025 Season 1 on at
    RE: Split timesheet based on project id

    I have not tested this, but this will get you started. Have a look at the validateSubmit method of the TsTimesheetTable table. It is called by the TsTimesheetService and TsWorkflowActionManager classes. Your code can be added in this method or perhaps in those two classes.

    By the way, what is the reason for splitting the timesheets per project?

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Announcing Our 2025 Season 1 Super Users!

A new season of Super Users has arrived, and we are so grateful for the daily…

Announcing Forum Attachment Improvements!

We're excited to announce that attachments for replies in forums and improved…

Vahid Ghafarpour – Community Spotlight

We are excited to recognize Vahid Ghafarpour as our February 2025 Community…

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 291,969 Super User 2025 Season 1

#2
Martin Dráb Profile Picture

Martin Dráb 230,842 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Product updates

Dynamics 365 release plans