-- ------------------------------------------------------
-- Sale Controller Temporary Database Objects Script File
-- ------------------------------------------------------
-- This is the base script which is able to join
-- objects from all other database schemas
-- defined for Sale Controller Component.
--
-- Copyright © 2008-2017 MWneo Corporation
-- Author: amerolli
--
-- ------------------------------------------------------

-- TempModifiers table: used during change dimension operation to backup current sale modifiers.
CREATE TEMPORARY TABLE TempModifiers(
    OrderId INTEGER,
    LineNumber INTEGER,
    ModifiedCode INTEGER,
    OnlyFlag INTEGER,
    ModifierCode INTEGER,
    ModifiedQty INTEGER
);
-- OrderTaxItem table: used during tax calculation for temporary order contents storage.
CREATE TEMPORARY TABLE OrderTaxItem (
    LineNumber INTEGER,
    Level VARCHAR(30),
    ItemId VARCHAR(50),
    MatchItemId VARCHAR(50),
    PartCode INTEGER,
    Context VARCHAR(50),
    BaseAmountBD VARCHAR(30),
    BaseAmountAD VARCHAR(30)
);
-- OrderDiscountItem table: used during discounts calculation for temporary order contents storage.
CREATE TEMPORARY TABLE OrderDiscountItem (
    LineNumber INTEGER NOT NULL,
    Level VARCHAR(30) NOT NULL,
    ItemId VARCHAR(50),
    PartCode INTEGER,
    DiscountId INTEGER NOT NULL DEFAULT -1,
    MultQty INTEGER NOT NULL,
    Qty INTEGER NOT NULL,
    ItemPrice VARCHAR(30),
    Discount VARCHAR(30)
);
-- OrderViewParameters table: tries to minimize the number of rows for certain views
CREATE TEMPORARY TABLE OrderViewParameters (
	LineNumber INTEGER
);
-- OrderLineFraction table: temporary table used to fractionate an order line (see procedure fractionateOrderLine)
CREATE TEMPORARY TABLE OrderLineFraction (
	OrderId,
	LineNumber INTEGER,
	FractionQty INTEGER
);
-- POSBackup table: temporary table for backup of the current state of orderdb.POS table
CREATE TEMPORARY TABLE POSBackup (
	POSId INTEGER,
	CurrentOrder INTEGER,
	ProdDescrId INTEGER,
	RoundingModeId INTEGER,
	RoundingScale INTEGER,
	CustomData VARCHAR
);


-- -----------------------------------------------------------------------------
-- Temporary POS table:
-- Used to get a multi order picture (ordermgr_pos_orderPicture).
-- The POSId defined here will be a temporary POS id to let the SaleController
-- component use the same queries (views) used to get the order's informations
-- (POSOrderView and POSOrderSummary).
-- Temporary POS id are registered and unregistered by the following functions:
--   - ordermgr_basic_registerTemporaryPOSId, and;
--   - ordermgr_basic_unregisterTemporaryPOSId.
-- -----------------------------------------------------------------------------

-- TempPOS table: register temporary POSes to use the same views for orders queries.
CREATE TEMPORARY TABLE TempPOS(
    POSId INTEGER NOT NULL,
    EquivPOSId INTEGER NOT NULL,
    OrderId INTEGER NOT NULL,
    PRIMARY KEY(POSId,OrderId)
);
-- TempOrderItem table: temporary table for order picture from other POSes.
CREATE TEMPORARY TABLE TempOrderItem (
    OrderId INTEGER NOT NULL,
    LineNumber INTEGER NOT NULL,
    ItemId VARCHAR(50) NOT NULL,
    Level VARCHAR(30) NOT NULL DEFAULT '0',
    PartCode INTEGER NOT NULL,
    OrderedQty VARCHAR(30) NULL DEFAULT 1,
    LastOrderedQty INTEGER NULL,
    IncQty INTEGER NOT NULL DEFAULT 0,
    DecQty INTEGER NOT NULL DEFAULT 0,
    PriceKey INTEGER NULL,
    DiscountAmount VARCHAR(30) NOT NULL DEFAULT '0.00',
    SurchargeAmount VARCHAR(30) NOT NULL DEFAULT '0.00',
    OnlyFlag INTEGER NOT NULL DEFAULT 0,
    OverwrittenUnitPrice VARCHAR(30),
    DefaultQty INTEGER NULL,
    LastUpdate DATETIME NULL,
    PRIMARY KEY(OrderId, LineNumber, ItemId, Level, PartCode)
);
-- TempPOS_BeforeInsert trigger: trigger responsible to recover the orders from
--                               the orderdb.OrderItem table to the
--                               orderdb.CurrentOrderItem.
CREATE TEMPORARY TRIGGER IF NOT EXISTS TempPOS_BeforeInsert
BEFORE INSERT ON TempPOS
BEGIN
	INSERT INTO TempOrderItem(OrderId, LineNumber, ItemId, Level, PartCode, OrderedQty, LastOrderedQty, IncQty, DecQty, PriceKey, DiscountAmount, SurchargeAmount, OnlyFlag, OverwrittenUnitPrice, DefaultQty, LastUpdate)
	SELECT
		OrderItem.OrderId,
		OrderItem.LineNumber,
		OrderItem.ItemId,
		OrderItem.Level,
		OrderItem.PartCode,
		OrderItem.OrderedQty,
		OrderItem.LastOrderedQty,
		OrderItem.IncQty,
		OrderItem.DecQty,
		OrderItem.PriceKey,
		OrderItem.DiscountAmount,
		OrderItem.SurchargeAmount,
		OrderItem.OnlyFlag,
		OrderItem.OverwrittenUnitPrice,
		CASE WHEN COALESCE(ParentItem.OrderedQty,0)>0 THEN ProductItemLeaf.DefaultQty ELSE NULL END AS DefaultQty,
        OrderItem.LastUpdate
	FROM
		OrderItem
	LEFT JOIN
		ProductItemTree
		ON ProductItemTree.ItemId=OrderItem.ItemId
	LEFT JOIN
		ProductItemLeaf
		ON ProductItemLeaf.ProductCode=ProductItemTree.ProductCode AND ProductItemLeaf.PartCode=OrderItem.PartCode
	LEFT JOIN (
			SELECT
				OI.OrderId AS OrderId,
				OI.LineNumber AS LineNumber,
				OI.ItemId AS ItemId,
				OI.Level AS Level,
				OI.PartCode AS PartCode,
				COALESCE(OI.OrderedQty,PIL.DefaultQty) AS OrderedQty
			FROM
				OrderItem OI
			LEFT JOIN
				ProductItemTree PIT
				ON PIT.ItemId=OI.ItemId
			LEFT JOIN
				ProductItemLeaf PIL
				ON PIL.ProductCode=PIT.ProductCode AND PIL.PartCode=OI.PartCode
			WHERE
				OI.OrderId=NEW.OrderId
		) ParentItem
		ON ParentItem.OrderId=OrderItem.OrderId AND
		   ParentItem.LineNumber=OrderItem.LineNumber AND
		   ParentItem.Level=(CAST(OrderItem.Level AS INTEGER)-1) AND
		   (ParentItem.ItemId||'.'||ParentItem.PartCode)=OrderItem.ItemId
	WHERE
		OrderItem.OrderId=NEW.OrderId;
END;
-- TempPOS_BeforeDelete trigger: trigger responsible to purge the data in the
--                               orderdb.CurrentOrderItem when the temporary
--                               POSId is not needed anymore.
CREATE TEMPORARY TRIGGER IF NOT EXISTS TempPOS_BeforeDelete
BEFORE DELETE ON TempPOS
BEGIN
  DELETE FROM TempOrderItem WHERE OrderId=OLD.OrderId;
END;
-- POSListForQueries view: view used in all other views to get the list of orders
--                         (OrderId), with its respective POSId (temporary or real),
--                         to be used.
CREATE TEMPORARY VIEW POSListForQueries AS
SELECT
    POS.POSId AS POSId,
    POS.CurrentOrder AS CurrentOrder,
    POS.ProdDescrId AS ProdDescrId,
    POS.RoundingModeId AS RoundingModeId,
    POS.RoundingScale AS RoundingScale
FROM orderdb.POS
UNION
SELECT
    POS.POSId AS POSId,
    tempPOS.OrderId AS CurrentOrder,
       POS.ProdDescrId AS ProdDescrId,
       POS.RoundingModeId AS RoundingModeId,
       POS.RoundingScale AS RoundingScale
FROM orderdb.POS POS
JOIN temp.TempPOS TempPOS ON TempPOS.EquivPOSId=POS.POSId;
--
-- CurrentOrderItemView: orderdb.CurrentOrderItem was renamed to
--                       temp.CurrentOrderItemView.
CREATE TEMPORARY VIEW CurrentOrderItemView AS
SELECT
    OrderId,
    LineNumber,
    ItemId,
    Level,
    PartCode,
    OrderedQty,
    LastOrderedQty,
    IncQty,
    DecQty,
    PriceKey,
    DiscountAmount,
    SurchargeAmount,
    OnlyFlag,
    OverwrittenUnitPrice,
    DefaultQty,
    LastUpdate
FROM
	orderdb.CurrentOrderItem
WHERE
    OrderId=(SELECT CurrentOrder FROM orderdb.POS LIMIT 1)
	AND LineNumber=COALESCE((SELECT LineNumber from temp.OrderViewParameters LIMIT 1), LineNumber)
UNION
SELECT
    OrderId,
    LineNumber,
    ItemId,
    Level,
    PartCode,
    OrderedQty,
    LastOrderedQty,
    IncQty,
    DecQty,
    PriceKey,
    DiscountAmount,
    SurchargeAmount,
    OnlyFlag,
    OverwrittenUnitPrice,
    DefaultQty,
    LastUpdate
FROM
    temp.TempOrderItem
WHERE
	OrderId NOT IN (SELECT DISTINCT OrderId FROM orderdb.CurrentOrderItem);

