protected virtual void _(Events.FieldDefaulting <CROpportunityProducts, FSxCROpportunityProducts.billingRule> e)
        {
            if (e.Row == null)
            {
                return;
            }

            CROpportunityProducts    crOpportunityProductsRow    = (CROpportunityProducts)e.Row;
            FSxCROpportunityProducts fsxCROpportunityProductsRow = e.Cache.GetExtension <FSxCROpportunityProducts>(crOpportunityProductsRow);

            if (crOpportunityProductsRow.InventoryID != null)
            {
                InventoryItem inventoryItemRow = SharedFunctions.GetInventoryItemRow(Base, crOpportunityProductsRow.InventoryID);

                if (inventoryItemRow.ItemType == INItemTypes.ServiceItem)
                {
                    FSxService fsxServiceRow = PXCache <InventoryItem> .GetExtension <FSxService>(inventoryItemRow);

                    e.NewValue = fsxServiceRow?.BillingRule;
                    e.Cancel   = true;
                }
                else
                {
                    e.NewValue = ID.BillingRule.FLAT_RATE;
                    e.Cancel   = true;
                }
            }
        }
        protected virtual void _(Events.FieldDefaulting <CROpportunityProducts, FSxCROpportunityProducts.estimatedDuration> e)
        {
            if (e.Row == null)
            {
                return;
            }

            CROpportunityProducts    crOpportunityProductsRow    = (CROpportunityProducts)e.Row;
            FSxCROpportunityProducts fsxCROpportunityProductsRow = e.Cache.GetExtension <FSxCROpportunityProducts>(crOpportunityProductsRow);

            if (fsxCROpportunityProductsRow != null)
            {
                InventoryItem inventoryItemRow = SharedFunctions.GetInventoryItemRow(Base, crOpportunityProductsRow.InventoryID);

                if (inventoryItemRow != null)
                {
                    FSxService fsxServiceRow = PXCache <InventoryItem> .GetExtension <FSxService>(inventoryItemRow);

                    if (inventoryItemRow.ItemType == INItemTypes.ServiceItem ||
                        inventoryItemRow.ItemType == INItemTypes.NonStockItem)
                    {
                        e.NewValue = fsxServiceRow?.EstimatedDuration;
                        e.Cancel   = true;
                    }
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Enable/Disable the ActionType field for a Service depending on the appointments related to that service.
        /// </summary>
        public virtual void EnableDisableActionType(PXCache cache, InventoryItem inventoryItemRow)
        {
            bool       enableActionType = true;
            FSxService fsxServiceRow    = PXCache <InventoryItem> .GetExtension <FSxService>(inventoryItemRow);

            if (cache.GetStatus(inventoryItemRow) != PXEntryStatus.Inserted)
            {
                int rowCount = PXSelect <FSAppointmentDet,
                                         Where <
                                             FSAppointmentDet.lineType, Equal <ListField_LineType_Pickup_Delivery.Pickup_Delivery>,
                                             And <FSAppointmentDet.pickupDeliveryServiceID, Equal <Required <FSAppointmentDet.pickupDeliveryServiceID> > > > >
                               .SelectSingleBound(cache.Graph, null, inventoryItemRow.InventoryID).Count;

                enableActionType = rowCount == 0;
            }

            PXUIFieldAttribute.SetEnabled <FSxService.actionType>(cache, inventoryItemRow, enableActionType);

            if (enableActionType == false)
            {
                cache.RaiseExceptionHandling <FSxService.actionType>(inventoryItemRow,
                                                                     null,
                                                                     new PXSetPropertyException(
                                                                         PXMessages.LocalizeFormatNoPrefix(TX.Warning.CANNOT_MODIFY_FIELD, "Appoinments", "Service"),
                                                                         PXErrorLevel.Warning));
            }
        }
예제 #4
0
        /// <summary>
        /// Enable/Disable the PickUp/Delivery Grid for a Service if the ActionType is No Items Related or another option.
        /// </summary>
        public virtual void EnableDisablePickUpDelivery(PXCache cache, InventoryItem inventoryItemRow)
        {
            FSxService fsxServiceRow = PXCache <InventoryItem> .GetExtension <FSxService>(inventoryItemRow);

            if (fsxServiceRow != null)
            {
                bool enable = fsxServiceRow.ActionType != ID.Service_Action_Type.NO_ITEMS_RELATED;

                ServiceInventoryItems.Cache.AllowInsert = enable;
                ServiceInventoryItems.Cache.AllowUpdate = enable;
                ServiceInventoryItems.Cache.AllowDelete = enable;
            }
        }
예제 #5
0
        protected virtual void _(Events.RowPersisting <InventoryItem> e)
        {
            if (e.Row == null)
            {
                return;
            }

            InventoryItem item  = (InventoryItem)e.Row;
            PXCache       cache = e.Cache;

            InventoryItem oldItem = SharedFunctions.GetInventoryItemRow(cache.Graph, item.InventoryID);

            if (oldItem != null && e.Operation == PXDBOperation.Update &&
                item.BaseUnit?.Equals(oldItem.BaseUnit) == false &&
                SharedFunctions.IsServiceRelatedToAnyContract(cache, item.InventoryID) == true)
            {
                if (WebDialogResult.Yes == ServiceInventoryItems.Ask(TX.WebDialogTitles.CONFIRM_CHANGE_FSSALESPRICE_UOM, TX.Messages.ASK_CONFIRM_CHANGE_UOM_FSSALESPRICE, MessageButtons.YesNo))
                {
                    baseUnitChanged = true;
                }
            }

            if (item.ItemType == INItemTypes.ServiceItem)
            {
                FSxService service = cache.GetExtension <FSxService>(e.Row);

                if (service.EstimatedDuration == null || service.EstimatedDuration == 0)
                {
                    cache.RaiseExceptionHandling <FSxService.estimatedDuration>(e.Row,
                                                                                service.EstimatedDuration,
                                                                                new PXSetPropertyException(TX.Warning.INVALID_SERVICE_DURATION, PXErrorLevel.Error));
                }

                if (PXAccess.FeatureInstalled <FeaturesSet.distributionModule>())
                {
                    if (item.ItemClassID == null)
                    {
                        cache.RaiseExceptionHandling <InventoryItem.itemClassID>(e.Row,
                                                                                 null,
                                                                                 new PXSetPropertyException <InventoryItem.itemClassID>(TX.Error.FIELD_EMPTY, PXErrorLevel.Error));
                    }
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Assign the default Billing Rule set in the ItemClass.
        /// </summary>
        public virtual void SetDefaultBillingRule(PXCache cache, InventoryItem nonStockItemRow)
        {
            if (nonStockItemRow == null || nonStockItemRow.ItemClassID == null)
            {
                return;
            }

            if (nonStockItemRow.ItemType == INItemTypes.ServiceItem)
            {
                INItemClass inItemClassRow = PXSelect <INItemClass,
                                                       Where <
                                                           INItemClass.itemClassID, Equal <Required <InventoryItem.itemClassID> > > >
                                             .Select(Base, nonStockItemRow.ItemClassID);

                FSxServiceClass fsxServiceClassRow = PXCache <INItemClass> .GetExtension <FSxServiceClass>(inItemClassRow);

                FSxService service = cache.GetExtension <FSxService>(nonStockItemRow);
                service.BillingRule = fsxServiceClassRow.DfltBillingRule;
            }
        }
예제 #7
0
        protected virtual void _(Events.FieldUpdated <InventoryItem, FSxService.estimatedDuration> e)
        {
            if (e.Row == null)
            {
                return;
            }

            InventoryItem inventoryItemRow = (InventoryItem)e.Row;
            FSxService    fsxServiceRow    = PXCache <InventoryItem> .GetExtension <FSxService>(inventoryItemRow);

            PXSetPropertyException exception = null;

            if (fsxServiceRow.EstimatedDuration < 1)
            {
                exception = new PXSetPropertyException(TX.Warning.INVALID_SERVICE_DURATION, PXErrorLevel.Error);
            }

            e.Cache.RaiseExceptionHandling <FSxService.estimatedDuration>(inventoryItemRow,
                                                                          fsxServiceRow.EstimatedDuration,
                                                                          exception);
        }
        /// <summary>
        /// Create a Service Order from a TimeSlot.
        /// </summary>
        protected void CreateServiceOrder(TimeSlot timeSlotServiceOrder, bool createAppointmentFlag = false, bool appointmentsBelongToRoute = false)
        {
            // This action allows to avoid errors related to cache
            if (graphServiceOrderEntry != null)
            {
                graphServiceOrderEntry.Clear(PXClearOption.ClearAll);
            }
            else
            {
                graphServiceOrderEntry = PXGraph.CreateInstance <ServiceOrderEntry>();
                graphServiceOrderEntry.DisableServiceOrderUnboundFieldCalc = true;
            }

            FSSchedule        fsScheduleRow        = ScheduleSelected.Select(timeSlotServiceOrder.ScheduleID);
            FSServiceContract fsServiceContractRow = ServiceContractSelected.Select(fsScheduleRow.EntityID);

            bool isPrepaidContract = fsServiceContractRow.BillingType == ID.Contract_BillingType.STANDARDIZED_BILLINGS;

            //Services from the Schedule
            var fsScheduleDetSet = ScheduleLinesSelected.Select(timeSlotServiceOrder.ScheduleID);

            //Templates from the Schedule
            var fsScheduleDetTemplateSet = ScheduleTemplatesSelected.Select(timeSlotServiceOrder.ScheduleID);

            FSServiceOrder fsServiceOrderRow = new FSServiceOrder();

            fsServiceOrderRow.SrvOrdType = fsScheduleRow.SrvOrdType;
            graphServiceOrderEntry.ServiceOrderRecords.Insert(fsServiceOrderRow);

            fsServiceOrderRow = graphServiceOrderEntry.ServiceOrderRecords.Cache.CreateCopy(graphServiceOrderEntry.ServiceOrderRecords.Current) as FSServiceOrder;

            fsServiceOrderRow.BranchID         = fsScheduleRow.BranchID;
            fsServiceOrderRow.BranchLocationID = fsScheduleRow.BranchLocationID;
            fsServiceOrderRow.OrderDate        = timeSlotServiceOrder.DateTimeBegin.Date;
            fsServiceOrderRow.CustomerID       = fsServiceContractRow.CustomerID;
            fsServiceOrderRow.LocationID       = fsScheduleRow.CustomerLocationID;

            graphServiceOrderEntry.ServiceOrderRecords.Update(fsServiceOrderRow);
            fsServiceOrderRow = graphServiceOrderEntry.ServiceOrderRecords.Cache.CreateCopy(graphServiceOrderEntry.ServiceOrderRecords.Current) as FSServiceOrder;

            // Currently Service-Management's contracts DO NOT support multi-currency specification
            // therefore their ServiceOrders MUST be created in customer base currency
            if (PXAccess.FeatureInstalled <FeaturesSet.multicurrency>())
            {
                string curyID = null;

                Customer customer = (Customer)PXSelect <Customer,
                                                        Where <Customer.bAccountID, Equal <Required <Customer.bAccountID> > > >
                                    .Select(this, fsServiceContractRow.CustomerID);

                if (customer != null)
                {
                    curyID = customer.CuryID;
                }

                if (string.IsNullOrEmpty(curyID) == true)
                {
                    curyID = this.Accessinfo.BaseCuryID ?? new PXSetup <PX.Objects.GL.Company>(this).Current?.BaseCuryID;
                }

                fsServiceOrderRow.CuryID = curyID;
            }

            fsServiceOrderRow.DocDesc           = timeSlotServiceOrder.Descr;
            fsServiceOrderRow.BillCustomerID    = fsServiceContractRow.BillCustomerID;
            fsServiceOrderRow.BillLocationID    = fsServiceContractRow.BillLocationID;
            fsServiceOrderRow.ServiceContractID = fsServiceContractRow.ServiceContractID;
            fsServiceOrderRow.ProjectID         = fsServiceContractRow.ProjectID;
            fsServiceOrderRow.DfltProjectTaskID = fsServiceContractRow.DfltProjectTaskID;

            if (isPrepaidContract == true &&
                graphServiceOrderEntry.BillingCycleRelated.Current != null &&
                graphServiceOrderEntry.BillingCycleRelated.Current.BillingBy == ID.Billing_By.SERVICE_ORDER)
            {
                fsServiceOrderRow.BillServiceContractID = fsServiceContractRow.ServiceContractID;
            }

            fsServiceOrderRow.ScheduleID        = timeSlotServiceOrder.ScheduleID;
            fsServiceOrderRow.ServiceContractID = fsServiceContractRow.ServiceContractID;
            fsServiceOrderRow.GenerationID      = timeSlotServiceOrder.GenerationID;

            fsServiceOrderRow.SalesPersonID  = fsServiceContractRow.SalesPersonID;
            fsServiceOrderRow.Commissionable = fsServiceContractRow.Commissionable;

            fsServiceOrderRow = graphServiceOrderEntry.ServiceOrderRecords.Update(fsServiceOrderRow);

            if (fsServiceOrderRow.SalesPersonID == null)
            {
                object salesPersonID;
                graphServiceOrderEntry.ServiceOrderRecords.Cache.RaiseFieldDefaulting <FSServiceOrder.salesPersonID>(fsServiceOrderRow, out salesPersonID);
                fsServiceOrderRow.SalesPersonID = (int?)salesPersonID;

                object commissionable;
                graphServiceOrderEntry.ServiceOrderRecords.Cache.RaiseFieldDefaulting <FSServiceOrder.commissionable>(fsServiceOrderRow, out commissionable);
                fsServiceOrderRow.Commissionable = (bool?)commissionable;
            }

            graphServiceOrderEntry.Answers.CopyAllAttributes(fsServiceOrderRow, fsScheduleRow);

            #region Setting Service Order Details
            foreach (FSScheduleDet fsScheduleDetRow in fsScheduleDetSet)
            {
                if (fsScheduleDetRow.LineType == ID.LineType_ServiceContract.SERVICE_TEMPLATE)
                {
                    foreach (FSScheduleDet fsScheduleDetLocalRow in fsScheduleDetTemplateSet.Where(x => ((FSScheduleDet)x).ServiceTemplateID == fsScheduleDetRow.ServiceTemplateID))
                    {
                        var fsServiceTemplateDetSet_Service = ServiceTemplateSelected.Select(fsScheduleDetRow.ServiceTemplateID);

                        foreach (FSServiceTemplateDet fsServiceTemplateDetRow_Service in fsServiceTemplateDetSet_Service)
                        {
                            FSSODet fsSODetRow = new FSSODet();

                            // Insert the new row with key fields
                            fsSODetRow.ScheduleID    = fsScheduleDetLocalRow.ScheduleID;
                            fsSODetRow.ScheduleDetID = fsScheduleDetLocalRow.ScheduleDetID;
                            fsSODetRow.LineType      = fsServiceTemplateDetRow_Service.LineType;

                            fsSODetRow = graphServiceOrderEntry.ServiceOrderDetails.Insert(fsSODetRow);

                            fsSODetRow.InventoryID = fsServiceTemplateDetRow_Service.InventoryID;

                            fsSODetRow = graphServiceOrderEntry.ServiceOrderDetails.Update(fsSODetRow);

                            PXNoteAttribute.CopyNoteAndFiles(ScheduleLinesSelected.Cache,
                                                             fsScheduleDetLocalRow,
                                                             graphServiceOrderEntry.ServiceOrderDetails.Cache,
                                                             fsSODetRow,
                                                             copyNotes: true,
                                                             copyFiles: true);

                            // Create a copy to update the other fields
                            fsSODetRow = (FSSODet)graphServiceOrderEntry.ServiceOrderDetails.Cache.CreateCopy(fsSODetRow);

                            fsSODetRow.TranDesc = fsServiceTemplateDetRow_Service.TranDesc;

                            InventoryItem inventoryItemRow = SharedFunctions.GetInventoryItemRow(this, fsServiceTemplateDetRow_Service.InventoryID);

                            if (inventoryItemRow != null)
                            {
                                FSxService fsxServiceRow = PXCache <InventoryItem> .GetExtension <FSxService>(inventoryItemRow);

                                if (fsxServiceRow != null && fsxServiceRow.BillingRule == ID.BillingRule.TIME)
                                {
                                    int?estimatedDuration = CalculateEstimatedDuration(fsSODetRow, fsServiceTemplateDetRow_Service.Qty);
                                    fsSODetRow.EstimatedDuration = estimatedDuration;
                                }
                                else
                                {
                                    fsSODetRow.EstimatedQty = fsServiceTemplateDetRow_Service.Qty;
                                }
                            }

                            if (fsServiceContractRow.SourcePrice == ID.SourcePrice.CONTRACT)
                            {
                                fsSODetRow.ManualPrice = true;
                                // TODO: Check where is assigned the contract price?
                            }

                            if (createAppointmentFlag)
                            {
                                fsSODetRow.Scheduled = true;
                                fsSODetRow.Status    = ID.Status_SODet.SCHEDULED;
                            }

                            fsSODetRow.EquipmentAction  = fsScheduleDetRow.EquipmentAction;
                            fsSODetRow.SMEquipmentID    = fsScheduleDetRow.SMEquipmentID;
                            fsSODetRow.ComponentID      = fsScheduleDetRow.ComponentID;
                            fsSODetRow.EquipmentLineRef = fsScheduleDetRow.EquipmentLineRef;
                            fsSODetRow.ProjectTaskID    = fsScheduleDetRow.ProjectTaskID;
                            fsSODetRow.CostCodeID       = fsScheduleDetRow.CostCodeID;

                            if (fsSODetRow.InventoryID != null)
                            {
                                fsSODetRow.ProjectTaskID = fsScheduleDetRow.ProjectTaskID;
                                fsSODetRow.CostCodeID    = fsScheduleDetRow.CostCodeID;
                            }

                            graphServiceOrderEntry.ServiceOrderDetails.Update(fsSODetRow);
                        }
                    }
                }
                else
                {
                    FSSODet fsSODetRow = new FSSODet();

                    // Insert the new row with key fields
                    fsSODetRow.ScheduleID    = fsScheduleDetRow.ScheduleID;
                    fsSODetRow.ScheduleDetID = fsScheduleDetRow.ScheduleDetID;
                    fsSODetRow.LineType      = fsScheduleDetRow.LineType;

                    fsSODetRow = graphServiceOrderEntry.ServiceOrderDetails.Insert(fsSODetRow);

                    fsSODetRow.InventoryID = fsScheduleDetRow.InventoryID;

                    fsSODetRow = graphServiceOrderEntry.ServiceOrderDetails.Update(fsSODetRow);

                    PXNoteAttribute.CopyNoteAndFiles(ScheduleLinesSelected.Cache,
                                                     fsScheduleDetRow,
                                                     graphServiceOrderEntry.ServiceOrderDetails.Cache,
                                                     fsSODetRow,
                                                     copyNotes: true,
                                                     copyFiles: true);

                    // Create a copy to update the other fields
                    fsSODetRow = (FSSODet)graphServiceOrderEntry.ServiceOrderDetails.Cache.CreateCopy(fsSODetRow);

                    fsSODetRow.TranDesc    = fsScheduleDetRow.TranDesc;
                    fsSODetRow.BillingRule = fsScheduleDetRow.BillingRule;

                    if (fsSODetRow.BillingRule == ID.BillingRule.TIME)
                    {
                        int?estimatedDuration = CalculateEstimatedDuration(fsSODetRow, fsScheduleDetRow?.Qty);
                        fsSODetRow.EstimatedDuration = estimatedDuration;
                    }
                    else
                    {
                        fsSODetRow.EstimatedQty = fsScheduleDetRow.Qty;
                    }

                    if (fsServiceContractRow.SourcePrice == ID.SourcePrice.CONTRACT)
                    {
                        fsSODetRow.ManualPrice = true;
                        // TODO: AC-142850 Check where is assigned the contract price?
                    }

                    if (createAppointmentFlag)
                    {
                        fsSODetRow.Scheduled = true;
                        fsSODetRow.Status    = ID.Status_SODet.SCHEDULED;
                    }

                    fsSODetRow.EquipmentAction  = fsScheduleDetRow.EquipmentAction;
                    fsSODetRow.SMEquipmentID    = fsScheduleDetRow.SMEquipmentID;
                    fsSODetRow.ComponentID      = fsScheduleDetRow.ComponentID;
                    fsSODetRow.EquipmentLineRef = fsScheduleDetRow.EquipmentLineRef;
                    fsSODetRow.ProjectTaskID    = fsScheduleDetRow.ProjectTaskID;
                    fsSODetRow.CostCodeID       = fsScheduleDetRow.CostCodeID;

                    if (fsSODetRow.InventoryID != null)
                    {
                        fsSODetRow.ProjectTaskID = fsScheduleDetRow.ProjectTaskID;
                        fsSODetRow.CostCodeID    = fsScheduleDetRow.CostCodeID;
                    }

                    graphServiceOrderEntry.ServiceOrderDetails.Update(fsSODetRow);
                }
            }

            if (fsScheduleRow.VendorID != null)
            {
                FSSOEmployee fsSOEmployeeRow = new FSSOEmployee();
                fsSOEmployeeRow.EmployeeID = fsScheduleRow.VendorID;
                graphServiceOrderEntry.ServiceOrderEmployees.Insert(fsSOEmployeeRow);
            }

            #endregion

            graphServiceOrderEntry.Save.Press();

            if (createAppointmentFlag)
            {
                string origStatus = graphServiceOrderEntry.ServiceOrderRecords.Current.Status;

                if (origStatus != ID.Status_ServiceOrder.OPEN)
                {
                    //Due to FSAppointment.sORefNbr selector, Service Order status must be OPEN to allow the SetValueExt<SORefNbr> inside createAppointment() work properly.
                    //PXUpdate is used to avoid raising any ServiceOrderEntry event.
                    PXUpdate <
                        Set <FSServiceOrder.status, FSServiceOrder.status.Open>,
                        FSServiceOrder,
                        Where <
                            FSServiceOrder.sOID, Equal <Required <FSServiceOrder.sOID> > > >
                    .Update(this, graphServiceOrderEntry.ServiceOrderRecords.Current.SOID);
                }

                CreateAppointment(graphServiceOrderEntry.ServiceOrderRecords.Current, timeSlotServiceOrder, fsScheduleRow, true, appointmentsBelongToRoute, isPrepaidContract);

                if (origStatus != ID.Status_ServiceOrder.OPEN)
                {
                    PXUpdate <
                        Set <FSServiceOrder.status, Required <FSServiceOrder.status> >,
                        FSServiceOrder,
                        Where <
                            FSServiceOrder.sOID, Equal <Required <FSServiceOrder.sOID> > > >
                    .Update(this, origStatus, graphServiceOrderEntry.ServiceOrderRecords.Current.SOID);
                }
            }
        }
        public static void X_InventoryID_FieldUpdated <DAC, SubItemID,
                                                       SiteID, SiteLocationID, UOM,
                                                       EstimatedDuration, EstimatedQty, BillingRule,
                                                       ActualDuration, ActualQty>(
            PXCache cache,
            PXFieldUpdatedEventArgs e,
            int?branchLocationID,
            Customer billCustomerRow,
            bool useActualFields)
            where DAC : class, IBqlTable, IFSSODetBase, new()
            where SubItemID : class, IBqlField
            where SiteID : class, IBqlField
            where SiteLocationID : class, IBqlField
            where UOM : class, IBqlField
            where EstimatedDuration : class, IBqlField
            where EstimatedQty : class, IBqlField
            where BillingRule : class, IBqlField
            where ActualDuration : class, IBqlField
            where ActualQty : class, IBqlField
        {
            if (e.Row == null)
            {
                return;
            }

            var row = (DAC)e.Row;

            // This is required in Inventory FieldUpdated events
            if (e.ExternalCall)
            {
                row.CuryUnitPrice = 0m;
            }


            if (IsInventoryLine(row.LineType) == false ||
                (row.InventoryID == null && row.LineType != ID.LineType_All.PICKUP_DELIVERY))
            {
                // Clear fields for non-inventory lines

                row.IsBillable  = false;
                row.ManualPrice = false;

                row.TranDesc       = null;
                row.SubItemID      = null;
                row.SiteID         = null;
                row.SiteLocationID = null;

                cache.SetDefaultExt <FSSODet.uOM>(e.Row);

                cache.RaiseExceptionHandling <UOM>(e.Row, null, null);

                row.SetDuration(FieldType.EstimatedField, 0, cache, false);
                row.SetQty(FieldType.EstimatedField, 0, cache, false);

                if (useActualFields == true)
                {
                    row.SetDuration(FieldType.ActualField, 0, cache, false);
                    row.SetQty(FieldType.ActualField, 0, cache, false);
                }

                row.BillingRule = ID.BillingRule.NONE;

                return;
            }

            InventoryItem inventoryItemRow = SharedFunctions.GetInventoryItemRow(cache.Graph, row.InventoryID);

            row.TranDesc = null;
            if (inventoryItemRow != null)
            {
                row.TranDesc = PXDBLocalizableStringAttribute.GetTranslation(cache.Graph.Caches[typeof(InventoryItem)], inventoryItemRow, "Descr", billCustomerRow?.LocaleName);
            }


            // UOM is assigned to null here to avoid price calculation while duration and qty fields are defaulted.
            row.UOM = null;
            cache.RaiseExceptionHandling <UOM>(e.Row, null, null);

            cache.SetDefaultExt <SubItemID>(e.Row);
            cache.SetDefaultExt <SiteID>(e.Row);

            if (inventoryItemRow != null)
            {
                if (row.SiteID == null)
                {
                    row.SiteID = inventoryItemRow.DfltSiteID;
                }

                if (row.SiteID == null)
                {
                    //TODO: this query may return multiple records
                    INItemSite inItemSiteRow = PXSelect <INItemSite,
                                                         Where <
                                                             INItemSite.inventoryID, Equal <Required <INItemSite.inventoryID> > > >
                                               .Select(cache.Graph, inventoryItemRow.InventoryID);

                    if (inItemSiteRow != null)
                    {
                        row.SiteID = inItemSiteRow.SiteID;
                    }
                }
            }

            cache.SetDefaultExt <SiteLocationID>(e.Row);

            if (inventoryItemRow != null)
            {
                if (row.SiteLocationID == null && row.LineType == ID.LineType_All.INVENTORY_ITEM)
                {
                    row.SiteLocationID = inventoryItemRow.DfltShipLocationID;
                }
            }

            int?   defaultSubItemID = row.SubItemID;
            object newValue         = null;

            cache.RaiseFieldDefaulting <UOM>(e.Row, out newValue);
            string defaultUOM    = (string)newValue;
            int?   defaultSiteID = row.SiteID;

            CompleteItemInfoUsingBranchLocation(
                cache.Graph,
                branchLocationID,
                inventoryItemRow != null ? inventoryItemRow.DefaultSubItemOnEntry : false,
                ref defaultSubItemID,
                ref defaultUOM,
                ref defaultSiteID);
            row.SubItemID = defaultSubItemID;

            if (defaultSiteID != null)
            {
                cache.SetValueExt <SiteID>(e.Row, defaultSiteID);
            }

            cache.SetValueExt <UOM>(e.Row, defaultUOM);

            row.SetDuration(FieldType.EstimatedField, 0, cache, false);

            // EstimatedQty MUST be assigned after BillingRule BUT before EstimatedDuration.

            if (row.LineType == ID.LineType_All.SERVICE && inventoryItemRow != null)
            {
                FSxService fsxServiceRow = PXCache <InventoryItem> .GetExtension <FSxService>(inventoryItemRow);

                cache.SetValueExt <BillingRule>(e.Row, fsxServiceRow.BillingRule);
                cache.SetDefaultExt <EstimatedQty>(e.Row);

                cache.SetValueExt <EstimatedDuration>(e.Row, fsxServiceRow.EstimatedDuration ?? 0);
            }
            else
            {
                cache.SetValueExt <BillingRule>(e.Row, ID.BillingRule.FLAT_RATE);
                cache.SetDefaultExt <EstimatedQty>(e.Row);
            }

            if (useActualFields == true)
            {
                cache.SetDefaultExt <ActualQty>(e.Row);
                cache.SetDefaultExt <ActualDuration>(e.Row);
            }
        }