private void CloneServices(AppointmentEntry sourceAppointmentGraph, AppointmentEntry newAppointmentGraph, FSAppointment newAppointmentRow)
        {
            foreach (FSAppointmentDetService sourceRow in sourceAppointmentGraph.AppointmentDetServices.Select())
            {
                FSSODet fsSODetRow = ServiceOrderCore.GetSODetFromAppointmentDet(sourceAppointmentGraph, sourceRow);

                if (fsSODetRow != null &&
                    (fsSODetRow.Status == ID.Status_AppointmentDet.CANCELED ||
                     fsSODetRow.Status == ID.Status_AppointmentDet.COMPLETED))
                {
                    continue;
                }

                FSAppointmentDetService newRow = PXCache <FSAppointmentDetService> .CreateCopy(sourceRow);

                newRow.ActualDuration      = 0;
                newRow.ActualDateTimeBegin = null;
                newRow.ActualDateTimeEnd   = null;
                newRow.Qty = 0;

                newRow = AppointmentEntry.InsertServicePartLine <FSAppointmentDetService, FSAppointmentDetService>(
                    newAppointmentGraph.AppointmentDetServices.Cache,
                    newRow,
                    sourceAppointmentGraph.AppointmentDetServices.Cache,
                    sourceRow,
                    null,
                    sourceRow.SODetID,
                    copyTranDate: false,
                    tranDate: sourceRow.TranDate,
                    SetValuesAfterAssigningSODetID: true,
                    copyingFromQuote: false);

                PXNoteAttribute.CopyNoteAndFiles(
                    sourceAppointmentGraph.AppointmentDetServices.Cache,
                    sourceRow,
                    newAppointmentGraph.AppointmentDetServices.Cache,
                    newRow,
                    copyNotes: true,
                    copyFiles: false);


                newAppointmentGraph.AppointmentDetServices.SetValueExt <FSAppointmentDetService.acctID>(newRow, sourceRow.AcctID);
                newAppointmentGraph.AppointmentDetServices.SetValueExt <FSAppointmentDetService.subID>(newRow, sourceRow.SubID);

                AppointmentCore.UpdateAppointmentsInfoInServiceOrder(newAppointmentGraph.AppointmentDetServices.Cache, newRow, ServiceOrderRelated);
            }
        }
        private void CloneParts(AppointmentEntry sourceAppointmentGraph, AppointmentEntry newAppointmentGraph, FSAppointment newAppointmentRow)
        {
            foreach (FSAppointmentDetPart sourceRow in sourceAppointmentGraph.AppointmentDetParts.Select())
            {
                FSSODet fsSODetRow = ServiceOrderCore.GetSODetFromAppointmentDet(sourceAppointmentGraph, sourceRow);

                if (fsSODetRow != null &&
                    (fsSODetRow.Status == ID.Status_AppointmentDet.CANCELED ||
                     fsSODetRow.Status == ID.Status_AppointmentDet.COMPLETED))
                {
                    continue;
                }

                FSAppointmentDet sumFSAppointmentDetPartBillable =
                    PXSelectJoinGroupBy <FSAppointmentDet,
                                         InnerJoin <FSAppointment, On <FSAppointment.srvOrdType, Equal <FSAppointmentDet.srvOrdType>,
                                                                       And <FSAppointment.refNbr, Equal <FSAppointmentDetPart.refNbr> > > >,
                                         Where <FSAppointmentDet.sODetID, Equal <Required <FSAppointmentDet.sODetID> >,
                                                And <FSAppointment.status, NotEqual <FSAppointment.status.Canceled>,
                                                     And <FSAppointmentDet.status, NotEqual <FSAppointmentDet.status.Canceled> > > >,
                                         Aggregate <GroupBy <FSAppointmentDet.sODetID, Sum <FSAppointmentDet.billableQty> > > >
                    .Select(dummyGraph, sourceRow.SODetID);

                decimal?openQty    = fsSODetRow.BillableQty - sumFSAppointmentDetPartBillable.BillableQty;
                bool?   lineCloned = false;

                FSAppointmentDetPart newRow = PXCache <FSAppointmentDetPart> .CreateCopy(sourceRow);

                if (openQty >= sourceRow.BillableQty)
                {
                    newRow = AppointmentEntry.InsertServicePartLine <FSAppointmentDetPart, FSAppointmentDetPart>(
                        newAppointmentGraph.AppointmentDetParts.Cache,
                        newRow,
                        sourceAppointmentGraph.AppointmentDetParts.Cache,
                        sourceRow,
                        null,
                        sourceRow.SODetID,
                        copyTranDate: false,
                        tranDate: sourceRow.TranDate,
                        SetValuesAfterAssigningSODetID: true,
                        copyingFromQuote: false);
                    lineCloned = true;
                }
                else
                {
                    if (openQty > 0)
                    {
                        decimal?remainingQty = sourceRow.BillableQty - openQty;

                        newRow.Qty             = 0;
                        sourceRow.EstimatedQty = openQty;
                        sourceRow.BillableQty  = openQty;
                        newRow = AppointmentEntry.InsertServicePartLine <FSAppointmentDetPart, FSAppointmentDetPart>(
                            newAppointmentGraph.AppointmentDetParts.Cache,
                            newRow,
                            sourceAppointmentGraph.AppointmentDetParts.Cache,
                            sourceRow,
                            null,
                            sourceRow.SODetID,
                            copyTranDate: false,
                            tranDate: sourceRow.TranDate,
                            SetValuesAfterAssigningSODetID: true,
                            copyingFromQuote: false);
                        lineCloned = true;

                        FSAppointmentDetPart secondNewRow = PXCache <FSAppointmentDetPart> .CreateCopy(sourceRow);

                        secondNewRow.Qty       = 0;
                        sourceRow.EstimatedQty = remainingQty;
                        sourceRow.BillableQty  = remainingQty;
                        secondNewRow.SODetID   = null;
                        secondNewRow           = AppointmentEntry.InsertServicePartLine <FSAppointmentDetPart, FSAppointmentDetPart>(
                            newAppointmentGraph.AppointmentDetParts.Cache,
                            secondNewRow,
                            sourceAppointmentGraph.AppointmentDetParts.Cache,
                            sourceRow,
                            null,
                            null,
                            copyTranDate: false,
                            tranDate: sourceRow.TranDate,
                            SetValuesAfterAssigningSODetID: false,
                            copyingFromQuote: false);
                    }
                    else
                    {
                        newRow.SODetID = null;
                        newRow.Qty     = 0;
                        newRow         = AppointmentEntry.InsertServicePartLine <FSAppointmentDetPart, FSAppointmentDetPart>(
                            newAppointmentGraph.AppointmentDetParts.Cache,
                            newRow,
                            sourceAppointmentGraph.AppointmentDetParts.Cache,
                            sourceRow,
                            null,
                            null,
                            copyTranDate: false,
                            tranDate: sourceRow.TranDate,
                            SetValuesAfterAssigningSODetID: false,
                            copyingFromQuote: false);
                    }
                }


                if (lineCloned == true)
                {
                    PXNoteAttribute.CopyNoteAndFiles(
                        sourceAppointmentGraph.AppointmentDetParts.Cache,
                        sourceRow,
                        newAppointmentGraph.AppointmentDetParts.Cache,
                        newRow,
                        copyNotes: true,
                        copyFiles: false);

                    AppointmentCore.UpdateAppointmentsInfoInServiceOrder(newAppointmentGraph.AppointmentDetParts.Cache, newRow, ServiceOrderRelated);
                }
            }
        }