-- ---------------------------------------------------------------------------------
-- Triggers for DefaultQty quantity definition in the current order
-- ---------------------------------------------------------------------------------
CREATE TEMPORARY TRIGGER IF NOT EXISTS TMPTGR_CurrentOrderItem_DefaultQty_AfterInsert
AFTER INSERT ON CurrentOrderItem
FOR EACH ROW BEGIN
	UPDATE CurrentOrderItem
	SET DefaultQty=(
		SELECT
			CASE
				WHEN (COALESCE(ParentItem.OrderedQty,ParentItem.DefaultQty,0)>0)
					THEN ProductItemLeaf.DefaultQty
				ELSE
					NULL
			END AS DefaultQty
		FROM
			CurrentOrderItem
		JOIN
			ProductItemTree
			ON ProductItemTree.ItemId=CurrentOrderItem.ItemId
		JOIN
			ProductItemLeaf
			ON ProductItemLeaf.ProductCode=ProductItemTree.ProductCode AND ProductItemLeaf.PartCode=CurrentOrderItem.PartCode
		JOIN (
			SELECT
				CurrentOrderItem.OrderId AS OrderId,
				CurrentOrderItem.LineNumber AS LineNumber,
				(CurrentOrderItem.ItemId||'.'||CurrentOrderItem.PartCode) AS ItemId,
				CurrentOrderItem.OrderedQty AS OrderedQty,
				CurrentOrderItem.DefaultQty AS DefaultQty
			FROM
				CurrentOrderItem
			WHERE
				CurrentOrderItem.OrderId=NEW.OrderId AND
				CurrentOrderItem.LineNumber=NEW.LineNumber AND
				(CurrentOrderItem.ItemId||'.'||CurrentOrderItem.PartCode)=NEW.ItemId
		)	ParentItem
			ON ParentItem.OrderId=CurrentOrderItem.OrderId AND
			   ParentItem.LineNumber=CurrentOrderItem.LineNumber AND
			   ParentItem.ItemId=CurrentOrderItem.ItemId
		WHERE
			CurrentOrderItem.OrderId=NEW.OrderId AND
			CurrentOrderItem.LineNumber=NEW.LineNumber AND
			CurrentOrderItem.ItemId=NEW.ItemId AND
			CurrentOrderItem.PartCode=NEW.PartCode
	)
	WHERE CurrentOrderItem.OrderId=NEW.OrderId AND
	      CurrentOrderItem.LineNumber=NEW.LineNumber AND
		  CurrentOrderItem.ItemId=NEW.ItemId AND
		  CurrentOrderItem.Level=NEW.Level AND
		  CurrentOrderItem.PartCode=NEW.PartCode;
END;

CREATE TEMPORARY TRIGGER IF NOT EXISTS TMPTGR_CurrentOrderItem_DefaultQty_AfterOrderedQtyUpdate
AFTER UPDATE OF OrderedQty ON CurrentOrderItem
FOR EACH ROW WHEN ((CAST(NEW.Level AS INTEGER)>0) AND EXISTS (SELECT 1 FROM CurrentOrderItem WHERE OrderId=NEW.OrderId AND LineNumber=NEW.LineNumber AND CAST(Level AS INTEGER)=0 AND OrderedQty>0))
BEGIN
	INSERT OR REPLACE INTO CurrentOrderItem(OrderId, LineNumber, ItemId, Level, PartCode, OrderedQty, LastOrderedQty, IncQty, DecQty, PriceKey, DiscountAmount, SurchargeAmount, OnlyFlag, OverwrittenUnitPrice, DefaultQty)
	SELECT
		CurrentOrderItem.OrderId AS OrderId,
		CurrentOrderItem.LineNumber AS LineNumber,
		CurrentOrderItem.ItemId AS ItemId,
		CurrentOrderItem.Level AS Level,
		CurrentOrderItem.PartCode AS PartCode,
		CurrentOrderItem.OrderedQty AS OrderedQty,
		CurrentOrderItem.LastOrderedQty AS LastOrderedQty,
		CurrentOrderItem.IncQty AS IncQty,
		CurrentOrderItem.DecQty AS DecQty,
		CurrentOrderItem.PriceKey AS PriceKey,
		CurrentOrderItem.DiscountAmount AS DiscountAmount,
		CurrentOrderItem.SurchargeAmount AS SurchargeAmount,
		CurrentOrderItem.OnlyFlag AS OnlyFlag,
		CurrentOrderItem.OverwrittenUnitPrice AS OverwrittenUnitPrice,
		CASE
			WHEN (COALESCE(NEW.OrderedQty,0)>0)
			THEN ProductItemLeaf.DefaultQty
			ELSE NULL
		END AS DefaultQty
	FROM
		CurrentOrderItem
	JOIN
		ProductItemTree
		ON ProductItemTree.ItemId=CurrentOrderItem.ItemId
	JOIN
		ProductItemLeaf
		ON ProductItemLeaf.ProductCode=ProductItemTree.ProductCode AND ProductItemLeaf.PartCode=CurrentOrderItem.PartCode
	WHERE
		CurrentOrderItem.OrderId=NEW.OrderId AND
		CurrentOrderItem.LineNumber=NEW.LineNumber AND
		CurrentOrderItem.ItemId=(NEW.ItemId||'.'||NEW.PartCode);
END;

-- ---------------------------------------------------------------------------------
-- Triggers that updates the connection's OrderPrice table
-- ---------------------------------------------------------------------------------
CREATE TEMPORARY TRIGGER IF NOT EXISTS TMPTGR_CurrentOrderItem_OrderPrice_AfterInsert
AFTER INSERT ON CurrentOrderItem
FOR EACH ROW WHEN NOT EXISTS (SELECT 1 FROM OrderPrice WHERE OrderId=NEW.OrderId AND PriceKey=NEW.PriceKey)
BEGIN
	INSERT OR REPLACE INTO OrderPrice(OrderId,PriceKey,DefaultUnitPrice,AddedUnitPrice,SubtractedUnitPrice,Computed,IncludedQty,ValidFrom,ValidThru)
	SELECT NEW.OrderId,PriceKey,DefaultUnitPrice,AddedUnitPrice,SubtractedUnitPrice,Computed,IncludedQty,ValidFrom,ValidThru
	FROM Price
	WHERE PriceKey=NEW.PriceKey;
END;

CREATE TEMPORARY TRIGGER IF NOT EXISTS TMPTGR_CurrentOrderItem_OrderPrice_AfterUpdate
AFTER UPDATE OF PriceKey ON CurrentOrderItem
FOR EACH ROW WHEN NOT EXISTS (SELECT 1 FROM OrderPrice WHERE OrderId=NEW.OrderId AND PriceKey=NEW.PriceKey)
BEGIN
	INSERT OR REPLACE INTO OrderPrice(OrderId,PriceKey,DefaultUnitPrice,AddedUnitPrice,SubtractedUnitPrice,Computed,IncludedQty,ValidFrom,ValidThru)
	SELECT NEW.OrderId,PriceKey,DefaultUnitPrice,AddedUnitPrice,SubtractedUnitPrice,Computed,IncludedQty,ValidFrom,ValidThru
	FROM Price
	WHERE PriceKey=NEW.PriceKey;
END;

-- ---------------------------------------------------------------------------------
-- OrderDiscountsView: view used during discounts calculation to acquire all
--                     discounts applied in a aggregated way.
-- ---------------------------------------------------------------------------------
CREATE TEMPORARY VIEW IF NOT EXISTS OrderDiscountsView AS
SELECT A.LineNumber AS LineNumber,
       A.Level AS Level,
       A.ItemId AS ItemId,
       A.PartCode AS PartCode,
       B.MultQty AS MultQty,
       B.Qty AS Qty,
       A.ItemDiscount AS ItemDiscount,
       A.DiscountsApplied AS DiscountApplied,
       tdsub(B.ItemPrice,A.ItemDiscount) AS ItemPriceAD
FROM (
    SELECT
        LineNumber,
        Level,
        COALESCE(ItemId,'0') AS ItemId,
        COALESCE(PartCode,0) AS PartCode,
        tdsum(Discount) AS ItemDiscount,
        GROUP_CONCAT(CAST(DiscountId AS VARCHAR) || ':' || Discount) AS DiscountsApplied
    FROM temp.OrderDiscountItem
    GROUP BY LineNumber, Level, ItemId, PartCode
)   A
JOIN (
    SELECT
        LineNumber,
        Level,
        COALESCE(ItemId,'0') AS ItemId,
        COALESCE(PartCode,0) AS PartCode,
        MultQty,
        Qty,
        ItemPrice
    FROM temp.OrderDiscountItem
    GROUP BY LineNumber, Level, ItemId, PartCode
)   B
    ON  B.LineNumber=A.LineNumber AND
        B.Level=A.Level AND
        B.ItemId=A.ItemId AND
        B.PartCode=A.PartCode;

-- ---------------------------------------------------------------------------------
-- Global system Views definition
-- These views can be used by all components and they are defined as temporary views
-- because SQLite can only create views that access multiple databases if the view
-- is a temporary view.
-- ---------------------------------------------------------------------------------

--
-- MainMenu view: configured menu
--
CREATE TEMPORARY VIEW MainMenu AS
SELECT
    P1.ProductName                 AS ProductName,
    P2.ProductName                 AS PartName,
    PI.ItemId                      AS ItemId,
    PIL.PartCode                   AS PartCode
FROM sysproddb.ProductItemTree PI
JOIN productdb.Product P1 ON P1.ProductCode=PI.ProductCode
JOIN sysproddb.ProductItemLeaf PIL ON PIL.ProductCode=PI.ProductCode
JOIN productdb.Product P2 ON P2.ProductCode=PIL.PartCode
WHERE PIL.PartCode IS NOT NULL
ORDER BY PI.ItemId || '.' || PIL.PartCode;
-- PriceListItem view: brings the price list related to the current order items
--                     (in CurrentOrderItem table).
--                     This view is not used anymore because the PriceKey is now
--                     obtained during the item insertion in the database (see
--                     ordermgr_basic_newOrderLine for more details) but, the
--                     main idea tosearch the correct price for the item was
--                     maintained. The PriceLisTItem view was left here for debug
--                     purposes.
CREATE TEMPORARY VIEW PriceListItem AS
SELECT
     OrderPrice.ItemId                           AS ItemId,
     OrderPrice.PriceTag                         AS PriceTag,
     Price.PriceListId                           AS PriceListId,
     COALESCE(Price.DefaultUnitPrice, '0.00')    AS DefaultUnitPrice,
     COALESCE(Price.AddedUnitPrice, '0.00')      AS AddedUnitPrice,
     COALESCE(Price.SubtractedUnitPrice, '0.00') AS SubtractedUnitPrice,
     Price.Computed                              AS Computed
FROM (
       SELECT
         ProductPrice.ItemId AS ItemId,
         MAX(
             CAST(
                  CASE ProductPrice.PriceListId
                    WHEN Orders.PriceListId1 THEN 1
                    WHEN Orders.PriceListId2 THEN 2
                    WHEN Orders.PriceListId3 THEN 3
                  END * 100 + LENGTH(COALESCE(ProductPrice.Context,'')) AS CHAR(3)
                 ) || '-' ||
                CAST(ProductPrice.PriceKey AS VARCHAR(8))
           ) AS PriceTag
         FROM temp.POSListForQueries POS
         JOIN orderdb.Orders Orders
         ON   Orders.OrderId = POS.CurrentOrder
         JOIN temp.CurrentOrderItemView OrderItem
         ON   OrderItem.OrderId = Orders.OrderId
         JOIN sysproddb.ProductPrice ProductPrice
         ON   ProductPrice.ItemId = OrderItem.ItemId || '.' || OrderItem.PartCode AND
              Orders.CreatedAt BETWEEN ProductPrice.ValidFrom AND ProductPrice.ValidThru AND
              ( ProductPrice.PriceListId = Orders.PriceListId1 OR
                ProductPrice.PriceListId = Orders.PriceListId2 OR
                ProductPrice.PriceListId = Orders.PriceListId3 )
       GROUP BY ProductPrice.ItemId
     ) AS OrderPrice
