IDEMPIERE-5057 Implement Deductible and non deductible input tax for purchasing and costing (#1277)
* IDEMPIERE-5057 Implement Deductible and non deductible input tax for purchasing and costing * IDEMPIERE-5057 Implement Deductible and non deductible input tax for purchasing and costing * IDEMPIERE-5057 Implement Deductible and non deductible input tax for purchasing and costing - Fix rounding error
This commit is contained in:
parent
cfb4ebe785
commit
a41aeb2205
|
@ -0,0 +1,89 @@
|
|||
SELECT register_migration_script('202203290700_IDEMPIERE-5057.sql') FROM dual
|
||||
;
|
||||
|
||||
SET SQLBLANKLINES ON
|
||||
SET DEFINE OFF
|
||||
|
||||
-- Mar 28, 2022 3:27:22 PM MYT
|
||||
-- IDEMPIERE-5057 Implement Deductible and non deductible input tax for purchasing and costing
|
||||
INSERT INTO AD_Element (AD_Element_ID,ColumnName,Updated,Name,PrintName,AD_Element_UU,IsActive,Created,CreatedBy,UpdatedBy,AD_Client_ID,EntityType,AD_Org_ID) VALUES (203283,'TaxPostingIndicator',TO_DATE('2022-03-28 15:27:21','YYYY-MM-DD HH24:MI:SS'),'Posting Indicator','Posting Indicator','6de750b3-2872-44ba-a78b-94fa6af96acf','Y',TO_DATE('2022-03-28 15:27:21','YYYY-MM-DD HH24:MI:SS'),100,100,0,'D',0)
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:32:00 PM MYT
|
||||
INSERT INTO AD_Reference (AD_Reference_ID,Name,AD_Reference_UU,IsOrderByValue,ValidationType,Updated,IsActive,CreatedBy,UpdatedBy,AD_Client_ID,Created,EntityType,AD_Org_ID) VALUES (200160,'C_Tax Posting Indicator','429065e5-80c4-458e-a7ae-d20761dcb5a8','N','L',TO_DATE('2022-03-28 15:31:59','YYYY-MM-DD HH24:MI:SS'),'Y',100,100,0,TO_DATE('2022-03-28 15:31:59','YYYY-MM-DD HH24:MI:SS'),'D',0)
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:35:42 PM MYT
|
||||
INSERT INTO AD_Ref_List (AD_Ref_List_ID,Description,AD_Ref_List_UU,Name,IsActive,CreatedBy,UpdatedBy,AD_Client_ID,Created,Updated,EntityType,AD_Reference_ID,Value,AD_Org_ID) VALUES (200446,'Tax is calculated on the full amount of the item and posted separately.','e84b618c-a8b3-47cf-89a6-dd674e52d3e4','Separate Tax Posting','Y',100,100,0,TO_DATE('2022-03-28 15:35:41','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2022-03-28 15:35:41','YYYY-MM-DD HH24:MI:SS'),'D',200160,'0',0)
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:37:59 PM MYT
|
||||
INSERT INTO AD_Ref_List (AD_Ref_List_ID,Description,AD_Ref_List_UU,Name,IsActive,CreatedBy,UpdatedBy,AD_Client_ID,Created,Updated,EntityType,AD_Reference_ID,Value,AD_Org_ID) VALUES (200447,'Tax amount is added to the item amount during account posting time and for updating of Product Cost.','3e8e0d29-29ac-4c67-ae2c-92c0ee43d2e6','Distribute Tax with Relevant Expense','Y',100,100,0,TO_DATE('2022-03-28 15:37:58','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2022-03-28 15:37:58','YYYY-MM-DD HH24:MI:SS'),'D',200160,'1',0)
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:38:05 PM MYT
|
||||
UPDATE AD_Reference SET IsOrderByValue='Y',Updated=TO_DATE('2022-03-28 15:38:05','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Reference_ID=200160
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:42:45 PM MYT
|
||||
INSERT INTO AD_Column (AD_Column_ID,SeqNoSelection,IsSyncDatabase,Version,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsParent,FieldLength,IsSelectionColumn,IsKey,ReadOnlyLogic,IsAutocomplete,IsAllowLogging,MandatoryLogic,AD_Column_UU,Updated,IsUpdateable,ColumnName,DefaultValue,Name,IsAllowCopy,IsActive,CreatedBy,UpdatedBy,IsAlwaysUpdateable,AD_Client_ID,Created,EntityType,IsEncrypted,IsSecure,FKConstraintType,AD_Element_ID,AD_Reference_Value_ID,AD_Table_ID,AD_Reference_ID,IsToolbarButton,AD_Org_ID,IsHtml) VALUES (213805,0,'N',0,'N','N','N',0,'N',1,'N','N','@IsSummary@=Y','N','Y','@IsSummary@=N','e7a97d28-f550-4253-a77b-b6fab1e7b38a',TO_DATE('2022-03-28 15:42:44','YYYY-MM-DD HH24:MI:SS'),'Y','TaxPostingIndicator','0','Posting Indicator','Y','Y',100,100,'N',0,TO_DATE('2022-03-28 15:42:44','YYYY-MM-DD HH24:MI:SS'),'D','N','N','N',203283,200160,261,17,'N',0,'N')
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:42:52 PM MYT
|
||||
INSERT INTO AD_TreeNode (AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, AD_Tree_ID, Node_ID, Parent_ID, SeqNo, AD_TreeNode_UU) SELECT t.AD_Client_ID, 0, 'Y', SysDate, 100, SysDate, 100,t.AD_Tree_ID, 200012, 0, 999, Generate_UUID() FROM AD_Tree t WHERE t.AD_Client_ID=0 AND t.IsActive='Y' AND t.IsAllNodes='Y' AND t.TreeType='TL' AND t.AD_Table_ID=282 AND NOT EXISTS (SELECT * FROM AD_TreeNode e WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=200012)
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:42:53 PM MYT
|
||||
ALTER TABLE C_Tax ADD TaxPostingIndicator CHAR(1) DEFAULT '0'
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:55:05 PM MYT
|
||||
INSERT INTO AD_Field (SortNo,AD_Field_ID,IsEncrypted,DisplayLength,IsSameLine,IsHeading,SeqNo,IsCentrallyMaintained,IsReadOnly,DisplayLogic,Updated,Name,AD_Field_UU,IsDisplayed,IsFieldOnly,CreatedBy,UpdatedBy,IsActive,IsDisplayedGrid,SeqNoGrid,XPosition,IsQuickEntry,AD_Client_ID,Created,ColumnSpan,NumLines,IsAdvancedField,IsDefaultFocus,AD_Column_ID,EntityType,AD_Tab_ID,AD_Org_ID) VALUES (0,205862,'N',0,'N','N',1010,'Y','N','@IsDocumentLevel@=N',TO_DATE('2022-03-28 15:55:04','YYYY-MM-DD HH24:MI:SS'),'Posting Indicator','96a2af5a-4a6f-4d44-ab54-da4713d70fc5','Y','N',100,100,'Y','Y',1010,4,'N',0,TO_DATE('2022-03-28 15:55:04','YYYY-MM-DD HH24:MI:SS'),2,1,'N','N',213805,'D',174,0)
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:55:33 PM MYT
|
||||
UPDATE AD_Field SET SeqNo=180,SeqNoGrid=180,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=205862
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:55:33 PM MYT
|
||||
UPDATE AD_Field SET SeqNo=190,SeqNoGrid=190,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=203325
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:55:33 PM MYT
|
||||
UPDATE AD_Field SET SeqNo=200,SeqNoGrid=200,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=203326
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:55:33 PM MYT
|
||||
UPDATE AD_Field SET SeqNo=210,SeqNoGrid=210,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=974
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:55:33 PM MYT
|
||||
UPDATE AD_Field SET SeqNo=220,SeqNoGrid=220,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=976
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:55:33 PM MYT
|
||||
UPDATE AD_Field SET SeqNo=230,SeqNoGrid=230,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=975
|
||||
;
|
||||
|
||||
UPDATE AD_Field SET SeqNo=240,SeqNoGrid=240,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=977
|
||||
;
|
||||
|
||||
UPDATE AD_Field SET SeqNo=250,SeqNoGrid=250,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=202402
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:56:15 PM MYT
|
||||
UPDATE AD_Column SET ReadOnlyLogic='@IsDocumentLevel@=Y', MandatoryLogic='@IsDocumentLevel@=N',Updated=TO_DATE('2022-03-28 15:56:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=213805
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 6:43:36 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@IsDocumentLevel@=N & @IsSummary@=N', AD_Val_Rule_ID=NULL, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2022-03-28 18:43:36','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=205862
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 8:10:21 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@IsDocumentLevel@=N & @IsSummary@=N & @SOPOType@!S', AD_Val_Rule_ID=NULL, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2022-03-28 20:10:21','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=205862
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 8:10:34 PM MYT
|
||||
INSERT INTO AD_TreeNode (AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, AD_Tree_ID, Node_ID, Parent_ID, SeqNo, AD_TreeNode_UU) SELECT t.AD_Client_ID, 0, 'Y', SysDate, 100, SysDate, 100,t.AD_Tree_ID, 200014, 0, 999, Generate_UUID() FROM AD_Tree t WHERE t.AD_Client_ID=0 AND t.IsActive='Y' AND t.IsAllNodes='Y' AND t.TreeType='TL' AND t.AD_Table_ID=282 AND NOT EXISTS (SELECT * FROM AD_TreeNode e WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=200014)
|
||||
;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
-- IDEMPIERE-5057 Implement Deductible and non deductible input tax for purchasing and costing
|
||||
SELECT register_migration_script('202204011738_IDEMPIERE-5057.sql') FROM dual;
|
||||
|
||||
SET SQLBLANKLINES ON
|
||||
SET DEFINE OFF
|
||||
|
||||
-- Apr 1, 2022, 5:38:03 PM MYT
|
||||
UPDATE AD_Element SET Description='Type of input tax (deductible and non deductible)', Help='Separate Tax Posting: Tax is calculated on the full amount of the item and posted separately.
|
||||
Distribute Tax with Relevant Expense: Tax amount is added to the item amount during account posting time and for updating of Product Cost.',Updated=TO_TIMESTAMP('2022-04-01 17:38:03','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Element_ID=203283
|
||||
;
|
||||
|
||||
-- Apr 1, 2022, 5:38:03 PM MYT
|
||||
UPDATE AD_Column SET ColumnName='TaxPostingIndicator', Name='Posting Indicator', Description='Type of input tax (deductible and non deductible)', Help='Separate Tax Posting: Tax is calculated on the full amount of the item and posted separately.
|
||||
Distribute Tax with Relevant Expense: Tax amount is added to the item amount during account posting time and for updating of Product Cost.', Placeholder=NULL WHERE AD_Element_ID=203283
|
||||
;
|
||||
|
||||
-- Apr 1, 2022, 5:38:03 PM MYT
|
||||
UPDATE AD_Process_Para SET ColumnName='TaxPostingIndicator', Name='Posting Indicator', Description='Type of input tax (deductible and non deductible)', Help='Separate Tax Posting: Tax is calculated on the full amount of the item and posted separately.
|
||||
Distribute Tax with Relevant Expense: Tax amount is added to the item amount during account posting time and for updating of Product Cost.', AD_Element_ID=203283 WHERE UPPER(ColumnName)='TAXPOSTINGINDICATOR' AND IsCentrallyMaintained='Y' AND AD_Element_ID IS NULL
|
||||
;
|
||||
|
||||
-- Apr 1, 2022, 5:38:03 PM MYT
|
||||
UPDATE AD_Process_Para SET ColumnName='TaxPostingIndicator', Name='Posting Indicator', Description='Type of input tax (deductible and non deductible)', Help='Separate Tax Posting: Tax is calculated on the full amount of the item and posted separately.
|
||||
Distribute Tax with Relevant Expense: Tax amount is added to the item amount during account posting time and for updating of Product Cost.', Placeholder=NULL WHERE AD_Element_ID=203283 AND IsCentrallyMaintained='Y'
|
||||
;
|
||||
|
||||
-- Apr 1, 2022, 5:38:03 PM MYT
|
||||
UPDATE AD_InfoColumn SET ColumnName='TaxPostingIndicator', Name='Posting Indicator', Description='Type of input tax (deductible and non deductible)', Help='Separate Tax Posting: Tax is calculated on the full amount of the item and posted separately.
|
||||
Distribute Tax with Relevant Expense: Tax amount is added to the item amount during account posting time and for updating of Product Cost.', Placeholder=NULL WHERE AD_Element_ID=203283 AND IsCentrallyMaintained='Y'
|
||||
;
|
||||
|
||||
-- Apr 1, 2022, 5:38:03 PM MYT
|
||||
UPDATE AD_Field SET Name='Posting Indicator', Description='Type of input tax (deductible and non deductible)', Help='Separate Tax Posting: Tax is calculated on the full amount of the item and posted separately.
|
||||
Distribute Tax with Relevant Expense: Tax amount is added to the item amount during account posting time and for updating of Product Cost.', Placeholder=NULL WHERE AD_Column_ID IN (SELECT AD_Column_ID FROM AD_Column WHERE AD_Element_ID=203283) AND IsCentrallyMaintained='Y'
|
||||
;
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
SELECT register_migration_script('202203290700_IDEMPIERE-5057.sql') FROM dual
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:27:22 PM MYT
|
||||
-- IDEMPIERE-5057 Implement Deductible and non deductible input tax for purchasing and costing
|
||||
INSERT INTO AD_Element (AD_Element_ID,ColumnName,Updated,Name,PrintName,AD_Element_UU,IsActive,Created,CreatedBy,UpdatedBy,AD_Client_ID,EntityType,AD_Org_ID) VALUES (203283,'TaxPostingIndicator',TO_TIMESTAMP('2022-03-28 15:27:21','YYYY-MM-DD HH24:MI:SS'),'Posting Indicator','Posting Indicator','6de750b3-2872-44ba-a78b-94fa6af96acf','Y',TO_TIMESTAMP('2022-03-28 15:27:21','YYYY-MM-DD HH24:MI:SS'),100,100,0,'D',0)
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:32:00 PM MYT
|
||||
INSERT INTO AD_Reference (AD_Reference_ID,Name,AD_Reference_UU,IsOrderByValue,ValidationType,Updated,IsActive,CreatedBy,UpdatedBy,AD_Client_ID,Created,EntityType,AD_Org_ID) VALUES (200160,'C_Tax Posting Indicator','429065e5-80c4-458e-a7ae-d20761dcb5a8','N','L',TO_TIMESTAMP('2022-03-28 15:31:59','YYYY-MM-DD HH24:MI:SS'),'Y',100,100,0,TO_TIMESTAMP('2022-03-28 15:31:59','YYYY-MM-DD HH24:MI:SS'),'D',0)
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:35:42 PM MYT
|
||||
INSERT INTO AD_Ref_List (AD_Ref_List_ID,Description,AD_Ref_List_UU,Name,IsActive,CreatedBy,UpdatedBy,AD_Client_ID,Created,Updated,EntityType,AD_Reference_ID,Value,AD_Org_ID) VALUES (200446,'Tax is calculated on the full amount of the item and posted separately.','e84b618c-a8b3-47cf-89a6-dd674e52d3e4','Separate Tax Posting','Y',100,100,0,TO_TIMESTAMP('2022-03-28 15:35:41','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2022-03-28 15:35:41','YYYY-MM-DD HH24:MI:SS'),'D',200160,'0',0)
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:37:59 PM MYT
|
||||
INSERT INTO AD_Ref_List (AD_Ref_List_ID,Description,AD_Ref_List_UU,Name,IsActive,CreatedBy,UpdatedBy,AD_Client_ID,Created,Updated,EntityType,AD_Reference_ID,Value,AD_Org_ID) VALUES (200447,'Tax amount is added to the item amount during account posting time and for updating of Product Cost.','3e8e0d29-29ac-4c67-ae2c-92c0ee43d2e6','Distribute Tax with Relevant Expense','Y',100,100,0,TO_TIMESTAMP('2022-03-28 15:37:58','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2022-03-28 15:37:58','YYYY-MM-DD HH24:MI:SS'),'D',200160,'1',0)
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:38:05 PM MYT
|
||||
UPDATE AD_Reference SET IsOrderByValue='Y',Updated=TO_TIMESTAMP('2022-03-28 15:38:05','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Reference_ID=200160
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:42:45 PM MYT
|
||||
INSERT INTO AD_Column (AD_Column_ID,SeqNoSelection,IsSyncDatabase,Version,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsParent,FieldLength,IsSelectionColumn,IsKey,ReadOnlyLogic,IsAutocomplete,IsAllowLogging,MandatoryLogic,AD_Column_UU,Updated,IsUpdateable,ColumnName,DefaultValue,Name,IsAllowCopy,IsActive,CreatedBy,UpdatedBy,IsAlwaysUpdateable,AD_Client_ID,Created,EntityType,IsEncrypted,IsSecure,FKConstraintType,AD_Element_ID,AD_Reference_Value_ID,AD_Table_ID,AD_Reference_ID,IsToolbarButton,AD_Org_ID,IsHtml) VALUES (213805,0,'N',0,'N','N','N',0,'N',1,'N','N','@IsSummary@=Y','N','Y','@IsSummary@=N','e7a97d28-f550-4253-a77b-b6fab1e7b38a',TO_TIMESTAMP('2022-03-28 15:42:44','YYYY-MM-DD HH24:MI:SS'),'Y','TaxPostingIndicator','0','Posting Indicator','Y','Y',100,100,'N',0,TO_TIMESTAMP('2022-03-28 15:42:44','YYYY-MM-DD HH24:MI:SS'),'D','N','N','N',203283,200160,261,17,'N',0,'N')
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:42:52 PM MYT
|
||||
INSERT INTO AD_TreeNode (AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, AD_Tree_ID, Node_ID, Parent_ID, SeqNo, AD_TreeNode_UU) SELECT t.AD_Client_ID, 0, 'Y', statement_timestamp(), 100, statement_timestamp(), 100,t.AD_Tree_ID, 200012, 0, 999, Generate_UUID() FROM AD_Tree t WHERE t.AD_Client_ID=0 AND t.IsActive='Y' AND t.IsAllNodes='Y' AND t.TreeType='TL' AND t.AD_Table_ID=282 AND NOT EXISTS (SELECT * FROM AD_TreeNode e WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=200012)
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:42:53 PM MYT
|
||||
ALTER TABLE C_Tax ADD COLUMN TaxPostingIndicator CHAR(1) DEFAULT '0'
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:55:05 PM MYT
|
||||
INSERT INTO AD_Field (SortNo,AD_Field_ID,IsEncrypted,DisplayLength,IsSameLine,IsHeading,SeqNo,IsCentrallyMaintained,IsReadOnly,DisplayLogic,Updated,Name,AD_Field_UU,IsDisplayed,IsFieldOnly,CreatedBy,UpdatedBy,IsActive,IsDisplayedGrid,SeqNoGrid,XPosition,IsQuickEntry,AD_Client_ID,Created,ColumnSpan,NumLines,IsAdvancedField,IsDefaultFocus,AD_Column_ID,EntityType,AD_Tab_ID,AD_Org_ID) VALUES (0,205862,'N',0,'N','N',1010,'Y','N','@IsDocumentLevel@=N',TO_TIMESTAMP('2022-03-28 15:55:04','YYYY-MM-DD HH24:MI:SS'),'Posting Indicator','96a2af5a-4a6f-4d44-ab54-da4713d70fc5','Y','N',100,100,'Y','Y',1010,4,'N',0,TO_TIMESTAMP('2022-03-28 15:55:04','YYYY-MM-DD HH24:MI:SS'),2,1,'N','N',213805,'D',174,0)
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:55:33 PM MYT
|
||||
UPDATE AD_Field SET SeqNo=180,SeqNoGrid=180,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=205862
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:55:33 PM MYT
|
||||
UPDATE AD_Field SET SeqNo=190,SeqNoGrid=190,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=203325
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:55:33 PM MYT
|
||||
UPDATE AD_Field SET SeqNo=200,SeqNoGrid=200,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=203326
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:55:33 PM MYT
|
||||
UPDATE AD_Field SET SeqNo=210,SeqNoGrid=210,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=974
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:55:33 PM MYT
|
||||
UPDATE AD_Field SET SeqNo=220,SeqNoGrid=220,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=976
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:55:33 PM MYT
|
||||
UPDATE AD_Field SET SeqNo=230,SeqNoGrid=230,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=975
|
||||
;
|
||||
|
||||
UPDATE AD_Field SET SeqNo=240,SeqNoGrid=240,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=977
|
||||
;
|
||||
|
||||
UPDATE AD_Field SET SeqNo=250,SeqNoGrid=250,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=202402
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 3:56:15 PM MYT
|
||||
UPDATE AD_Column SET ReadOnlyLogic='@IsDocumentLevel@=Y', MandatoryLogic='@IsDocumentLevel@=N',Updated=TO_TIMESTAMP('2022-03-28 15:56:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=213805
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 6:43:36 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@IsDocumentLevel@=N & @IsSummary@=N', AD_Val_Rule_ID=NULL, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-03-28 18:43:36','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=205862
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 8:10:21 PM MYT
|
||||
UPDATE AD_Field SET DisplayLogic='@IsDocumentLevel@=N & @IsSummary@=N & @SOPOType@!S', AD_Val_Rule_ID=NULL, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-03-28 20:10:21','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=205862
|
||||
;
|
||||
|
||||
-- Mar 28, 2022 8:10:34 PM MYT
|
||||
INSERT INTO AD_TreeNode (AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, AD_Tree_ID, Node_ID, Parent_ID, SeqNo, AD_TreeNode_UU) SELECT t.AD_Client_ID, 0, 'Y', statement_timestamp(), 100, statement_timestamp(), 100,t.AD_Tree_ID, 200014, 0, 999, Generate_UUID() FROM AD_Tree t WHERE t.AD_Client_ID=0 AND t.IsActive='Y' AND t.IsAllNodes='Y' AND t.TreeType='TL' AND t.AD_Table_ID=282 AND NOT EXISTS (SELECT * FROM AD_TreeNode e WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=200014)
|
||||
;
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
-- IDEMPIERE-5057 Implement Deductible and non deductible input tax for purchasing and costing
|
||||
SELECT register_migration_script('202204011738_IDEMPIERE-5057.sql') FROM dual;
|
||||
|
||||
-- Apr 1, 2022, 5:38:03 PM MYT
|
||||
UPDATE AD_Element SET Description='Type of input tax (deductible and non deductible)', Help='Separate Tax Posting: Tax is calculated on the full amount of the item and posted separately.
|
||||
Distribute Tax with Relevant Expense: Tax amount is added to the item amount during account posting time and for updating of Product Cost.',Updated=TO_TIMESTAMP('2022-04-01 17:38:03','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Element_ID=203283
|
||||
;
|
||||
|
||||
-- Apr 1, 2022, 5:38:03 PM MYT
|
||||
UPDATE AD_Column SET ColumnName='TaxPostingIndicator', Name='Posting Indicator', Description='Type of input tax (deductible and non deductible)', Help='Separate Tax Posting: Tax is calculated on the full amount of the item and posted separately.
|
||||
Distribute Tax with Relevant Expense: Tax amount is added to the item amount during account posting time and for updating of Product Cost.', Placeholder=NULL WHERE AD_Element_ID=203283
|
||||
;
|
||||
|
||||
-- Apr 1, 2022, 5:38:03 PM MYT
|
||||
UPDATE AD_Process_Para SET ColumnName='TaxPostingIndicator', Name='Posting Indicator', Description='Type of input tax (deductible and non deductible)', Help='Separate Tax Posting: Tax is calculated on the full amount of the item and posted separately.
|
||||
Distribute Tax with Relevant Expense: Tax amount is added to the item amount during account posting time and for updating of Product Cost.', AD_Element_ID=203283 WHERE UPPER(ColumnName)='TAXPOSTINGINDICATOR' AND IsCentrallyMaintained='Y' AND AD_Element_ID IS NULL
|
||||
;
|
||||
|
||||
-- Apr 1, 2022, 5:38:03 PM MYT
|
||||
UPDATE AD_Process_Para SET ColumnName='TaxPostingIndicator', Name='Posting Indicator', Description='Type of input tax (deductible and non deductible)', Help='Separate Tax Posting: Tax is calculated on the full amount of the item and posted separately.
|
||||
Distribute Tax with Relevant Expense: Tax amount is added to the item amount during account posting time and for updating of Product Cost.', Placeholder=NULL WHERE AD_Element_ID=203283 AND IsCentrallyMaintained='Y'
|
||||
;
|
||||
|
||||
-- Apr 1, 2022, 5:38:03 PM MYT
|
||||
UPDATE AD_InfoColumn SET ColumnName='TaxPostingIndicator', Name='Posting Indicator', Description='Type of input tax (deductible and non deductible)', Help='Separate Tax Posting: Tax is calculated on the full amount of the item and posted separately.
|
||||
Distribute Tax with Relevant Expense: Tax amount is added to the item amount during account posting time and for updating of Product Cost.', Placeholder=NULL WHERE AD_Element_ID=203283 AND IsCentrallyMaintained='Y'
|
||||
;
|
||||
|
||||
-- Apr 1, 2022, 5:38:03 PM MYT
|
||||
UPDATE AD_Field SET Name='Posting Indicator', Description='Type of input tax (deductible and non deductible)', Help='Separate Tax Posting: Tax is calculated on the full amount of the item and posted separately.
|
||||
Distribute Tax with Relevant Expense: Tax amount is added to the item amount during account posting time and for updating of Product Cost.', Placeholder=NULL WHERE AD_Column_ID IN (SELECT AD_Column_ID FROM AD_Column WHERE AD_Element_ID=203283) AND IsCentrallyMaintained='Y'
|
||||
;
|
||||
|
|
@ -31,30 +31,112 @@ import org.compiere.process.ProcessInfo;
|
|||
*/
|
||||
public interface ITaxProvider {
|
||||
|
||||
/**
|
||||
* Calculate order tax
|
||||
* @param provider
|
||||
* @param order
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
public boolean calculateOrderTaxTotal(MTaxProvider provider, MOrder order);
|
||||
|
||||
/**
|
||||
* Update order tax for line
|
||||
* @param provider
|
||||
* @param line
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
public boolean updateOrderTax(MTaxProvider provider, MOrderLine line);
|
||||
|
||||
/**
|
||||
* Re-calculate order tax for line (if line tax id change)
|
||||
* @param provider
|
||||
* @param line
|
||||
* @param newRecord
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
public boolean recalculateTax(MTaxProvider provider, MOrderLine line, boolean newRecord);
|
||||
|
||||
/**
|
||||
* Update order tax total
|
||||
* @param provider
|
||||
* @param line
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
public boolean updateHeaderTax(MTaxProvider provider, MOrderLine line);
|
||||
|
||||
/**
|
||||
* Calculate invoice tax total
|
||||
* @param provider
|
||||
* @param invoice
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
public boolean calculateInvoiceTaxTotal(MTaxProvider provider, MInvoice invoice);
|
||||
|
||||
/**
|
||||
* Update invoice tax for line
|
||||
* @param provider
|
||||
* @param line
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
public boolean updateInvoiceTax(MTaxProvider provider, MInvoiceLine line);
|
||||
|
||||
/**
|
||||
* Re-calculate invoice tax for line (if line tax id change)
|
||||
* @param provider
|
||||
* @param line
|
||||
* @param newRecord
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
public boolean recalculateTax(MTaxProvider provider, MInvoiceLine line, boolean newRecord);
|
||||
|
||||
/**
|
||||
* Update invoice tax total
|
||||
* @param provider
|
||||
* @param line
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
public boolean updateHeaderTax(MTaxProvider provider, MInvoiceLine line);
|
||||
|
||||
/**
|
||||
* Calculate rma tax total
|
||||
* @param provider
|
||||
* @param rma
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
public boolean calculateRMATaxTotal(MTaxProvider provider, MRMA rma);
|
||||
|
||||
/**
|
||||
* Update rma tax for rma line
|
||||
* @param provider
|
||||
* @param line
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
public boolean updateRMATax(MTaxProvider provider, MRMALine line);
|
||||
|
||||
/**
|
||||
* Re-calculate rma tax for ram line (if line tax id change)
|
||||
* @param provider
|
||||
* @param line
|
||||
* @param newRecord
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
public boolean recalculateTax(MTaxProvider provider, MRMALine line, boolean newRecord);
|
||||
|
||||
/**
|
||||
* Update rma header total
|
||||
* @param provider
|
||||
* @param line
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
public boolean updateHeaderTax(MTaxProvider provider, MRMALine line);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param provider
|
||||
* @param pi
|
||||
* @return error message
|
||||
* @throws Exception
|
||||
*/
|
||||
public String validateConnection(MTaxProvider provider, ProcessInfo pi) throws Exception;
|
||||
|
||||
}
|
|
@ -20,6 +20,7 @@ import java.math.BigDecimal;
|
|||
import java.math.RoundingMode;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.compiere.model.I_C_OrderLine;
|
||||
|
@ -616,9 +617,57 @@ public class Doc_InOut extends Doc
|
|||
int stdPrecision = MCurrency.getStdPrecision(getCtx(), C_Currency_ID);
|
||||
BigDecimal costTax = tax.calculateTax(costs, true, stdPrecision);
|
||||
if (log.isLoggable(Level.FINE)) log.fine("Costs=" + costs + " - Tax=" + costTax);
|
||||
costs = costs.subtract(costTax);
|
||||
if(tax.isSummary())
|
||||
{
|
||||
MTax[] cTaxes = tax.getChildTaxes(false);
|
||||
List<MTax> toSubtract = new ArrayList<>();
|
||||
for(MTax cTax : cTaxes)
|
||||
{
|
||||
if (!cTax.isDistributeTaxWithLineItem())
|
||||
toSubtract.add(cTax);
|
||||
}
|
||||
if (toSubtract.size() > 0)
|
||||
{
|
||||
BigDecimal base = costs.subtract(costTax);
|
||||
for(MTax cTax : toSubtract)
|
||||
{
|
||||
BigDecimal ts = cTax.calculateTax(base, false, stdPrecision);
|
||||
costs = costs.subtract(ts);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!tax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
costs = costs.subtract(costTax);
|
||||
}
|
||||
}
|
||||
} // correct included Tax
|
||||
else if (C_Tax_ID != 0)
|
||||
{
|
||||
MTax tax = MTax.get(getCtx(), C_Tax_ID);
|
||||
if(tax.isSummary())
|
||||
{
|
||||
MTax[] cTaxes = tax.getChildTaxes(false);
|
||||
BigDecimal base = costs;
|
||||
for(MTax cTax : cTaxes)
|
||||
{
|
||||
if (cTax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
//do not round to stdprecision before multiply qty
|
||||
BigDecimal costTax = cTax.calculateTax(base, false, 12);
|
||||
if (log.isLoggable(Level.FINE)) log.fine("Costs=" + base + " - Tax=" + costTax);
|
||||
costs = costs.add(costTax);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
//do not round to stdprecision before multiply qty
|
||||
BigDecimal costTax = tax.calculateTax(costs, false, 12);
|
||||
if (log.isLoggable(Level.FINE)) log.fine("Costs=" + costs + " - Tax=" + costTax);
|
||||
costs = costs.add(costTax);
|
||||
}
|
||||
}
|
||||
}
|
||||
costs = costs.multiply(line.getQty());
|
||||
}
|
||||
|
@ -781,18 +830,50 @@ public class Doc_InOut extends Doc
|
|||
MOrderLine originalOrderLine = (MOrderLine) originalInOutLine.getC_OrderLine();
|
||||
// Goodwill: Correct included Tax
|
||||
int C_Tax_ID = originalOrderLine.getC_Tax_ID();
|
||||
MTax tax = MTax.get(getCtx(), C_Tax_ID);
|
||||
int stdPrecision = MCurrency.getStdPrecision(getCtx(), originalOrderLine.getC_Currency_ID());
|
||||
if (originalOrderLine.isTaxIncluded() && C_Tax_ID != 0)
|
||||
{
|
||||
MTax tax = MTax.get(getCtx(), C_Tax_ID);
|
||||
if (!tax.isZeroTax())
|
||||
BigDecimal costTax = tax.calculateTax(costs, true, stdPrecision);
|
||||
if (log.isLoggable(Level.FINE)) log.fine("Costs=" + costs + " - Tax=" + costTax);
|
||||
if (tax.isSummary())
|
||||
{
|
||||
costs = costs.subtract(costTax);
|
||||
BigDecimal base = costs;
|
||||
for(MTax cTax : tax.getChildTaxes(false))
|
||||
{
|
||||
if (!cTax.isZeroTax() && cTax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
costTax = cTax.calculateTax(base, false, stdPrecision);
|
||||
costs = costs.add(costTax);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!tax.isZeroTax() && !tax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
int stdPrecision = MCurrency.getStdPrecision(getCtx(), originalOrderLine.getC_Currency_ID());
|
||||
BigDecimal costTax = tax.calculateTax(costs, true, stdPrecision);
|
||||
if (log.isLoggable(Level.FINE)) log.fine("Costs=" + costs + " - Tax=" + costTax);
|
||||
costs = costs.subtract(costTax);
|
||||
}
|
||||
} // correct included Tax
|
||||
|
||||
else
|
||||
{
|
||||
if (tax.isSummary())
|
||||
{
|
||||
BigDecimal base = costs;
|
||||
for(MTax cTax : tax.getChildTaxes(false))
|
||||
{
|
||||
if (!cTax.isZeroTax() && cTax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
BigDecimal costTax = cTax.calculateTax(base, false, stdPrecision);
|
||||
costs = costs.add(costTax);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
BigDecimal costTax = tax.calculateTax(costs, false, stdPrecision);
|
||||
costs = costs.add(costTax);
|
||||
}
|
||||
}
|
||||
// different currency
|
||||
if (C_Currency_ID != originalOrderLine.getC_Currency_ID())
|
||||
{
|
||||
|
|
|
@ -74,6 +74,9 @@ public class Doc_Invoice extends Doc
|
|||
|
||||
/** Contained Optional Tax Lines */
|
||||
protected DocTax[] m_taxes = null;
|
||||
/** Contained Optional Tax Lines Distributed to Line Item */
|
||||
@SuppressWarnings("unused")
|
||||
private DocTax[] m_addToLineTaxes = null;
|
||||
/** Currency Precision */
|
||||
protected int m_precision = -1;
|
||||
/** All lines are Service */
|
||||
|
@ -109,6 +112,7 @@ public class Doc_Invoice extends Doc
|
|||
private DocTax[] loadTaxes()
|
||||
{
|
||||
ArrayList<DocTax> list = new ArrayList<DocTax>();
|
||||
ArrayList<DocTax> distributeList = new ArrayList<DocTax>();
|
||||
String sql = "SELECT it.C_Tax_ID, t.Name, t.Rate, it.TaxBaseAmt, it.TaxAmt, t.IsSalesTax "
|
||||
+ "FROM C_Tax t, C_InvoiceTax it "
|
||||
+ "WHERE t.C_Tax_ID=it.C_Tax_ID AND it.C_Invoice_ID=?";
|
||||
|
@ -129,10 +133,18 @@ public class Doc_Invoice extends Doc
|
|||
BigDecimal amount = rs.getBigDecimal(5);
|
||||
boolean salesTax = "Y".equals(rs.getString(6));
|
||||
//
|
||||
MTax tax = MTax.get(getCtx(), C_Tax_ID);
|
||||
DocTax taxLine = new DocTax(C_Tax_ID, name, rate,
|
||||
taxBaseAmt, amount, salesTax);
|
||||
if (log.isLoggable(Level.FINE)) log.fine(taxLine.toString());
|
||||
list.add(taxLine);
|
||||
if (!tax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
list.add(taxLine);
|
||||
}
|
||||
else
|
||||
{
|
||||
distributeList.add(taxLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
|
@ -148,6 +160,9 @@ public class Doc_Invoice extends Doc
|
|||
// Return Array
|
||||
DocTax[] tl = new DocTax[list.size()];
|
||||
list.toArray(tl);
|
||||
// Distribute list
|
||||
m_addToLineTaxes = distributeList.toArray(new DocTax[0]);
|
||||
|
||||
return tl;
|
||||
} // loadTaxes
|
||||
|
||||
|
@ -184,24 +199,33 @@ public class Doc_Invoice extends Doc
|
|||
{
|
||||
BigDecimal LineNetAmtTax = tax.calculateTax(LineNetAmt, true, getStdPrecision());
|
||||
if (log.isLoggable(Level.FINE)) log.fine("LineNetAmt=" + LineNetAmt + " - Tax=" + LineNetAmtTax);
|
||||
LineNetAmt = LineNetAmt.subtract(LineNetAmtTax);
|
||||
|
||||
if (tax.isSummary()) {
|
||||
LineNetAmt = LineNetAmt.subtract(LineNetAmtTax);
|
||||
BigDecimal base = LineNetAmt;
|
||||
BigDecimal sumChildLineNetAmtTax = Env.ZERO;
|
||||
DocTax taxToApplyDiff = null;
|
||||
for (MTax childTax : tax.getChildTaxes(false)) {
|
||||
if (!childTax.isZeroTax())
|
||||
{
|
||||
BigDecimal childLineNetAmtTax = childTax.calculateTax(LineNetAmt, false, getStdPrecision());
|
||||
if (log.isLoggable(Level.FINE)) log.fine("LineNetAmt=" + LineNetAmt + " - Child Tax=" + childLineNetAmtTax);
|
||||
for (int t = 0; t < m_taxes.length; t++)
|
||||
BigDecimal childLineNetAmtTax = childTax.calculateTax(base, false, getStdPrecision());
|
||||
if (log.isLoggable(Level.FINE)) log.fine("LineNetAmt=" + base + " - Child Tax=" + childLineNetAmtTax);
|
||||
if (childTax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
LineNetAmt = LineNetAmt.add(childLineNetAmtTax);
|
||||
LineNetAmtTax = LineNetAmtTax.subtract(childLineNetAmtTax);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_taxes[t].getC_Tax_ID() == childTax.getC_Tax_ID())
|
||||
for (int t = 0; t < m_taxes.length; t++)
|
||||
{
|
||||
m_taxes[t].addIncludedTax(childLineNetAmtTax);
|
||||
taxToApplyDiff = m_taxes[t];
|
||||
sumChildLineNetAmtTax = sumChildLineNetAmtTax.add(childLineNetAmtTax);
|
||||
break;
|
||||
if (m_taxes[t].getC_Tax_ID() == childTax.getC_Tax_ID())
|
||||
{
|
||||
m_taxes[t].addIncludedTax(childLineNetAmtTax);
|
||||
taxToApplyDiff = m_taxes[t];
|
||||
sumChildLineNetAmtTax = sumChildLineNetAmtTax.add(childLineNetAmtTax);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -211,12 +235,16 @@ public class Doc_Invoice extends Doc
|
|||
taxToApplyDiff.addIncludedTax(diffChildVsSummary);
|
||||
}
|
||||
} else {
|
||||
for (int t = 0; t < m_taxes.length; t++)
|
||||
{
|
||||
if (m_taxes[t].getC_Tax_ID() == C_Tax_ID)
|
||||
if (!tax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
LineNetAmt = LineNetAmt.subtract(LineNetAmtTax);
|
||||
for (int t = 0; t < m_taxes.length; t++)
|
||||
{
|
||||
m_taxes[t].addIncludedTax(LineNetAmtTax);
|
||||
break;
|
||||
if (m_taxes[t].getC_Tax_ID() == C_Tax_ID)
|
||||
{
|
||||
m_taxes[t].addIncludedTax(LineNetAmtTax);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -225,6 +253,29 @@ public class Doc_Invoice extends Doc
|
|||
PriceList = PriceList.subtract(PriceListTax);
|
||||
}
|
||||
} // correct included Tax
|
||||
else
|
||||
{
|
||||
int stdPrecision = MCurrency.getStdPrecision(getCtx(), invoice.getC_Currency_ID());
|
||||
MTax tax = MTax.get(getCtx(), C_Tax_ID);
|
||||
if (tax.isSummary())
|
||||
{
|
||||
MTax[] cTaxes = tax.getChildTaxes(false);
|
||||
BigDecimal base = LineNetAmt;
|
||||
for(MTax cTax : cTaxes)
|
||||
{
|
||||
if (cTax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
BigDecimal taxAmt = cTax.calculateTax(base, false, stdPrecision);
|
||||
LineNetAmt = LineNetAmt.add(taxAmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
BigDecimal taxAmt = tax.calculateTax(LineNetAmt, false, stdPrecision);
|
||||
LineNetAmt = LineNetAmt.add(taxAmt);
|
||||
}
|
||||
}
|
||||
|
||||
docLine.setAmount (LineNetAmt, PriceList, Qty); // qty for discount calc
|
||||
if (docLine.isItem())
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.compiere.model.MAcctSchema;
|
|||
import org.compiere.model.MAcctSchemaElement;
|
||||
import org.compiere.model.MConversionRate;
|
||||
import org.compiere.model.MCostDetail;
|
||||
import org.compiere.model.MCurrency;
|
||||
import org.compiere.model.MFactAcct;
|
||||
import org.compiere.model.MInOut;
|
||||
import org.compiere.model.MInOutLine;
|
||||
|
@ -44,6 +45,7 @@ import org.compiere.model.MInvoice;
|
|||
import org.compiere.model.MInvoiceLine;
|
||||
import org.compiere.model.MMatchInv;
|
||||
import org.compiere.model.MOrderLandedCostAllocation;
|
||||
import org.compiere.model.MTax;
|
||||
import org.compiere.model.MUOM;
|
||||
import org.compiere.model.ProductCost;
|
||||
import org.compiere.model.Query;
|
||||
|
@ -533,6 +535,56 @@ public class Doc_MatchInv extends Doc
|
|||
}
|
||||
}
|
||||
tAmt = tAmt.add(LineNetAmt); //Invoice Price
|
||||
// adjust for tax
|
||||
MTax tax = MTax.get(getCtx(), m_invoiceLine.getC_Tax_ID());
|
||||
int stdPrecision = MCurrency.getStdPrecision(getCtx(), m_invoiceLine.getParent().getC_Currency_ID());
|
||||
if (m_invoiceLine.isTaxIncluded())
|
||||
{
|
||||
BigDecimal tAmtTax = tax.calculateTax(tAmt, true, stdPrecision);
|
||||
if (tax.isSummary())
|
||||
{
|
||||
tAmt = tAmt.subtract(tAmtTax);
|
||||
BigDecimal base = tAmt;
|
||||
for (MTax childTax : tax.getChildTaxes(false))
|
||||
{
|
||||
if (!childTax.isZeroTax())
|
||||
{
|
||||
if (childTax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
BigDecimal taxAmt = childTax.calculateTax(base, false, stdPrecision);
|
||||
tAmt = tAmt.add(taxAmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!tax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
tAmt = tAmt.subtract(tAmtTax);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tax.isSummary())
|
||||
{
|
||||
BigDecimal base = tAmt;
|
||||
for (MTax childTax : tax.getChildTaxes(false))
|
||||
{
|
||||
if (!childTax.isZeroTax())
|
||||
{
|
||||
if (childTax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
BigDecimal taxAmt = childTax.calculateTax(base, false, stdPrecision);
|
||||
tAmt = tAmt.add(taxAmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
BigDecimal taxAmt = tax.calculateTax(tAmt, false, stdPrecision);
|
||||
tAmt = tAmt.add(taxAmt);
|
||||
}
|
||||
}
|
||||
|
||||
// Different currency
|
||||
MInvoice invoice = m_invoiceLine.getParent();
|
||||
|
|
|
@ -286,17 +286,53 @@ public class Doc_MatchPO extends Doc
|
|||
poCost = m_oLine.getPriceActual();
|
||||
// Goodwill: Correct included Tax
|
||||
int C_Tax_ID = m_oLine.getC_Tax_ID();
|
||||
MTax tax = MTax.get(getCtx(), C_Tax_ID);
|
||||
int stdPrecision = MCurrency.getStdPrecision(getCtx(), m_oLine.getC_Currency_ID());
|
||||
if (m_oLine.isTaxIncluded() && C_Tax_ID != 0)
|
||||
{
|
||||
MTax tax = MTax.get(getCtx(), C_Tax_ID);
|
||||
{
|
||||
if (!tax.isZeroTax())
|
||||
{
|
||||
int stdPrecision = MCurrency.getStdPrecision(getCtx(), m_oLine.getC_Currency_ID());
|
||||
{
|
||||
BigDecimal costTax = tax.calculateTax(poCost, true, stdPrecision);
|
||||
if (log.isLoggable(Level.FINE)) log.fine("Costs=" + poCost + " - Tax=" + costTax);
|
||||
poCost = poCost.subtract(costTax);
|
||||
if (tax.isSummary())
|
||||
{
|
||||
poCost = poCost.subtract(costTax);
|
||||
BigDecimal base = poCost;
|
||||
for (MTax childTax : tax.getChildTaxes(false))
|
||||
{
|
||||
if (!childTax.isZeroTax() && childTax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
BigDecimal taxAmt = childTax.calculateTax(base, false, stdPrecision);
|
||||
poCost = poCost.add(taxAmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!tax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
poCost = poCost.subtract(costTax);
|
||||
}
|
||||
}
|
||||
} // correct included Tax
|
||||
else
|
||||
{
|
||||
if (tax.isSummary())
|
||||
{
|
||||
BigDecimal base = poCost;
|
||||
for (MTax childTax : tax.getChildTaxes(false))
|
||||
{
|
||||
if (childTax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
BigDecimal taxAmt = childTax.calculateTax(base, false, stdPrecision);
|
||||
poCost = poCost.add(taxAmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tax.isDistributeTaxWithLineItem())
|
||||
{
|
||||
BigDecimal taxAmt = tax.calculateTax(poCost, false, stdPrecision);
|
||||
poCost = poCost.add(taxAmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MInOutLine receiptLine = new MInOutLine (getCtx(), m_M_InOutLine_ID, getTrxName());
|
||||
|
@ -383,7 +419,7 @@ public class Doc_MatchPO extends Doc
|
|||
|
||||
if (MAcctSchema.COSTINGMETHOD_StandardCosting.equals(costingMethod))
|
||||
{
|
||||
if (m_matchPO.getReversal_ID() > 0)
|
||||
if (m_matchPO.isReversal())
|
||||
{
|
||||
// Product PPV
|
||||
FactLine cr = fact.createLine(null,
|
||||
|
@ -582,7 +618,7 @@ public class Doc_MatchPO extends Doc
|
|||
tAmt = tAmt.add(isReturnTrx ? poCost.negate() : poCost);
|
||||
tQty = tQty.add(isReturnTrx ? getQty().negate() : getQty());
|
||||
|
||||
if (mMatchPO.getReversal_ID() > 0)
|
||||
if (mMatchPO.isReversal())
|
||||
{
|
||||
String error = createLandedCostAdjustments(as, landedCostMap, mMatchPO, tQty);
|
||||
if (!Util.isEmpty(error))
|
||||
|
@ -601,7 +637,7 @@ public class Doc_MatchPO extends Doc
|
|||
return "SaveError";
|
||||
}
|
||||
|
||||
if (mMatchPO.getReversal_ID() <= 0)
|
||||
if (!mMatchPO.isReversal())
|
||||
{
|
||||
String error = createLandedCostAdjustments(as, landedCostMap, mMatchPO, tQty);
|
||||
if (!Util.isEmpty(error))
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.compiere.util.KeyNamePair;
|
|||
|
||||
/** Generated Interface for C_Tax
|
||||
* @author iDempiere (generated)
|
||||
* @version Release 9
|
||||
* @version Release 10
|
||||
*/
|
||||
public interface I_C_Tax
|
||||
{
|
||||
|
@ -44,8 +44,8 @@ public interface I_C_Tax
|
|||
/** Column name AD_Client_ID */
|
||||
public static final String COLUMNNAME_AD_Client_ID = "AD_Client_ID";
|
||||
|
||||
/** Get Client.
|
||||
* Client/Tenant for this installation.
|
||||
/** Get Tenant.
|
||||
* Tenant for this installation.
|
||||
*/
|
||||
public int getAD_Client_ID();
|
||||
|
||||
|
@ -53,12 +53,12 @@ public interface I_C_Tax
|
|||
public static final String COLUMNNAME_AD_Org_ID = "AD_Org_ID";
|
||||
|
||||
/** Set Organization.
|
||||
* Organizational entity within client
|
||||
* Organizational entity within tenant
|
||||
*/
|
||||
public void setAD_Org_ID (int AD_Org_ID);
|
||||
|
||||
/** Get Organization.
|
||||
* Organizational entity within client
|
||||
* Organizational entity within tenant
|
||||
*/
|
||||
public int getAD_Org_ID();
|
||||
|
||||
|
@ -358,6 +358,15 @@ public interface I_C_Tax
|
|||
*/
|
||||
public String getTaxIndicator();
|
||||
|
||||
/** Column name TaxPostingIndicator */
|
||||
public static final String COLUMNNAME_TaxPostingIndicator = "TaxPostingIndicator";
|
||||
|
||||
/** Set Posting Indicator */
|
||||
public void setTaxPostingIndicator (String TaxPostingIndicator);
|
||||
|
||||
/** Get Posting Indicator */
|
||||
public String getTaxPostingIndicator();
|
||||
|
||||
/** Column name To_Country_ID */
|
||||
public static final String COLUMNNAME_To_Country_ID = "To_Country_ID";
|
||||
|
||||
|
|
|
@ -943,14 +943,49 @@ public class MInvoiceLine extends X_C_InvoiceLine
|
|||
* author teo_sarca [ 1583825 ]
|
||||
*/
|
||||
protected boolean updateInvoiceTax(boolean oldTax) {
|
||||
MInvoiceTax tax = MInvoiceTax.get (this, getPrecision(), oldTax, get_TrxName());
|
||||
if (tax != null) {
|
||||
if (!tax.calculateTaxFromLines())
|
||||
return false;
|
||||
int C_Tax_ID = getC_Tax_ID();
|
||||
boolean isOldTax = oldTax && is_ValueChanged(MInvoiceTax.COLUMNNAME_C_Tax_ID);
|
||||
if (isOldTax)
|
||||
{
|
||||
Object old = get_ValueOld(MInvoiceTax.COLUMNNAME_C_Tax_ID);
|
||||
if (old == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
C_Tax_ID = ((Integer)old).intValue();
|
||||
}
|
||||
if (C_Tax_ID == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// red1 - solving BUGS #[ 1701331 ] , #[ 1786103 ]
|
||||
if (!tax.save(get_TrxName()))
|
||||
return false;
|
||||
MTax t = MTax.get(C_Tax_ID);
|
||||
if (t.isSummary())
|
||||
{
|
||||
MInvoiceTax[] invoiceTaxes = MInvoiceTax.getChildTaxes(this, getPrecision(), oldTax, get_TrxName());
|
||||
if (invoiceTaxes != null && invoiceTaxes.length > 0)
|
||||
{
|
||||
for(MInvoiceTax tax : invoiceTaxes)
|
||||
{
|
||||
if (!tax.calculateTaxFromLines())
|
||||
return false;
|
||||
|
||||
if (!tax.save(get_TrxName()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MInvoiceTax tax = MInvoiceTax.get (this, getPrecision(), oldTax, get_TrxName());
|
||||
if (tax != null) {
|
||||
if (!tax.calculateTaxFromLines())
|
||||
return false;
|
||||
|
||||
// red1 - solving BUGS #[ 1701331 ] , #[ 1786103 ]
|
||||
if (!tax.save(get_TrxName()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ import java.math.BigDecimal;
|
|||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
@ -104,6 +106,74 @@ public class MInvoiceTax extends X_C_InvoiceTax
|
|||
return retValue;
|
||||
} // get
|
||||
|
||||
/**
|
||||
* Get Child Tax Lines for Invoice Line
|
||||
* @param line invoice line
|
||||
* @param precision currency precision
|
||||
* @param oldTax if true old tax is returned
|
||||
* @param trxName transaction name
|
||||
* @return existing or new tax
|
||||
*/
|
||||
public static MInvoiceTax[] getChildTaxes(MInvoiceLine line, int precision,
|
||||
boolean oldTax, String trxName)
|
||||
{
|
||||
List<MInvoiceTax> invoiceTaxes = new ArrayList<MInvoiceTax>();
|
||||
|
||||
if (line == null || line.getC_Invoice_ID() == 0)
|
||||
return invoiceTaxes.toArray(new MInvoiceTax[0]);
|
||||
|
||||
int C_Tax_ID = line.getC_Tax_ID();
|
||||
if (oldTax)
|
||||
{
|
||||
Object old = line.get_ValueOld(MInvoiceLine.COLUMNNAME_C_Tax_ID);
|
||||
if (old == null)
|
||||
return invoiceTaxes.toArray(new MInvoiceTax[0]);
|
||||
C_Tax_ID = ((Integer)old).intValue();
|
||||
}
|
||||
if (C_Tax_ID == 0)
|
||||
{
|
||||
return invoiceTaxes.toArray(new MInvoiceTax[0]);
|
||||
}
|
||||
|
||||
MTax tax = MTax.get(C_Tax_ID);
|
||||
if (!tax.isSummary())
|
||||
return invoiceTaxes.toArray(new MInvoiceTax[0]);
|
||||
|
||||
MTax[] cTaxes = tax.getChildTaxes(false);
|
||||
for(MTax cTax : cTaxes) {
|
||||
MInvoiceTax invoiceTax = new Query(line.getCtx(), Table_Name, "C_Invoice_ID=? AND C_Tax_ID=?", trxName)
|
||||
.setParameters(line.getC_Invoice_ID(), cTax.getC_Tax_ID())
|
||||
.firstOnly();
|
||||
if (invoiceTax != null)
|
||||
{
|
||||
invoiceTax.set_TrxName(trxName);
|
||||
invoiceTax.setPrecision(precision);
|
||||
invoiceTaxes.add(invoiceTax);
|
||||
}
|
||||
// If the old tax was required and there is no MInvoiceTax for that
|
||||
// return null, and not create another MInvoiceTax - teo_sarca [ 1583825 ]
|
||||
else
|
||||
{
|
||||
if (oldTax)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (invoiceTax == null)
|
||||
{
|
||||
// Create New
|
||||
invoiceTax = new MInvoiceTax(line.getCtx(), 0, trxName);
|
||||
invoiceTax.set_TrxName(trxName);
|
||||
invoiceTax.setClientOrg(line);
|
||||
invoiceTax.setC_Invoice_ID(line.getC_Invoice_ID());
|
||||
invoiceTax.setC_Tax_ID(line.getC_Tax_ID());
|
||||
invoiceTax.setPrecision(precision);
|
||||
invoiceTax.setIsTaxIncluded(line.isTaxIncluded());
|
||||
invoiceTaxes.add(invoiceTax);
|
||||
}
|
||||
}
|
||||
return invoiceTaxes.toArray(new MInvoiceTax[0]);
|
||||
}
|
||||
|
||||
/** Static Logger */
|
||||
private static CLogger s_log = CLogger.getCLogger (MInvoiceTax.class);
|
||||
|
||||
|
|
|
@ -1422,4 +1422,16 @@ public class MMatchPO extends X_M_MatchPO
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this is created to reverse another match po document
|
||||
*/
|
||||
public boolean isReversal() {
|
||||
if (getReversal_ID() > 0) {
|
||||
MMatchPO reversal = new MMatchPO (getCtx(), getReversal_ID(), get_TrxName());
|
||||
if (reversal.getM_MatchPO_ID() < getM_MatchPO_ID())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // MMatchPO
|
||||
|
|
|
@ -980,17 +980,57 @@ public class MOrderLine extends X_C_OrderLine
|
|||
* author teo_sarca [ 1583825 ]
|
||||
*/
|
||||
public boolean updateOrderTax(boolean oldTax) {
|
||||
MOrderTax tax = MOrderTax.get (this, getPrecision(), oldTax, get_TrxName());
|
||||
if (tax != null) {
|
||||
if (!tax.calculateTaxFromLines())
|
||||
return false;
|
||||
if (tax.getTaxAmt().signum() != 0) {
|
||||
if (!tax.save(get_TrxName()))
|
||||
return false;
|
||||
int C_Tax_ID = getC_Tax_ID();
|
||||
boolean isOldTax = oldTax && is_ValueChanged(MOrderLine.COLUMNNAME_C_Tax_ID);
|
||||
if (isOldTax)
|
||||
{
|
||||
Object old = get_ValueOld(MOrderLine.COLUMNNAME_C_Tax_ID);
|
||||
if (old == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (!tax.is_new() && !tax.delete(false, get_TrxName()))
|
||||
C_Tax_ID = ((Integer)old).intValue();
|
||||
}
|
||||
if (C_Tax_ID == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
MTax t = MTax.get(C_Tax_ID);
|
||||
if (t.isSummary())
|
||||
{
|
||||
MOrderTax[] taxes = MOrderTax.getChildTaxes(this, getPrecision(), isOldTax, get_TrxName());
|
||||
if (taxes != null && taxes.length > 0)
|
||||
{
|
||||
for(MOrderTax tax : taxes)
|
||||
{
|
||||
if (!tax.calculateTaxFromLines())
|
||||
return false;
|
||||
if (tax.getTaxAmt().signum() != 0) {
|
||||
if (!tax.save(get_TrxName()))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (!tax.is_new() && !tax.delete(false, get_TrxName()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MOrderTax tax = MOrderTax.get (this, getPrecision(), oldTax, get_TrxName());
|
||||
if (tax != null) {
|
||||
if (!tax.calculateTaxFromLines())
|
||||
return false;
|
||||
if (tax.getTaxAmt().signum() != 0) {
|
||||
if (!tax.save(get_TrxName()))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (!tax.is_new() && !tax.delete(false, get_TrxName()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -19,6 +19,8 @@ package org.compiere.model;
|
|||
import java.math.BigDecimal;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
@ -124,6 +126,99 @@ public class MOrderTax extends X_C_OrderTax
|
|||
return retValue;
|
||||
} // get
|
||||
|
||||
/**
|
||||
* Get Child Tax Line for Order Line
|
||||
* @param line Order line
|
||||
* @param precision currency precision
|
||||
* @param oldTax get old tax
|
||||
* @param trxName transaction
|
||||
* @return existing or new tax
|
||||
*/
|
||||
public static MOrderTax[] getChildTaxes(MOrderLine line, int precision,
|
||||
boolean oldTax, String trxName)
|
||||
{
|
||||
List<MOrderTax> orderTaxes = new ArrayList<MOrderTax>();
|
||||
|
||||
if (line == null || line.getC_Order_ID() == 0)
|
||||
{
|
||||
return orderTaxes.toArray(new MOrderTax[0]);
|
||||
}
|
||||
|
||||
int C_Tax_ID = line.getC_Tax_ID();
|
||||
if (oldTax)
|
||||
{
|
||||
Object old = line.get_ValueOld(MOrderTax.COLUMNNAME_C_Tax_ID);
|
||||
if (old == null)
|
||||
{
|
||||
return orderTaxes.toArray(new MOrderTax[0]);
|
||||
}
|
||||
C_Tax_ID = ((Integer)old).intValue();
|
||||
}
|
||||
if (C_Tax_ID == 0)
|
||||
{
|
||||
return orderTaxes.toArray(new MOrderTax[0]);
|
||||
}
|
||||
|
||||
MTax tax = MTax.get(C_Tax_ID);
|
||||
if (!tax.isSummary())
|
||||
return orderTaxes.toArray(new MOrderTax[0]);
|
||||
|
||||
MTax[] cTaxes = tax.getChildTaxes(false);
|
||||
for(MTax cTax : cTaxes) {
|
||||
MOrderTax orderTax = null;
|
||||
String sql = "SELECT * FROM C_OrderTax WHERE C_Order_ID=? AND C_Tax_ID=?";
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{
|
||||
pstmt = DB.prepareStatement (sql, trxName);
|
||||
pstmt.setInt (1, line.getC_Order_ID());
|
||||
pstmt.setInt (2, cTax.getC_Tax_ID());
|
||||
rs = pstmt.executeQuery ();
|
||||
if (rs.next ())
|
||||
orderTax = new MOrderTax (line.getCtx(), rs, trxName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
s_log.log(Level.SEVERE, sql, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DB.close(rs, pstmt);
|
||||
rs = null;
|
||||
pstmt = null;
|
||||
}
|
||||
if (orderTax != null)
|
||||
{
|
||||
orderTax.setPrecision(precision);
|
||||
orderTax.set_TrxName(trxName);
|
||||
orderTaxes.add(orderTax);
|
||||
}
|
||||
// If the old tax was required and there is no MOrderTax for that
|
||||
// return null, and not create another MOrderTax - teo_sarca [ 1583825 ]
|
||||
else
|
||||
{
|
||||
if (oldTax)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (orderTax == null)
|
||||
{
|
||||
// Create New
|
||||
orderTax = new MOrderTax(line.getCtx(), 0, trxName);
|
||||
orderTax.set_TrxName(trxName);
|
||||
orderTax.setClientOrg(line);
|
||||
orderTax.setC_Order_ID(line.getC_Order_ID());
|
||||
orderTax.setC_Tax_ID(line.getC_Tax_ID());
|
||||
orderTax.setPrecision(precision);
|
||||
orderTax.setIsTaxIncluded(line.isTaxIncluded());
|
||||
orderTaxes.add(orderTax);
|
||||
}
|
||||
}
|
||||
|
||||
return orderTaxes.toArray(new MOrderTax[0]);
|
||||
}
|
||||
|
||||
/** Static Logger */
|
||||
private static CLogger s_log = CLogger.getCLogger (MOrderTax.class);
|
||||
|
||||
|
|
|
@ -378,22 +378,69 @@ public class MRMALine extends X_M_RMALine
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param oldTax true if the old C_Tax_ID should be used
|
||||
* @return true if success, false otherwise
|
||||
*/
|
||||
protected boolean updateOrderTax(boolean oldTax)
|
||||
{
|
||||
MRMATax tax = MRMATax.get (this, getPrecision(), oldTax, get_TrxName());
|
||||
if (tax != null)
|
||||
int C_Tax_ID = getC_Tax_ID();
|
||||
boolean isOldTax = oldTax && is_ValueChanged(MRMALine.COLUMNNAME_C_Tax_ID);
|
||||
if (isOldTax)
|
||||
{
|
||||
if (!tax.calculateTaxFromLines())
|
||||
return false;
|
||||
if (tax.getTaxAmt().signum() != 0)
|
||||
Object old = get_ValueOld(MRMALine.COLUMNNAME_C_Tax_ID);
|
||||
if (old == null)
|
||||
{
|
||||
if (!tax.save(get_TrxName()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
C_Tax_ID = ((Integer)old).intValue();
|
||||
}
|
||||
if (C_Tax_ID == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
MTax t = MTax.get(C_Tax_ID);
|
||||
if (t.isSummary())
|
||||
{
|
||||
MRMATax[] taxes = MRMATax.getChildTaxes(this, getPrecision(), oldTax, get_TrxName());
|
||||
if (taxes != null && taxes.length > 0)
|
||||
{
|
||||
if (!tax.is_new() && !tax.delete(false, get_TrxName()))
|
||||
for(MRMATax tax : taxes)
|
||||
{
|
||||
if (!tax.calculateTaxFromLines())
|
||||
return false;
|
||||
if (tax.getTaxAmt().signum() != 0)
|
||||
{
|
||||
if (!tax.save(get_TrxName()))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!tax.is_new() && !tax.delete(false, get_TrxName()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MRMATax tax = MRMATax.get (this, getPrecision(), oldTax, get_TrxName());
|
||||
if (tax != null)
|
||||
{
|
||||
if (!tax.calculateTaxFromLines())
|
||||
return false;
|
||||
if (tax.getTaxAmt().signum() != 0)
|
||||
{
|
||||
if (!tax.save(get_TrxName()))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!tax.is_new() && !tax.delete(false, get_TrxName()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -16,6 +16,8 @@ package org.compiere.model;
|
|||
import java.math.BigDecimal;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
@ -118,6 +120,96 @@ public class MRMATax extends X_M_RMATax
|
|||
return retValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Child Tax Lines for RMA Line
|
||||
* @param line RMA line
|
||||
* @param precision currency precision
|
||||
* @param oldTax get old tax
|
||||
* @param trxName transaction
|
||||
* @return existing or new tax
|
||||
*/
|
||||
public static MRMATax[] getChildTaxes(MRMALine line, int precision,
|
||||
boolean oldTax, String trxName)
|
||||
{
|
||||
List<MRMATax> rmaTaxes = new ArrayList<MRMATax>();
|
||||
if (line == null || line.getM_RMA_ID() == 0)
|
||||
{
|
||||
return rmaTaxes.toArray(new MRMATax[0]);
|
||||
}
|
||||
int C_Tax_ID = line.getC_Tax_ID();
|
||||
if (oldTax)
|
||||
{
|
||||
Object old = line.get_ValueOld(MRMATax.COLUMNNAME_C_Tax_ID);
|
||||
if (old == null)
|
||||
{
|
||||
return rmaTaxes.toArray(new MRMATax[0]);
|
||||
}
|
||||
C_Tax_ID = ((Integer)old).intValue();
|
||||
}
|
||||
if (C_Tax_ID == 0)
|
||||
{
|
||||
return rmaTaxes.toArray(new MRMATax[0]);
|
||||
}
|
||||
|
||||
MTax tax = MTax.get(C_Tax_ID);
|
||||
if (!tax.isSummary())
|
||||
return rmaTaxes.toArray(new MRMATax[0]);
|
||||
|
||||
MTax[] cTaxes = tax.getChildTaxes(false);
|
||||
for(MTax cTax : cTaxes) {
|
||||
MRMATax rmaTax = null;
|
||||
String sql = "SELECT * FROM M_RMATax WHERE M_RMA_ID=? AND C_Tax_ID=?";
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{
|
||||
pstmt = DB.prepareStatement (sql, trxName);
|
||||
pstmt.setInt (1, line.getM_RMA_ID());
|
||||
pstmt.setInt (2, cTax.getC_Tax_ID());
|
||||
rs = pstmt.executeQuery ();
|
||||
if (rs.next ())
|
||||
rmaTax = new MRMATax (line.getCtx(), rs, trxName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
s_log.log(Level.SEVERE, sql, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DB.close(rs, pstmt);
|
||||
rs = null;
|
||||
pstmt = null;
|
||||
}
|
||||
if (rmaTax != null)
|
||||
{
|
||||
rmaTax.setPrecision(precision);
|
||||
rmaTax.set_TrxName(trxName);
|
||||
rmaTaxes.add(rmaTax);
|
||||
}
|
||||
// If the old tax was required and there is no MOrderTax for that
|
||||
// return null, and not create another MOrderTax - teo_sarca [ 1583825 ]
|
||||
else
|
||||
{
|
||||
if (oldTax)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rmaTax == null)
|
||||
{
|
||||
// Create New
|
||||
rmaTax = new MRMATax(line.getCtx(), 0, trxName);
|
||||
rmaTax.set_TrxName(trxName);
|
||||
rmaTax.setClientOrg(line);
|
||||
rmaTax.setM_RMA_ID(line.getM_RMA_ID());
|
||||
rmaTax.setC_Tax_ID(line.getC_Tax_ID());
|
||||
rmaTax.setPrecision(precision);
|
||||
rmaTax.setIsTaxIncluded(line.getParent().isTaxIncluded());
|
||||
rmaTaxes.add(rmaTax);
|
||||
}
|
||||
}
|
||||
return rmaTaxes.toArray(new MRMATax[0]);
|
||||
}
|
||||
|
||||
/** Static Logger */
|
||||
private static CLogger s_log = CLogger.getCLogger (MRMATax.class);
|
||||
|
||||
|
|
|
@ -411,4 +411,12 @@ public class MTax extends X_C_Tax implements ImmutablePOSupport
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if input tax is added to product cost
|
||||
*/
|
||||
public boolean isDistributeTaxWithLineItem()
|
||||
{
|
||||
return TAXPOSTINGINDICATOR_DistributeTaxWithRelevantExpense.equals(getTaxPostingIndicator());
|
||||
}
|
||||
} // MTax
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.compiere.util.KeyNamePair;
|
|||
|
||||
/** Generated Model for C_Tax
|
||||
* @author iDempiere (generated)
|
||||
* @version Release 9 - $Id$ */
|
||||
* @version Release 10 - $Id$ */
|
||||
@org.adempiere.base.Model(table="C_Tax")
|
||||
public class X_C_Tax extends PO implements I_C_Tax, I_Persistent
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ public class X_C_Tax extends PO implements I_C_Tax, I_Persistent
|
|||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 20220116L;
|
||||
private static final long serialVersionUID = 20220329L;
|
||||
|
||||
/** Standard Constructor */
|
||||
public X_C_Tax (Properties ctx, int C_Tax_ID, String trxName)
|
||||
|
@ -599,6 +599,28 @@ public class X_C_Tax extends PO implements I_C_Tax, I_Persistent
|
|||
return (String)get_Value(COLUMNNAME_TaxIndicator);
|
||||
}
|
||||
|
||||
/** TaxPostingIndicator AD_Reference_ID=200160 */
|
||||
public static final int TAXPOSTINGINDICATOR_AD_Reference_ID=200160;
|
||||
/** Separate Tax Posting = 0 */
|
||||
public static final String TAXPOSTINGINDICATOR_SeparateTaxPosting = "0";
|
||||
/** Distribute Tax with Relevant Expense = 1 */
|
||||
public static final String TAXPOSTINGINDICATOR_DistributeTaxWithRelevantExpense = "1";
|
||||
/** Set Posting Indicator.
|
||||
@param TaxPostingIndicator Posting Indicator
|
||||
*/
|
||||
public void setTaxPostingIndicator (String TaxPostingIndicator)
|
||||
{
|
||||
|
||||
set_Value (COLUMNNAME_TaxPostingIndicator, TaxPostingIndicator);
|
||||
}
|
||||
|
||||
/** Get Posting Indicator.
|
||||
@return Posting Indicator */
|
||||
public String getTaxPostingIndicator()
|
||||
{
|
||||
return (String)get_Value(COLUMNNAME_TaxPostingIndicator);
|
||||
}
|
||||
|
||||
/** Set To.
|
||||
@param To_Country_ID Receiving Country
|
||||
*/
|
||||
|
|
|
@ -25,14 +25,44 @@
|
|||
package org.idempiere.test.model;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
import org.adempiere.base.Core;
|
||||
import org.compiere.model.MAccount;
|
||||
import org.compiere.model.MAcctSchema;
|
||||
import org.compiere.model.MBPartner;
|
||||
import org.compiere.model.MClientInfo;
|
||||
import org.compiere.model.MCost;
|
||||
import org.compiere.model.MDocType;
|
||||
import org.compiere.model.MFactAcct;
|
||||
import org.compiere.model.MInOut;
|
||||
import org.compiere.model.MInOutLine;
|
||||
import org.compiere.model.MInvoice;
|
||||
import org.compiere.model.MInvoiceLine;
|
||||
import org.compiere.model.MMatchPO;
|
||||
import org.compiere.model.MOrder;
|
||||
import org.compiere.model.MOrderLine;
|
||||
import org.compiere.model.MPriceList;
|
||||
import org.compiere.model.MPriceListVersion;
|
||||
import org.compiere.model.MProduct;
|
||||
import org.compiere.model.MProductPrice;
|
||||
import org.compiere.model.MTax;
|
||||
import org.compiere.model.MTaxCategory;
|
||||
import org.compiere.model.MWarehouse;
|
||||
import org.compiere.model.ProductCost;
|
||||
import org.compiere.model.Tax;
|
||||
import org.compiere.process.DocAction;
|
||||
import org.compiere.process.DocumentEngine;
|
||||
import org.compiere.process.ProcessInfo;
|
||||
import org.compiere.util.CacheMgt;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.TimeUtil;
|
||||
import org.compiere.wf.MWorkflow;
|
||||
import org.idempiere.test.AbstractTestCase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -46,8 +76,11 @@ public class MTaxTest extends AbstractTestCase {
|
|||
private static final int STANDARD_TAX_ID = 104;
|
||||
private static final int STANDARD_TAX_CATEGORY_ID=107;
|
||||
|
||||
private final static int BP_JOE_BLOCK = 118;
|
||||
private static final int PRODUCT_MULCH = 137;
|
||||
private static final int BP_JOE_BLOCK_ID = 118;
|
||||
private static final int PRODUCT_MULCH_ID = 137;
|
||||
private static final int PURCHASE_PRICE_LIST_ID = 102;
|
||||
private static final int BP_PATIO_ID = 121;
|
||||
private static final int MM_RECEIPT_DOCTYPE_ID = 122;
|
||||
|
||||
public MTaxTest() {
|
||||
}
|
||||
|
@ -73,20 +106,308 @@ public class MTaxTest extends AbstractTestCase {
|
|||
int taxExemptId = Tax.getExemptTax(Env.getCtx(), getAD_Org_ID(), getTrxName());
|
||||
assertTrue(taxExemptId>0, "Fail to get tax exempt Id");
|
||||
|
||||
MBPartner bp = new MBPartner(Env.getCtx(), BP_JOE_BLOCK, getTrxName());
|
||||
MBPartner bp = new MBPartner(Env.getCtx(), BP_JOE_BLOCK_ID, getTrxName());
|
||||
bp.setIsTaxExempt(true);
|
||||
bp.saveEx();
|
||||
|
||||
int id = Core.getTaxLookup().get(Env.getCtx(), PRODUCT_MULCH, 0, getLoginDate(), getLoginDate(), getAD_Org_ID(), getM_Warehouse_ID(),
|
||||
int id = Core.getTaxLookup().get(Env.getCtx(), PRODUCT_MULCH_ID, 0, getLoginDate(), getLoginDate(), getAD_Org_ID(), getM_Warehouse_ID(),
|
||||
bp.getPrimaryC_BPartner_Location_ID(), bp.getPrimaryC_BPartner_Location_ID(), true, null, getTrxName());
|
||||
assertEquals(taxExemptId, id, "Unexpected tax id");
|
||||
|
||||
bp.setIsTaxExempt(false);
|
||||
bp.saveEx();
|
||||
|
||||
id = Core.getTaxLookup().get(Env.getCtx(), PRODUCT_MULCH, 0, getLoginDate(), getLoginDate(), getAD_Org_ID(), getM_Warehouse_ID(),
|
||||
id = Core.getTaxLookup().get(Env.getCtx(), PRODUCT_MULCH_ID, 0, getLoginDate(), getLoginDate(), getAD_Org_ID(), getM_Warehouse_ID(),
|
||||
bp.getPrimaryC_BPartner_Location_ID(), bp.getPrimaryC_BPartner_Location_ID(), true, null, getTrxName());
|
||||
assertTrue(id != taxExemptId, "Unexpected tax id: " + id);
|
||||
assertEquals(STANDARD_TAX_ID, id, "Unexpected tax id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistributeTaxToProductCost() {
|
||||
MProduct product = null;
|
||||
MTaxCategory category = null;
|
||||
MTax tax = null;
|
||||
try {
|
||||
category = new MTaxCategory(Env.getCtx(), 0, null);
|
||||
category.setName("testDistributeTaxToProductCost");
|
||||
category.saveEx();
|
||||
|
||||
//need to create tax without trx as tax is cache
|
||||
tax = new MTax(Env.getCtx(), 0, null);
|
||||
tax.setC_TaxCategory_ID(category.get_ID());
|
||||
tax.setIsDocumentLevel(false);
|
||||
tax.setIsSummary(false);
|
||||
tax.setRate(new BigDecimal("5.00"));
|
||||
tax.setTaxPostingIndicator(MTax.TAXPOSTINGINDICATOR_DistributeTaxWithRelevantExpense);
|
||||
tax.setSOPOType(MTax.SOPOTYPE_PurchaseTax);
|
||||
tax.setName("testDistributeTaxToProductCost");
|
||||
tax.saveEx();
|
||||
CacheMgt.get().reset();
|
||||
|
||||
//need to create product with trx as order line get product from cache
|
||||
MProduct p = MProduct.get(PRODUCT_MULCH_ID);
|
||||
product = new MProduct(Env.getCtx(), 0, null);
|
||||
product.setM_Product_Category_ID(p.getM_Product_Category_ID());
|
||||
product.setC_TaxCategory_ID(category.get_ID());
|
||||
product.setIsStocked(true);
|
||||
product.setIsPurchased(true);
|
||||
product.setIsSold(true);
|
||||
product.setIsStocked(true);
|
||||
product.setProductType(MProduct.PRODUCTTYPE_Item);
|
||||
product.setName("testDistributeTaxToProductCost");
|
||||
product.setC_UOM_ID(p.getC_UOM_ID());
|
||||
product.saveEx();
|
||||
|
||||
MPriceList priceList = MPriceList.get(PURCHASE_PRICE_LIST_ID);
|
||||
MPriceListVersion priceListVersion = priceList.getPriceListVersion(null);
|
||||
MProductPrice productPrice = new MProductPrice(Env.getCtx(), 0, getTrxName());
|
||||
productPrice.setM_PriceList_Version_ID(priceListVersion.get_ID());
|
||||
productPrice.setM_Product_ID(product.getM_Product_ID());
|
||||
productPrice.setPrices(new BigDecimal("2.00"), new BigDecimal("2.00"), new BigDecimal("2.00"));
|
||||
productPrice.saveEx();
|
||||
|
||||
//purchase price of 2 + 5% tax
|
||||
BigDecimal expectedCost = new BigDecimal("2.00").add(new BigDecimal("2.00").multiply(new BigDecimal("0.05"))).setScale(2, RoundingMode.HALF_EVEN);
|
||||
|
||||
MBPartner bpartner = MBPartner.get(Env.getCtx(), BP_PATIO_ID);
|
||||
MOrder order = new MOrder(Env.getCtx(), 0, getTrxName());
|
||||
order.setBPartner(bpartner);
|
||||
order.setIsSOTrx(false);
|
||||
order.setC_DocTypeTarget_ID();
|
||||
order.setDocStatus(DocAction.STATUS_Drafted);
|
||||
order.setDocAction(DocAction.ACTION_Complete);
|
||||
order.saveEx();
|
||||
|
||||
MOrderLine orderLine = new MOrderLine(order);
|
||||
orderLine.setLine(10);
|
||||
orderLine.setProduct(product);
|
||||
orderLine.setQty(new BigDecimal("1"));
|
||||
orderLine.setTax();
|
||||
orderLine.saveEx();
|
||||
|
||||
assertEquals(tax.get_ID(), orderLine.getC_Tax_ID(), "Un-expected tax id");
|
||||
|
||||
ProcessInfo info = MWorkflow.runDocumentActionWorkflow(order, DocAction.ACTION_Complete);
|
||||
assertFalse(info.isError(), info.getSummary());
|
||||
order.load(getTrxName());
|
||||
assertEquals(DocAction.STATUS_Completed, order.getDocStatus());
|
||||
assertEquals(expectedCost, order.getGrandTotal().setScale(2, RoundingMode.HALF_EVEN), "Un-expected order grand total");
|
||||
|
||||
MInOut receipt = new MInOut(order, MM_RECEIPT_DOCTYPE_ID, order.getDateOrdered()); // MM Receipt
|
||||
receipt.saveEx();
|
||||
|
||||
MWarehouse wh = MWarehouse.get(Env.getCtx(), receipt.getM_Warehouse_ID());
|
||||
int M_Locator_ID = wh.getDefaultLocator().getM_Locator_ID();
|
||||
|
||||
MInOutLine receiptLine = new MInOutLine(receipt);
|
||||
receiptLine.setOrderLine(orderLine, M_Locator_ID, new BigDecimal("1"));
|
||||
receiptLine.setLine(10);
|
||||
receiptLine.setQty(new BigDecimal("1"));
|
||||
receiptLine.saveEx();
|
||||
|
||||
info = MWorkflow.runDocumentActionWorkflow(receipt, DocAction.ACTION_Complete);
|
||||
assertFalse(info.isError(), info.getSummary());
|
||||
receipt.load(getTrxName());
|
||||
assertEquals(DocAction.STATUS_Completed, receipt.getDocStatus());
|
||||
MInvoice invoice = new MInvoice(order, MDocType.getOfDocBaseType(Env.getCtx(), MDocType.DOCBASETYPE_APInvoice)[0].getC_DocType_ID(), order.getDateAcct());
|
||||
invoice.setDocStatus(DocAction.STATUS_Drafted);
|
||||
invoice.setDocAction(DocAction.ACTION_Complete);
|
||||
invoice.saveEx();
|
||||
|
||||
MInvoiceLine invoiceLine = new MInvoiceLine(invoice);
|
||||
invoiceLine.setShipLine(receiptLine);
|
||||
invoiceLine.setLine(10);
|
||||
invoiceLine.setProduct(product);
|
||||
invoiceLine.setQty(new BigDecimal("1"));
|
||||
invoiceLine.saveEx();
|
||||
|
||||
info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Complete);
|
||||
assertFalse(info.isError(), info.getSummary());
|
||||
invoice.load(getTrxName());
|
||||
assertEquals(DocAction.STATUS_Completed, invoice.getDocStatus());
|
||||
|
||||
//ensure match po have been posted
|
||||
MMatchPO[] matchPOs = MMatchPO.getOrderLine(Env.getCtx(), orderLine.get_ID(), getTrxName());
|
||||
assertNotNull(matchPOs, "Can't retrive match po for order line");
|
||||
assertEquals(1, matchPOs.length, "Un-expected number of match po record for order line");
|
||||
if (!matchPOs[0].isPosted())
|
||||
DocumentEngine.postImmediate(Env.getCtx(), getAD_Client_ID(), MMatchPO.Table_ID, matchPOs[0].get_ID(), true, getTrxName());
|
||||
ProductCost productCost = new ProductCost(Env.getCtx(), product.get_ID(), 0, getTrxName());
|
||||
productCost.setQty(new BigDecimal("1"));
|
||||
MAcctSchema schema = MClientInfo.get().getMAcctSchema1();
|
||||
BigDecimal averageCost = productCost.getProductCosts(schema, getAD_Org_ID(), MCost.COSTINGMETHOD_AveragePO, 0, true);
|
||||
if (averageCost == null)
|
||||
averageCost = BigDecimal.ZERO;
|
||||
averageCost = averageCost.setScale(2, RoundingMode.HALF_EVEN);
|
||||
assertEquals(expectedCost, averageCost, "Un-expected average cost");
|
||||
|
||||
MAccount acctAsset = productCost.getAccount(ProductCost.ACCTTYPE_P_Asset, schema);
|
||||
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MInOut.Table_ID
|
||||
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + receipt.get_ID()
|
||||
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + schema.getC_AcctSchema_ID();
|
||||
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
|
||||
BigDecimal totalDebit = new BigDecimal("0.00");
|
||||
for(int id : ids) {
|
||||
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
|
||||
if (fa.getAccount_ID() == acctAsset.getAccount_ID()) {
|
||||
totalDebit = totalDebit.add(fa.getAmtAcctDr());
|
||||
}
|
||||
}
|
||||
assertEquals(expectedCost, totalDebit.setScale(2, RoundingMode.HALF_EVEN), "Un-expected product asset account posted amount");
|
||||
} finally {
|
||||
rollback();
|
||||
if (product != null && product.get_ID() > 0)
|
||||
product.deleteEx(true);
|
||||
if (tax != null && tax.get_ID() > 0)
|
||||
tax.deleteEx(true);
|
||||
if (category != null && category.get_ID() > 0)
|
||||
category.deleteEx(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSeparateTaxPosting() {
|
||||
MProduct product = null;
|
||||
MTaxCategory category = null;
|
||||
MTax tax = null;
|
||||
try {
|
||||
category = new MTaxCategory(Env.getCtx(), 0, null);
|
||||
category.setName("testSeparateTaxPosting");
|
||||
category.saveEx();
|
||||
|
||||
//need to create tax without trx as tax is cache
|
||||
tax = new MTax(Env.getCtx(), 0, null);
|
||||
tax.setC_TaxCategory_ID(category.get_ID());
|
||||
tax.setIsDocumentLevel(false);
|
||||
tax.setIsSummary(false);
|
||||
tax.setRate(new BigDecimal("5.00"));
|
||||
tax.setTaxPostingIndicator(MTax.TAXPOSTINGINDICATOR_SeparateTaxPosting);
|
||||
tax.setSOPOType(MTax.SOPOTYPE_PurchaseTax);
|
||||
tax.setName("testSeparateTaxPosting");
|
||||
tax.saveEx();
|
||||
CacheMgt.get().reset();
|
||||
|
||||
//need to create product with trx as order line get product from cache
|
||||
MProduct p = MProduct.get(PRODUCT_MULCH_ID);
|
||||
product = new MProduct(Env.getCtx(), 0, null);
|
||||
product.setM_Product_Category_ID(p.getM_Product_Category_ID());
|
||||
product.setC_TaxCategory_ID(category.get_ID());
|
||||
product.setIsStocked(true);
|
||||
product.setIsPurchased(true);
|
||||
product.setIsSold(true);
|
||||
product.setIsStocked(true);
|
||||
product.setProductType(MProduct.PRODUCTTYPE_Item);
|
||||
product.setName("testSeparateTaxPosting");
|
||||
product.setC_UOM_ID(p.getC_UOM_ID());
|
||||
product.saveEx();
|
||||
|
||||
MPriceList priceList = MPriceList.get(PURCHASE_PRICE_LIST_ID);
|
||||
MPriceListVersion priceListVersion = priceList.getPriceListVersion(null);
|
||||
MProductPrice productPrice = new MProductPrice(Env.getCtx(), 0, getTrxName());
|
||||
productPrice.setM_PriceList_Version_ID(priceListVersion.get_ID());
|
||||
productPrice.setM_Product_ID(product.getM_Product_ID());
|
||||
productPrice.setPrices(new BigDecimal("2.00"), new BigDecimal("2.00"), new BigDecimal("2.00"));
|
||||
productPrice.saveEx();
|
||||
|
||||
//purchase price of 2
|
||||
BigDecimal expectedCost = new BigDecimal("2.00").setScale(2, RoundingMode.HALF_EVEN);
|
||||
//purchase price of 2 + 5% tax
|
||||
BigDecimal expectedTotal = new BigDecimal("2.00").add(new BigDecimal("2.00").multiply(new BigDecimal("0.05"))).setScale(2, RoundingMode.HALF_EVEN);
|
||||
|
||||
MBPartner bpartner = MBPartner.get(Env.getCtx(), BP_PATIO_ID);
|
||||
MOrder order = new MOrder(Env.getCtx(), 0, getTrxName());
|
||||
order.setBPartner(bpartner);
|
||||
order.setIsSOTrx(false);
|
||||
order.setC_DocTypeTarget_ID();
|
||||
order.setDocStatus(DocAction.STATUS_Drafted);
|
||||
order.setDocAction(DocAction.ACTION_Complete);
|
||||
order.saveEx();
|
||||
|
||||
MOrderLine orderLine = new MOrderLine(order);
|
||||
orderLine.setLine(10);
|
||||
orderLine.setProduct(product);
|
||||
orderLine.setQty(new BigDecimal("1"));
|
||||
orderLine.setTax();
|
||||
orderLine.saveEx();
|
||||
|
||||
assertEquals(tax.get_ID(), orderLine.getC_Tax_ID(), "Un-expected tax id");
|
||||
|
||||
ProcessInfo info = MWorkflow.runDocumentActionWorkflow(order, DocAction.ACTION_Complete);
|
||||
assertFalse(info.isError(), info.getSummary());
|
||||
order.load(getTrxName());
|
||||
assertEquals(DocAction.STATUS_Completed, order.getDocStatus());
|
||||
assertEquals(expectedTotal, order.getGrandTotal().setScale(2, RoundingMode.HALF_EVEN), "Un-expected order grand total");
|
||||
|
||||
MInOut receipt = new MInOut(order, MM_RECEIPT_DOCTYPE_ID, order.getDateOrdered()); // MM Receipt
|
||||
receipt.saveEx();
|
||||
|
||||
MWarehouse wh = MWarehouse.get(Env.getCtx(), receipt.getM_Warehouse_ID());
|
||||
int M_Locator_ID = wh.getDefaultLocator().getM_Locator_ID();
|
||||
|
||||
MInOutLine receiptLine = new MInOutLine(receipt);
|
||||
receiptLine.setOrderLine(orderLine, M_Locator_ID, new BigDecimal("1"));
|
||||
receiptLine.setLine(10);
|
||||
receiptLine.setQty(new BigDecimal("1"));
|
||||
receiptLine.saveEx();
|
||||
|
||||
info = MWorkflow.runDocumentActionWorkflow(receipt, DocAction.ACTION_Complete);
|
||||
assertFalse(info.isError(), info.getSummary());
|
||||
receipt.load(getTrxName());
|
||||
assertEquals(DocAction.STATUS_Completed, receipt.getDocStatus());
|
||||
MInvoice invoice = new MInvoice(order, MDocType.getOfDocBaseType(Env.getCtx(), MDocType.DOCBASETYPE_APInvoice)[0].getC_DocType_ID(), order.getDateAcct());
|
||||
invoice.setDocStatus(DocAction.STATUS_Drafted);
|
||||
invoice.setDocAction(DocAction.ACTION_Complete);
|
||||
invoice.saveEx();
|
||||
|
||||
MInvoiceLine invoiceLine = new MInvoiceLine(invoice);
|
||||
invoiceLine.setShipLine(receiptLine);
|
||||
invoiceLine.setLine(10);
|
||||
invoiceLine.setProduct(product);
|
||||
invoiceLine.setQty(new BigDecimal("1"));
|
||||
invoiceLine.saveEx();
|
||||
|
||||
info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Complete);
|
||||
assertFalse(info.isError(), info.getSummary());
|
||||
invoice.load(getTrxName());
|
||||
assertEquals(DocAction.STATUS_Completed, invoice.getDocStatus());
|
||||
|
||||
//ensure match po have been posted
|
||||
MMatchPO[] matchPOs = MMatchPO.getOrderLine(Env.getCtx(), orderLine.get_ID(), getTrxName());
|
||||
assertNotNull(matchPOs, "Can't retrive match po for order line");
|
||||
assertEquals(1, matchPOs.length, "Un-expected number of match po record for order line");
|
||||
if (!matchPOs[0].isPosted())
|
||||
DocumentEngine.postImmediate(Env.getCtx(), getAD_Client_ID(), MMatchPO.Table_ID, matchPOs[0].get_ID(), true, getTrxName());
|
||||
ProductCost productCost = new ProductCost(Env.getCtx(), product.get_ID(), 0, getTrxName());
|
||||
productCost.setQty(new BigDecimal("1"));
|
||||
MAcctSchema schema = MClientInfo.get().getMAcctSchema1();
|
||||
BigDecimal averageCost = productCost.getProductCosts(schema, getAD_Org_ID(), MCost.COSTINGMETHOD_AveragePO, 0, true);
|
||||
if (averageCost == null)
|
||||
averageCost = BigDecimal.ZERO;
|
||||
averageCost = averageCost.setScale(2, RoundingMode.HALF_EVEN);
|
||||
assertEquals(expectedCost, averageCost, "Un-expected average cost");
|
||||
|
||||
MAccount acctAsset = productCost.getAccount(ProductCost.ACCTTYPE_P_Asset, schema);
|
||||
String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MInOut.Table_ID
|
||||
+ " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + receipt.get_ID()
|
||||
+ " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + schema.getC_AcctSchema_ID();
|
||||
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
|
||||
BigDecimal totalDebit = new BigDecimal("0.00");
|
||||
for(int id : ids) {
|
||||
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
|
||||
if (fa.getAccount_ID() == acctAsset.getAccount_ID()) {
|
||||
totalDebit = totalDebit.add(fa.getAmtAcctDr());
|
||||
}
|
||||
}
|
||||
assertEquals(expectedCost, totalDebit.setScale(2, RoundingMode.HALF_EVEN), "Un-expected product asset account posted amount");
|
||||
} finally {
|
||||
rollback();
|
||||
if (product != null && product.get_ID() > 0)
|
||||
product.deleteEx(true);
|
||||
if (tax != null && tax.get_ID() > 0)
|
||||
tax.deleteEx(true);
|
||||
if (category != null && category.get_ID() > 0)
|
||||
category.deleteEx(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue