public POLandedCostReceiptLineAdjustment(POReceiptLine receiptLine, POLandedCostReceiptLine landedCostReceiptLine,
                                          POLandedCostDetail landedCostDetail, decimal qtyToAssign, int?branchID)
     : base(receiptLine, qtyToAssign, branchID)
 {
     LandedCostReceiptLine = landedCostReceiptLine;
     LandedCostDetail      = landedCostDetail;
 }
        protected virtual decimal GetAllocationAmount(POLandedCostDetail landedCostDetail, IEnumerable <PXResult <POLandedCostTax, Tax> > taxes)
        {
            var landedCostTax = taxes
                                .Where(t => ((Tax)t).TaxCalcLevel == CSTaxCalcLevel.Inclusive && ((Tax)t).TaxType != CSTaxType.Withholding && ((Tax)t).ReverseTax != true)
                                .RowCast <POLandedCostTax>()
                                .FirstOrDefault(t => t.LineNbr == landedCostDetail.LineNbr);

            if (landedCostTax != null)
            {
                return(landedCostTax.TaxableAmt ?? 0);
            }

            return(landedCostDetail.LineAmt ?? 0);
        }
        public virtual bool IsApplicable(PXGraph graph, POLandedCostDetail aTran, LandedCostCode aCode, POReceiptLine aLine)
        {
            if (!IsApplicable(graph, aCode, aLine))
            {
                return(false);
            }

            if (aTran.InventoryID.HasValue)
            {
                if (aTran.InventoryID != aLine.InventoryID)
                {
                    return(false);
                }
            }

            return(true);
        }
        public virtual bool ValidateLCTran(PXGraph graph, POLandedCostDoc doc, IEnumerable <POLandedCostReceiptLine> landedCostReceiptLines, POLandedCostDetail row, out string message)
        {
            decimal valueToCompare = decimal.Zero;
            int     count          = 0;

            if (row != null && !String.IsNullOrEmpty(row.LandedCostCodeID))
            {
                LandedCostCode code = PXSelect <LandedCostCode,
                                                Where <LandedCostCode.landedCostCodeID, Equal <Required <LandedCostCode.landedCostCodeID> > > > .Select(graph, row.LandedCostCodeID);

                var receiptLines = GetReceiptLines(graph, landedCostReceiptLines);

                foreach (POReceiptLine it in receiptLines)
                {
                    var landedCostReceiptLine = landedCostReceiptLines.Single(t =>
                                                                              t.POReceiptType == it.ReceiptType && t.POReceiptNbr == it.ReceiptNbr && t.POReceiptLineNbr == it.LineNbr);

                    if (IsApplicable(graph, row, code, it))
                    {
                        var landedCostAllocationItem = new LandedCostAllocationItem()
                        {
                            LandedCostCode        = code,
                            ReceiptLine           = it,
                            LandedCostDetail      = row,
                            LandedCostReceiptLine = landedCostReceiptLine
                        };

                        valueToCompare += GetBaseValue(landedCostAllocationItem);
                    }
                    count++;
                }

                if (!HasApplicableTransfers)
                {
                    message = Messages.LandedCostCannotBeDistributed;
                    return(false);
                }

                switch (code.AllocationMethod)
                {
                case LandedCostAllocationMethod.ByCost:
                    message = Messages.LandedCostReceiptTotalCostIsZero;
                    break;

                case LandedCostAllocationMethod.ByWeight:
                    message = Messages.LandedCostReceiptTotalWeightIsZero;
                    break;

                case LandedCostAllocationMethod.ByVolume:
                    message = Messages.LandedCostReceiptTotalVolumeIsZero;
                    break;

                case LandedCostAllocationMethod.ByQuantity:
                    message = Messages.LandedCostReceiptTotalQuantityIsZero;
                    break;

                case LandedCostAllocationMethod.None:
                    message        = Messages.LandedCostReceiptNoReceiptLines;
                    valueToCompare = count;
                    break;

                default:
                    message = Messages.LandedCostUnknownAllocationType;
                    break;
                }
                if (valueToCompare == Decimal.Zero)
                {
                    return(false);
                }
            }
            message = String.Empty;
            return(true);
        }
        public virtual List <POLandedCostReceiptLineAdjustment> AllocateLCOverRCTLines(
            PXGraph graph,
            POLandedCostDetail landedCostDetail,
            IEnumerable <POLandedCostReceiptLine> landedCostReceiptLines,
            IEnumerable <PXResult <POLandedCostTax, Tax> > taxes,
            IEnumerable <POReceiptLine> receiptLines,
            IEnumerable <LandedCostCode> landedCostCodes,
            IEnumerable <POReceipt> receipts)
        {
            var landedCostCode = landedCostCodes.Single(t => t.LandedCostCodeID == landedCostDetail.LandedCostCodeID);

            var     rctLinesList       = receiptLines.Where(rl => IsApplicable(graph, landedCostDetail, landedCostCode, rl)).ToList();
            var     rctLinesAllocItems = new LandedCostAllocationItem[rctLinesList.Count];
            Decimal toDistribute       = GetAllocationAmount(landedCostDetail, taxes);
            Decimal baseTotal          = decimal.Zero;

            for (int i = 0; i < rctLinesList.Count; i++)
            {
                POReceiptLine receiptLine           = rctLinesList[i];
                var           landedCostReceiptLine = landedCostReceiptLines.Single(t
                                                                                    => t.POReceiptType == receiptLine.ReceiptType &&
                                                                                    t.POReceiptNbr == receiptLine.ReceiptNbr &&
                                                                                    t.POReceiptLineNbr == receiptLine.LineNbr);

                rctLinesAllocItems[i] = new LandedCostAllocationItem()
                {
                    LandedCostCode        = landedCostCode,
                    ReceiptLine           = receiptLine,
                    LandedCostDetail      = landedCostDetail,
                    LandedCostReceiptLine = landedCostReceiptLine
                };

                baseTotal += GetBaseValue(rctLinesAllocItems[i]);
            }

            var     result               = new List <POReceiptLineAdjustment>();
            decimal allocatedAmt         = 0m;
            decimal handledLinesAllocAmt = 0m;
            int?    maxLineIndex         = null;
            decimal maxLineAllocAmt      = 0m;

            for (int i = 0; i < rctLinesList.Count; i++)
            {
                decimal allocAmt = CalcAllocationValue(graph, rctLinesAllocItems[i], baseTotal, toDistribute);
                handledLinesAllocAmt += allocAmt;

                if (maxLineIndex == null || maxLineAllocAmt < allocAmt)
                {
                    maxLineIndex    = i;
                    maxLineAllocAmt = allocAmt;
                }

                allocAmt = handledLinesAllocAmt - allocatedAmt;
                if (allocAmt > 0m)
                {
                    POReceiptLine maxLine   = rctLinesList[maxLineIndex.Value];
                    var           poreceipt = receipts.Single(r
                                                              => r.ReceiptType == maxLine.ReceiptType &&
                                                              r.ReceiptNbr == maxLine.ReceiptNbr);

                    decimal lineAllocatedAmt = AllocateOverRCTLine(graph, result, rctLinesAllocItems[maxLineIndex.Value], allocAmt, poreceipt.BranchID);
                    if (lineAllocatedAmt != 0m)
                    {
                        maxLineIndex    = null;
                        maxLineAllocAmt = 0m;
                        allocatedAmt   += lineAllocatedAmt;
                    }
                }
            }

            AllocateRestOverRCTLines(result, toDistribute - allocatedAmt);

            var castResult = result.Cast <POLandedCostReceiptLineAdjustment>().ToList();

            return(castResult);
        }
        protected virtual INTran[] CreateTransactions(POLandedCostDoc doc, POLandedCostDetail landedCostDetail, IEnumerable <LandedCostAllocationService.POLandedCostReceiptLineAdjustment> pOLinesToProcess)
        {
            var result = new List <INTran>();

            var landedCostCode = GetLandedCostCode(landedCostDetail.LandedCostCodeID);
            var reasonCode     = landedCostCode.ReasonCode;

            foreach (LandedCostAllocationService.POLandedCostReceiptLineAdjustment poreceiptline in pOLinesToProcess)
            {
                INTran intran = new INTran();

                INTran origtran   = LandedCostAllocationService.Instance.GetOriginalInTran(_pxGraph, poreceiptline.ReceiptLine.ReceiptNbr, poreceiptline.ReceiptLine.LineNbr);
                bool   isDropShip = (poreceiptline.ReceiptLine.LineType == POLineType.GoodsForDropShip || poreceiptline.ReceiptLine.LineType == POLineType.NonStockForDropShip);

                if (!isDropShip && origtran == null)
                {
                    throw new PXException(AP.Messages.CannotFindINReceipt, poreceiptline.ReceiptLine.ReceiptNbr);
                }

                //Drop-Ships are considered non-stocks
                if (poreceiptline.ReceiptLine.IsStockItem())
                {
                    intran.TranType = INTranType.ReceiptCostAdjustment;
                }
                else
                {
                    //Landed cost and PPV for non-stock items are handled in special way in the inventory.
                    //They should create a GL Batch, but for convinience and unforminty this functionality is placed into IN module
                    //Review this part when the functionality is implemented in IN module
                    intran.IsCostUnmanaged = true;
                    intran.TranType        = INTranType.Adjustment;
                    intran.InvtMult        = 0;
                }
                intran.InventoryID = poreceiptline.ReceiptLine.InventoryID;
                intran.SubItemID   = poreceiptline.ReceiptLine.SubItemID;
                intran.SiteID      = poreceiptline.ReceiptLine.SiteID;
                intran.BAccountID  = doc.VendorID;
                intran.BranchID    = landedCostDetail.BranchID;


                if (isDropShip && intran.SiteID != null)
                {
                    INSite invSite = PXSelect <INSite, Where <INSite.siteID, Equal <Required <POReceiptLine.siteID> > > > .Select(_pxGraph, intran.SiteID);

                    if (invSite.DropShipLocationID == null)
                    {
                        throw new PXException(SO.Messages.NoDropShipLocation, invSite.SiteCD);
                    }

                    intran.LocationID = invSite.DropShipLocationID;
                }
                else
                {
                    intran.LocationID = poreceiptline.ReceiptLine.LocationID ?? origtran.LocationID;
                }

                intran.LotSerialNbr     = poreceiptline.ReceiptLine.LotSerialNbr;
                intran.POReceiptType    = poreceiptline.ReceiptLine.ReceiptType;
                intran.POReceiptNbr     = poreceiptline.ReceiptLine.ReceiptNbr;
                intran.POReceiptLineNbr = poreceiptline.ReceiptLine.LineNbr;

                //tran.Qty = poreceiptline.ReceiptQty;
                intran.TranDesc = landedCostDetail.Descr;
                //tran.UnitCost = PXDBPriceCostAttribute.Round(inGraph.transactions.Cache, (decimal)(poreceiptline.ExtCost / poreceiptline.ReceiptQty));
                intran.TranCost   = poreceiptline.QtyToAssign;
                intran.ReasonCode = reasonCode;
                if (origtran != null && origtran.DocType == INDocType.Issue)
                {
                    intran.ARDocType = origtran.ARDocType;
                    intran.ARRefNbr  = origtran.ARRefNbr;
                    intran.ARLineNbr = origtran.ARLineNbr;
                }
                if (!isDropShip)
                {
                    intran.OrigTranType = origtran.DocType;
                    intran.OrigRefNbr   = origtran.RefNbr;
                }

                int?acctID = null;
                int?subID  = null;
                intran.AcctID = landedCostDetail.LCAccrualAcct;
                intran.SubID  = landedCostDetail.LCAccrualSub;
                GetLCVarianceAccountSub(ref acctID, ref subID, poreceiptline.ReceiptLine);
                intran.COGSAcctID = acctID;
                intran.COGSSubID  = subID;

                result.Add(intran);
            }

            return(result.ToArray());
        }