JOIN Price
ON   Price.PriceKey = CAST(SUBSTR(OrderPrice.PriceTag,5) AS INT);


-- SpecialOptions view: Dummy view to be used later in specific configurations where
--                      another business logic is required to determine if an option
--                      must be solved.
--
CREATE TEMPORARY VIEW SpecialOptions AS
SELECT * FROM (
	SELECT PC.ClassCode AS OptionItem, PC.ProductCode AS OptionSolutionItem
	FROM productdb.ProductClassification PC
	JOIN productdb.ProductTags PT ON PT.ProductCode=PC.ProductCode
	WHERE PC.ClassCode=(
		SELECT ProductCode FROM productdb.ProductTags WHERE Tag='MEAL_UPGRADE' LIMIT 1
	) AND PT.Tag='QUICK_NO_ITEM'
) T
WHERE T.OptionItem IS NOT NULL;


--
-- SpecialOptionItems view: View that implements the rule similar to a Meal Upgrade logic
--                          (an optional choice that is converted to a required choice if
--                          another item is sold as part of another choice)
--
CREATE TEMPORARY VIEW SpecialOptionItems AS
SELECT OI.OrderId AS OrderId, OI.LineNumber AS LineNumber, PT.Context AS ItemId, PT1.RecursionLevel AS Level, PT.ProductCode AS PartCode, PT2.ItemId AS PP2_ItemId, PL2.PartCode AS PP2_PartCode, PT2.RecursionLevel AS PP2_Level, PL1.DefaultQty AS PP2_DefaultQty
  FROM temp.SpecialOptions SO
  JOIN orderdb.CurrentOrderItem OI ON 1=1
  JOIN sysproddb.ProductItemTree PT ON PT.ItemId=OI.ItemId
  JOIN sysproddb.ProductItemLeaf PL ON PL.ProductCode=PT.ProductCode AND PL.PartCode=OI.PartCode
  JOIN productdb.ProductTags Tag ON Tag.ProductCode=PL.PartCode AND Tag.Tag='AllowMealUpgrade'
  JOIN sysproddb.ProductItemTree PT1 ON PT1.ItemId=PT.Context
  JOIN sysproddb.ProductItemLeaf PL1 ON PL1.ProductCode=PT1.ProductCode AND PL1.PartCode=PT.ProductCode
  JOIN sysproddb.ProductItemTree PT2 ON PT2.ItemId=PT1.ItemId
  JOIN sysproddb.ProductItemLeaf PL2 ON PL2.ProductCode=PT2.ProductCode AND PL2.PartCode=SO.OptionItem
WHERE OI.OrderedQty>0;
--
-- OrderView view: This is the main view for all queries or views that are intended
--                 to get information about the current order items.
CREATE TEMPORARY VIEW OrderView AS
WITH RECURSIVE OIMultiply AS (
    SELECT
        Main.OrderId AS OrderId,
        Main.LineNumber AS LineNumber,
        Main.Level AS Level,
        Main.ItemId AS ItemId,
        Main.PartCode AS PartCode,
        NULL AS ParentQty,
        Main.OrderedQty AS Qty,
        Main.OrderedQty AS MultQty,
        3 AS ParentType,
        (SELECT ProductType FROM ProductKernelParams WHERE ProductCode=PartCode) AS ProductType
    FROM temp.CurrentOrderItemView Main
    WHERE Level=0
    UNION ALL
    SELECT
        OrderItem.OrderId AS OrderId,
        OrderItem.LineNumber AS LineNumber,
        OrderItem.Level AS Level,
        OrderItem.ItemId AS ItemId,
        OrderItem.PartCode AS PartCode,
        CASE WHEN M.ProductType = 1 THEN M.ParentQty ELSE M.MultQty END AS ParentQty,
        COALESCE(OrderItem.OrderedQty,
            (CASE WHEN COALESCE(Options.ChosenQty,0)>OrderItem.DefaultQty THEN Options.ChosenQty ELSE NULL END),
            COALESCE(SpecialOptionItems.PP2_DefaultQty,OrderItem.DefaultQty)
        ) AS Qty,
        tdmul(CASE WHEN M.ProductType = 1 THEN M.ParentQty ELSE M.MultQty END,
            COALESCE(OrderItem.OrderedQty, (CASE WHEN COALESCE(Options.ChosenQty,0)>OrderItem.DefaultQty THEN Options.ChosenQty ELSE NULL END),
              COALESCE(SpecialOptionItems.PP2_DefaultQty,OrderItem.DefaultQty))
        ) AS MultQty,
        M.ProductType AS ParentType,
        Params.ProductType AS ProductType
    FROM OIMultiply M
    JOIN temp.CurrentOrderItemView OrderItem
        ON OrderItem.OrderId=M.OrderId
            AND OrderItem.LineNumber=M.LineNumber
            AND OrderItem.ItemId=M.ItemId||'.'||M.PartCode
            AND OrderItem.Level=M.Level+1
    JOIN ProductKernelParams Params ON OrderItem.PartCode = Params.ProductCode
    LEFT JOIN (
            SELECT
                OrderItem.OrderId AS OrderId,
                OrderItem.LineNumber AS LineNumber,
                A.ItemId AS ItemId,
                SUM(COALESCE(OrderItem.OrderedQty,0)) AS ChosenQty,
                PP.IncludedQty AS IncludedQty
            FROM temp.POSListForQueries POS
            JOIN temp.CurrentOrderItemView OrderItem ON OrderItem.OrderId = POS.CurrentOrder
            JOIN sysproddb.ProductItemTree A ON A.ItemId = OrderItem.ItemId AND A.IsClass=1
            JOIN sysproddb.ProductItemTree B ON B.ItemId=A.Context
            JOIN productdb.ProductPart PP ON PP.ProductCode=B.ProductCode AND PP.PartCode=A.ProductCode
            GROUP BY OrderItem.OrderId, OrderItem.LineNumber, A.ItemId
    ) Options
    ON Options.OrderId=OrderItem.OrderId AND
       Options.LineNumber=OrderItem.LineNumber AND
       Options.ItemId=(OrderItem.ItemId||'.'||OrderItem.PartCode)
    LEFT JOIN temp.SpecialOptionItems SpecialOptionItems
    ON   SpecialOptionItems.OrderId=OrderItem.OrderId AND
         SpecialOptionItems.LineNumber=OrderItem.LineNumber AND
         SpecialOptionItems.PP2_Level=OrderItem.Level AND
         SpecialOptionItems.PP2_ItemId=OrderItem.ItemId AND
         SpecialOptionItems.PP2_PartCode=OrderItem.PartCode
)
SELECT
    POS.POSId                          AS POSId,
    OrderItem.OrderId                  AS OrderId,
    OrderItem.LineNumber               AS LineNumber,
    OrderItem.Level                    AS Level,
    OrderItem.ItemId                   AS ItemId,
    OrderItem.PartCode                 AS PartCode,
    Product.ProductName                AS ProductName,
    OIMultiply.ParentQty               AS ParentQty,
    OIMultiply.MultQty                 AS MultQty,
    OIMultiply.ParentType              AS ParentType,
    OIMultiply.ProductType             AS ProductType,
    OrderItem.LastOrderedQty           AS LastOrderedQty,
    OIMultiply.Qty                     AS Qty,
    OrderItem.IncQty                   AS IncQty,
    OrderItem.DecQty                   AS DecQty,
    OrderItem.OverwrittenUnitPrice     AS OverwrittenUnitPrice,
    CASE WHEN OrderItem.OverwrittenUnitPrice IS NOT NULL
    THEN
        tdmul(OIMultiply.MultQty, OrderItem.OverwrittenUnitPrice, POS.RoundingScale, POS.RoundingModeId)
    ELSE
        tdmul(
            COALESCE(OIMultiply.ParentQty, 1),
            tdadd(
                CASE
                    WHEN COALESCE(PriceListItem.Computed,0) = 0
                    THEN tdscale('0',POS.RoundingScale,POS.RoundingModeId)
                    ELSE
                        tdmul(
                            MAX(0,
                                (COALESCE(OrderItem.OrderedQty,Options.ChosenQty,OrderItem.DefaultQty)-COALESCE(Options.IncludedQty,PriceListItem.IncludedQty,0))
                            ),
                            PriceListItem.DefaultUnitPrice, POS.RoundingScale, POS.RoundingModeId
                        )
                END
                ,
                tdsub(
                 tdmul(MAX(0,COALESCE(OrderItem.OrderedQty,Options.ChosenQty,OrderItem.DefaultQty)-COALESCE(Options.IncludedQty,PriceListItem.IncludedQty,OrderItem.DefaultQty,0)),
                       COALESCE(PriceListItem.AddedUnitPrice, CASE WHEN PriceListItem.DefaultUnitPrice IS NOT NULL THEN '0.00' ELSE NULL END),
                               POS.RoundingScale,POS.RoundingModeId)
                 ,
                 tdmul(MAX(0,COALESCE(OrderItem.DefaultQty,0)-COALESCE(OrderItem.OrderedQty,OrderItem.DefaultQty)),
                       COALESCE(PriceListItem.SubtractedUnitPrice, CASE WHEN PriceListItem.DefaultUnitPrice IS NOT NULL THEN '0.00' ELSE NULL END),
                               POS.RoundingScale,POS.RoundingModeId)
                 ,
                 POS.RoundingScale
                 ,
                 POS.RoundingModeId
                )
                ,
                POS.RoundingScale
                ,
                POS.RoundingModeId
            ),
            POS.RoundingScale, POS.RoundingModeId
        )
    END                               AS ItemPrice,
    OrderItem.DiscountAmount          AS DiscountAmount,
    Options.ChosenQty				  AS ChosenQty,
    COALESCE(
      SpecialOptionItems.PP2_DefaultQty,
      OrderItem.DefaultQty
    )                                 AS DefaultQty,
    MAX(0,(COALESCE(OrderItem.OrderedQty,Options.ChosenQty,OrderItem.DefaultQty) - OrderItem.DefaultQty))
                                     AS AddedQty,
    MAX(0,OrderItem.DefaultQty - COALESCE(OrderItem.OrderedQty,OrderItem.DefaultQty))
                                     AS SubtractedQty,
    tdscale(PriceListItem.DefaultUnitPrice,POS.RoundingScale,POS.RoundingModeId)
                                     AS DefaultUnitPrice,
    tdscale(PriceListItem.AddedUnitPrice,POS.RoundingScale,POS.RoundingModeId)
                                     AS AddedUnitPrice,
    tdscale(PriceListItem.SubtractedUnitPrice,POS.RoundingScale,POS.RoundingModeId)
                                     AS SubtractedUnitPrice,
    PriceListItem.PriceKey            AS PriceKey,
    ProductKernelParams.ProductPriority
                                     AS ProductPriority,
    OrderItem.OnlyFlag                AS OnlyModifiers,
    Discounts.ItemDiscount            AS ItemDiscount,
    Discounts.DiscountsApplied        AS DiscountsApplied,
    COALESCE(Options.IncludedQty,PriceListItem.IncludedQty)
                                     AS IncludedQty,
    OrderItem.LastUpdate AS LastUpdate
