From fb1634fb000c80a7b66d3af521c964dea9923d79 Mon Sep 17 00:00:00 2001
From: lihongji <3117313295@qq.com>
Date: 星期日, 04 八月 2024 17:38:14 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into dev

---
 _Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMaxMonthDate.qbl                      |   13 
 _Main/BL/Type_LocalCell_ProductionComparison/Method_GetAttributeByName.qbl                   |   18 -
 _Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_Gap.qbl                              |    7 
 _Main/BL/Type_LocalCell_OfflinePlanComparison/DefaultValue_CompareVersionValue.qbl           |    0 
 _Main/BL/Type_LocalCell_OfflinePlanComparison/StaticMethod_GetColumnXML.qbl                  |   97 ++++++
 _Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_BaseVersion.qbl                      |    7 
 _Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMinWeekDate.qbl                       |   13 
 _Main/BL/Type_FinancialProductionReport/Method_GetCurrentPeriod.qbl                          |   53 +++
 _Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_BaseVersionValue.qbl                 |    7 
 _Main/BL/Type_TemplateManager/StaticMethod_GetIDSTemplate.qbl                                |    8 
 _Main/BL/Type_LibCal_SubscriberEventTable/Method_ProcessColumnDay.qbl                        |   17 +
 _Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MaxDayDate.qbl                           |    8 
 _Main/BL/Type_LocalCell_OfflinePlanComparison/StaticMethod_GetAttributeNames.qbl             |   16 +
 _Main/BL/Type_LocalCell_OfflinePlanComparison/StaticMethod_AsyncExport.qbl                   |   32 ++
 _Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_GetAttributeNames.qbl              |    4 
 _Main/BL/Type_TemplateManager/StaticMethod_GetPPATemplate.qbl                                |    4 
 _Main/BL/Type_LocalCell_OfflinePlanComparison/Method_GetAttributeByName.qbl                  |   44 ++
 _Main/BL/Type_TemplateManager/StaticMethod_GetCurveTemplate.qbl                              |   64 ++--
 _Main/BL/Type_InventorySummarySource/StaticMethod_Initialize.qbl                             |    2 
 _Main/BL/Type_LocalRow/Attribute_Remark.qbl                                                  |    7 
 _Main/BL/Type_InventorySummaryReport/StaticMethod_GetDefaultCCUnit.qbl                       |    2 
 _Main/BL/Type_LocalCell_OfflinePlanComparison/_ROOT_Type_LocalCell_OfflinePlanComparison.qbl |    9 
 _Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MaxMonthDate.qbl                         |    8 
 _Main/BL/Type_FinancialProductionReport/StaticMethod_GetDefaultDLUnit.qbl                    |    2 
 _Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MinMonthDate.qbl                         |    8 
 _Main/BL/Type_LibCal_SubscriberEventTable/Method_ProcessColumnMonth#1.qbl                    |   17 +
 _Main/BL/Type_LibCal_SubscriberEventTable/Method_ProcessColumnWeek.qbl                       |   17 +
 _Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMaxWeekDate.qbl                       |   13 
 _Main/BL/Type_FinancialProductionReport/StaticMethod_GetDefaultCCUnit.qbl                    |    2 
 _Main/BL/Type_FinancialProductionSource/StaticMethod_Initialize.qbl                          |   90 ++---
 _Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMaxDayDate.qbl                        |   13 
 _Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_CompareVersion.qbl                   |    7 
 _Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_CompareVersionValue.qbl              |    7 
 _Main/BL/Type_LibCal_SubscriberEventTable/Method_GetColumnByTimeUnit.qbl                     |    2 
 _Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MaxWeekDate.qbl                          |    8 
 /dev/null                                                                                    |   39 --
 _Main/BL/Type_LocalCell_OfflinePlanComparison/Function_CalcGap.qbl                           |   13 
 _Main/BL/Type_LocalCell_OfflinePlanComparison/StaticMethod_Compared.qbl                      |  107 +++++++
 _Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MinDayDate.qbl                           |    8 
 _Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMinDayDate.qbl                        |   13 
 _Main/BL/Type_FinancialProductionRow/Method_Initialize.qbl                                   |    4 
 _Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MinWeekDate.qbl                          |    8 
 _Main/BL/Type_FinancialProductionReport/Method_GetRowByUnit.qbl                              |   22 +
 _Main/BL/Type_LocalCell_OfflinePlanComparison/DefaultValue_BaseVersionValue.qbl              |    0 
 _Main/BL/Type_InventorySummaryReport/StaticMethod_GetDefaultDLUnit.qbl                       |    2 
 _Main/BL/Type_LibCal_Event/StaticMethod_ValidDate.qbl                                        |    1 
 _Main/BL/Type_LibCal_SubscriberEventTable/Method_InitializeTable.qbl                         |   27 +
 _Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMinMonthDate.qbl                      |   13 
 48 files changed, 722 insertions(+), 161 deletions(-)

diff --git a/_Main/BL/Type_FinancialProductionReport/Method_GetCurrentPeriod.qbl b/_Main/BL/Type_FinancialProductionReport/Method_GetCurrentPeriod.qbl
new file mode 100644
index 0000000..6e9b192
--- /dev/null
+++ b/_Main/BL/Type_FinancialProductionReport/Method_GetCurrentPeriod.qbl
@@ -0,0 +1,53 @@
+Quintiq file version 2.0
+#parent: #root
+Method GetCurrentPeriod (
+  Date startofplanning,
+  Period_MPs periods
+) as owning Period_MPs
+{
+  Description: '鑾峰彇褰撳墠鏈堢殑璁″垝鍛ㄦ湡---------------搴熷純'
+  TextBody:
+  [*
+    // 鐢勫叞楦� Aug-2-2024 (created)
+    //寮�濮嬫棩鏈熷埌涓嬩釜鏈堢殑闂撮殧澶╂暟
+    currentperiods            := construct( Period_MPs );
+    startofnextmonth          := startofplanning.StartOfNextMonth();
+    //鐗规畩鎯呭喌锛屽綋寮�濮嬫棩鏈熸濂芥槸杩欎釜鏈堢涓�澶╋紝 鍒欑洿鎺ヤ娇鐢═imeUnit涓烘湀鐨勬暟鎹�
+    if( startofplanning.StartOfMonth() = startofplanning ){
+      period                  := selectobject( periods, Elements, period, period.TimeUnit() = Translations::MP_GlobalParameters_Month() and period.StartDate() = startofplanning );
+      currentperiods.Add( period );
+    } else if( startofplanning.StartOfWeek() = startofplanning ){
+      //鐗规畩鎯呭喌锛屽綋寮�濮嬫棩鏈熸濂芥槸杩欎釜鍛ㄧ涓�澶╋紝 鍒欑洿鎺ヤ娇鐢═imeUnit涓哄懆鐨勬暟鎹紝 璺ㄥ懆鏃朵娇鐢╠ay
+      traverse( periods, Elements, period, ( period.TimeUnit() =  Translations::MP_GlobalParameters_Week() and period.StartDate() < startofnextmonth ) 
+                or (  period.TimeUnit() =  Translations::MP_GlobalParameters_Day() and period.EndDate() = startofnextmonth ) ){
+        currentperiods.Add( period );
+      }
+    } else {
+      duration                := startofplanning.StartOfNextMonth() - startofplanning;
+      //濡傛灉璁″垝寮�濮嬫棩鏈熷埌涓嬩釜鏈堝皬浜�7澶╋紝鍒欏彲浠ョ洿鎺ヤ娇鐢≒eriod鐨凾imeUnit涓哄ぉ鐨勬暟鎹�
+      if( duration <= 7 ){
+        i := 1;
+        traverse( periods, Elements, period, period.TimeUnit() = Translations::MP_GlobalParameters_Day() and i < duration ){
+          currentperiods.Add( period );
+          i ++;
+        }
+      }else{
+        //鍙嶄箣闇�瑕佸湪鍔犱笂Period鐨凾imeUnit涓哄懆鐨勬暟鎹�
+        day := startofplanning;
+        while( day < startofnextmonth ){
+          if( day = day.StartOfWeek() ){
+            period     := selectobject( periods, Elements, cperiod, cperiod.TimeUnit() = Translations::MP_GlobalParameters_Week() and cperiod.StartDate() = day );
+            day        := period.EndDate();
+            currentperiods.Add( period );
+          } else {
+            period     := selectobject( periods, Elements, cperiod, cperiod.TimeUnit() = Translations::MP_GlobalParameters_Day() and cperiod.StartDate() = day );
+            day        := period.EndDate();
+            currentperiods.Add( period );
+          }
+        }
+      }
+    }
+    
+    return &currentperiods;
+  *]
+}
diff --git a/_Main/BL/Type_FinancialProductionReport/Method_GetRowByUnit.qbl b/_Main/BL/Type_FinancialProductionReport/Method_GetRowByUnit.qbl
new file mode 100644
index 0000000..8de3af4
--- /dev/null
+++ b/_Main/BL/Type_FinancialProductionReport/Method_GetRowByUnit.qbl
@@ -0,0 +1,22 @@
+Quintiq file version 2.0
+#parent: #root
+Method GetRowByUnit (
+  String product,
+  String unit
+) as FinancialProductionRow
+{
+  Description: '鏍规嵁宸ュ巶鑾峰彇琛�'
+  TextBody:
+  [*
+    // 鐢勫叞楦� Aug-2-2024 (created)
+    row := selectobject( this, FinancialProductionRow, row, row.Name() = product and row.Unit() = unit );
+    if( isnull( row ) ){
+      //鍒濆鍖栧崟鍏冩牸
+      row := this.FinancialProductionRow( relnew, Name := product, Unit := unit );
+      traverse( this, FinancialProductionColumn, column ){
+        row.Initialize( column, unit );
+      }
+    }
+    return row;
+  *]
+}
diff --git a/_Main/BL/Type_FinancialProductionReport/StaticMethod_GetDefaultCCUnit.qbl b/_Main/BL/Type_FinancialProductionReport/StaticMethod_GetDefaultCCUnit.qbl
index 77d1f16..4a17ee3 100644
--- a/_Main/BL/Type_FinancialProductionReport/StaticMethod_GetDefaultCCUnit.qbl
+++ b/_Main/BL/Type_FinancialProductionReport/StaticMethod_GetDefaultCCUnit.qbl
@@ -5,7 +5,7 @@
   TextBody:
   [*
     // 鐢勫叞楦� Jun-25-2024 (created)
-    return '闀挎槬';
+    return '闀挎槬宸ュ巶';
     //return 'Assembly Plant (France)';
   *]
 }