FROM temp.POSListForQueries POS
JOIN temp.CurrentOrderItemView OrderItem
ON OrderItem.OrderId = POS.CurrentOrder
JOIN productdb.ProductKernelParams ProductKernelParams
ON ProductKernelParams.ProductCode=OrderItem.PartCode
JOIN productdb.Product Product
ON Product.ProductCode=OrderItem.PartCode
LEFT JOIN (
    SELECT
        Price.PriceKey AS PriceKey,
        Price.Computed AS Computed,
        CASE WHEN
            Price.DefaultUnitPrice IS NULL AND
            (Price.AddedUnitPrice IS NOT NULL OR Price.SubtractedUnitPrice IS NOT NULL)
        THEN '0.00'
        ELSE Price.DefaultUnitPrice END AS DefaultUnitPrice,
        CASE WHEN
            Price.AddedUnitPrice IS NULL AND
            (Price.DefaultUnitPrice IS NOT NULL OR Price.SubtractedUnitPrice IS NOT NULL)
        THEN '0.00'
        ELSE Price.AddedUnitPrice END AS AddedUnitPrice,
        CASE WHEN
            Price.SubtractedUnitPrice IS NULL AND
            (Price.DefaultUnitPrice IS NOT NULL OR Price.AddedUnitPrice IS NOT NULL)
        THEN '0.00'
        ELSE Price.SubtractedUnitPrice END AS SubtractedUnitPrice,
        Price.IncludedQty AS IncludedQty
    FROM temp.POSListForQueries POS
    JOIN temp.CurrentOrderItemView OrderItem
    ON OrderItem.OrderId = POS.CurrentOrder
    JOIN orderdb.OrderPrice Price
    ON Price.OrderId = OrderItem.OrderId AND Price.PriceKey = OrderItem.PriceKey
    GROUP BY Price.PriceKey
) PriceListItem
ON PriceListItem.PriceKey = OrderItem.PriceKey
LEFT JOIN (
        SELECT
                OrderItem.OrderId AS OrderId,
                OrderItem.LineNumber AS LineNumber,
                A.ItemId AS ItemId,
                SUM(COALESCE(OrderItem.OrderedQty,0)) AS ChosenQty,
                PP.IncludedQty AS IncludedQty
        FROM temp.POSListForQueries POS
        JOIN temp.CurrentOrderItemView OrderItem ON OrderItem.OrderId = POS.CurrentOrder
        JOIN sysproddb.ProductItemTree A ON A.ItemId = OrderItem.ItemId AND A.IsClass=1
        JOIN sysproddb.ProductItemTree B ON B.ItemId=A.Context
        JOIN productdb.ProductPart PP ON PP.ProductCode=B.ProductCode AND PP.PartCode=A.ProductCode
        GROUP BY OrderItem.OrderId, OrderItem.LineNumber, A.ItemId
) Options
ON Options.OrderId=OrderItem.OrderId AND
   Options.LineNumber=OrderItem.LineNumber AND
   Options.ItemId=(OrderItem.ItemId||'.'||OrderItem.PartCode)
LEFT JOIN temp.SpecialOptionItems SpecialOptionItems
ON   SpecialOptionItems.OrderId=OrderItem.OrderId AND
     SpecialOptionItems.LineNumber=OrderItem.LineNumber AND
     SpecialOptionItems.PP2_Level=OrderItem.Level AND
     SpecialOptionItems.PP2_ItemId=OrderItem.ItemId AND
     SpecialOptionItems.PP2_PartCode=OrderItem.PartCode
LEFT JOIN (
    SELECT
        OrderDiscount.OrderId AS OrderId,
        OrderDiscount.LineNumber AS LineNumber,
        OrderDiscount.ItemId AS ItemId,
        OrderDiscount.Level AS Level,
        OrderDiscount.PartCode AS PartCode,
        tdsum(OrderDiscount.DiscountAmount,POS.RoundingScale,POS.RoundingModeId) AS ItemDiscount,
        GROUP_CONCAT(CAST(DiscountId AS VARCHAR) || ':' || DiscountAmount) AS DiscountsApplied
    FROM temp.POSListForQueries POS
    JOIN orderdb.OrderDiscount OrderDiscount
    ON OrderDiscount.OrderId = POS.CurrentOrder
    GROUP BY OrderDiscount.OrderId, OrderDiscount.LineNumber, OrderDiscount.ItemId, OrderDiscount.Level, OrderDiscount.PartCode
) Discounts
ON Discounts.OrderId=OrderItem.OrderId AND
   Discounts.LineNumber=OrderItem.LineNumber AND
   Discounts.ItemId=OrderItem.ItemId AND
   Discounts.Level=OrderItem.Level AND
   Discounts.PartCode=OrderItem.PartCode
LEFT JOIN OIMultiply
ON OIMultiply.OrderId=OrderItem.OrderId AND
   OIMultiply.LineNumber=OrderItem.LineNumber AND
   OIMultiply.ItemId=OrderItem.ItemId AND
   OIMultiply.Level=OrderItem.Level AND
   OIMultiply.PartCode=OrderItem.PartCode
WHERE Qty IS NOT NULL
ORDER BY OrderItem.OrderId, OrderItem.LineNumber, OrderItem.Level, OrderItem.ItemId;
-- OrderOptions view: used to get the list of options available in the current order items.
--                    This view is used by the ordermgr_basicquery_listOptions function.
CREATE TEMPORARY VIEW OrderOptions AS
SELECT
    POS.POSId AS POSId,
    OrderView.OrderId AS OrderId,
    OrderView.LineNumber AS LineNumber,
    OrderView.ItemId AS ItemId,
    OrderView.Level AS Level,
    OrderView.PartCode AS PartCode,
    OrderView.ParentQty AS ParentQty,
    OrderView.Qty AS Qty,
    OrderView.ChosenQty AS ChosenQty,
    OrderView.MultQty AS MultQty,
    OrderView.DefaultQty AS DefaultQty,
    PIL.MinQty AS MinQty,
    PIL.MaxQty AS MaxQty,
    PP.IncludedQty AS IncludedQty,
    OrderView.ProductName AS ProductName,
    DG.DimChar AS DimChar
FROM orderdb.POS POS
JOIN temp.OrderView OrderView
  ON OrderView.OrderId = POS.CurrentOrder
JOIN sysproddb.ProductItemTree PIT
  ON PIT.ItemId=OrderView.ItemId
LEFT JOIN sysproddb.ProductItemLeaf PIL
  ON PIL.ProductCode=PIT.ProductCode AND PIL.PartCode=Orderview.PartCode AND PIL.PartType=0
LEFT JOIN productdb.ProductPart PP
  ON PP.ProductCode=PIL.ProductCode AND PP.PartCode = PIL.PartCode
LEFT JOIN productdb.DimensionGroups DG
  ON DG.ProductCode=OrderView.PartCode
WHERE OrderView.ChosenQty IS NOT NULL
GROUP BY POS.POSId, OrderView.OrderId, OrderView.LineNumber, OrderView.ItemId, OrderView.Level, OrderView.PartCode;
-- OptionItems view: used to list the possible options solutions, that means;
--                   the list of items that can be used to solve any opened
--                   options in the current order items.
--                   See ordermgr_basicquery_listAllOptionsMade function.
CREATE TEMPORARY VIEW OptionItems AS
SELECT OrderItem.OrderId    AS OrderId,
       OrderItem.LineNumber AS LineNumber,
       OrderItem.ItemId     AS ItemId,
       OrderItem.Level      AS Level,
       OrderItem.PartCode   AS PartCode,
       OrderItem.OrderedQty AS OrderedQty,
       Product.ProductName  AS ProductName
FROM temp.OrderView OrderView
JOIN orderdb.CurrentOrderItem OrderItem
ON   OrderItem.OrderId = OrderView.OrderId AND OrderItem.LineNumber=OrderView.LineNumber AND OrderItem.ItemId=(OrderView.ItemId||'.'||OrderView.PartCode)
JOIN productdb.Product Product
ON   Product.ProductCode = OrderItem.PartCode
WHERE OrderView.ChosenQty IS NOT NULL;
-- OptionsMade view: used to list the options currently made for each in-progress order.
--
CREATE TEMPORARY VIEW OptionsMade AS
SELECT OrderItem.OrderId    AS OrderId,
       OrderItem.LineNumber AS LineNumber,
       OrderItem.Level      AS Level,
       OrderItem.ItemId     AS ItemId,
       OrderItem.PartCode   AS PartCode,
       Product.ProductName  AS ProductName,
       OrderItem.OrderedQty AS ChosenQty,
       OrderView.PartCode   AS OptionCode