diff --git a/_Main/BL/Type_FinancialProductionReport/StaticMethod_GetDefaultDLUnit.qbl b/_Main/BL/Type_FinancialProductionReport/StaticMethod_GetDefaultDLUnit.qbl
index 4759121..ba77240 100644
--- a/_Main/BL/Type_FinancialProductionReport/StaticMethod_GetDefaultDLUnit.qbl
+++ b/_Main/BL/Type_FinancialProductionReport/StaticMethod_GetDefaultDLUnit.qbl
@@ -5,7 +5,7 @@
   TextBody:
   [*
     // 鐢勫叞楦� Jun-25-2024 (created)
-    return '澶ц繛';
+    return '澶ц繛宸ュ巶';
     //return 'Assembly Plant (Spain)';
   *]
 }
diff --git a/_Main/BL/Type_FinancialProductionRow/Method_Initialize.qbl b/_Main/BL/Type_FinancialProductionRow/Method_Initialize.qbl
index 2bdcc0c..da223ae 100644
--- a/_Main/BL/Type_FinancialProductionRow/Method_Initialize.qbl
+++ b/_Main/BL/Type_FinancialProductionRow/Method_Initialize.qbl
@@ -2,7 +2,7 @@
 #parent: #root
 Method Initialize (
   FinancialProductionColumn column,
-  Real quantity
+  Number quantity
 )
 {
   TextBody:
@@ -10,7 +10,7 @@
     // 鐢勫叞楦� Jun-24-2024 (created)
     cell := selectobject( this, FinancialProductionCell, cell, cell.FinancialProductionColumn() = column );
           
-    value := [Real]cell.Value() + quantity;
+    value := [Number]cell.Value() + quantity;
     cell.Value( [String]value );
   *]
 }
diff --git a/_Main/BL/Type_FinancialProductionSource/StaticMethod_Initialize.qbl b/_Main/BL/Type_FinancialProductionSource/StaticMethod_Initialize.qbl
index 7a5ef26..63d3a59 100644
--- a/_Main/BL/Type_FinancialProductionSource/StaticMethod_Initialize.qbl
+++ b/_Main/BL/Type_FinancialProductionSource/StaticMethod_Initialize.qbl
@@ -14,66 +14,54 @@
     source                    := owner.FinancialProductionSource( relnew, IsImport := false, Name := FinancialProductionReport::GetDefaultName() );
     table                     := source.FinancialProductionReport( relnew, ID := source.Name(), Name := source.Name(), IsImport := false );
     showtable                 := source.FinancialProductionReport( relnew, ID := source.Name() + 'Show', Name := source.Name(), IsImport := false, IsShow := true );
-    startofplanning           := owner.StartOfPlanning();
-    startofnextmonth          := owner.StartOfPlanning().StartOfNextMonth();
-    startofyear               := startofplanning.StartOfYear();
+    startofplanning           := owner.StartOfPlanning().Date();
+    //startofnextmonth          := startofplanning.StartOfNextMonth();
     startofnextyear           := startofplanning.StartOfNextYear();
     
     search                    := source.FinancialProductionSearch( relnew, Unit := allunit, Generation := allunit, MqbMlb := allunit, Power := allunit );
     
     products                  := construct( Product_MPs );
-    
+    //闇�瑕佺殑鏃ユ湡鍖洪棿锛� 鍛ㄥ拰澶╃殑鍙渶瑕佸綋鍓嶆湀
+    //periods                   := selectset( owner, Period_MP, period, not period.IsHistorical() 
+    //                                        and period.StartDate() < startofnextmonth 
+    //                                        and period.TimeUnit() <> Translations::MP_GlobalParameters_Quarter()
+    //                                        );
+    //鑾峰彇褰撳墠鏈堥渶瑕佺殑Period
+    //currentperiods            := table.GetCurrentPeriod( startofplanning, periods );
     table.GenerateColumn( owner );
-    
-    traverse( owner, Product_MP.ProductInStockingPoint_MP, pisp, pisp.Product_MP().IsLeaf() and ( pisp.StockingPoint_MP().UnitID() = ccunit or pisp.StockingPoint_MP().UnitID() = dlunit ) ){
-      unit := pisp.StockingPoint_MP().UnitID();
-      info( unit, pisp.ProductID() );
-      ccrow := null( FinancialProductionRow );
-      dlrow := null( FinancialProductionRow );
-      allrow := selectobject( table, FinancialProductionRow, row, row.Name() = pisp.ProductID() and row.Unit() = allunit );
-      if( unit = ccunit ){
-        ccrow := table.FinancialProductionRow( relnew, Name := pisp.ProductID(), Unit := unit );
-      }else{
-        dlrow := table.FinancialProductionRow( relnew, Name := pisp.ProductID(), Unit := unit );
-      }
-      if( isnull( allrow ) ){
-        products.Add( pisp.Product_MP() );
-        allrow := table.FinancialProductionRow( relnew, Name := pisp.ProductID(), Unit := allunit );
-      }
-      
-      for( start := startofyear; start < startofnextyear; start := start.StartOfNextMonth() ){
-        periodtime := start.Date();
-        periodname := periodtime.Format( "M2/D2/Y" );
-        column := selectobject( table, FinancialProductionColumn, column, column.Name() = periodname and column.Period() = periodtime );
-        
-        if( not isnull( ccrow ) ){
-          ccrow.Initialize( column, ccunit );
+    //鍙栧綋鍓嶇増鏈殑product planning閲宯ew supply瀛楁锛屽垎澶ц繛鍜岄暱鏄ュ伐鍘傜殑浜х嚎锛岃繘琛屽姞鎬�
+    traverse( owner, StockingPoint_MP, stockingpoint ){
+      unit         := stockingpoint.Unit();
+      parentunits  := unit.GetAllParent();
+      //鏄惁灞炰簬闀挎槬宸ュ巶
+      iscc         := unit.ID() = ccunit or exists( parentunits, Elements, punit, punit.ID() = ccunit );
+      //鏄惁灞炰簬澶ц繛宸ュ巶
+      isdl         := unit.ID() = dlunit or exists( parentunits, Elements, punit, punit.ID() = dlunit );
+      if( iscc or isdl ){
+        traverse( stockingpoint, ProductInStockingPoint_MP, pisp,  pisp.Product_MP().IsLeaf() ){
+          //鑾峰彇宸ュ巶琛�
+          factoryrow := table.GetRowByUnit( pisp.ProductID(), ifexpr( iscc, ccunit, dlunit ) );
+          //鑾峰彇鍚堣琛�
+          allrow     := table.GetRowByUnit( pisp.ProductID(), allunit );
+          products.Add( pisp.Product_MP() );
+          //褰損roduct planning鐨勬棩鏈熷尯闂村湪闇�瑕佺殑鏃ユ湡鍖洪棿鍐� 
+          traverse( pisp, ProductInStockingPointInPeriod, pispip, not pispip.Period_MP().IsHistorical() and pispip.Period_MP().StartDate() < startofnextyear
+    //                and ( ( pispip.Period_MP().StartDate().StartOfMonth() = startofplanning.StartOfMonth() and currentperiods.Find( pispip.Period_MP() ) >= 0 )
+    //                 or ( pispip.Period_MP().TimeUnit() = Translations::MP_GlobalParameters_Month() and pispip.Period_MP().StartDate() < startofnextyear ) ) 
+                    ){
+            periodtime := pispip.Start().StartOfMonth().Date();
+            periodname := periodtime.Format( "M2/D2/Y" );
+            quantity   := ceil( pispip.NewSupplyQuantity() );//鍚戜笂鍙栨暣
+            
+            column := selectobject( table, FinancialProductionColumn, column, column.Name() = periodname and column.Period() = periodtime );
+            
+            factoryrow.Initialize( column, quantity );
+            allrow.Initialize( column, quantity );
+          }    
         }
-        if( not isnull( dlrow ) ){
-          dlrow.Initialize( column, dlunit );
-        }
-        if( not exists( allrow, FinancialProductionCell, allcell, allcell.FinancialProductionColumn() = column ) ){
-          allrow.Initialize( column, allunit );
-        }
-      }
-      
-      traverse( pisp, ProductInStockingPointInPeriod, pispip, pispip.Start() >= startofplanning
-                and ( ( pispip.Start() < startofnextmonth and pispip.Period_MP().TimeUnit() = Translations::MP_GlobalParameters_Day() ) 
-                      or ( pispip.Start() < startofnextyear and pispip.Period_MP().TimeUnit() = Translations::MP_GlobalParameters_Month() ) ) ){
-        periodtime := pispip.Start().StartOfMonth().Date();
-        periodname := periodtime.Format( "M2/D2/Y" );
-        
-        column := selectobject( table, FinancialProductionColumn, column, column.Name() = periodname and column.Period() = periodtime );
-        
-        if( not isnull( ccrow ) ){
-          ccrow.Initialize( column, pispip.NewSupplyProductionQuantity() );
-        }
-        if( not isnull( dlrow ) ){
-          dlrow.Initialize( column, pispip.NewSupplyProductionQuantity() );
-        }
-        allrow.Initialize( column, pispip.NewSupplyProductionQuantity() );
       }
     }
+    
     rows := selectsortedset( table, FinancialProductionRow, row, row.Name() );
     i    := 0;
     traverse( rows, Elements, e ){
diff --git a/_Main/BL/Type_InventorySummaryReport/StaticMethod_GetDefaultCCUnit.qbl b/_Main/BL/Type_InventorySummaryReport/StaticMethod_GetDefaultCCUnit.qbl
index 739a84b..e504a84 100644
--- a/_Main/BL/Type_InventorySummaryReport/StaticMethod_GetDefaultCCUnit.qbl
+++ b/_Main/BL/Type_InventorySummaryReport/StaticMethod_GetDefaultCCUnit.qbl
@@ -5,7 +5,7 @@
   TextBody:
   [*
     // 鐢勫叞楦� Jun-28-2024 (created)
-    return '闀挎槬';
+    return '闀挎槬宸ョ▼';
     //return 'Assembly Plant (France)';
   *]
 }
diff --git a/_Main/BL/Type_InventorySummaryReport/StaticMethod_GetDefaultDLUnit.qbl b/_Main/BL/Type_InventorySummaryReport/StaticMethod_GetDefaultDLUnit.qbl
index d544c74..781dc80 100644
--- a/_Main/BL/Type_InventorySummaryReport/StaticMethod_GetDefaultDLUnit.qbl
+++ b/_Main/BL/Type_InventorySummaryReport/StaticMethod_GetDefaultDLUnit.qbl
@@ -5,7 +5,7 @@
   TextBody:
   [*
     // 鐢勫叞楦� Jun-28-2024 (created)
-    return '澶ц繛';
+    return '澶ц繛宸ュ巶';
     //return 'Assembly Plant (Spain)';
   *]
 }
diff --git a/_Main/BL/Type_InventorySummarySource/StaticMethod_Initialize.qbl b/_Main/BL/Type_InventorySummarySource/StaticMethod_Initialize.qbl
index 455d0bc..f3c7208 100644
--- a/_Main/BL/Type_InventorySummarySource/StaticMethod_Initialize.qbl
+++ b/_Main/BL/Type_InventorySummarySource/StaticMethod_Initialize.qbl
@@ -27,7 +27,7 @@
     table.GenerateColumn( owner, 'All', startofyear, startofnextyear );
     //info( '-----------------------------------', table.InventorySummaryColumn( relsize ) );
     //搴撳瓨鏁伴噺涓篈ctual inventories閲岄潰鐨勭偣Planned inventories瀛楁搴撳瓨閲忓姞鎬�
-    traverse( owner, Product_MP.ProductInStockingPoint_MP, pisp, pisp.IsLeaf() and not pisp.IsSystem() and ( pisp.StockingPoint_MP().UnitID() = ccunit or pisp.StockingPoint_MP().UnitID() = dlunit ) ){
+    traverse( owner, Product_MP.ProductInStockingPoint_MP, pisp, pisp.IsLeaf() and not pisp.IsSystem() and not isnull( pisp.StockingPoint_MP() ) and ( pisp.StockingPoint_MP().UnitID() = ccunit or pisp.StockingPoint_MP().UnitID() = dlunit ) ){
       unit := pisp.StockingPoint_MP().UnitID();
       product := pisp.Product_MP();
     //  info( '-----------------------------------', unit, product.ID() );
diff --git a/_Main/BL/Type_LibCal_Event/StaticMethod_ValidDate.qbl b/_Main/BL/Type_LibCal_Event/StaticMethod_ValidDate.qbl
index 5b0cd8e..b96238b 100644
--- a/_Main/BL/Type_LibCal_Event/StaticMethod_ValidDate.qbl
+++ b/_Main/BL/Type_LibCal_Event/StaticMethod_ValidDate.qbl
@@ -22,5 +22,6 @@
       feedback_o := Translations::MP_LibCal_Event_ValidDate();
     }
     return feedback_o = '';
+    //return true;
   *]
 }
diff --git a/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MaxDayDate.qbl b/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MaxDayDate.qbl
new file mode 100644
index 0000000..beb02f5
--- /dev/null
+++ b/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MaxDayDate.qbl
@@ -0,0 +1,8 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute MaxDayDate
+{
+  #keys: '3[415136.0.960591378][415136.0.960591377][415136.0.960591379]'
+  Description: '鏈�澶ф棩鏈�-澶�'
+  ValueType: Date
+}
diff --git a/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MaxMonthDate.qbl b/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MaxMonthDate.qbl
new file mode 100644
index 0000000..dd8ffe2
--- /dev/null
+++ b/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MaxMonthDate.qbl
@@ -0,0 +1,8 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute MaxMonthDate
+{
+  #keys: '3[415136.0.960591412][415136.0.960591411][415136.0.960591413]'
+  Description: '鏈�澶ф棩鏈�-鏈�'
+  ValueType: Date
+}
diff --git a/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MaxWeekDate.qbl b/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MaxWeekDate.qbl
new file mode 100644
index 0000000..420f1c1
--- /dev/null
+++ b/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MaxWeekDate.qbl
@@ -0,0 +1,8 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute MaxWeekDate
+{
+  #keys: '3[415136.0.960591398][415136.0.960591397][415136.0.960591399]'
+  Description: '鏈�澶ф棩鏈�-鍛�'
+  ValueType: Date
+}
diff --git a/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MinDayDate.qbl b/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MinDayDate.qbl
new file mode 100644
index 0000000..d57dbac
--- /dev/null
+++ b/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MinDayDate.qbl
@@ -0,0 +1,8 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute MinDayDate
+{
+  #keys: '3[415136.0.960591388][415136.0.960591387][415136.0.960591389]'
+  Description: '鏈�灏忔棩鏈�-澶�'
+  ValueType: Date
+}
diff --git a/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MinMonthDate.qbl b/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MinMonthDate.qbl
new file mode 100644
index 0000000..aa63d99
--- /dev/null
+++ b/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MinMonthDate.qbl
@@ -0,0 +1,8 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute MinMonthDate
+{
+  #keys: '3[415136.0.960591419][415136.0.960591418][415136.0.960591420]'
+  Description: '鏈�灏忔棩鏈�-鏈�'
+  ValueType: Date
+}
diff --git a/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MinWeekDate.qbl b/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MinWeekDate.qbl
new file mode 100644
index 0000000..96a3954
--- /dev/null
+++ b/_Main/BL/Type_LibCal_SubscriberEventTable/Attribute_MinWeekDate.qbl
@@ -0,0 +1,8 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute MinWeekDate
+{
+  #keys: '3[415136.0.960591405][415136.0.960591404][415136.0.960591406]'
+  Description: '鏈�灏忔棩鏈�-鍛�'
+  ValueType: Date
+}
diff --git a/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMaxDayDate.qbl b/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMaxDayDate.qbl
new file mode 100644
index 0000000..03052fe
--- /dev/null
+++ b/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMaxDayDate.qbl
@@ -0,0 +1,13 @@
+Quintiq file version 2.0
+#parent: #root
+Function CalcMaxDayDate
+{
+  TextBody:
+  [*
+    // 鐢勫叞楦� Aug-1-2024 (created)
+    
+    value := maxobject( this,LibCal_SubscriberEventColumn, column, column.TimeUnit() = Translations::MP_GlobalParameters_Day(), column.Period() );
+    
+    this.MaxDayDate( value.Period() );
+  *]
+}
diff --git a/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMaxMonthDate.qbl b/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMaxMonthDate.qbl
new file mode 100644
index 0000000..ea3887c
--- /dev/null
+++ b/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMaxMonthDate.qbl
@@ -0,0 +1,13 @@
+Quintiq file version 2.0
+#parent: #root
+Function CalcMaxMonthDate
+{
+  TextBody:
+  [*
+    // 鐢勫叞楦� Aug-1-2024 (created)
+    
+    value := maxobject( this,LibCal_SubscriberEventColumn, column, column.TimeUnit() = Translations::MP_GlobalParameters_Month(), column.Period() );
+    
+    this.MaxMonthDate( value.Period() );
+  *]
+}
diff --git a/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMaxWeekDate.qbl b/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMaxWeekDate.qbl
new file mode 100644
index 0000000..ed0f2bd
--- /dev/null
+++ b/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMaxWeekDate.qbl
@@ -0,0 +1,13 @@
+Quintiq file version 2.0
+#parent: #root
+Function CalcMaxWeekDate
+{
+  TextBody:
+  [*
+    // 鐢勫叞楦� Aug-1-2024 (created)
+    
+    value := maxobject( this,LibCal_SubscriberEventColumn, column, column.TimeUnit() = Translations::MP_GlobalParameters_Week(), column.Period() );
+    
+    this.MaxWeekDate( value.Period() );
+  *]
+}
diff --git a/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMinDayDate.qbl b/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMinDayDate.qbl
new file mode 100644
index 0000000..6965360
--- /dev/null
+++ b/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMinDayDate.qbl
@@ -0,0 +1,13 @@
+Quintiq file version 2.0
+#parent: #root
+Function CalcMinDayDate
+{
+  TextBody:
+  [*
+    // 鐢勫叞楦� Aug-1-2024 (created)
+    
+    value := minobject( this, LibCal_SubscriberEventColumn, column, column.TimeUnit() = Translations::MP_GlobalParameters_Day(), column.Period() );
+    
+    this.MinDayDate( value.Period() );
+  *]
+}
diff --git a/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMinMonthDate.qbl b/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMinMonthDate.qbl
new file mode 100644
index 0000000..02cc12a
--- /dev/null
+++ b/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMinMonthDate.qbl
@@ -0,0 +1,13 @@
+Quintiq file version 2.0
+#parent: #root
+Function CalcMinMonthDate
+{
+  TextBody:
+  [*
+    // 鐢勫叞楦� Aug-1-2024 (created)
+    
+    value := minobject( this, LibCal_SubscriberEventColumn, column, column.TimeUnit() = Translations::MP_GlobalParameters_Month(), column.Period() );
+    
+    this.MinMonthDate( value.Period() );
+  *]
+}
diff --git a/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMinWeekDate.qbl b/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMinWeekDate.qbl
new file mode 100644
index 0000000..e5564d3
--- /dev/null
+++ b/_Main/BL/Type_LibCal_SubscriberEventTable/Function_CalcMinWeekDate.qbl
@@ -0,0 +1,13 @@
+Quintiq file version 2.0
+#parent: #root
+Function CalcMinWeekDate
+{
+  TextBody:
+  [*
+    // 鐢勫叞楦� Aug-1-2024 (created)
+    
+    value := minobject( this, LibCal_SubscriberEventColumn, column, column.TimeUnit() = Translations::MP_GlobalParameters_Week(), column.Period() );
+    
+    this.MinWeekDate( value.Period() );
+  *]
+}
diff --git a/_Main/BL/Type_LibCal_SubscriberEventTable/Method_GetColumnByTimeUnit.qbl b/_Main/BL/Type_LibCal_SubscriberEventTable/Method_GetColumnByTimeUnit.qbl
index 757b1d4..00583cb 100644
--- a/_Main/BL/Type_LibCal_SubscriberEventTable/Method_GetColumnByTimeUnit.qbl
+++ b/_Main/BL/Type_LibCal_SubscriberEventTable/Method_GetColumnByTimeUnit.qbl
@@ -9,7 +9,7 @@
   TextBody:
   [*
     // 鐢勫叞楦� Jul-26-2024 (created)
-    column := selectobject( table, LibCal_SubscriberEventColumn, column, column.Name() = time.Format( 'M/D/Y' ) );
+    column := selectobject( table, LibCal_SubscriberEventColumn, column, column.Name() = time.Format( 'M/D/Y' ), column.TimeUnit() = timeunit );
     if( isnull( column ) ){
       column := table.LibCal_SubscriberEventColumn( relnew, Name := time.Format( 'M/D/Y' ), Period := time, TimeUnit := timeunit );
     }
diff --git a/_Main/BL/Type_LibCal_SubscriberEventTable/Method_InitializeTable.qbl b/_Main/BL/Type_LibCal_SubscriberEventTable/Method_InitializeTable.qbl
index 1c22d42..1171045 100644
--- a/_Main/BL/Type_LibCal_SubscriberEventTable/Method_InitializeTable.qbl
+++ b/_Main/BL/Type_LibCal_SubscriberEventTable/Method_InitializeTable.qbl
@@ -33,14 +33,27 @@
     
       }
     }
-    
+    //info( '----------------------1------------------------', this.LibCal_SubscriberEventColumn( relsize ) );
     //traverse( this, LibCal_SubscriberEventColumn, column ){