FROM temp.OrderView OrderView
JOIN orderdb.CurrentOrderItem OrderItem
ON   OrderItem.OrderId = OrderView.OrderId AND OrderItem.LineNumber=OrderView.LineNumber AND OrderItem.ItemId=(OrderView.ItemId||'.'||OrderView.PartCode)
JOIN productdb.Product Product
ON   Product.ProductCode = OrderItem.PartCode
WHERE OrderView.ChosenQty IS NOT NULL AND OrderItem.OrderedQty>0;
-- OIMTemp table: temporary table used for performance enhancement
--                during listModifiers operations
CREATE TEMPORARY TABLE OIMTemp (
	POSId			INTEGER,
	OrderId			INTEGER,
	LineNumber		INTEGER,
	ItemId			VARCHAR,
	ProductCode		INTEGER,
	Level			VARCHAR,
	PartCode		INTEGER,
	DefaultQty		INTEGER,
	MinQty			INTEGER,
	MaxQty			INTEGER,
	OrderedQty		INTEGER,
	ProductName		VARCHAR,
	ModifierName	VARCHAR,
	ModifierLabels	VARCHAR,
	ProductPriority	INTEGER,
	Enabled			INTEGER
);
-- OrderItemModifiersNoPrice table: Same OrderItemModifiers view but without prices
--
CREATE TEMPORARY VIEW OrderItemModifiersNoPrice AS
SELECT P.POSId AS POSId,
       OV.OrderId AS OrderId,
       OV.LineNumber AS LineNumber,
       PIT.ItemId AS ItemId,
       PIT.ProductCode AS ProductCode,
       CASE
            WHEN CAST(tdsub(OV.Level, tdscale(OV.Level, 0, 4)) AS DOUBLE) > 0 THEN tdadd(PIT.RecursionLevel, tdsub(OV.Level, tdscale(OV.Level, 0, 4)), 3, 4)
            ELSE PIT.RecursionLevel
       END AS Level,
       PIL.PartCode AS PartCode,
       PIL.DefaultQty AS DefaultQty,
       PIL.MinQty AS MinQty,
       PIL.MaxQty AS MaxQty,
       COALESCE(I.OrderedQty,PIL.DefaultQty,0) AS OrderedQty,
       OV.ProductName AS ProductName,
       PPP.ProductName AS ModifierName,
       MQL.ModifierLabels AS ModifierLabels,
	   PKP.ProductPriority AS ProductPriority,
	   PKP.Enabled AS Enabled
FROM orderdb.POS P
JOIN temp.OrderView OV
ON OV.OrderId=P.CurrentOrder AND OV.MultQty>0
JOIN sysproddb.ProductItemTree PIT
ON PIT.ItemId=(OV.ItemId||'.'||OV.PartCode)
JOIN sysproddb.ProductItemLeaf PIL
ON PIL.ProductCode=PIT.ProductCode AND PIL.PartType=1
JOIN productdb.Product PPP
ON PPP.ProductCode=PIL.PartCode
JOIN productdb.ProductKernelParams PKP
ON PKP.ProductCode=PIL.PartCode
LEFT JOIN (
   SELECT ProductCode AS ProductCode,
          GROUP_CONCAT(Qty||':'||Label) AS ModifierLabels
   FROM productdb.ModifierQtyLabels
   GROUP BY ProductCode
) MQL
ON MQL.ProductCode=PIL.PartCode
LEFT JOIN orderdb.CurrentOrderItem I
ON I.OrderId=OV.OrderId AND
   I.LineNumber=OV.LineNumber AND
   I.ItemId=PIT.ItemId AND
   I.Level=PIT.RecursionLevel AND
   I.PartCode=PIL.PartCode;
-- OrderItemModifiers view: optimized version
--                          used to list the current order items available modifiers.
--                          It brings the modifiers available with its current state
--                          in the order, this is done to help the SaleController
--                          component during the changes to the items recipe.
--                          See ordermgr_pos_listModifiers, ordermgr_pos_changeModifiers and
--                          ordermgr_pos_changeModifier.
CREATE TEMPORARY VIEW OrderItemModifiers AS
SELECT OI.POSId AS POSId,
       OI.OrderId AS OrderId,
       OI.LineNumber AS LineNumber,
       OI.ItemId AS ItemId,
       OI.ProductCode AS ProductCode,
       OI.Level AS Level,
       OI.PartCode AS PartCode,
       OI.DefaultQty AS DefaultQty,
       OI.MinQty AS MinQty,
       OI.MaxQty AS MaxQty,
       OI.OrderedQty AS OrderedQty,
       SUBSTR(PP.PricePath,5) AS PriceKey,
       OI.ProductName AS ProductName,
       OI.ModifierName AS ModifierName,
       OI.ModifierLabels AS ModifierLabels,
	   OI.ProductPriority AS ProductPriority,
	   OI.Enabled AS Enabled
FROM OIMTemp OI
LEFT JOIN (
    SELECT
        Orders.OrderId AS OrderId,
        ProductPrice.ItemId AS ItemId,
        MAX(
            CAST(
                CASE ProductPrice.PriceListId
                    WHEN Orders.PriceListId1 THEN 1
                    WHEN Orders.PriceListId2 THEN 2
                    WHEN Orders.PriceListId3 THEN 3
                END * 100 + LENGTH(COALESCE(ProductPrice.Context,'')) AS CHAR(3)
            )
            || '-' ||
            CAST(ProductPrice.PriceKey AS VARCHAR(8))
        ) AS PricePath
    FROM orderdb.POS POS
    JOIN orderdb.Orders Orders ON Orders.OrderId=POS.CurrentOrder
    JOIN (
        SELECT DISTINCT ItemId, PartCode FROM OIMTemp
    ) OI ON 1=1
    JOIN sysproddb.ProductPrice
      ON ProductPrice.ItemId=(OI.ItemId||'.'||OI.PartCode) AND Orders.CreatedAt BETWEEN ProductPrice.ValidFrom AND ProductPrice.ValidThru
     AND ProductPrice.PriceListId IN (Orders.PriceListId3,Orders.PriceListId2,Orders.PriceListId1)
    GROUP BY Orders.OrderId, ProductPrice.ItemId
) PP ON PP.OrderId=OI.OrderId AND PP.ItemId=(OI.ItemId||'.'||OI.PartCode);
-- OrderTotal view: Used to calculate the total amount of the order.
CREATE TEMPORARY VIEW OrderTotal AS
SELECT
    POS.POSId AS POSId,
    OrderItem.OrderId AS OrderId,
    SUM(CASE WHEN CAST(OrderItem.Level AS INTEGER)=0 THEN OrderItem.MultQty ELSE 0 END) AS TotalQty,
    tdsum(
        COALESCE(OrderItem.ItemPrice, 0),
        POS.RoundingScale,POS.RoundingModeId
    ) AS TotalPrice
FROM
    temp.POSListForQueries POS
JOIN
    temp.OrderView OrderItem
    ON OrderItem.OrderId=POS.CurrentOrder
GROUP BY POS.POSId, OrderItem.OrderId;
-- OrderTaxTotal view: Used to calculate the total amount with taxes.
CREATE TEMPORARY VIEW OrderTaxTotal AS
SELECT
    POS.POSId,
    TaxDiscountTotal.OrderId,
    TaxDiscountTotal.TotalQty,
    TaxDiscountTotal.TotalPrice,
    TaxDiscountTotal.TotalNetPrice,
    TaxDiscountTotal.TotalGrossPrice,
    tdscale(TaxDiscountTotal.TotalDiscount,POS.RoundingScale,POS.RoundingModeId) AS TotalDiscount,
    tdsub(
        TaxDiscountTotal.TotalNetPrice,
        tdscale(TaxDiscountTotal.TotalDiscount,POS.RoundingScale,POS.RoundingModeId),
        POS.RoundingScale,POS.RoundingModeId
    ) AS TotalNetPriceAD,
    tdsub(
        TaxDiscountTotal.TotalGrossPrice,
        tdscale(TaxDiscountTotal.TotalDiscount,POS.RoundingScale,POS.RoundingModeId),
        POS.RoundingScale,POS.RoundingModeId
    ) AS TotalGrossPriceAD,
    TaxDiscountTotal.OrderDiscounts AS OrderDiscounts,
    TaxDiscountTotal.OrderDiscountsApplied AS OrderDiscountsApplied
FROM
    temp.POSListForQueries POS
JOIN (
	SELECT
		POS.POSId AS POSId,
		OrderItem.OrderId AS OrderId,
		SUM(CASE WHEN CAST(OrderItem.Level AS INTEGER)=0 THEN OrderItem.MultQty ELSE 0 END) AS TotalQty,
		tdsum(
			(
				CASE
					WHEN OrderItem.ItemPrice NOT NULL AND tdcmp(OrderItem.Qty,0)>0
					THEN tdscale(OrderItem.ItemPrice,POS.RoundingScale,POS.RoundingModeId)
					ELSE '0.00'
				END
			),
			POS.RoundingScale,POS.RoundingModeId
		) AS TotalPrice,
		tdsub(
			tdsum(
				CASE
					WHEN OrderItem.ItemPrice NOT NULL AND tdcmp(OrderItem.Qty,0)>0
					THEN
                        tdsub(
                            COALESCE(OrderItem.ItemPrice,'0.00'),
                            COALESCE(OrderTax.IncludedTaxAD,'0.00'),
                            8,POS.RoundingModeId
                        )
					ELSE '0.00'
				END,
				POS.RoundingScale,POS.RoundingModeId
			),
			(
				CASE
					WHEN Orders.TotalTaxIncluded = 1
					THEN COALESCE(Orders.TotalTaxAmountAD,'0.00')
					ELSE '0.00'
				END
			),
			POS.RoundingScale,POS.RoundingModeId
		) AS TotalNetPrice,
		tdadd(
			tdsum(
				CASE
					WHEN OrderItem.ItemPrice NOT NULL AND tdcmp(OrderItem.Qty,0)>0
					THEN
                        tdadd(
                            COALESCE(OrderItem.ItemPrice,'0.00'),
                            COALESCE(OrderTax.AddedTaxAD,'0.00'),
                            8,POS.RoundingModeId
                        )
					ELSE '0.00'
				END,
				POS.RoundingScale,POS.RoundingModeId
			),
			(
				CASE
					WHEN Orders.TotalTaxIncluded = 0
					THEN COALESCE(Orders.TotalTaxAmountAD,'0.00')
					ELSE '0.00'
				END
			),
			POS.RoundingScale,POS.RoundingModeId
		) AS TotalGrossPrice,
        tdadd(
            COALESCE(OrderDiscount.TotalOrderDiscount,0),
            tdsum(
                (
                    CASE
                        WHEN OrderItem.DiscountAmount NOT NULL AND tdcmp(OrderItem.Qty,0)>0
                        THEN OrderItem.DiscountAmount
                        ELSE '0.00'
                    END
                )
            ),
            POS.RoundingScale,POS.RoundingModeId
        ) AS TotalDiscount,
        tdscale(COALESCE(OrderDiscount.TotalOrderDiscount,0),POS.RoundingScale,POS.RoundingModeId) AS OrderDiscounts,
        OrderDiscount.OrderDiscountsApplied AS OrderDiscountsApplied
    FROM
        temp.POSListForQueries POS
    JOIN
        orderdb.Orders Orders
        ON Orders.OrderId=POS.CurrentOrder
    LEFT JOIN (
        SELECT
            OrderDiscount.OrderId AS OrderId,
            tdsum(OrderDiscount.DiscountAmount) AS TotalOrderDiscount,
            GROUP_CONCAT(OrderDiscount.DiscountId||':'||OrderDiscount.DiscountAmount) AS OrderDiscountsApplied
        FROM temp.POSListForQueries POS
        JOIN orderdb.OrderDiscount OrderDiscount
        ON OrderDiscount.OrderId=POS.CurrentOrder
        WHERE OrderDiscount.LineNumber=0
        GROUP BY OrderDiscount.OrderId
    )   OrderDiscount
        ON  OrderDiscount.OrderId=Orders.OrderId
	JOIN
		temp.OrderView OrderItem
		ON OrderItem.OrderId=Orders.OrderId
	LEFT JOIN (
		SELECT
			OrderTax.OrderId    AS OrderId,
			OrderTax.LineNumber AS LineNumber,
			OrderTax.ItemId     AS ItemId,
			OrderTax.Level      AS Level,
			OrderTax.PartCode   AS PartCode,
			tdsum(CASE WHEN OrderTax.TaxIncluded = 0 THEN COALESCE(OrderTax.TaxAmountBD,0) ELSE '0.00' END,8,POS.RoundingModeId) AS AddedTaxBD,
			tdsum(CASE WHEN OrderTax.TaxIncluded = 0 THEN COALESCE(OrderTax.TaxAmountAD,0) ELSE '0.00' END,8,POS.RoundingModeId) AS AddedTaxAD,
			tdsum(CASE WHEN OrderTax.TaxIncluded = 1 THEN COALESCE(OrderTax.TaxAmountBD,0) ELSE '0.00' END,8,POS.RoundingModeId) AS IncludedTaxBD,
			tdsum(CASE WHEN OrderTax.TaxIncluded = 1 THEN COALESCE(OrderTax.TaxAmountAD,0) ELSE '0.00' END,8,POS.RoundingModeId) AS IncludedTaxAD
		FROM temp.POSListForQueries POS
		JOIN orderdb.OrderTax OrderTax
		ON OrderTax.OrderId=POS.CurrentOrder
		GROUP BY OrderTax.OrderId, OrderTax.LineNumber, OrderTax.Level, OrderTax.ItemId, OrderTax.PartCode
	) AS OrderTax
	ON OrderTax.OrderId = OrderItem.OrderId AND
	   OrderTax.LineNumber = OrderItem.LineNumber AND
	   OrderTax.ItemId = OrderItem.ItemId AND
	   OrderTax.Level = OrderItem.Level AND
	   OrderTax.PartCode = OrderItem.PartCode
	GROUP BY POS.POSId, OrderItem.OrderId
)	TaxDiscountTotal
	ON TaxDiscountTotal.OrderId=POS.CurrentOrder;
-- POSOrderSummary view: Used get the current orders summary. All the informations available in
--                       the tag Order of the Order Picture XML (ordermgr_pos_orderPicture) are
--                       obtained from this view.
--                       This view calculates the total amount, total tendered, current due amount,
--                       total tax amount and the change.
CREATE TEMPORARY VIEW POSOrderSummary AS
SELECT P.POSId AS POSId,
       O.OrderId AS OrderId,
       O.StateId AS StateId,
       S.StateDescr AS StateDescr,
       O.OrderType AS OrderType,
       O.OrderSubType AS OrderSubType,
       T.TypeDescr AS TypeDescr,
       O.OriginatorId AS OriginatorId,
       O.OriginatorNumber AS OriginatorNumber,
       O.LineCounter AS LineCounter,
       strftime('%Y-%m-%dT%H:%M:%f',O.CreatedAt,'localtime') AS CreatedAt,
       strftime('%Y-%m-%dT%H:%M:%f',O.LastNewLineAt,'localtime') AS LastNewLineAt,
       strftime('%Y-%m-%dT%H:%M:%f',O.CreatedAt) AS CreatedAtGMT,
       strftime('%Y-%m-%dT%H:%M:%f',O.LastNewLineAt) AS LastNewLineAtGMT,
       CAST(O.BusinessPeriod AS VARCHAR) AS BusinessPeriod,
       O.DistributionPoint AS DistributionPoint,
       O.SessionId AS SessionId,
       tdscale(COALESCE(OTT.TotalNetPrice,'0'),P.RoundingScale,P.RoundingModeId) AS TotalNetPrice,
       tdscale(COALESCE(OTT.TotalGrossPrice,'0'),P.RoundingScale,P.RoundingModeId) AS TotalGrossPrice,
       tdscale(COALESCE(OTT.TotalNetPriceAD,'0'),P.RoundingScale,P.RoundingModeId) AS TotalNetPriceAD,
       tdscale(COALESCE(OTT.TotalGrossPriceAD,'0'),P.RoundingScale,P.RoundingModeId) AS TotalGrossPriceAD,
       tdscale(tdsum(COALESCE(OTD.TenderAmount,'0')),P.RoundingScale,P.RoundingModeId) AS TotalTender,
       tdscale(COALESCE(OTT.TotalDiscount,'0'),P.RoundingScale,P.RoundingModeId) AS TotalDiscount,
       tdsub(COALESCE(OTT.TotalGrossPrice,'0'),COALESCE(OTT.TotalNetPrice,'0'),P.RoundingScale,P.RoundingModeId) AS TotalTax,
       CASE WHEN O.StateId=5
            THEN tdsum(COALESCE(OTD.ChangeAmount,'0.00'),P.RoundingScale,P.RoundingModeId)
            ELSE tdscale('0',P.RoundingScale,P.RoundingModeId)
       END AS Change,
       CASE WHEN O.StateId=3
            THEN tdsub(COALESCE(OTT.TotalGrossPriceAD,'0'), tdsub(COALESCE(tdsum(OTD.TenderAmount),'0'), COALESCE(NULLIF(CAST(O.Tip AS REAL),0), tdsum(OTD.TipAmount), '0')), P.RoundingScale, P.RoundingModeId)
            ELSE tdscale('0',P.RoundingScale,P.RoundingModeId)
       END AS DueAmount,
       CASE WHEN O.PriceListId1 NOTNULL AND O.PriceListId2 NOTNULL AND O.PriceListId3 NOTNULL
            THEN O.PriceListId1 || '.' || O.PriceListId2 || '.' || O.PriceListId3
            WHEN O.PriceListId1 NOTNULL AND O.PriceListId2
            THEN O.PriceListId1 || '.' || O.PriceListId2
            ELSE O.PriceListId1
       END AS PriceList,
       COALESCE(PL.MenuPriceBasis,'U') AS MenuPriceBasis,
       O.SaleType AS SaleType,
       ST.TypeDescr AS SaleTypeDescr,
       O.ExemptionCode AS ExemptionCode,
       O.LastModifiedLine AS LastModifiedLine,
       O.AdditionalInfo AS AdditionalInfo,
       O.MultiOrderId AS MultiOrderId,
       O.Major AS Major,
       O.Minor AS Minor,
       OTT.OrderDiscounts AS OrderDiscounts,
       OTT.OrderDiscountsApplied AS OrderDiscountsApplied,
       tdscale(COALESCE(O.Tip,'0'),P.RoundingScale,P.RoundingModeId) AS Tip
FROM temp.POSListForQueries P
JOIN orderdb.Orders O ON O.OrderId=P.CurrentOrder
LEFT JOIN productdb.PriceList PL ON PL.PriceListId=COALESCE(O.PriceListId3,O.PriceListId2,O.PriceListId1)
LEFT JOIN OrderTaxTotal OTT ON OTT.OrderId=O.OrderId
LEFT JOIN orderdb.OrderTender OTD ON OTD.OrderId=O.OrderId
LEFT JOIN orderdb.OrderState S ON S.StateId=O.StateId
LEFT JOIN orderdb.OrderType T ON T.TypeId=O.OrderType
LEFT JOIN orderdb.SaleType ST ON ST.TypeId=O.SaleType
GROUP BY P.POSId, O.OrderId;
-- POSOrderView view: As the previous view, this is used to get the order items details included
--                    in the tag SaleLine of the Order Picture XML (ordermgr_pos_orderPicture)
--                    The informations in this view is based on the OrderView already presented.
--                    Additionally, this view includes the logic to categorize the sale items into
--                    predefined groups: COMBO, PRODUCT, OPTION, INGREDIENT and CANADD
--                    Theses groups are used, for example, by a user interface to display the items
--                    with different colors.
CREATE TEMPORARY VIEW POSOrderView AS
SELECT
    OV.POSId AS POSId,
    OV.OrderId AS OrderId,
    OV.LineNumber AS LineNumber,
    OV.Level AS Level,
    OV.ItemId AS ItemId,
    OV.PartCode AS PartCode,
    OV.ProductName AS ProductName,
    OV.MultQty AS MultQty,
    OV.LastOrderedQty AS LastOrderedQty,
    OV.Qty AS Qty,
    OV.IncQty AS IncQty,
    OV.DecQty AS DecQty,
    OV.ItemPrice AS ItemPrice,
    OV.DefaultQty AS DefaultQty,
    PIL.MinQty AS MinQty,
    PIL.MaxQty AS MaxQty,
    OV.AddedQty AS AddedQty,
    OV.SubtractedQty AS SubtractedQty,
    OV.DefaultUnitPrice AS DefaultUnitPrice,
    OV.AddedUnitPrice AS AddedUnitPrice,
    OV.SubtractedUnitPrice AS SubtractedUnitPrice,
    CASE
        WHEN PKP.ProductType=0
            THEN CASE
                WHEN COALESCE(PIL.DefaultQty,0)>0 AND CAST(OV.Level AS INTEGER)>0 AND COALESCE(PIL.PartType,0)=1
                    THEN 'INGREDIENT'
                WHEN COALESCE(PIL.DefaultQty,0)=0 AND CAST(OV.Level AS INTEGER)>0 AND (COALESCE(PIL.PartType,0)=1 OR COALESCE(PIT.IsClass,0)=1)
                    THEN 'CANADD'
                ELSE 'PRODUCT'
            END
        WHEN PKP.ProductType=1
            THEN 'OPTION'
        WHEN PKP.ProductType=2
            THEN 'COMBO'
        WHEN PKP.ProductType=6
            THEN 'COUPON'
        ELSE 'PRODUCT'
    END AS ItemType,
    OV.ChosenQty AS ChosenQty,
    CASE WHEN (PKP.ProductType=0 AND COALESCE(PIL.PartType,0)=1)
        -- Get modifier label when needed
        THEN (SELECT Label FROM productdb.ModifierQtyLabels WHERE ProductCode=OV.PartCode AND Qty=OV.Qty)
        ELSE NULL
    END AS ModifierLabel,
    OV.PriceKey AS PriceKey,
    OV.ProductPriority AS ProductPriority,
    NULLIF(OV.OnlyModifiers,0) AS OnlyModifiers,
    OV.ItemDiscount AS ItemDiscount,
    OV.DiscountsApplied AS DiscountsApplied,
    PKP.MeasureUnit AS MeasureUnit,
    OV.IncludedQty AS IncludedQty,
    OV.OverwrittenUnitPrice AS OverwrittenUnitPrice,
    OV.LastUpdate AS LastUpdate