-    //  traverse( this, LibCal_SubscriberEventRow, row ){
-    //    if( not exists( column, LibCal_SubscriberEventCell, cell, cell.LibCal_SubscriberEventRow() = row ) ) {
-    //      cell := column.LibCal_SubscriberEventCell( relnew, Value := '' );
-    //      row.LibCal_SubscriberEventCell( relinsert, cell );
-    //    }
-    //  }
+    //  info( '------------------------', column.Name(), column.Period(), column.TimeUnit() );
     //}
+            
+    Transaction::Transaction().Propagate( attribute( LibCal_SubscriberEventTable, MaxDayDate ) );
+    Transaction::Transaction().Propagate( attribute( LibCal_SubscriberEventTable, MaxWeekDate ) );
+    Transaction::Transaction().Propagate( attribute( LibCal_SubscriberEventTable, MaxMonthDate ) );
+    Transaction::Transaction().Propagate( attribute( LibCal_SubscriberEventTable, MinDayDate ) );
+    Transaction::Transaction().Propagate( attribute( LibCal_SubscriberEventTable, MinWeekDate ) );
+    Transaction::Transaction().Propagate( attribute( LibCal_SubscriberEventTable, MinMonthDate ) );
+    this.ProcessColumnDay();
+    this.ProcessColumnWeek();
+    this.ProcessColumnMonth();
+    traverse( this, LibCal_SubscriberEventColumn, column ){
+      traverse( this, LibCal_SubscriberEventRow, row ){
+        if( not exists( column, LibCal_SubscriberEventCell, cell, cell.LibCal_SubscriberEventRow() = row ) ) {
+          cell := column.LibCal_SubscriberEventCell( relnew, Value := '' );
+          row.LibCal_SubscriberEventCell( relinsert, cell );
+        }
+      }
+    }
   *]
 }
diff --git a/_Main/BL/Type_LibCal_SubscriberEventTable/Method_ProcessColumnDay.qbl b/_Main/BL/Type_LibCal_SubscriberEventTable/Method_ProcessColumnDay.qbl
new file mode 100644
index 0000000..c754148
--- /dev/null
+++ b/_Main/BL/Type_LibCal_SubscriberEventTable/Method_ProcessColumnDay.qbl
@@ -0,0 +1,17 @@
+Quintiq file version 2.0
+#parent: #root
+Method ProcessColumnDay
+{
+  TextBody:
+  [*
+    // 鐢勫叞楦� Aug-1-2024 (created)
+    day      := ( this.MinDayDate() + Duration::Days( 1 ) ).Date();
+    
+    while( day < this.MaxDayDate() ){
+      if( not exists( this, LibCal_SubscriberEventColumn, column, column.Period() = day and column.TimeUnit() = Translations::MP_GlobalParameters_Day() ) ){
+        this.LibCal_SubscriberEventColumn( relnew, Name := day.Format( 'M/D/Y' ), Period := day, TimeUnit := Translations::MP_GlobalParameters_Day() );
+      }
+      day      := ( day + Duration::Days( 1 ) ).Date();
+    }
+  *]
+}
diff --git "a/_Main/BL/Type_LibCal_SubscriberEventTable/Method_ProcessColumnMonth\0431.qbl" "b/_Main/BL/Type_LibCal_SubscriberEventTable/Method_ProcessColumnMonth\0431.qbl"
new file mode 100644
index 0000000..01051f1
--- /dev/null
+++ "b/_Main/BL/Type_LibCal_SubscriberEventTable/Method_ProcessColumnMonth\0431.qbl"
@@ -0,0 +1,17 @@
+Quintiq file version 2.0
+#parent: #root
+Method ProcessColumnMonth
+{
+  TextBody:
+  [*
+    // 鐢勫叞楦� Aug-1-2024 (created)
+    day      := this.MinMonthDate().StartOfNextMonth();
+    
+    while( day < this.MaxMonthDate()){
+      if( not exists( this, LibCal_SubscriberEventColumn, column, column.Period() = day and column.TimeUnit() = Translations::MP_GlobalParameters_Month()) ){
+        this.LibCal_SubscriberEventColumn( relnew, Name := day.Format( 'M/D/Y' ), Period := day, TimeUnit := Translations::MP_GlobalParameters_Month() );
+      }
+      day      := day.StartOfNextMonth();
+    }
+  *]
+}
diff --git a/_Main/BL/Type_LibCal_SubscriberEventTable/Method_ProcessColumnWeek.qbl b/_Main/BL/Type_LibCal_SubscriberEventTable/Method_ProcessColumnWeek.qbl
new file mode 100644
index 0000000..404a4e7
--- /dev/null
+++ b/_Main/BL/Type_LibCal_SubscriberEventTable/Method_ProcessColumnWeek.qbl
@@ -0,0 +1,17 @@
+Quintiq file version 2.0
+#parent: #root
+Method ProcessColumnWeek
+{
+  TextBody:
+  [*
+    // 鐢勫叞楦� Aug-1-2024 (created)
+    day      := this.MinWeekDate().StartOfNextWeek();
+    
+    while( day < this.MaxWeekDate() ){
+      if( not exists( this, LibCal_SubscriberEventColumn, column, column.Period() = day and column.TimeUnit() = Translations::MP_GlobalParameters_Week() ) ){
+        this.LibCal_SubscriberEventColumn( relnew, Name := day.Format( 'M/D/Y' ), Period := day, TimeUnit := Translations::MP_GlobalParameters_Week() );
+      }
+      day      := day.StartOfNextWeek();
+    }
+  *]
+}
diff --git a/_Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_BaseVersion.qbl b/_Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_BaseVersion.qbl
new file mode 100644
index 0000000..724913f
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_BaseVersion.qbl
@@ -0,0 +1,7 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute BaseVersion
+{
+  #keys: '3[412672.1.76654685][412672.1.76654684][412672.1.76654686]'
+  ValueType: Real
+}
diff --git a/_Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_BaseVersionValue.qbl b/_Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_BaseVersionValue.qbl
new file mode 100644
index 0000000..07a2d97
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_BaseVersionValue.qbl
@@ -0,0 +1,7 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute BaseVersionValue
+{
+  #keys: '3[412672.1.76654688][412672.1.76654687][412672.1.76654689]'
+  ValueType: String
+}
diff --git a/_Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_CompareVersion.qbl b/_Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_CompareVersion.qbl
new file mode 100644
index 0000000..6f60c77
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_CompareVersion.qbl
@@ -0,0 +1,7 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute CompareVersion
+{
+  #keys: '3[412672.1.76654691][412672.1.76654690][412672.1.76654692]'
+  ValueType: Real
+}
diff --git a/_Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_CompareVersionValue.qbl b/_Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_CompareVersionValue.qbl
new file mode 100644
index 0000000..e53dce9
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_CompareVersionValue.qbl
@@ -0,0 +1,7 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute CompareVersionValue
+{
+  #keys: '3[412672.1.76654694][412672.1.76654693][412672.1.76654695]'
+  ValueType: String
+}
diff --git a/_Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_Gap.qbl b/_Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_Gap.qbl
new file mode 100644
index 0000000..2fd61e4
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_OfflinePlanComparison/Attribute_Gap.qbl
@@ -0,0 +1,7 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute Gap
+{
+  #keys: '3[412672.1.76654697][412672.1.76654696][412672.1.76654698]'
+  ValueType: Real
+}
diff --git a/_Main/BL/Type_LocalCell_ProductionComparison/DefaultValue_BaseVersionValue.qbl b/_Main/BL/Type_LocalCell_OfflinePlanComparison/DefaultValue_BaseVersionValue.qbl
similarity index 100%
rename from _Main/BL/Type_LocalCell_ProductionComparison/DefaultValue_BaseVersionValue.qbl
rename to _Main/BL/Type_LocalCell_OfflinePlanComparison/DefaultValue_BaseVersionValue.qbl
diff --git a/_Main/BL/Type_LocalCell_ProductionComparison/DefaultValue_CompareVersionValue.qbl b/_Main/BL/Type_LocalCell_OfflinePlanComparison/DefaultValue_CompareVersionValue.qbl
similarity index 100%
rename from _Main/BL/Type_LocalCell_ProductionComparison/DefaultValue_CompareVersionValue.qbl
rename to _Main/BL/Type_LocalCell_OfflinePlanComparison/DefaultValue_CompareVersionValue.qbl
diff --git a/_Main/BL/Type_LocalCell_OfflinePlanComparison/Function_CalcGap.qbl b/_Main/BL/Type_LocalCell_OfflinePlanComparison/Function_CalcGap.qbl
new file mode 100644
index 0000000..90a8d2f
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_OfflinePlanComparison/Function_CalcGap.qbl
@@ -0,0 +1,13 @@
+Quintiq file version 2.0
+#parent: #root
+Function CalcGap
+{
+  TextBody:
+  [*
+    // rislai Jun-21-2024 (created)
+    
+    value := this.BaseVersion() - this.CompareVersion();
+    
+    this.Gap( value );
+  *]
+}
diff --git a/_Main/BL/Type_LocalCell_OfflinePlanComparison/Method_GetAttributeByName.qbl b/_Main/BL/Type_LocalCell_OfflinePlanComparison/Method_GetAttributeByName.qbl
new file mode 100644
index 0000000..f51ae7a
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_OfflinePlanComparison/Method_GetAttributeByName.qbl
@@ -0,0 +1,44 @@
+Quintiq file version 2.0
+#parent: #root
+Method GetAttributeByName (
+  String attributeName
+) const declarative as String
+{
+  TextBody:
+  [*
+    // rislai Jun-21-2024 (created)
+    value := "";
+    
+    if( attributeName = "BaseVersion" ){
+       if( not this.LocalColumn().IsAttrbuteColumn() ){
+         value := this.BaseVersion().Format( "N(Dec)" );
+       }
+    }
+    if( attributeName = "CompareVersion" ){
+      if( not this.LocalColumn().IsAttrbuteColumn() ){
+        value := this.CompareVersion().Format( "N(Dec)" );
+      }
+    }
+    if( attributeName = "Gap" ){
+      if( not this.LocalColumn().IsAttrbuteColumn() ){
+        value := this.Gap().Format( "N(Dec)" );
+      }
+    }
+    if( attributeName = "BaseVersionValue" ){
+      if( not this.LocalColumn().IsAttrbuteColumn() ){
+        value := "0";
+      }else{
+        value := this.BaseVersionValue();
+      }
+    }
+    if( attributeName = "CompareVersionValue" ){
+      if( not this.LocalColumn().IsAttrbuteColumn() ){
+        value := "0";
+      }else{
+        value := this.CompareVersionValue();
+      }
+    }
+    
+    return value;
+  *]
+}
diff --git a/_Main/BL/Type_LocalCell_OfflinePlanComparison/StaticMethod_AsyncExport.qbl b/_Main/BL/Type_LocalCell_OfflinePlanComparison/StaticMethod_AsyncExport.qbl
new file mode 100644
index 0000000..d19420b
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_OfflinePlanComparison/StaticMethod_AsyncExport.qbl
@@ -0,0 +1,32 @@
+Quintiq file version 2.0
+#parent: #root
+StaticMethod AsyncExport (
+  RecycleBin recycleBin,
+  const constcontent LocalRows rows,
+  const constcontent LocalColumns columns,
+  const MacroPlan macroPlan
+)
+{
+  TextBody:
+  [*
+    // rislai Jun-20-2024 (created)
+    sortColumns := selectsortedset( columns,Elements,column,true,column.Index());
+    
+    attributeNames := LocalCell_DemandComparison::GetAttributeNames();
+    
+    columnstring := emit( "" );
+    flag := true;
+    traverse( sortColumns,Elements,sortColumn ){
+      if( flag ){
+        attributeXML := rows -> LocalCell_DemandComparison::GetColumnXML( sortColumn,attributeNames,"attribute",macroPlan );
+        columnstring := columnstring.Merge( attributeXML )
+        flag := false;
+      }
+      
+      cellxml := rows -> LocalCell_DemandComparison::GetColumnXML( sortColumn,attributeNames ,"data",macroPlan );
+      columnstring := columnstring.Merge( cellxml);
+    }
+     
+    columnstring -> GroupAll() -> ExportXMLManager::AwaitLocalTableXMLData( recycleBin,guard( rows.Element(0).LocalTable().Name(),"Sheet1") );
+  *]
+}
diff --git a/_Main/BL/Type_LocalCell_OfflinePlanComparison/StaticMethod_Compared.qbl b/_Main/BL/Type_LocalCell_OfflinePlanComparison/StaticMethod_Compared.qbl
new file mode 100644
index 0000000..16f2c4d
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_OfflinePlanComparison/StaticMethod_Compared.qbl
@@ -0,0 +1,107 @@
+Quintiq file version 2.0
+#parent: #root
+StaticMethod Compared (
+  RecycleBin recycleBin,
+  const OfflinePlanTable baseOfflinePlan,
+  const OfflinePlanTable compareOfflinePlan
+) as LocalTable
+{
+  TextBody:
+  [*
+    // rislai Jun-20-2024 (created)
+    table := recycleBin.LocalTable( relnew,Name := "涓嬬嚎璁″垝鎶ヨ〃瀵规瘮");
+    
+    localColumns := construct( LocalColumns );
+    localColumnIndexTree := NamedValueTree::Create();
+    traverse( baseOfflinePlan,OfflinePlanColumn,column,column.ColumnDate() >=  baseOfflinePlan.MacroPlan().StartOfPlanning().Date()){
+      localColumnHandle := localColumnIndexTree.GetHandle( column.ColumnDate().AsQUILL() );
+      localColumnIndex := guard( localColumnIndexTree.Root().Child( localColumnHandle ),null( NamedValue ));
+      if( isnull( localColumnIndex )){
+        localColumn := table.LocalColumn( relnew,CustomDate := column.ColumnDate());
+        localColumns.Add( localColumn );
+        localColumnIndexTree.Root().AddChild( localColumnHandle,localColumns.Size() - 1 );
+      }
+    }
+    traverse( compareOfflinePlan,OfflinePlanColumn,column,column.ColumnDate() >=  compareOfflinePlan.MacroPlan().StartOfPlanning().Date()){
+      localColumnHandle := localColumnIndexTree.GetHandle( column.ColumnDate().AsQUILL() );
+      localColumnIndex := guard( localColumnIndexTree.Root().Child( localColumnHandle ),null( NamedValue ));
+      if( isnull( localColumnIndex )){
+        localColumn := table.LocalColumn( relnew,CustomDate := column.ColumnDate());
+        localColumns.Add( localColumn );
+        localColumnIndexTree.Root().AddChild( localColumnHandle,localColumns.Size() - 1 );
+      }
+    }
+    
+    baseOfflinePlanCells := construct( OfflinePlanCells, constcontent );
+    baseOfflinePlanCellIndexTree := NamedValueTree::Create();
+    compareOfflinePlanCells := construct( OfflinePlanCells, constcontent );
+    compareOfflinePlanCellIndexTree := NamedValueTree::Create();
+    
+    localRows := construct( LocalRows );
+    localRowIndexTree := NamedValueTree::Create();
+    
+    traverse( baseOfflinePlan,OfflinePlanRow,row,row.Type() = "1" ){
+      rowKey := row.ProductID() + "@$#" + row.ProductionLine()+ "@$#";
+      localRowHandle := localRowIndexTree.GetHandle( rowKey );
+      localRowIndex := guard( localRowIndexTree.Root().Child( localRowHandle ),null( NamedValue ));
+      if( isnull( localRowIndex )){
+        localRow := table.LocalRow( relnew,Index := table.GetRowIndexCache(),CustomName := row.ProductID(),Remark := rowKey );
+        localRows.Add( localRow );
+        localRowIndexTree.Root().AddChild( localRowHandle,localRows.Size() - 1 );
+      }
+      traverse( row,OfflinePlanCell,cell ){
+        columnKey := cell.OfflinePlanColumn().ColumnDate().AsQUILL();
+        cellKey := rowKey + columnKey;
+        cellHandle := baseOfflinePlanCellIndexTree.GetHandle( cellKey );
+        baseOfflinePlanCells.Add( cell );
+        baseOfflinePlanCellIndexTree.Root().AddChild( cellHandle,baseOfflinePlanCells.Size() - 1 );
+      }
+    }
+    traverse( compareOfflinePlan,OfflinePlanRow,row,row.Type() = "1" ){
+      rowKey := row.ProductID() + "@$#" + row.ProductionLine()+ "@$#";
+      localRowHandle := localRowIndexTree.GetHandle( rowKey );
+      localRowIndex := guard( localRowIndexTree.Root().Child( localRowHandle ),null( NamedValue ));
+      if( isnull( localRowIndex )){
+        localRow := table.LocalRow( relnew,Index := table.GetRowIndexCache(),CustomName := row.ProductID(),Remark := rowKey );
+        localRows.Add( localRow );
+        localRowIndexTree.Root().AddChild( localRowHandle,localRows.Size() - 1 );
+      }
+      traverse( row,OfflinePlanCell,cell ){
+        columnKey := cell.OfflinePlanColumn().ColumnDate().AsQUILL();
+        cellHandle := compareOfflinePlanCellIndexTree.GetHandle( rowKey + columnKey );
+        compareOfflinePlanCells.Add( cell );
+        compareOfflinePlanCellIndexTree.Root().AddChild( cellHandle,compareOfflinePlanCells.Size() - 1 );
+      }
+    }
+    
+    traverse( localRows,Elements,localRow ){
+      rowKey := localRow.Remark();
+      traverse( localColumns,Elements,localColumn ){
+        columnKey := localColumn.CustomDate().AsQUILL();
+        cellKey := rowKey + columnKey;
+        
+        baseOfflinePlanCell := constnull( OfflinePlanCell );
+        compareOfflinePlanCell := constnull( OfflinePlanCell );
+        baseOfflinePlanCellIndex := guard( baseOfflinePlanCellIndexTree.Root().Child( baseOfflinePlanCellIndexTree.GetHandle( cellKey ) ),null( NamedValue ));
+        compareOfflinePlanCellIndex := guard( compareOfflinePlanCellIndexTree.Root().Child( compareOfflinePlanCellIndexTree.GetHandle( cellKey ) ),null( NamedValue ));
+        if( not isnull( baseOfflinePlanCellIndex )){
+          baseOfflinePlanCell := baseOfflinePlanCells.Element( baseOfflinePlanCellIndex.GetValueAsNumber() ); 
+        }
+        if( not isnull( compareOfflinePlanCellIndex )){
+          compareOfflinePlanCell := compareOfflinePlanCells.Element( compareOfflinePlanCellIndex.GetValueAsNumber() ); 
+        }
+        
+        localRow.LocalCell( relnew,LocalCell_OfflinePlanComparison,LocalColumn := localColumn,
+                            BaseVersion := ifexpr( isnull( baseOfflinePlanCell),0.0,baseOfflinePlanCell.Quantity()),
+                            CompareVersion := ifexpr( isnull( compareOfflinePlanCell),0.0,compareOfflinePlanCell.Quantity()));
+      }
+    }
+    traverse( table,LocalColumn,column ){
+      if( column.LocalCell( relsize ) = 0 ){
+        column.Delete(); 
+      } 
+    }
+    
+    return table;
+  *]
+}
diff --git a/_Main/BL/Type_LocalCell_OfflinePlanComparison/StaticMethod_GetAttributeNames.qbl b/_Main/BL/Type_LocalCell_OfflinePlanComparison/StaticMethod_GetAttributeNames.qbl
new file mode 100644
index 0000000..1072935
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_OfflinePlanComparison/StaticMethod_GetAttributeNames.qbl
@@ -0,0 +1,16 @@
+Quintiq file version 2.0
+#parent: #root
+StaticMethod GetAttributeNames () const declarative as owning Strings
+{
+  TextBody:
+  [*
+    // rislai Jun-21-2024 (created)
+    attributeNames := construct( Strings );
+    
+    attributeNames.Add( "BaseVersion" );
+    attributeNames.Add( "CompareVersion" );
+    attributeNames.Add( "Gap" );
+    
+    return &attributeNames;
+  *]
+}
diff --git a/_Main/BL/Type_LocalCell_OfflinePlanComparison/StaticMethod_GetColumnXML.qbl b/_Main/BL/Type_LocalCell_OfflinePlanComparison/StaticMethod_GetColumnXML.qbl
new file mode 100644
index 0000000..6d45dc4
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_OfflinePlanComparison/StaticMethod_GetColumnXML.qbl
@@ -0,0 +1,97 @@
+Quintiq file version 2.0
+#parent: #root
+StaticMethod GetColumnXML (
+  const constcontent LocalRows rows,
+  const LocalColumn column,
+  const Strings attributeNames,
+  String type,
+  const MacroPlan macroPlan
+) const as String
+{
+  TextBody:
+  [*
+    // rislai Jun-21-2024 (created)
+    // rislai Jun-20-2024 (created)
+    columnXML := "";
+    cells := selectsortedset( column, LocalCell.astype( LocalCell_DemandComparison ), cell,
+                                  exists( rows,Elements,element,element = cell.LocalRow()), cell.LocalRow().Index());
+    if( type = "data" ){
+      columnXML := "";
+      if( column.IsAttrbuteColumn() ){
+        columnXML := "<column><name>" + column.Name() + "</name><type>String</type>"; 
+      }else{
+        columnXML := "<column><name>" + column.Name() + "</name><type>Number</type>"; 
+      }
+      traverse ( cells, Elements, cell ) {
+        traverse( attributeNames ,Elements,e ){
+          cellXML := '<cell value="' + cell.GetAttributeByName( e ) + '"/>'
+          columnXML := columnXML + cellXML;
+        }
+      }
+      columnXML := columnXML + "</column>";
+    }
+    if( type = "attribute" ){
+      columnXML0_1 := "<column><name>Sales Segment</name><type>String</type>";
+      columnXML0_2 := "<column><name>Generation</name><type>String</type>";
+      columnXML0_3 := "<column><name>MQB/MLB</name><type>String</type>";
+      columnXML0_4 := "<column><name>鍔熺巼</name><type>String</type>";
+      
+      columnXML1 := "<column><name>Product ID</name><type>String</type>";
+      columnXML2 := "<column><name>Attribute</name><type>String</type>";
+      
+      traverse ( cells, Elements, cell ) {
+        flag := true;
+        traverse( attributeNames ,Elements,e ){
+          if( flag ){
+            cellXML := '<cell value="' + cell.LocalRow().Name() + '"/>'
+            columnXML1 := columnXML1 + cellXML;
+            
+            salesSegment := select( cell.LocalRow().LocalTable(),LocalColumn.LocalCell.astype( LocalCell_DemandComparison ),temp_cell,temp_cell.LocalRow() = cell.LocalRow() and temp_cell.LocalColumn().Name() = "浜у湴");
+            if( not isnull( salesSegment )){
+              cellXML0_1 := '<cell value="' + ifexpr( salesSegment.BaseVersionValue() <> "绌�",salesSegment.BaseVersionValue(),salesSegment.CompareVersionValue()) + '"/>';
+              columnXML0_1 := columnXML0_1 + cellXML0_1;
+            }else{
+              cellXML0_1 := '<cell value="  "/>'
+              columnXML0_1 := columnXML0_1 + cellXML0_1;
+            }
+            
+            product := select( macroPlan,Product_MP,product,product.ID() = cell.LocalRow().Name() );
+            if( not isnull( product )){
+              cellXML0_2 := '<cell value="' + product.Generation() + '"/>';
+              cellXML0_3 := '<cell value="' + product.MQBMLB() + '"/>';
+              cellXML0_4 := '<cell value="' + product.Power() + '"/>';
+              columnXML0_2 := columnXML0_2 + cellXML0_2;
+              columnXML0_3 := columnXML0_3 + cellXML0_3;
+              columnXML0_4 := columnXML0_4 + cellXML0_4;
+            }else{
+              cellXML0_2 := '<cell value="  "/>';
+              cellXML0_3 := '<cell value="  "/>';
+              cellXML0_4 := '<cell value="  "/>';
+              columnXML0_2 := columnXML0_2 + cellXML0_2;
+              columnXML0_3 := columnXML0_3 + cellXML0_3;
+              columnXML0_4 := columnXML0_4 + cellXML0_4;
+            }
+            
+            flag := false;
+          }else{
+            cellXML := '<cell value="  "/>'
+            columnXML1 := columnXML1 + cellXML;
+            cellXML0_1 := '<cell value="  "/>'
+            cellXML0_2 := '<cell value="  "/>';
+            cellXML0_3 := '<cell value="  "/>';
+            cellXML0_4 := '<cell value="  "/>';
+            columnXML0_1 := columnXML0_1 + cellXML0_1;
+            columnXML0_2 := columnXML0_2 + cellXML0_2;
+            columnXML0_3 := columnXML0_3 + cellXML0_3;
+            columnXML0_4 := columnXML0_4 + cellXML0_4;
+          }
+          cellXML := '<cell value="' + e + '"/>'
+          columnXML2 := columnXML2 + cellXML;
+        }
+      }
+      columnXML := columnXML0_1 + "</column>" + columnXML0_2 + "</column>" + columnXML0_3 + "</column>" + columnXML0_4 + "</column>" + columnXML1 + "</column>" + columnXML2 + "</column>";
+    }
+     
+    return columnXML;
+  *]
+}
diff --git a/_Main/BL/Type_LocalCell_OfflinePlanComparison/_ROOT_Type_LocalCell_OfflinePlanComparison.qbl b/_Main/BL/Type_LocalCell_OfflinePlanComparison/_ROOT_Type_LocalCell_OfflinePlanComparison.qbl
new file mode 100644
index 0000000..d360987
--- /dev/null
+++ b/_Main/BL/Type_LocalCell_OfflinePlanComparison/_ROOT_Type_LocalCell_OfflinePlanComparison.qbl
@@ -0,0 +1,9 @@
+Quintiq file version 2.0
+#root
+#parent: #DomainModel
+TypeSpecialization LocalCell_OfflinePlanComparison
+{
+  #keys: '2[412672.1.76654683][412672.1.76654682]'
+  Parent: LocalCell
+  StructuredName: 'LocalCell_OfflinePlanComparisons'
+}
diff --git a/_Main/BL/Type_LocalCell_ProductionComparison/Attribute_BaseVersionValue.qbl b/_Main/BL/Type_LocalCell_ProductionComparison/Attribute_BaseVersionValue.qbl
deleted file mode 100644
index 7abefbe..0000000
--- a/_Main/BL/Type_LocalCell_ProductionComparison/Attribute_BaseVersionValue.qbl
+++ /dev/null
@@ -1,7 +0,0 @@
-Quintiq file version 2.0
-#parent: #root
-Attribute BaseVersionValue
-{
-  #keys: '3[412672.1.64753763][412672.1.64753762][412672.1.64753764]'
-  ValueType: String
-}
diff --git a/_Main/BL/Type_LocalCell_ProductionComparison/Attribute_CompareVersionValue.qbl b/_Main/BL/Type_LocalCell_ProductionComparison/Attribute_CompareVersionValue.qbl
deleted file mode 100644
index 8e0d3b4..0000000
--- a/_Main/BL/Type_LocalCell_ProductionComparison/Attribute_CompareVersionValue.qbl
+++ /dev/null
@@ -1,7 +0,0 @@
-Quintiq file version 2.0
-#parent: #root
-Attribute CompareVersionValue
-{
-  #keys: '3[412672.1.64753752][412672.1.64753751][412672.1.64753753]'
-  ValueType: String
-}
diff --git a/_Main/BL/Type_LocalCell_ProductionComparison/Method_GetAttributeByName.qbl b/_Main/BL/Type_LocalCell_ProductionComparison/Method_GetAttributeByName.qbl
index f235f04..28b4f37 100644
--- a/_Main/BL/Type_LocalCell_ProductionComparison/Method_GetAttributeByName.qbl
+++ b/_Main/BL/Type_LocalCell_ProductionComparison/Method_GetAttributeByName.qbl
@@ -9,12 +9,12 @@
     // rislai Jun-21-2024 (created)
     value := "";
     