FROM OrderView OV
-- Gets item's type from the ProductKernelParams table
JOIN productdb.ProductKernelParams PKP ON PKP.ProductCode=OV.PartCode
-- Gets parts information
LEFT JOIN sysproddb.ProductItemTree PIT ON PIT.ItemId=OV.ItemId
LEFT JOIN sysproddb.ProductItemLeaf PIL ON PIL.ProductCode=PIT.ProductCode AND PIL.PartCode=OV.PartCode
ORDER BY OV.OrderId, OV.LineNumber, (OV.ItemId||'.'||OV.PartCode), OV.Level;
-- OrderSizableItems view: Used to find out all the possible current order items sizes.
--                         This is helpfull in upsize/downsize operations in which it is
--                         needed to search for the related sale items in terms of sizes.
--                         See ordermgr_pos_changeDimension function.
CREATE TEMPORARY VIEW OrderSizableItems AS
SELECT POSId, OrderId, LineNumber, Level, ItemId, Context, ProductCode, ProductName, Size, Priority, IsCurrentSize, OrderedQty
FROM (
	SELECT P.POSId AS POSId,
	       OI.OrderId AS OrderId,
	       OI.LineNumber AS LineNumber,
	       OI.Level AS Level,
	       PIT2.Context AS ItemId,
	       PIT2.Context AS Context,
	       PIT2.ProductCode AS ProductCode,
	       PP.ProductName AS ProductName,
	       PD.DimChar AS Size,
	       D.DimPrio AS Priority,
	       CASE WHEN PIT2.ItemId=(OI.ItemId||'.'||OI.PartCode) THEN 1 ELSE 0 END AS IsCurrentSize,
	       OI.OrderedQty AS OrderedQty
	FROM orderdb.POS P
	JOIN orderdb.CurrentOrderItem OI ON OI.OrderId=P.CurrentOrder AND OI.OrderedQty IS NOT NULL
	JOIN sysproddb.ProductItemTree PIT ON PIT.ItemId=(OI.ItemId||'.'||OI.PartCode)
	JOIN productdb.ProductDimensions PD ON PD.ProductCode=PIT.ProductCode
	JOIN productdb.Dimensions D ON D.DimChar=PD.DimChar
	JOIN sysproddb.ProductItemTree PIT2 ON PIT2.ItemId=(PIT.Context||'.'||PD.DimPCode)
	JOIN productdb.Product PP ON PP.ProductCode=PD.DimPCode
	WHERE OI.Level='0'
	UNION ALL
	SELECT T.POSId AS POSId,
	       T.OrderId AS OrderId,
	       OV.LineNumber AS LineNumber,
	       OV.Level AS Level,
	       T.ItemId AS ItemId,
	       T.Context AS Context,
	       PD.DimPCode AS DimPCode,
	       P.ProductName AS ProductName,
	       PD.DimChar AS Size,
	       PD.DimPrio AS Priority,
	       (CASE WHEN PD.DimPCode=OV.PartCode THEN 1 ELSE 0 END) AS IsCurrentSize,
	       OV.Qty AS OrderedQty
	FROM (
		SELECT OI.POSId, OI.OrderId, PIT.ItemId, PIT.Context, PIT.ProductCode, PIT.RecursionLevel, PIL.PartCode
		FROM temp.OrderView OI
		JOIN sysproddb.ProductItemTree PIT ON PIT.Context=OI.ItemId AND PIT.ProductCode=OI.PartCode
		LEFT JOIN sysproddb.ProductItemLeaf PIL ON PIL.ProductCode=PIT.ProductCode
		WHERE OI.MultQty>0 AND PIT.IsClass=1
	) T
	LEFT JOIN temp.OrderView OV ON OV.ItemId=T.ItemId AND OV.PartCode=T.PartCode
	LEFT JOIN productdb.ProductDimensions PD ON PD.ProductCode=OV.PartCode
	LEFT JOIN productdb.Product P ON P.ProductCode=PD.DimPCode
	WHERE OV.MultQty>0 AND PD.DimGroupId IS NOT NULL
) D
ORDER BY OrderId, LineNumber, Level, Priority;
-- OrderFiscalView view: This view is used in order to generate important data for fiscal components.
--                       It is used in the ordermgr_pos_orderFiscalLinePicture function which is
--                       used when a item quantity is changed and the SAleCOntroller component needs
--                       to notify the system about these changes.
CREATE TEMPORARY VIEW OrderFiscalView AS
SELECT
	OV.POSId,
	CAST(O.BusinessPeriod AS VARCHAR) AS BusinessPeriod,
	OV.OrderId AS OrderId,
	OV.LineNumber AS LineNumber,
	OV.ItemId AS ItemId,
	OV.PartCode AS PartCode,
	OV.Level AS Level,
	OV.ProductName AS ProductName,
    OV.MultQty AS OrderedQty,
    OV.DefaultUnitPrice AS UnitPrice,
    OV.ItemPrice AS ItemPrice,
	PKP.MeasureUnit,
	COALESCE((CASE WHEN OV.ChosenQty<OV.Qty THEN 1 ELSE 0 END),0) AS IsOpen,
    O.OrderType AS OrderType,
    O.OrderSubType AS OrderSubType
FROM temp.OrderView OV
JOIN orderdb.Orders O ON O.OrderId=OV.OrderId
LEFT JOIN productdb.ProductKernelParams PKP ON PKP.ProductCode=OV.PartCode
ORDER BY OV.POSId,O.BusinessPeriod,OV.OrderId,OV.LineNumber,OV.Level,(OV.ItemId||'.'||OV.PartCode);


--
-- New helper views for Modifiers screen
--

CREATE TEMPORARY TABLE ProductModifierSets AS
-- List of Products and its possible modification groups
SELECT ProductCode, '['||GROUP_CONCAT('"'||(TagVal)||'"',',')||']' AS ModifierSets
FROM (
    SELECT SUBSTR(TAG,1,INSTR(TAG,'=')-1) AS TagKey, SUBSTR(TAG,INSTR(TAG,'=')+1) AS TagVal, ProductCode  FROM productdb.ProductTags
) Tags
WHERE TagKey='Modifiers'
GROUP BY ProductCode;

CREATE TEMPORARY TABLE ModifierSetProducts AS
-- List of Products and its possible modification groups
SELECT TagVal AS ModifierSet, '['||GROUP_CONCAT(ProductCode,',')||']' AS Products
FROM (
    SELECT SUBSTR(TAG,1,INSTR(TAG,'=')-1) AS TagKey, SUBSTR(TAG,INSTR(TAG,'=')+1) AS TagVal, ProductCode  FROM productdb.ProductTags
) Tags
WHERE TagKey='ModifierSet'
GROUP BY TagVal;


--
-- New view for Default Option kernel implementation
--
CREATE TEMPORARY TABLE IF NOT EXISTS CatalogDefaultOptions AS
SELECT ItemId, DefaultChoice, Level, Priority, Context, ProductCode, OptionCode, DefaultQty FROM (
    SELECT
        DO.ItemId||'.'||DO.PartCode AS ItemId,
        P.ProductCode AS DefaultChoice,
        CAST(DO.RecursionLevel+1 AS VARCHAR) AS Level,
        instr('|'||DO.DefaultOption||'|','|'||P.ProductCode||'|') AS Priority,
        DO.Context AS Context,
        DO.ProductCode AS ProductCode,
        DO.PartCode AS OptionCode,
        DO.DefaultQty AS DefaultQty,
        (SELECT (LENGTH(DO.DefaultOption) - LENGTH(REPLACE(DO.DefaultOption, P.ProductCode, ''))) / LENGTH(P.ProductCode)) as DefaultNumber 
    FROM (
        SELECT
            T.ItemId,
            T.Context,
            T.ProductCode,
            T.RecursionLevel,
            L.PartCode,
            L.MinQty,
            L.MaxQty,
            L.DefaultQty,
            -- Look for a JSON setup or a Custom parameter
            COALESCE(
              CASE WHEN (SUBSTR(PP.CustomAttr,-1) = '}')
                THEN
                REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(
                JSONGet('defaultOption', PP.CustomAttr),
                JSONGet('DefaultOption', PP.CustomAttr),
                JSONGet('default_option', PP.CustomAttr),
                JSONGet('default-option', PP.CustomAttr),
                JSONGet('defaultoption', PP.CustomAttr)
                ), '[', ''),']', ''),' ', ''),',', '|')
                ELSE NULL
              END,
              PCP.CustomParamValue
            ) AS DefaultOption
          FROM sysproddb.ProductItemTree T
          JOIN sysproddb.ProductItemLeaf L
            ON L.ProductCode=T.ProductCode
          JOIN productdb.ProductPart PP
            ON PP.ProductCode=L.ProductCode
           AND PP.PartCode=L.PartCode
          LEFT JOIN productdb.ProductCustomParams PCP
            ON PCP.ProductCode IN (T.ProductCode, L.PartCode)
           AND PCP.CustomParamId IN ('DefaultOption', 'defaultOption', 'default_option', 'default-option', 'defaultoption')
    ) DO
    JOIN productdb.Product P ON instr('|'||DO.DefaultOption||'|','|'||P.ProductCode||'|')>0
    JOIN productdb.ProductKernelParams PKP ON PKP.ProductCode=DO.PartCode AND PKP.ProductType=1
    JOIN productdb.ProductClassification PC ON PC.ClassCode=DO.PartCode AND PC.ProductCode=P.ProductCode
    WHERE DO.DefaultOption IS NOT NULL AND DO.DefaultQty > 0
) JOIN (SELECT aa.a + 10*bb.b AS numbers FROM 
    (SELECT 0 a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) aa, 
    (SELECT 0 b UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) bb)
WHERE numbers < DefaultNumber;

CREATE TEMPORARY VIEW OrderDefaultOptions AS
WITH RECURSIVE CurrentOrderItemMultiplied AS (
    SELECT *, NULL AS ParentQty, OrderedQty AS MultQty
    FROM orderdb.CurrentOrderItem
    WHERE Level=0
    UNION ALL
    SELECT O.*, M.MultQty AS ParentQty, TDMUL(COALESCE(M.OrderedQty,M.MultQty),COALESCE(O.DefaultQty,O.OrderedQty)) AS MultQty
    FROM CurrentOrderItemMultiplied M
    JOIN orderdb.CurrentOrderItem O ON O.OrderId=M.OrderId AND O.LineNumber=M.LineNumber AND O.ItemId=M.ItemId||'.'||M.PartCode AND O.Level=M.Level+1
),
SelectOptions AS (
		SELECT OI.OrderId, OI.LineNumber, OI.ItemId, OI.Level, OI.PartCode, OI.PriceKey, DO.Priority, MAX(DO.DefaultQty) AS DefaultQty, COUNT(1) AS Qty
		FROM CurrentOrderItemMultiplied OI
		JOIN temp.CatalogDefaultOptions DO ON  DO.ItemId=OI.ItemId AND DO.Level=OI.Level AND DO.DefaultChoice=OI.PartCode
		WHERE OI.ParentQty IS NOT NULL
		GROUP BY OI.OrderId, OI.LineNumber, OI.ItemId, OI.Level, OI.PartCode, OI.PriceKey, DO.Priority
)
SELECT DO.OrderId, DO.LineNumber, DO.ItemId, DO.Level, DO.PartCode, DO.PriceKey, DO.DefaultQty, DO.Qty
FROM temp.OrderOptions OO
JOIN SelectOptions DO
 ON DO.OrderId=OO.OrderId
AND DO.LineNumber=OO.LineNumber
AND DO.ItemId=OO.ItemId||'.'||OO.PartCode
AND DO.Level=CAST((CAST(OO.Level AS INTEGER)+1) AS VARCHAR)
WHERE OO.DefaultQty-OO.ChosenQty > 0
ORDER BY DO.OrderId, DO.LineNumber, DO.ItemId, DO.Level, DO.Priority;

CREATE TEMPORARY TABLE DistributeCurrentOrderDefaultOptions (
    OrderId INTEGER,
    LineNumber INTEGER,
    ItemId VARCHAR(50),
    Level VARCHAR(30),
    PartCode INTEGER,
    PriceKey INTEGER,
    DefaultQty INTEGER,
    RequiredQty INTEGER,
    AvailQty INTEGER,
    Checked INTEGER NOT NULL DEFAULT 0
);

CREATE TEMPORARY TRIGGER TGR_DistributeCurrentOrderDefaultOptions_AfterUpdate_Checked
AFTER UPDATE OF Checked ON DistributeCurrentOrderDefaultOptions
FOR EACH ROW WHEN OLD.Checked=0 AND NEW.Checked=1 BEGIN
	UPDATE DistributeCurrentOrderDefaultOptions
	SET AvailQty=AvailQty-MIN(NEW.RequiredQty, NEW.AvailQty)
	WHERE OrderId=NEW.OrderId
	  AND LineNumber=NEW.LineNumber
	  AND Level=NEW.Level
	  AND PartCode=NEW.PartCode
	  AND _ROWID_!=NEW._ROWID_;

	UPDATE DistributeCurrentOrderDefaultOptions
	SET RequiredQty=RequiredQty-MIN(NEW.RequiredQty, NEW.AvailQty)
	WHERE OrderId=NEW.OrderId
	  AND LineNumber=NEW.LineNumber
	  AND ItemId=NEW.ItemId
	  AND Level=NEW.LEVEL
	  AND _ROWID_!=NEW._ROWID_;
END;

CREATE TEMPORARY VIEW CurrentOrderDefaultOptions AS
SELECT OrderId, LineNumber, ItemId, Level, PartCode, PriceKey, DefaultQty, AvailQty AS Qty
FROM temp.DistributeCurrentOrderDefaultOptions WHERE AvailQty>0 AND Checked>0;


--
-- FractionateOrderLineView: Used by fractionateOrderLine procedure.
--                           Parameterized by the OrderLineFraction temp table.
--
CREATE TEMPORARY VIEW FractionateOrderLineView AS
	WITH RECURSIVE LineFraction AS (
		SELECT
			1 AS RowNum,
			OrderId,
			LineNumber,
			ItemId,
			Level,
			PartCode,
			OrderedQty,
			LastOrderedQty,
			IncQty,
			DecQty,
			PriceKey,
			DiscountAmount,
			SurchargeAmount,
			OnlyFlag,
			OverwrittenUnitPrice,
			DefaultQty,
			LastUpdate,
			OrderItem._ROWID_ AS FractionRefId,
			tddiv(
				OrderedQty,
				(SELECT FractionQty FROM temp.OrderLineFraction LIMIT 1),
				POS.RoundingScale,
				POS.RoundingModeId
			) AS FractionatedQty
		  FROM orderdb.POS, orderdb.OrderItem
		 WHERE
		  OrderId=(SELECT OrderId FROM temp.OrderLineFraction LIMIT 1)
		 AND LineNumber=(SELECT LineNumber FROM temp.OrderLineFraction LIMIT 1)
		 AND Level=0
		UNION ALL
		SELECT
			(RowNum+1) AS RowNum,
			OrderId,
			LineNumber,
			ItemId,
			Level,
			PartCode,
			OrderedQty,
			LastOrderedQty,
			IncQty,
			DecQty,
			PriceKey,
			DiscountAmount,
			SurchargeAmount,
			OnlyFlag,
			OverwrittenUnitPrice,
			DefaultQty,
			LastUpdate,
			FractionRefId,
			FractionatedQty
		FROM LineFraction
		LIMIT (SELECT FractionQty FROM temp.OrderLineFraction LIMIT 1)
	),
	RoundingError AS (
		SELECT
			TDSUB(
				TDSUM(FractionatedQty),
				OrderedQty,
				POS.RoundingScale,
				POS.RoundingModeId
			) AS Qty,
			POS.RoundingScale,
			POS.RoundingModeId
		FROM LineFraction, POS
	),
	OrderLineFractionated AS (
		SELECT
			RowNum,
			LineFraction.OrderId,
			CASE WHEN RowNum=1
				THEN LineNumber
				ELSE (Orders.LineCounter+(RowNum-1))
			END AS LineNumber,
			ItemId,
			Level,
			PartCode,
			OrderedQty,
			CASE WHEN RowNum=(SELECT FractionQty FROM temp.OrderLineFraction LIMIT 1)
				THEN TDSUB(FractionatedQty, RoundingError.Qty, RoundingScale, RoundingModeId)
				ELSE FractionatedQty
			END AS FractionQty,
			LastOrderedQty,
			CASE WHEN RowNum=1
				THEN IncQty
				ELSE 0
			END AS IncQty,
			CASE WHEN RowNum=1
				THEN DecQty
				ELSE 0
			END AS DecQty,
			PriceKey,
			LineFraction.DiscountAmount,
			SurchargeAmount,
			OnlyFlag,
			OverwrittenUnitPrice,
			DefaultQty,
			strftime('%Y-%m-%dT%H:%M:%f', 'now') AS LastUpdate,
			FractionRefId
		FROM LineFraction, RoundingError
		JOIN orderdb.Orders
		  ON Orders.OrderId=LineFraction.OrderId
	),
	RemaningLevels AS (
		SELECT
			F.RowNum,
			F.OrderId,
			F.LineNumber,
			OILevels.ItemId,
			OILevels.Level,
			OILevels.PartCode,
			OILevels.OrderedQty,
			NULL AS FractionQty,
			OILevels.LastOrderedQty,
			OILevels.IncQty,
			OILevels.DecQty,
			OILevels.PriceKey,
			OILevels.DiscountAmount,
			OILevels.SurchargeAmount,
			OILevels.OnlyFlag,
			OILevels.OverwrittenUnitPrice,
			OILevels.DefaultQty,
			strftime('%Y-%m-%dT%H:%M:%f', 'now') AS LastUpdate,
			NULL AS FractionRefId
		FROM OrderLineFractionated F
		JOIN orderdb.OrderItem OI
		  ON OI.OrderId=F.OrderId
		 AND OI._ROWID_=F.FractionRefId
		 AND F.RowNum>1
		JOIN orderdb.OrderItem OILevels
		  ON OILevels.OrderId=OI.OrderId
		 AND OILevels.LineNumber=OI.LineNumber
		 AND OILevels.Level>0
	)
	SELECT *
	  FROM OrderLineFractionated
	UNION ALL
	SELECT *
	  FROM RemaningLevels
	ORDER BY 2,3,4,5;


--
-- RevertFractionatedOrderLineView: Used by revertFractionatedOrderLine procedure.
--                                  Parameterized by the OrderLineFraction temp table.
--
CREATE TEMPORARY VIEW RevertFractionatedOrderLineView AS
	WITH LineFractions AS (
		SELECT OrderId, LineNumber, ItemId, Level, PartCode, CAST(Value AS INTEGER) AS OriginalLineNumber
		  FROM orderdb.OrderItemCustomProperties
		 WHERE OrderItemCustomProperties.OrderId=(SELECT OrderId FROM temp.OrderLineFraction LIMIT 1)
		   AND OrderItemCustomProperties.Key='OMGR_FRACTION_FROM_LINE'
		   AND OrderItemCustomProperties.Value=(SELECT LineNumber FROM temp.OrderLineFraction LIMIT 1)
	),
	OriginalOrdered AS (
		SELECT TDSUM(CurrentOrderItem.OrderedQty, 0, 0) AS Qty
		  FROM LineFractions
		  JOIN orderdb.CurrentOrderItem
		    ON CurrentOrderItem.OrderId=LineFractions.OrderId
		   AND CurrentOrderItem.LineNumber=LineFractions.LineNumber
		   AND CurrentOrderItem.ItemId=LineFractions.ItemId
		   AND CurrentOrderItem.Level=LineFractions.Level
		   AND CurrentOrderItem.PartCode=LineFractions.PartCode
	)
	SELECT
			CurrentOrderItem.OrderId,
			CurrentOrderItem.LineNumber,
			CurrentOrderItem.ItemId,
			CurrentOrderItem.Level,
			CurrentOrderItem.PartCode,
			CASE WHEN CurrentOrderItem.LineNumber=LineFractions.OriginalLineNumber THEN
				(SELECT Qty FROM OriginalOrdered)
			ELSE 0 END AS OrderedQty,
			CurrentOrderItem.IncQty,
			CurrentOrderItem.DecQty,
			CurrentOrderItem.PriceKey,
			CurrentOrderItem.DiscountAmount,
			CurrentOrderItem.SurchargeAmount,
			CurrentOrderItem.OverwrittenUnitPrice,
			CurrentOrderItem.DefaultQty,
			strftime('%Y-%m-%dT%H:%M:%f', 'now') AS LastUpdate
	  FROM LineFractions
	  JOIN orderdb.CurrentOrderItem
	    ON CurrentOrderItem.OrderId=LineFractions.OrderId
	   AND CurrentOrderItem.LineNumber=LineFractions.LineNumber
	   AND CurrentOrderItem.ItemId=LineFractions.ItemId
	   AND CurrentOrderItem.Level=LineFractions.Level
	   AND CurrentOrderItem.PartCode=LineFractions.PartCode;