-    if( attributeName = "BaseVersion" ){
+    if( attributeName = "Plan" ){
        if( not this.LocalColumn().IsAttrbuteColumn() ){
          value := this.Plan().Format( "N(Dec)" );
        }
     }
-    if( attributeName = "CompareVersion" ){
+    if( attributeName = "Actual" ){
       if( not this.LocalColumn().IsAttrbuteColumn() ){
         value := this.Actual().Format( "N(Dec)" );
       }
@@ -22,20 +22,6 @@
     if( attributeName = "Gap" ){
       if( not this.LocalColumn().IsAttrbuteColumn() ){
         value := this.Gap().Format( "N(Dec)" );
-      }
-    }
-    if( attributeName = "BaseVersionValue" ){
-      if( not this.LocalColumn().IsAttrbuteColumn() ){
-        value := "0";
-      }else{
-        value := this.BaseVersionValue();
-      }
-    }
-    if( attributeName = "CompareVersionValue" ){
-      if( not this.LocalColumn().IsAttrbuteColumn() ){
-        value := "0";
-      }else{
-        value := this.CompareVersionValue();
       }
     }
     
diff --git a/_Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_Compared.qbl b/_Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_Compared.qbl
deleted file mode 100644
index 3c0055a..0000000
--- a/_Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_Compared.qbl
+++ /dev/null
@@ -1,118 +0,0 @@
-Quintiq file version 2.0
-#parent: #root
-StaticMethod Compared (
-  RecycleBin recycleBin,
-  String baseVersionPath,
-  String compareVersionPath,
-  String baseVersionName,
-  String compareVersionName
-) as LocalTable
-{
-  TextBody:
-  [*
-    // rislai Jun-20-2024 (created)
-    localTable := recycleBin.LocalTable( relnew,Name := baseVersionName + "__" + compareVersionName );
-    
-    baseVersionFile := OSFile::Construct();
-    compareVersionFile := OSFile::Construct();
-    
-    try {
-      baseVersionFile.Open( baseVersionPath, "Read", false );
-      baseVersionDataSource := GeneralExcelImportAndExportDataSource::Upload( recycleBin, baseVersionFile.ReadBinary(), baseVersionPath );
-      baseVersionDataSource.ReadStructure();
-      
-      compareVersionFile.Open( compareVersionPath, "Read", false );
-      compareVersionDataSource := GeneralExcelImportAndExportDataSource::Upload( recycleBin, compareVersionFile.ReadBinary(), compareVersionPath );
-      compareVersionDataSource.ReadStructure();
-      
-      baseVersionTable := select( baseVersionDataSource, GeneralExcelImportAndExportDataTable, tempGEIAEDT, true );
-      compareVersionTable := select( compareVersionDataSource, GeneralExcelImportAndExportDataTable, tempGEIAEDT, true );
-      
-      if( not isnull( baseVersionTable ) and not isnull( compareVersionTable )){
-        
-        //鐢熸垚琛屾暟鎹�
-        rowKeys := construct( Strings );
-        baseVersionRowTree := NamedValueTree::Create();
-        baseVersionRows := construct( GeneralExcelImportAndExportDataRows ,constcontent);
-        compareVersionRowTree := NamedValueTree::Create();
-        compareVersionRows := construct( GeneralExcelImportAndExportDataRows ,constcontent);
-        LocalCell_DemandComparison::FillRows( baseVersionTable,rowKeys,baseVersionRowTree,baseVersionRows );
-        LocalCell_DemandComparison::FillRows( compareVersionTable,rowKeys,compareVersionRowTree,compareVersionRows );
-        
-        // 鐢熸垚鍒楁暟鎹�
-        columnTree := NamedValueTree::Create();
-        columns := construct( LocalColumns );
-        LocalCell_DemandComparison::GenerateColumnIndex( baseVersionTable,localTable,columnTree,columns );
-        LocalCell_DemandComparison::GenerateColumnIndex( compareVersionTable,localTable,columnTree,columns );
-        columnNames := selectvalues( columns,Elements,column,true,column.Name() );
-        
-        // 鐢熸垚鏁版嵁
-        
-        for ( rowIndex := 0; rowIndex < rowKeys.Size(); rowIndex++ ) {
-          rowKey := rowKeys.Element( rowIndex );
-          
-          baseVersionCellTree := NamedValueTree::Create();
-          baseVersionCells := construct( GeneralExcelImportAndExportDataCells ,constcontent);
-          
-          compareVersionCellTree := NamedValueTree::Create();
-          compareVersionCells := construct( GeneralExcelImportAndExportDataCells ,constcontent);
-          
-          LocalCell_DemandComparison::FillCells( rowKey,baseVersionRowTree,baseVersionRows,baseVersionCellTree,baseVersionCells );
-          LocalCell_DemandComparison::FillCells( rowKey,compareVersionRowTree,compareVersionRows,compareVersionCellTree,compareVersionCells );
-          
-          row := localTable.LocalRow( relnew,Index := localTable.GetRowIndexCache()  );
-          
-          traverse( columnNames,Elements,columnName ){
-            columnHandle := columnTree.GetHandle( columnName );
-            columnIndex := columnTree.Root().Child( columnHandle ).GetValueAsNumber();
-            column := columns.Element( columnIndex );
-            
-            baseVersionCell := constnull( GeneralExcelImportAndExportDataCell );
-            baseVersionCellHandle := baseVersionCellTree.GetHandle( columnName );
-            try{
-              baseVersionCellIndex := baseVersionCellTree.Root().Child( baseVersionCellHandle ).GetValueAsNumber();
-              baseVersionCell := baseVersionCells.Element( baseVersionCellIndex );
-            }onerror{}
-            
-            compareVersionCell := constnull( GeneralExcelImportAndExportDataCell );
-            compareVersionCellHandle := compareVersionCellTree.GetHandle( columnName );
-            try{
-              compareVersionCellIndex := compareVersionCellTree.Root().Child( compareVersionCellHandle ).GetValueAsNumber();
-              compareVersionCell := compareVersionCells.Element( compareVersionCellIndex );
-            }onerror{}
-            
-            if( columnName = "浜у湴" or columnName = "杞﹀瀷" or columnName = "鍙戝姩鏈洪浂浠跺彿" or columnName = "鍙戝姩鏈哄洓浣嶇爜" ){
-              row.LocalCell( relnew,LocalCell_DemandComparison,LocalColumn := column,
-                             BaseVersionValue := ifexpr( isnull( baseVersionCell ), "绌�", baseVersionCell.Value()),
-                             CompareVersionValue := ifexpr( isnull( compareVersionCell ),"绌�",compareVersionCell.Value()));
-              column.IsAttrbuteColumn( true );
-              if( columnName = "鍙戝姩鏈洪浂浠跺彿" ){
-                row.CustomName( ifexpr( isnull( baseVersionCell ), ifexpr( isnull( compareVersionCell ),"绌�",compareVersionCell.Value()), baseVersionCell.Value()) );
-              }
-            }else{
-              row.LocalCell( relnew,LocalCell_DemandComparison,LocalColumn := column,
-                             BaseVersion := ifexpr( isnull( baseVersionCell ),0,[Real]baseVersionCell.Value()),
-                             CompareVersion := ifexpr( isnull( compareVersionCell ), 0 ,[Real]compareVersionCell.Value() ));
-            }
-          }
-        }
-      }
-      // 鍚庣画鍒犻櫎
-      baseVersionDataSource.Delete();
-      compareVersionDataSource.Delete();
-      
-      baseVersionFile.Close();
-      compareVersionFile.Close();
-    } onerror {
-      if( not isnull( baseVersionFile )){
-        baseVersionFile.Close(); 
-      }
-      if( not isnull( compareVersionFile )){
-        compareVersionFile.Close(); 
-      }
-      error( e );
-    }
-    
-    return localTable;
-  *]
-}
diff --git a/_Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_FillCells.qbl b/_Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_FillCells.qbl
deleted file mode 100644
index 6aeded1..0000000
--- a/_Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_FillCells.qbl
+++ /dev/null
@@ -1,30 +0,0 @@
-Quintiq file version 2.0
-#parent: #root
-StaticMethod FillCells (
-  String rowName,
-  NamedValueTree rowTree,
-  constcontent GeneralExcelImportAndExportDataRows rows,
-  NamedValueTree cellTree,
-  constcontent GeneralExcelImportAndExportDataCells cells
-)
-{
-  TextBody:
-  [*
-    // rislai Jun-22-2024 (created)
-    rowHandel := rowTree.GetHandle( rowName );
-    try{
-      rowIndex := rowTree.Root().Child( rowHandel ).GetValueAsNumber();
-      row := rows.Element( rowIndex );
-      
-      temp_cells := selectsortedset( row,GeneralExcelImportAndExportDataCell,cell,true,cell.GeneralExcelImportAndExportDataColumn().ColumnIndex() );
-      for( i := 0 ; i<temp_cells.Size();i++ ){
-        cell := temp_cells.Element( i );
-        tempHandle := cellTree.GetHandle( cell.GeneralExcelImportAndExportDataColumn().Name() );
-        
-        cells.Add( cell );
-        cellTree.Root().AddChild( tempHandle,cells.Size() - 1 );
-        
-      }
-    }onerror{}
-  *]
-}
diff --git a/_Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_FillRows.qbl b/_Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_FillRows.qbl
deleted file mode 100644
index 391100a..0000000
--- a/_Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_FillRows.qbl
+++ /dev/null
@@ -1,36 +0,0 @@
-Quintiq file version 2.0
-#parent: #root
-StaticMethod FillRows (
-  const GeneralExcelImportAndExportDataTable general,
-  Strings rowKeys,
-  NamedValueTree rowTree,
-  constcontent GeneralExcelImportAndExportDataRows rows
-)
-{
-  TextBody:
-  [*
-    // rislai Jun-22-2024 (created)
-    rowKeyColumn1 := select( general, GeneralExcelImportAndExportDataColumn, column, column.Name() = "浜у湴" );
-    rowKeyColumn2 := select( general, GeneralExcelImportAndExportDataColumn, column, column.Name() = "杞﹀瀷" );
-    rowKeyColumn3 := select( general, GeneralExcelImportAndExportDataColumn, column, column.Name() = "鍙戝姩鏈洪浂浠跺彿" );
-    rowKeyColumn4 := select( general, GeneralExcelImportAndExportDataColumn, column, column.Name() = "鍙戝姩鏈哄洓浣嶇爜" );
-    tempRowKeyCells1 := selectset( rowKeyColumn1,GeneralExcelImportAndExportDataCell,cell,true );
-    tempRowKeyCells2 := selectset( rowKeyColumn2,GeneralExcelImportAndExportDataCell,cell,true );
-    tempRowKeyCells3 := selectset( rowKeyColumn3,GeneralExcelImportAndExportDataCell,cell,true );
-    tempRowKeyCells4 := selectset( rowKeyColumn4,GeneralExcelImportAndExportDataCell,cell,true );
-    
-    for( i := 0; i< tempRowKeyCells1.Size(); i++ ){
-      tempRowKeyCell1 := tempRowKeyCells1.Element( i );
-      tempRowKeyCell2 := tempRowKeyCells2.Element( i );
-      tempRowKeyCell3 := tempRowKeyCells3.Element( i );
-      tempRowKeyCell4 := tempRowKeyCells4.Element( i );
-      
-      rowKey := tempRowKeyCell1.Value() + tempRowKeyCell2.Value() + tempRowKeyCell3.Value() + tempRowKeyCell4.Value();
-      
-      tempHandle := rowTree.GetHandle( rowKey );
-      rowTree.Root().AddChild( tempHandle ,i);
-      rows.Add( tempRowKeyCell1.GeneralExcelImportAndExportDataRow());
-      rowKeys.Add( rowKey );
-    }
-  *]
-}
diff --git a/_Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_GenerateColumnIndex.qbl b/_Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_GenerateColumnIndex.qbl
deleted file mode 100644
index 44609af..0000000
--- a/_Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_GenerateColumnIndex.qbl
+++ /dev/null
@@ -1,39 +0,0 @@
-Quintiq file version 2.0
-#parent: #root
-StaticMethod GenerateColumnIndex (
-  const GeneralExcelImportAndExportDataTable table,
-  LocalTable localTable,
-  NamedValueTree columnTree,
-  LocalColumns columns
-)
-{
-  TextBody:
-  [*
-    // rislai Jun-22-2024 (created)
-    tableColumns := selectset( table,GeneralExcelImportAndExportDataColumn,column,true );
-    for( i := 0; i< tableColumns.Size(); i++ ){
-      generalColumn := tableColumns.Element( i );
-      tempHandle := columnTree.GetHandle( generalColumn.Name() );
-    
-      nameValue := guard( columnTree.Root().Child( tempHandle ),null( NamedValue )); 
-      if( isnull( nameValue )){
-        index := 999;
-        if( generalColumn.Name() = "浜у湴" ){
-          index := 1;
-        }else if( generalColumn.Name() = "杞﹀瀷" ){
-          index := 2;
-        }else if( generalColumn.Name() = "鍙戝姩鏈洪浂浠跺彿" ){
-          index := 3;
-        }else if( generalColumn.Name() = "鍙戝姩鏈哄洓浣嶇爜" ){
-          index := 4;
-        }else{
-          // 2023/01/01
-          index := [Number]generalColumn.Name().ReplaceAll( "/", "" );
-        }
-        column := localTable.LocalColumn( relnew, Name := generalColumn.Name(),CustomIndex := index );
-        columns.Add( column );
-        columnTree.Root().AddChild( tempHandle,columns.Size() - 1 );
-      }
-    }
-  *]
-}
diff --git a/_Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_GetAttributeNames.qbl b/_Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_GetAttributeNames.qbl
index 1072935..bc72bc4 100644
--- a/_Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_GetAttributeNames.qbl
+++ b/_Main/BL/Type_LocalCell_ProductionComparison/StaticMethod_GetAttributeNames.qbl
@@ -7,8 +7,8 @@
     // rislai Jun-21-2024 (created)
     attributeNames := construct( Strings );
     
-    attributeNames.Add( "BaseVersion" );
-    attributeNames.Add( "CompareVersion" );
+    attributeNames.Add( "Actual" );
+    attributeNames.Add( "Plan" );
     attributeNames.Add( "Gap" );
     
     return &attributeNames;
diff --git a/_Main/BL/Type_LocalRow/Attribute_Remark.qbl b/_Main/BL/Type_LocalRow/Attribute_Remark.qbl
new file mode 100644
index 0000000..ccc01d0
--- /dev/null
+++ b/_Main/BL/Type_LocalRow/Attribute_Remark.qbl
@@ -0,0 +1,7 @@
+Quintiq file version 2.0
+#parent: #root
+Attribute Remark
+{
+  #keys: '3[412672.1.76649345][412672.1.76649344][412672.1.76649346]'
+  ValueType: String
+}
diff --git a/_Main/BL/Type_TemplateManager/StaticMethod_GetCurveTemplate.qbl b/_Main/BL/Type_TemplateManager/StaticMethod_GetCurveTemplate.qbl
index 2be5530..3d88d7f 100644
--- a/_Main/BL/Type_TemplateManager/StaticMethod_GetCurveTemplate.qbl
+++ b/_Main/BL/Type_TemplateManager/StaticMethod_GetCurveTemplate.qbl
@@ -23,84 +23,84 @@
     }
     xmlTemplate := xmlTemplate + "</column>";
     
-    xmlTemplate := xmlTemplate + "<column><name>AUDI B9 PA</name><type>Number</type>";
+    xmlTemplate := xmlTemplate + "<column><name>AUDI B9 PA</name><type>String</type>";
     for( i := 0; i < totalDate ; i++ ){
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      xmlTemplate := xmlTemplate + '<cell value=""/>';
     }
     xmlTemplate := xmlTemplate + "</column>";
-    xmlTemplate := xmlTemplate + "<column><name>AUDI C8</name><type>Number</type>";
+    xmlTemplate := xmlTemplate + "<column><name>AUDI C8</name><type>String</type>";
     for( i := 0; i < totalDate ; i++ ){
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      xmlTemplate := xmlTemplate + '<cell value=""/>';
     }
     xmlTemplate := xmlTemplate + "</column>";
-    xmlTemplate := xmlTemplate + "<column><name>Q5 Derivat</name><type>Number</type>";
+    xmlTemplate := xmlTemplate + "<column><name>Q5 Derivat</name><type>String</type>";
     for( i := 0; i < totalDate ; i++ ){
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      xmlTemplate := xmlTemplate + '<cell value=""/>';
     }
     xmlTemplate := xmlTemplate + "</column>";
-    xmlTemplate := xmlTemplate + "<column><name>Q5 NF PA</name><type>Number</type>";
+    xmlTemplate := xmlTemplate + "<column><name>Q5 NF PA</name><type>String</type>";
     for( i := 0; i < totalDate ; i++ ){
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      xmlTemplate := xmlTemplate + '<cell value=""/>';
     }
     xmlTemplate := xmlTemplate + "</column>";
-    xmlTemplate := xmlTemplate + "<column><name>Magotan B8L FL</name><type>Number</type>";
+    xmlTemplate := xmlTemplate + "<column><name>Magotan B8L FL</name><type>String</type>";
     for( i := 0; i < totalDate ; i++ ){
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      xmlTemplate := xmlTemplate + '<cell value=""/>';
     }
     xmlTemplate := xmlTemplate + "</column>";
-    xmlTemplate := xmlTemplate + "<column><name>Magotan B9</name><type>Number</type>";
+    xmlTemplate := xmlTemplate + "<column><name>Magotan B9</name><type>String</type>";
     for( i := 0; i < totalDate ; i++ ){
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      xmlTemplate := xmlTemplate + '<cell value=""/>';
     }
     xmlTemplate := xmlTemplate + "</column>";
-    xmlTemplate := xmlTemplate + "<column><name>CC FB PA</name><type>Number</type>";
+    xmlTemplate := xmlTemplate + "<column><name>CC FB PA</name><type>String</type>";
     for( i := 0; i < totalDate ; i++ ){
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      xmlTemplate := xmlTemplate + '<cell value=""/>';
     }
     xmlTemplate := xmlTemplate + "</column>";
-    xmlTemplate := xmlTemplate + "<column><name>CC ShBr</name><type>Number</type>";
+    xmlTemplate := xmlTemplate + "<column><name>CC ShBr</name><type>String</type>";
     for( i := 0; i < totalDate ; i++ ){
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      xmlTemplate := xmlTemplate + '<cell value=""/>';
     }
     xmlTemplate := xmlTemplate + "</column>";
-    xmlTemplate := xmlTemplate + "<column><name>B-SMV</name><type>Number</type>";
+    xmlTemplate := xmlTemplate + "<column><name>B-SMV</name><type>String</type>";
     for( i := 0; i < totalDate ; i++ ){
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      xmlTemplate := xmlTemplate + '<cell value=""/>';
     }
     xmlTemplate := xmlTemplate + "</column>";
-    xmlTemplate := xmlTemplate + "<column><name>B-Main SUV</name><type>Number</type>";
+    xmlTemplate := xmlTemplate + "<column><name>B-Main SUV</name><type>String</type>";
     for( i := 0; i < totalDate ; i++ ){
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      xmlTemplate := xmlTemplate + '<cell value=""/>';
     }
     xmlTemplate := xmlTemplate + "</column>";
-    xmlTemplate := xmlTemplate + "<column><name>Tayron PA</name><type>Number</type>";
+    xmlTemplate := xmlTemplate + "<column><name>Tayron PA</name><type>String</type>";
     for( i := 0; i < totalDate ; i++ ){
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      xmlTemplate := xmlTemplate + '<cell value=""/>';
     }
     xmlTemplate := xmlTemplate + "</column>";
-    xmlTemplate := xmlTemplate + "<column><name>Tayron NF</name><type>Number</type>";
+    xmlTemplate := xmlTemplate + "<column><name>Tayron NF</name><type>String</type>";
     for( i := 0; i < totalDate ; i++ ){
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      xmlTemplate := xmlTemplate + '<cell value=""/>';
     }
     xmlTemplate := xmlTemplate + "</column>";
-    xmlTemplate := xmlTemplate + "<column><name>Tayron X PA</name><type>Number</type>";
+    xmlTemplate := xmlTemplate + "<column><name>Tayron X PA</name><type>String</type>";
     for( i := 0; i < totalDate ; i++ ){
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      xmlTemplate := xmlTemplate + '<cell value=""/>';
     }
     xmlTemplate := xmlTemplate + "</column>";
-    xmlTemplate := xmlTemplate + "<column><name>Tayron GTE</name><type>Number</type>";
+    xmlTemplate := xmlTemplate + "<column><name>Tayron GTE</name><type>String</type>";
     for( i := 0; i < totalDate ; i++ ){
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      xmlTemplate := xmlTemplate + '<cell value=""/>';
     }
     xmlTemplate := xmlTemplate + "</column>";
-    xmlTemplate := xmlTemplate + "<column><name>Q3 NF</name><type>Number</type>";
+    xmlTemplate := xmlTemplate + "<column><name>Q3 NF</name><type>String</type>";
     for( i := 0; i < totalDate ; i++ ){
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      xmlTemplate := xmlTemplate + '<cell value=""/>';
     }
     xmlTemplate := xmlTemplate + "</column>";
-    xmlTemplate := xmlTemplate + "<column><name>Q3 Derivat</name><type>Number</type>";
+    xmlTemplate := xmlTemplate + "<column><name>Q3 Derivat</name><type>String</type>";
     for( i := 0; i < totalDate ; i++ ){
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      xmlTemplate := xmlTemplate + '<cell value=""/>';
     }
     xmlTemplate := xmlTemplate + "</column>";
     
diff --git a/_Main/BL/Type_TemplateManager/StaticMethod_GetIDSTemplate.qbl b/_Main/BL/Type_TemplateManager/StaticMethod_GetIDSTemplate.qbl
index 4616fe0..3c57d48 100644
--- a/_Main/BL/Type_TemplateManager/StaticMethod_GetIDSTemplate.qbl
+++ b/_Main/BL/Type_TemplateManager/StaticMethod_GetIDSTemplate.qbl
@@ -14,22 +14,22 @@
     xmlTemplate := '<?xml version="1.0" encoding="UTF-16"?><table><name>'+ sheetName +'</name>';
     
     xmlTemplate := xmlTemplate + "<column><name>浜у湴</name><type>String</type>";
-    xmlTemplate := xmlTemplate + '<cell value="闀挎槬"/>';
+    // xmlTemplate := xmlTemplate + '<cell value=""/>';
     xmlTemplate := xmlTemplate + "</column>";
     
     xmlTemplate := xmlTemplate + "<column><name>杞﹀瀷</name><type>String</type>";
-    xmlTemplate := xmlTemplate + '<cell value="30C"/>';
+    // xmlTemplate := xmlTemplate + '<cell value=""/>';
     xmlTemplate := xmlTemplate + "</column>";
     
     xmlTemplate := xmlTemplate + "<column><name>鍙戝姩鏈哄彿</name><type>String</type>";
-    xmlTemplate := xmlTemplate + '<cell value="06S 100 010 N"/>';
+    // xmlTemplate := xmlTemplate + '<cell value=""/>';
     xmlTemplate := xmlTemplate + "</column>";
     
     actualDate := Date::ActualDate();
     
     for( i := 0 ; i < dateNumber ; i++ ){
       xmlTemplate := xmlTemplate + "<column><name>" + (actualDate + i).Format( "Y/M/D" ) + "</name><type>Number</type>";
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      // xmlTemplate := xmlTemplate + '<cell value=""/>';
       xmlTemplate := xmlTemplate + "</column>";
     }
     
diff --git a/_Main/BL/Type_TemplateManager/StaticMethod_GetPPATemplate.qbl b/_Main/BL/Type_TemplateManager/StaticMethod_GetPPATemplate.qbl
index d6a6a66..1aba0e9 100644
--- a/_Main/BL/Type_TemplateManager/StaticMethod_GetPPATemplate.qbl
+++ b/_Main/BL/Type_TemplateManager/StaticMethod_GetPPATemplate.qbl
@@ -11,14 +11,14 @@
     
     xmlTemplate := xmlTemplate + "<column><name>鍏綅鐮�</name><type>String</type>";
     
-    xmlTemplate := xmlTemplate + '<cell value="86LC2G"/>';
+    // xmlTemplate := xmlTemplate + '<cell value=" "/>';
     xmlTemplate := xmlTemplate + "</column>";
     
     actualDate := Date::ActualDate();
     
     for( i := 1 ; i <= 12 ; i++ ){
       xmlTemplate := xmlTemplate + "<column><name>" + Date::Construct( actualDate.Year(),i,1 ).Format( "Y/M/D" ) + "</name><type>Number</type>";
-      xmlTemplate := xmlTemplate + '<cell value="0"/>';
+      // xmlTemplate := xmlTemplate + '<cell value=" "/>';
       xmlTemplate := xmlTemplate + "</column>";
     }
     

--
Gitblit v1.9.3