diff --git a/.liquibase/Data_alias/basic/2021.0.3/Checklists/change_phase_translation.xml b/.liquibase/Data_alias/basic/2021.0.3/Checklists/change_phase_translation.xml new file mode 100644 index 0000000000000000000000000000000000000000..a9c905e3140bee13d7a4972bd71e74c8b51f0796 --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/Checklists/change_phase_translation.xml @@ -0,0 +1,28 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <changeSet author="p.neub" id="79f72a80-0830-4185-a9cd-bb51b3d0c432"> + <update tableName="AB_KEYWORD_ENTRY"> + <column name="TITLE" value="${SALESPROJECT_PROSPECT}"/> + <where>AB_KEYWORD_ENTRYID = ?</where> + <whereParams> + <param value="5729d9c0-3884-4cd4-b6e0-009718913914"/> + </whereParams> + </update> + <update tableName="AB_KEYWORD_ENTRY"> + <column name="TITLE" value="${SALESPROJECT_LEAD}"/> + <where>AB_KEYWORD_ENTRYID = ?</where> + <whereParams> + <param value="98f46a57-a27d-4394-990a-c13513bbea3b"/> + </whereParams> + </update> + <update tableName="AB_KEYWORD_ENTRY"> + <column name="TITLE" value="${SALESPROJECT_CONTACT}"/> + <where>AB_KEYWORD_ENTRYID = ?</where> + <whereParams> + <param value="bc24b535-a226-47a3-b43d-bd739f8c9237"/> + </whereParams> + </update> + </changeSet> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/2021.0.3/Checklists/changelog.xml b/.liquibase/Data_alias/basic/2021.0.3/Checklists/changelog.xml new file mode 100644 index 0000000000000000000000000000000000000000..15bb01b42ab844870300a7b407ddbbea116bcf92 --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/Checklists/changelog.xml @@ -0,0 +1,11 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <include relativeToChangelogFile="true" file="update_phase.xml"/> + <include relativeToChangelogFile="true" file="update_checklistentry.xml"/> + <include relativeToChangelogFile="true" file="update_salesproject.xml"/> + <include relativeToChangelogFile="true" file="update_keyword.xml"/> + <include relativeToChangelogFile="true" file="update_ab_attributeusage_salesprojectorigin.xml"/> + <include relativeToChangelogFile="true" file="change_phase_translation.xml"/> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/2021.0.3/Checklists/update_ab_attributeusage_salesprojectorigin.xml b/.liquibase/Data_alias/basic/2021.0.3/Checklists/update_ab_attributeusage_salesprojectorigin.xml new file mode 100644 index 0000000000000000000000000000000000000000..e862924805fe7983d1720ca09354d22cb29e5850 --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/Checklists/update_ab_attributeusage_salesprojectorigin.xml @@ -0,0 +1,56 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <changeSet author="p.neub" id="cdd3790e-0f62-4169-9e74-c096dc56ede3"> + <insert tableName="AB_ATTRIBUTEUSAGE"> + <column name="MAX_COUNT" valueNumeric="1"/> + <column name="AB_ATTRIBUTEUSAGEID" value="47cffdf2-75b0-4395-8d3f-f8b4e1ecb3e6"/> + <column name="OBJECT_TYPE" value="Salesproject"/> + <column name="MIN_COUNT"/> + <column name="AB_ATTRIBUTE_ID" value="a6eee141-5ed6-4b87-986f-29e3fdccaf13"/> + </insert> + <insert tableName="AB_ATTRIBUTEUSAGE"> + <column name="MAX_COUNT" valueNumeric="1"/> + <column name="AB_ATTRIBUTEUSAGEID" value="dc9d8f2c-8381-4299-9b2a-d884852139c3"/> + <column name="OBJECT_TYPE" value="Salesproject"/> + <column name="MIN_COUNT"/> + <column name="AB_ATTRIBUTE_ID" value="d0ae40d2-1a7f-45f6-bb0c-20ce6ae7efe2"/> + </insert> + <insert tableName="AB_ATTRIBUTEUSAGE"> + <column name="MAX_COUNT" valueNumeric="1"/> + <column name="AB_ATTRIBUTEUSAGEID" value="16a1a657-f7d5-413c-9ec4-fb640c12d2b6"/> + <column name="OBJECT_TYPE" value="Salesproject"/> + <column name="MIN_COUNT"/> + <column name="AB_ATTRIBUTE_ID" value="956622a7-03b3-42a4-a7ef-f8936d92cff9"/> + </insert> + <insert tableName="AB_ATTRIBUTEUSAGE"> + <column name="MAX_COUNT" valueNumeric="1"/> + <column name="AB_ATTRIBUTEUSAGEID" value="d1c2cfac-f222-4022-9757-cea993c52bac"/> + <column name="OBJECT_TYPE" value="Salesproject"/> + <column name="MIN_COUNT"/> + <column name="AB_ATTRIBUTE_ID" value="f0f0b150-ea60-46e5-ba4f-727c78c993d0"/> + </insert> + <insert tableName="AB_ATTRIBUTEUSAGE"> + <column name="MAX_COUNT" valueNumeric="1"/> + <column name="AB_ATTRIBUTEUSAGEID" value="6f7972fb-8d04-4a81-a989-76a0cfb25d4f"/> + <column name="OBJECT_TYPE" value="Salesproject"/> + <column name="MIN_COUNT"/> + <column name="AB_ATTRIBUTE_ID" value="c5f8b5f7-ddc0-4c88-bebd-be96fd37bb9c"/> + </insert> + <insert tableName="AB_ATTRIBUTEUSAGE"> + <column name="MAX_COUNT" valueNumeric="1"/> + <column name="AB_ATTRIBUTEUSAGEID" value="789507e9-b665-46db-9c6d-0efee34a3f38"/> + <column name="OBJECT_TYPE" value="Salesproject"/> + <column name="MIN_COUNT"/> + <column name="AB_ATTRIBUTE_ID" value="262a8fbe-d6ef-4949-87ce-6202967136d7"/> + </insert> + <insert tableName="AB_ATTRIBUTEUSAGE"> + <column name="MAX_COUNT" valueNumeric="1"/> + <column name="AB_ATTRIBUTEUSAGEID" value="a940b942-f5b8-4108-b986-9803e282ca3c"/> + <column name="OBJECT_TYPE" value="Salesproject"/> + <column name="MIN_COUNT"/> + <column name="AB_ATTRIBUTE_ID" value="67edd12f-93cc-45d4-b86a-b59d19936442"/> + </insert> + </changeSet> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/2021.0.3/Checklists/update_checklistentry.xml b/.liquibase/Data_alias/basic/2021.0.3/Checklists/update_checklistentry.xml new file mode 100644 index 0000000000000000000000000000000000000000..384be08ae0fb2cad74820bf26b5536809a3af1b7 --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/Checklists/update_checklistentry.xml @@ -0,0 +1,53 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <changeSet author="p.neub" id="eb84935b-98d4-45a5-8e67-7188bdd76135"> + <delete tableName="CHECKLISTENTRYVALUE"> + <where>CHECKLISTENTRYVALUEID = ?</where> + <whereParams> + <param value="c4dc8c1e-e291-4d3f-8b36-cd8a0960abbf"/> + </whereParams> + </delete> + <delete tableName="CHECKLISTENTRYVALUE"> + <where>CHECKLISTENTRYVALUEID = ?</where> + <whereParams> + <param value="e12dbddc-301f-4da5-b48d-3fabad4c8634"/> + </whereParams> + </delete> + + <!--Contact--> + <update tableName="CHECKLISTENTRY"> + <column name="CHECKLIST_ID" value="179dcc0d-e6fa-411d-b5ee-cb25b9735dbe"></column> + <where>CHECKLIST_ID = ?</where> + <whereParams> + <param value="179dcc0d-e6fa-411d-b5ee-cb25b9735dbe"/> + </whereParams> + </update> + + <!--Lead--> + <update tableName="CHECKLISTENTRY"> + <column name="CHECKLIST_ID" value="3d0f1d25-cee8-4b83-a0de-3fded83ff9c4"></column> + <where>CHECKLIST_ID = ?</where> + <whereParams> + <param value="cb340ed2-ea49-45bb-a7a0-1a4f88d6e138"/> + </whereParams> + </update> + <update tableName="CHECKLISTENTRY"> + <column name="CHECKLIST_ID" value="3d0f1d25-cee8-4b83-a0de-3fded83ff9c4"></column> + <where>CHECKLIST_ID = ?</where> + <whereParams> + <param value="c2bb548c-2f0c-45be-9e49-2ebf86bd6ab8"/> + </whereParams> + </update> + + <!--Offer--> + <update tableName="CHECKLISTENTRY"> + <column name="CHECKLIST_ID" value="0f95ce44-3b0d-417b-969f-f84897868558"></column> + <where>CHECKLIST_ID = ?</where> + <whereParams> + <param value="c7b847b1-934a-4592-8c10-53da1d43dc4c"/> + </whereParams> + </update> + </changeSet> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/2021.0.3/Checklists/update_keyword.xml b/.liquibase/Data_alias/basic/2021.0.3/Checklists/update_keyword.xml new file mode 100644 index 0000000000000000000000000000000000000000..db309c871c68e5f9c9b02f6904d23cc363da15ec --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/Checklists/update_keyword.xml @@ -0,0 +1,190 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <changeSet author="p.neub" id="79f72a80-0830-4185-a9cd-bb51b3d0c432"> + <!--long names--> + <delete tableName="AB_KEYWORD_ATTRIBUTE"> + <where>AB_KEYWORD_ATTRIBUTEID = ?</where> + <whereParams> + <param value="f1413a2f-6631-4255-9dc9-a28e6eb30497"/> + </whereParams> + </delete> + <delete tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <where>AB_KEYWORD_ATTRIBUTERELATIONID = ?</where> + <whereParams> + <param value="4b4045ac-913c-4618-b6be-9458c2094d21"/> + </whereParams> + </delete> + <delete tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <where>AB_KEYWORD_ATTRIBUTERELATIONID = ?</where> + <whereParams> + <param value="b6a9f74b-bfc0-41b5-ac97-48f059cd1051"/> + </whereParams> + </delete> + <delete tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <where>AB_KEYWORD_ATTRIBUTERELATIONID = ?</where> + <whereParams> + <param value="77370a25-7b08-4a75-b09b-ff806c184a12"/> + </whereParams> + </delete> + <delete tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <where>AB_KEYWORD_ATTRIBUTERELATIONID = ?</where> + <whereParams> + <param value="16fd4267-46d0-4d66-8241-ad620ba359e0"/> + </whereParams> + </delete> + <delete tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <where>AB_KEYWORD_ATTRIBUTERELATIONID = ?</where> + <whereParams> + <param value="846c6387-56b0-45b5-8f4b-71f1177d7c25"/> + </whereParams> + </delete> + <delete tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <where>AB_KEYWORD_ATTRIBUTERELATIONID = ?</where> + <whereParams> + <param value="4284c1b3-c217-43b5-a06f-462626aadfdc"/> + </whereParams> + </delete> + <delete tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <where>AB_KEYWORD_ATTRIBUTERELATIONID = ?</where> + <whereParams> + <param value="945097dd-590f-4c53-bb33-5d425516495e"/> + </whereParams> + </delete> + <delete tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <where>AB_KEYWORD_ATTRIBUTERELATIONID = ?</where> + <whereParams> + <param value="440bd4c0-9d2a-4adc-a4ee-15aa8109a265"/> + </whereParams> + </delete> + + <!--icons--> + <delete tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <where>AB_KEYWORD_ATTRIBUTERELATIONID = ?</where> + <whereParams> + <param value="10974128-6961-43eb-9605-e747c1b795cd"/> + </whereParams> + </delete> + <delete tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <where>AB_KEYWORD_ATTRIBUTERELATIONID = ?</where> + <whereParams> + <param value="d487ac11-b85b-4489-89e1-1e93353ad9e9"/> + </whereParams> + </delete> + <delete tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <where>AB_KEYWORD_ATTRIBUTERELATIONID = ?</where> + <whereParams> + <param value="d109b169-f14a-4383-af43-f30c6d357971"/> + </whereParams> + </delete> + <delete tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <where>AB_KEYWORD_ATTRIBUTERELATIONID = ?</where> + <whereParams> + <param value="dbe97653-4b14-4f53-8bd8-ea36714d20e7"/> + </whereParams> + </delete> + <delete tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <where>AB_KEYWORD_ATTRIBUTERELATIONID = ?</where> + <whereParams> + <param value="f800d56a-f1e7-443b-849f-e041ff99f70a"/> + </whereParams> + </delete> + <delete tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <where>AB_KEYWORD_ATTRIBUTERELATIONID = ?</where> + <whereParams> + <param value="47b06455-e68b-4c1f-a174-6f5c108b0369"/> + </whereParams> + </delete> + <insert tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <column name="AB_KEYWORD_ENTRY_ID" value="bc24b535-a226-47a3-b43d-bd739f8c9237"/> + <column name="AB_KEYWORD_ATTRIBUTE_ID" value="93d60e4b-e984-423e-b97f-d2abf61de41d"/> + <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="b5c5534f-c3de-4c20-ace6-6edfebad60d7"/> + <column name="CHAR_VALUE" value="NEON:NQC"/> + </insert> + <insert tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <column name="AB_KEYWORD_ENTRY_ID" value="98f46a57-a27d-4394-990a-c13513bbea3b"/> + <column name="AB_KEYWORD_ATTRIBUTE_ID" value="93d60e4b-e984-423e-b97f-d2abf61de41d"/> + <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="3fb1d15f-be69-429c-9ca5-a48cdb7156ee"/> + <column name="CHAR_VALUE" value="NEON:MAL"/> + </insert> + <insert tableName="AB_KEYWORD_ATTRIBUTERELATION"> + <column name="AB_KEYWORD_ENTRY_ID" value="5729d9c0-3884-4cd4-b6e0-009718913914"/> + <column name="AB_KEYWORD_ATTRIBUTE_ID" value="93d60e4b-e984-423e-b97f-d2abf61de41d"/> + <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="d8d7f9e9-4b1b-43fb-9224-f72b2ee1bcbb"/> + <column name="CHAR_VALUE" value="NEON:MQL"/> + </insert> + + <!--keywords--> + <!--keywords.contact--> + <delete tableName="AB_KEYWORD_ENTRY"> + <where>AB_KEYWORD_ENTRYID = ?</where> + <whereParams> + <param value="b42caac9-8f8f-46e5-9f1c-d121cdf3ad8f"/> + </whereParams> + </delete> + <delete tableName="AB_KEYWORD_ENTRY"> + <where>AB_KEYWORD_ENTRYID = ?</where> + <whereParams> + <param value="028af5dd-1071-4108-8685-ed7124376706"/> + </whereParams> + </delete> + <insert tableName="AB_KEYWORD_ENTRY"> + <column name="CONTAINER" value="SalesprojectPhase"/> + <column name="SORTING" valueNumeric="0"/> + <column name="ISACTIVE" valueNumeric="1"/> + <column name="AB_KEYWORD_CATEGORY_ID" value="923217a2-991e-444a-9a86-c3f56ba90f93"/> + <column name="ISESSENTIAL" valueNumeric="0"/> + <column name="KEYID" value="SALPROJPHASECONTACT"/> + <column name="AB_KEYWORD_ENTRYID" value="bc24b535-a226-47a3-b43d-bd739f8c9237"/> + <column name="TITLE" value="Contact"/> + </insert> + <!--keywords.lead--> + <delete tableName="AB_KEYWORD_ENTRY"> + <where>AB_KEYWORD_ENTRYID = ?</where> + <whereParams> + <param value="8a2d19c9-bc32-437e-9261-78ed30110e92"/> + </whereParams> + </delete> + <delete tableName="AB_KEYWORD_ENTRY"> + <where>AB_KEYWORD_ENTRYID = ?</where> + <whereParams> + <param value="46f55a58-dbe4-40ae-9306-481df9095088"/> + </whereParams> + </delete> + <delete tableName="AB_KEYWORD_ENTRY"> + <where>AB_KEYWORD_ENTRYID = ?</where> + <whereParams> + <param value="afa8cf58-07e8-4ee9-b24e-96cb6fa76aec"/> + </whereParams> + </delete> + <insert tableName="AB_KEYWORD_ENTRY"> + <column name="CONTAINER" value="SalesprojectPhase"/> + <column name="SORTING" valueNumeric="1"/> + <column name="ISACTIVE" valueNumeric="1"/> + <column name="AB_KEYWORD_CATEGORY_ID" value="923217a2-991e-444a-9a86-c3f56ba90f93"/> + <column name="ISESSENTIAL" valueNumeric="0"/> + <column name="KEYID" value="SALPROJPHASELEAD"/> + <column name="AB_KEYWORD_ENTRYID" value="98f46a57-a27d-4394-990a-c13513bbea3b"/> + <column name="TITLE" value="Lead"/> + </insert> + <!--keywords.offer--> + <delete tableName="AB_KEYWORD_ENTRY"> + <where>AB_KEYWORD_ENTRYID = ?</where> + <whereParams> + <param value="c9483fb9-c295-43d2-94e0-8c949cf6dc47"/> + </whereParams> + </delete> + <!--keywords.prospect--> + <insert tableName="AB_KEYWORD_ENTRY"> + <column name="CONTAINER" value="SalesprojectPhase"/> + <column name="SORTING" valueNumeric="2"/> + <column name="ISACTIVE" valueNumeric="1"/> + <column name="AB_KEYWORD_CATEGORY_ID" value="923217a2-991e-444a-9a86-c3f56ba90f93"/> + <column name="ISESSENTIAL" valueNumeric="0"/> + <column name="KEYID" value="SALPROJPHASEPROS"/> + <column name="AB_KEYWORD_ENTRYID" value="5729d9c0-3884-4cd4-b6e0-009718913914"/> + <column name="TITLE" value="Prospect"/> + </insert> + </changeSet> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/2021.0.3/Checklists/update_phase.xml b/.liquibase/Data_alias/basic/2021.0.3/Checklists/update_phase.xml new file mode 100644 index 0000000000000000000000000000000000000000..837a9380da71b2d37b0cf7dbde31e6cca57d9313 --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/Checklists/update_phase.xml @@ -0,0 +1,99 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <changeSet author="p.neub" id="d204fc4f-f670-4df6-86ae-8a57a1fce5ae"> + <delete tableName="SALESPROJECTPHASEDEFINITION"/> + <delete tableName="CHECKLIST"/> + + <insert tableName="SALESPROJECTPHASEDEFINITION"> + <column name="PHASE" value="SALPROJPHASECONTACT"/> + <column name="CHECKLIST_ID" value="179dcc0d-e6fa-411d-b5ee-cb25b9735dbe"/> + <column name="DATE_EDIT"/> + <column name="DESCRIPTION" value="Voraussetzungen für die Phase: 'Contact'."/> + <column name="USER_EDIT"/> + <column name="USER_NEW" value="Admin"/> + <column name="SALESPROJECTPHASEDEFINITIONID" value="176e43db-1665-49b9-9c35-5c5c0aa135f3"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLIST"> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTID" value="179dcc0d-e6fa-411d-b5ee-cb25b9735dbe"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + + <insert tableName="SALESPROJECTPHASEDEFINITION"> + <column name="PHASE" value="SALPROJPHASELEAD"/> + <column name="CHECKLIST_ID" value="3d0f1d25-cee8-4b83-a0de-3fded83ff9c4"/> + <column name="DATE_EDIT"/> + <column name="DESCRIPTION" value="Voraussetzungen für die Phase: 'Lead'."/> + <column name="USER_EDIT"/> + <column name="USER_NEW" value="Admin"/> + <column name="SALESPROJECTPHASEDEFINITIONID" value="d29dcde8-24b4-470a-8189-1e2b0d812daa"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLIST"> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTID" value="3d0f1d25-cee8-4b83-a0de-3fded83ff9c4"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + + <insert tableName="SALESPROJECTPHASEDEFINITION"> + <column name="PHASE" value="SALPROJPHASEPROS"/> + <column name="CHECKLIST_ID" value="ecf50252-e0c2-4e7a-8cc6-078b5978d2c5"/> + <column name="DATE_EDIT"/> + <column name="DESCRIPTION" value="Voraussetzungen für die Phase: 'Prospect'."/> + <column name="USER_EDIT"/> + <column name="USER_NEW" value="Admin"/> + <column name="SALESPROJECTPHASEDEFINITIONID" value="d9605427-ba6b-42b2-8376-51e4ef654814"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLIST"> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTID" value="ecf50252-e0c2-4e7a-8cc6-078b5978d2c5"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + + <insert tableName="SALESPROJECTPHASEDEFINITION"> + <column name="PHASE" value="SALPROJPHASEOFFER"/> + <column name="CHECKLIST_ID" value="0f95ce44-3b0d-417b-969f-f84897868558"/> + <column name="DATE_EDIT"/> + <column name="DESCRIPTION" value="Voraussetzungen für die Phase: 'Offer'."/> + <column name="USER_EDIT"/> + <column name="USER_NEW" value="Admin"/> + <column name="SALESPROJECTPHASEDEFINITIONID" value="e8ff463f-692c-40a7-bafa-d168886700fd"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLIST"> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTID" value="0f95ce44-3b0d-417b-969f-f84897868558"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + + <insert tableName="SALESPROJECTPHASEDEFINITION"> + <column name="PHASE" value="SALPROJPHASENEGO"/> + <column name="CHECKLIST_ID" value="cb0357c9-a222-4d78-b2c5-035fffe3bb51"/> + <column name="DATE_EDIT"/> + <column name="DESCRIPTION" value="Voraussetzungen für die Phase: 'Negotiation'."/> + <column name="USER_EDIT"/> + <column name="USER_NEW" value="Admin"/> + <column name="SALESPROJECTPHASEDEFINITIONID" value="21011181-fe9f-4c6c-910e-344ce10e3fc1"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLIST"> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTID" value="cb0357c9-a222-4d78-b2c5-035fffe3bb51"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + </changeSet> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/2021.0.3/Checklists/update_salesproject.xml b/.liquibase/Data_alias/basic/2021.0.3/Checklists/update_salesproject.xml new file mode 100644 index 0000000000000000000000000000000000000000..8e16c2d4664e4ec52c3804b79e3ac17a3c36b2f7 --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/Checklists/update_salesproject.xml @@ -0,0 +1,54 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <changeSet author="p.neub" id="a627624f-e0a8-47d7-bce1-7e4bea790bb6"> + <!--Contact--> + <update tableName="SALESPROJECT"> + <column name="PHASE" value="SALPROJPHASECONTACT"></column> + <where>PHASE = ?</where> + <whereParams> + <param value="SALPROJPHASENQC"/> + </whereParams> + </update> + <update tableName="SALESPROJECT"> + <column name="PHASE" value="SALPROJPHASECONTACT"></column> + <where>PHASE = ?</where> + <whereParams> + <param value="SALPROJPHASEMQC"/> + </whereParams> + </update> + + <!--Lead--> + <update tableName="SALESPROJECT"> + <column name="PHASE" value="SALPROJPHASELEAD"></column> + <where>PHASE = ?</where> + <whereParams> + <param value="SALPROJPHASEMAL"/> + </whereParams> + </update> + <update tableName="SALESPROJECT"> + <column name="PHASE" value="SALPROJPHASELEAD"></column> + <where>PHASE = ?</where> + <whereParams> + <param value="SALPROJPHASEMQL"/> + </whereParams> + </update> + <update tableName="SALESPROJECT"> + <column name="PHASE" value="SALPROJPHASELEAD"></column> + <where>PHASE = ?</where> + <whereParams> + <param value="SALPROJPHASESAL"/> + </whereParams> + </update> + + <!--Offer--> + <update tableName="SALESPROJECT"> + <column name="PHASE" value="SALPROJPHASEOFFER"></column> + <where>PHASE = ?</where> + <whereParams> + <param value="SALPROJPHASESQO"/> + </whereParams> + </update> + </changeSet> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/2021.0.3/Planning/addKeywordForecastKind.xml b/.liquibase/Data_alias/basic/2021.0.3/Planning/addKeywordForecastKind.xml new file mode 100644 index 0000000000000000000000000000000000000000..c33bd4d89b784ce195f84eb29a02225120ec177e --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/Planning/addKeywordForecastKind.xml @@ -0,0 +1,32 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <changeSet author="j.luginger" id="26f06b1d-c550-4a6c-81a5-c9f061c7f50f"> + + <insert tableName="AB_KEYWORD_CATEGORY"> + <column name="AB_KEYWORD_CATEGORYID" value="9c26220e-0bdc-4f3a-bbf6-058198b0f038"/> + <column name="NAME" value="ForecastKind"/> + <column name="SORTINGBY" valueNumeric="0"/> + <column name="SORTINGDIRECTION" value="ASC"/> + </insert> + <insert tableName="AB_KEYWORD_ENTRY"> + <column name="AB_KEYWORD_ENTRYID" value="092318cc-fe67-4f9a-a18d-1e59d894fd58"/> + <column name="KEYID" value="FORECAST"/> + <column name="TITLE" value="Forecast"/> + <column name="AB_KEYWORD_CATEGORY_ID" value="9c26220e-0bdc-4f3a-bbf6-058198b0f038"/> + <column name="SORTING" valueNumeric="0"/> + <column name="ISACTIVE" valueNumeric="1"/> + <column name="ISESSENTIAL" valueNumeric="0"/> + </insert> + <insert tableName="AB_KEYWORD_ENTRY"> + <column name="AB_KEYWORD_ENTRYID" value="3b6cbb84-c05c-49fe-a46b-7c0295d41e6d"/> + <column name="KEYID" value="PLANNING"/> + <column name="TITLE" value="Planning"/> + <column name="AB_KEYWORD_CATEGORY_ID" value="9c26220e-0bdc-4f3a-bbf6-058198b0f038"/> + <column name="SORTING" valueNumeric="1"/> + <column name="ISACTIVE" valueNumeric="1"/> + <column name="ISESSENTIAL" valueNumeric="0"/> + </insert> + </changeSet> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/2021.0.3/Planning/addKeywordForecastStatus.xml b/.liquibase/Data_alias/basic/2021.0.3/Planning/addKeywordForecastStatus.xml new file mode 100644 index 0000000000000000000000000000000000000000..a5b05589beb6f9533ca93aa8b8eb4431048caee3 --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/Planning/addKeywordForecastStatus.xml @@ -0,0 +1,41 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <changeSet author="j.luginger" id="d25d18dd-c39c-49ed-9c58-4806f7426ef7"> + + <insert tableName="AB_KEYWORD_CATEGORY"> + <column name="AB_KEYWORD_CATEGORYID" value="ec675c54-405d-4564-879d-d537c220661a"/> + <column name="NAME" value="ForecastStatus"/> + <column name="SORTINGBY" valueNumeric="0"/> + <column name="SORTINGDIRECTION" value="ASC"/> + </insert> + <insert tableName="AB_KEYWORD_ENTRY"> + <column name="AB_KEYWORD_ENTRYID" value="37f8088f-ee2c-47ea-85ec-a43f96ee922a"/> + <column name="KEYID" value="IN_PLANNING"/> + <column name="TITLE" value="In planning"/> + <column name="AB_KEYWORD_CATEGORY_ID" value="ec675c54-405d-4564-879d-d537c220661a"/> + <column name="SORTING" valueNumeric="0"/> + <column name="ISACTIVE" valueNumeric="1"/> + <column name="ISESSENTIAL" valueNumeric="0"/> + </insert> + <insert tableName="AB_KEYWORD_ENTRY"> + <column name="AB_KEYWORD_ENTRYID" value="c6efd407-726c-40a1-a494-b6343ea412ce"/> + <column name="KEYID" value="PLANNED"/> + <column name="TITLE" value="Planned"/> + <column name="AB_KEYWORD_CATEGORY_ID" value="ec675c54-405d-4564-879d-d537c220661a"/> + <column name="SORTING" valueNumeric="1"/> + <column name="ISACTIVE" valueNumeric="1"/> + <column name="ISESSENTIAL" valueNumeric="0"/> + </insert> + <insert tableName="AB_KEYWORD_ENTRY"> + <column name="AB_KEYWORD_ENTRYID" value="0ef63392-f99d-4059-986c-7b027a183347"/> + <column name="KEYID" value="LOCKED"/> + <column name="TITLE" value="Fixed"/> + <column name="AB_KEYWORD_CATEGORY_ID" value="ec675c54-405d-4564-879d-d537c220661a"/> + <column name="SORTING" valueNumeric="2"/> + <column name="ISACTIVE" valueNumeric="1"/> + <column name="ISESSENTIAL" valueNumeric="0"/> + </insert> + </changeSet> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/2021.0.3/Planning/alterForecast.xml b/.liquibase/Data_alias/basic/2021.0.3/Planning/alterForecast.xml new file mode 100644 index 0000000000000000000000000000000000000000..e2b1b78b7513fb55ca12044fcde49a59e42efc5a --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/Planning/alterForecast.xml @@ -0,0 +1,15 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <changeSet author="j.luginger" id="2da921a6-a680-4662-8496-59f4eb22c6a5"> + <addColumn tableName="FORECAST"> + <column name="FORECAST_YEAR" type="INT"/> + <column name="CONTACT_ID" type="CHAR(36)"/> + <column name="KIND" type="VARCHAR(36)"/> + <column name="STATUS" type="VARCHAR(36)"/> + <column name="RESPONSIBLE_CONTACT_ID" type="CHAR(36)"/> + </addColumn> + + </changeSet> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/2021.0.3/Planning/alterForecastAddIndizes.xml b/.liquibase/Data_alias/basic/2021.0.3/Planning/alterForecastAddIndizes.xml new file mode 100644 index 0000000000000000000000000000000000000000..9917700bca56b7d20fe8f9ff3abb194c132338c7 --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/Planning/alterForecastAddIndizes.xml @@ -0,0 +1,13 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <changeSet author="j.luginger" id="2da921a6-a680-4662-8496-59f4eb22c6a5"> + <createIndex indexName="IDX_FORECAST_CONTACT_ID" tableName="FORECAST"> + <column name="CONTACT_ID"/> + </createIndex> + <createIndex indexName="IDX_FORECAST_RESPONSIBLE_CONTACT_ID" tableName="FORECAST"> + <column name="RESPONSIBLE_CONTACT_ID"/> + </createIndex> + </changeSet> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/2021.0.3/Planning/alterForecastDataKind.xml b/.liquibase/Data_alias/basic/2021.0.3/Planning/alterForecastDataKind.xml new file mode 100644 index 0000000000000000000000000000000000000000..fb39cdcdd08bb888840b8272923ce3fabfdcb9f9 --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/Planning/alterForecastDataKind.xml @@ -0,0 +1,12 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <changeSet author="j.luginger" id="26f06b1d-c550-4a6c-81a5-c9f061c7f50f"> + + <update tableName="FORECAST"> + <column name="KIND" value="FORECAST"/> + <where>KIND is null</where> + </update> + </changeSet> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/2021.0.3/Planning/alterForecastDropObjectRowIdNullable.xml b/.liquibase/Data_alias/basic/2021.0.3/Planning/alterForecastDropObjectRowIdNullable.xml new file mode 100644 index 0000000000000000000000000000000000000000..ad7b65d54b56aa039dc808d57c006291544ec00e --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/Planning/alterForecastDropObjectRowIdNullable.xml @@ -0,0 +1,16 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <changeSet author="j.luginger" id="fb33969b-17e5-45c4-9fe4-c19cb65320f6"> + <dropNotNullConstraint + columnDataType="char(36)" + columnName="OBJECT_ROWID" + tableName="FORECAST"/> + + <dropNotNullConstraint + columnDataType="varchar(63)" + columnName="OBJECT_TYPE" + tableName="FORECAST"/> + </changeSet> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/2021.0.3/Planning/changelog.xml b/.liquibase/Data_alias/basic/2021.0.3/Planning/changelog.xml new file mode 100644 index 0000000000000000000000000000000000000000..b6afce8a8cf1bbcbcc7d76a69d9ba687f857de94 --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/Planning/changelog.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <include file="alterForecast.xml" relativeToChangelogFile="true"/> + <include file="addKeywordForecastKind.xml" relativeToChangelogFile="true"/> + <include file="alterForecastDropObjectRowIdNullable.xml" relativeToChangelogFile="true"/> + <include file="addKeywordForecastStatus.xml" relativeToChangelogFile="true"/> + <include file="alterForecastDataKind.xml" relativeToChangelogFile="true"/> + <include file="createPlanningMonth.xml" relativeToChangelogFile="true"/> + <include file="insertPlanningMonthData.xml" relativeToChangelogFile="true"/> + <include file="alterForecastAddIndizes.xml" relativeToChangelogFile="true"/> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/2021.0.3/Planning/createPlanningMonth.xml b/.liquibase/Data_alias/basic/2021.0.3/Planning/createPlanningMonth.xml new file mode 100644 index 0000000000000000000000000000000000000000..6a785b68196bc068fa12c17a6fc17ce6a97d1ea3 --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/Planning/createPlanningMonth.xml @@ -0,0 +1,14 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <changeSet author="j.luginger" id="88a921a6-a680-4662-8496-59f4eb22c6a5"> + <createTable tableName="PLANNING_MONTH"> + <column name="PLANNING_MONTHID" type="CHAR(36)"> + <constraints primaryKey="true" primaryKeyName="PK_PLANNING_MONTH_PLANNING_MONTHID"/> + </column> + <column name="MONTH_NUMBER" type="INTEGER"/> + <column name="MONTH_FACTOR" type="NUMERIC(5,2)"/> + </createTable> + </changeSet> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/2021.0.3/Planning/insertPlanningMonthData.xml b/.liquibase/Data_alias/basic/2021.0.3/Planning/insertPlanningMonthData.xml new file mode 100644 index 0000000000000000000000000000000000000000..cdfc57c433334fef75a8c207d8a1456bf65156dc --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/Planning/insertPlanningMonthData.xml @@ -0,0 +1,65 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <changeSet author="j.luginger" id="24f68f1a-6103-4051-9f22-6b64428f6c38"> + <insert tableName="PLANNING_MONTH"> + <column name="PLANNING_MONTHID" value="80dc07b0-1ba7-42fb-b708-86488452c158"/> + <column name="MONTH_NUMBER" valueNumeric="1"/> + <column name="MONTH_FACTOR" valueNumeric="8.33"/> + </insert> + <insert tableName="PLANNING_MONTH"> + <column name="PLANNING_MONTHID" value="dbd384d4-fe89-4522-8c3e-67c2dc8068d9"/> + <column name="MONTH_NUMBER" valueNumeric="2"/> + <column name="MONTH_FACTOR" valueNumeric="8.33"/> + </insert> + <insert tableName="PLANNING_MONTH"> + <column name="PLANNING_MONTHID" value="3f16cc60-b166-42c8-bd78-6b5f6aa4d7b0"/> + <column name="MONTH_NUMBER" valueNumeric="3"/> + <column name="MONTH_FACTOR" valueNumeric="8.33"/> + </insert> + <insert tableName="PLANNING_MONTH"> + <column name="PLANNING_MONTHID" value="3bdb09ed-17f3-4eff-aa71-3e31bff9cbb6"/> + <column name="MONTH_NUMBER" valueNumeric="4"/> + <column name="MONTH_FACTOR" valueNumeric="8.33"/> + </insert> + <insert tableName="PLANNING_MONTH"> + <column name="PLANNING_MONTHID" value="9add0690-e967-40e4-8d6b-255e4d32a75e"/> + <column name="MONTH_NUMBER" valueNumeric="5"/> + <column name="MONTH_FACTOR" valueNumeric="8.33"/> + </insert> + <insert tableName="PLANNING_MONTH"> + <column name="PLANNING_MONTHID" value="5d00016a-2302-4011-9f98-db6ccc371f32"/> + <column name="MONTH_NUMBER" valueNumeric="6"/> + <column name="MONTH_FACTOR" valueNumeric="8.33"/> + </insert> + <insert tableName="PLANNING_MONTH"> + <column name="PLANNING_MONTHID" value="68f67a69-a62a-4925-83f8-c4c06f587f6d"/> + <column name="MONTH_NUMBER" valueNumeric="7"/> + <column name="MONTH_FACTOR" valueNumeric="8.33"/> + </insert> + <insert tableName="PLANNING_MONTH"> + <column name="PLANNING_MONTHID" value="e44f4275-7aa2-4218-9a28-c7da41083881"/> + <column name="MONTH_NUMBER" valueNumeric="8"/> + <column name="MONTH_FACTOR" valueNumeric="8.33"/> + </insert> + <insert tableName="PLANNING_MONTH"> + <column name="PLANNING_MONTHID" value="38547f0a-0752-4a8f-b6ce-280f09db6108"/> + <column name="MONTH_NUMBER" valueNumeric="9"/> + <column name="MONTH_FACTOR" valueNumeric="8.33"/> + </insert> + <insert tableName="PLANNING_MONTH"> + <column name="PLANNING_MONTHID" value="a821c1ef-3805-450a-83fd-ef3e1bb96ff6"/> + <column name="MONTH_NUMBER" valueNumeric="10"/> + <column name="MONTH_FACTOR" valueNumeric="8.33"/> + </insert> + <insert tableName="PLANNING_MONTH"> + <column name="PLANNING_MONTHID" value="c824e7c2-112c-483b-a116-e0bd9f4bc9bc"/> + <column name="MONTH_NUMBER" valueNumeric="11"/> + <column name="MONTH_FACTOR" valueNumeric="8.33"/> + </insert> + <insert tableName="PLANNING_MONTH"> + <column name="PLANNING_MONTHID" value="6f7428c5-473d-4622-826e-5225658cf5f6"/> + <column name="MONTH_NUMBER" valueNumeric="12"/> + <column name="MONTH_FACTOR" valueNumeric="8.33"/> + </insert> + </changeSet> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/2021.0.3/changelog.xml b/.liquibase/Data_alias/basic/2021.0.3/changelog.xml new file mode 100644 index 0000000000000000000000000000000000000000..4abf91ed480dd034b9ff2f9c53ef9a4fcb933f57 --- /dev/null +++ b/.liquibase/Data_alias/basic/2021.0.3/changelog.xml @@ -0,0 +1,7 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <include relativeToChangelogFile="true" file="Checklists/changelog.xml"/> + <include relativeToChangelogFile="true" file="Planning/changelog.xml"/> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/_demoData/changelog.xml b/.liquibase/Data_alias/basic/_demoData/changelog.xml index f6d11f67aca68ced3d37b0ba75215a15d7a8d4d9..d27f20c3d1e4c8f98ff2042dd3a2f2202d1c4ffb 100644 --- a/.liquibase/Data_alias/basic/_demoData/changelog.xml +++ b/.liquibase/Data_alias/basic/_demoData/changelog.xml @@ -14,6 +14,7 @@ <include file="generatedData/campaignparticipant.xml" relativeToChangelogFile="true"/> <include file="generatedData/campaignparticipantlog.xml" relativeToChangelogFile="true"/> <include file="generatedData/campaignstep.xml" relativeToChangelogFile="true"/> + <include file="generatedData/checklistentry.xml" relativeToChangelogFile="true"/> <include file="generatedData/classification.xml" relativeToChangelogFile="true"/> <include file="generatedData/classificationgrading.xml" relativeToChangelogFile="true"/> <include file="generatedData/classificationgroup.xml" relativeToChangelogFile="true"/> diff --git a/.liquibase/Data_alias/basic/_demoData/generatedData/checklistentry.xml b/.liquibase/Data_alias/basic/_demoData/generatedData/checklistentry.xml new file mode 100644 index 0000000000000000000000000000000000000000..2920277bd600a23d2ceb42d170a3a64e388ba0f2 --- /dev/null +++ b/.liquibase/Data_alias/basic/_demoData/generatedData/checklistentry.xml @@ -0,0 +1,253 @@ +<?xml version="1.1" encoding="UTF-8" standalone="no"?> +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> + <changeSet author="p.neub" id="ae84062f-4fe4-40e6-b8d3-d90a0ee0c45d"> + <delete tableName="CHECKLISTENTRY"/> + + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="1"/> + <column name="CHECKLIST_ID" value="179dcc0d-e6fa-411d-b5ee-cb25b9735dbe"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="75e715fb-55fb-455b-8a68-a72bb800d856"/> + <column name="TITLE" value="salesprojectContactsGenerationSource"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="1"/> + <column name="CHECKLIST_ID" value="179dcc0d-e6fa-411d-b5ee-cb25b9735dbe"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="aed8a754-b328-4fe0-89ef-b04b74d80ca2"/> + <column name="TITLE" value="salesprojectClassificationFields"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="0"/> + <column name="CHECKLIST_ID" value="3d0f1d25-cee8-4b83-a0de-3fded83ff9c4"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="3fa544d6-25a4-4597-a501-e36d8bfbc0ec"/> + <column name="TITLE" value="Ermittlung des Kundenbedarfs (Anforderungen abgefragt)"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="1"/> + <column name="CHECKLIST_ID" value="3d0f1d25-cee8-4b83-a0de-3fded83ff9c4"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="01f3515c-4b35-43f5-9943-d8ad8f42b804"/> + <column name="TITLE" value="salesprojectSegmentPrio"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="1"/> + <column name="CHECKLIST_ID" value="3d0f1d25-cee8-4b83-a0de-3fded83ff9c4"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="7a52650a-5e06-4ffe-9fb0-c0abdae67efa"/> + <column name="TITLE" value="salesprojectVolume"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="1"/> + <column name="CHECKLIST_ID" value="3d0f1d25-cee8-4b83-a0de-3fded83ff9c4"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="2dc42fbb-4e0b-498f-8032-0c5451bea157"/> + <column name="TITLE" value="salesprojectRoleProjectteam"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="1"/> + <column name="CHECKLIST_ID" value="3d0f1d25-cee8-4b83-a0de-3fded83ff9c4"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="7bd69f26-0dd6-453e-977d-108f0f2c7c64"/> + <column name="TITLE" value="salesprojectFirstCustConv"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="0"/> + <column name="CHECKLIST_ID" value="ecf50252-e0c2-4e7a-8cc6-078b5978d2c5"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="667d09bd-3c7f-4a6e-a71d-fff48fbd7c54"/> + <column name="TITLE" value="Spezifizierung der Anforderungen"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="0"/> + <column name="CHECKLIST_ID" value="ecf50252-e0c2-4e7a-8cc6-078b5978d2c5"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="083daafd-f349-42a6-94e2-9425f9b8afe6"/> + <column name="TITLE" value="Entwicklung der Lösungsstrategie"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="1"/> + <column name="CHECKLIST_ID" value="ecf50252-e0c2-4e7a-8cc6-078b5978d2c5"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="28705e11-8d57-4ff7-afa9-9d7c3b981009"/> + <column name="TITLE" value="salesprojectFurtherCustomerMeetings"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="1"/> + <column name="CHECKLIST_ID" value="ecf50252-e0c2-4e7a-8cc6-078b5978d2c5"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="1d3adc61-d1a0-41b7-972c-52e2b5f89551"/> + <column name="TITLE" value="salesprojectRoleProjectteam"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="1"/> + <column name="CHECKLIST_ID" value="ecf50252-e0c2-4e7a-8cc6-078b5978d2c5"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="361fd57d-9a7d-4a18-8e59-47d4b403efac"/> + <column name="TITLE" value="salesprojectRoleIntDist"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="0"/> + <column name="CHECKLIST_ID" value="ecf50252-e0c2-4e7a-8cc6-078b5978d2c5"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="3bba05b7-3d28-4a7a-8063-33d048e75a35"/> + <column name="TITLE" value="Analyse des Wettbewerbs​"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="1"/> + <column name="CHECKLIST_ID" value="ecf50252-e0c2-4e7a-8cc6-078b5978d2c5"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="17eb036c-44d9-45f3-8cfc-9ac37e4e0331"/> + <column name="TITLE" value="salesprojectProjStart"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="0"/> + <column name="CHECKLIST_ID" value="0f95ce44-3b0d-417b-969f-f84897868558"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="3004d2ea-037c-4639-863e-7f3eb1571392"/> + <column name="TITLE" value="Wahrscheinlichkeit überprüfen und ggf. nachjustieren"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="0"/> + <column name="CHECKLIST_ID" value="0f95ce44-3b0d-417b-969f-f84897868558"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="e3689c38-1c65-44e7-867d-5894a88715ac"/> + <column name="TITLE" value="Risikoaudit durchgeführt"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="1"/> + <column name="CHECKLIST_ID" value="0f95ce44-3b0d-417b-969f-f84897868558"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="81b44133-4ea7-4cc9-ba35-9d46ef9cd4c5"/> + <column name="TITLE" value="salesprojectOfferSent"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="0"/> + <column name="CHECKLIST_ID" value="0f95ce44-3b0d-417b-969f-f84897868558"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="011db14a-2ef0-43fa-a481-888aa4421118"/> + <column name="TITLE" value="Es ist ein Workshop zur Projektumsetzung geplant"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="0"/> + <column name="CHECKLIST_ID" value="0f95ce44-3b0d-417b-969f-f84897868558"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="b15ccc0d-f312-4cba-9ba8-c7f8c7d086f7"/> + <column name="TITLE" value="Ein Termin zur Abstimmung des Angebots hat stattgefunden"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="0"/> + <column name="CHECKLIST_ID" value="cb0357c9-a222-4d78-b2c5-035fffe3bb51"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="8cf4d84e-3fd6-409b-9107-2607d256576a"/> + <column name="TITLE" value="Analyse des Wettbewerbs"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="0"/> + <column name="CHECKLIST_ID" value="cb0357c9-a222-4d78-b2c5-035fffe3bb51"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="1933b7df-5eb9-4b7b-b2f2-ad5052457472"/> + <column name="TITLE" value="Finale Verhandlung​"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="1"/> + <column name="CHECKLIST_ID" value="cb0357c9-a222-4d78-b2c5-035fffe3bb51"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="8c042c85-1f3e-4e57-b25e-20fc323f56c3"/> + <column name="TITLE" value="salesprojectStatusWon"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="0"/> + <column name="CHECKLIST_ID" value="cb0357c9-a222-4d78-b2c5-035fffe3bb51"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="edb57304-3871-41af-9f00-1b4699038e6d"/> + <column name="TITLE" value="Zukünftige Projekte des Kunden abgefragt​"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + <insert tableName="CHECKLISTENTRY"> + <column name="AUTO" valueNumeric="0"/> + <column name="CHECKLIST_ID" value="cb0357c9-a222-4d78-b2c5-035fffe3bb51"/> + <column name="DATE_EDIT"/> + <column name="USER_EDIT"/> + <column name="CHECKLISTENTRYID" value="6755935e-aa0c-4d73-a710-dc6ae1849f39"/> + <column name="TITLE" value="Erarbeitung der Verhandlungsstrategie"/> + <column name="USER_NEW" value="Admin"/> + <column name="DATE_NEW"/> + </insert> + </changeSet> +</databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/_demoData/generatedData/forecast.xml b/.liquibase/Data_alias/basic/_demoData/generatedData/forecast.xml index a47c729277f37e18dbd1ec1201c8872fea52d279..15d1278c9e33f6d4e52ebaa94565be0cbc7ebe75 100644 --- a/.liquibase/Data_alias/basic/_demoData/generatedData/forecast.xml +++ b/.liquibase/Data_alias/basic/_demoData/generatedData/forecast.xml @@ -5,83 +5,92 @@ <insert tableName="forecast"> <column name="VOLUME" valueNumeric="25000"/> <column name="FORECASTID" value="2d5c65fe-708b-4e54-96cf-d2fcdc98001f"/> - <column name="DATE_START" valueDate="2020-10-29T12:00:00"/> + <column name="DATE_START" valueDate="2020-10-29T00:00:00"/> <column name="OBJECT_TYPE" value="Salesproject"/> <column name="GROUPCODE" value="PRODUCTGROUP3"/> <column name="OBJECT_ROWID" value="d422ad81-717f-42b0-bd64-fc892744aac7"/> <column name="INFO" value="fc"/> + <column name="KIND" value="FORECAST"/> </insert> <insert tableName="forecast"> <column name="VOLUME" valueNumeric="80000"/> <column name="FORECASTID" value="37016eaa-ce14-45cd-8977-930cf6a20bb1"/> - <column name="DATE_START" valueDate="2020-12-30T12:00:00"/> + <column name="DATE_START" valueDate="2020-12-30T00:00:00"/> <column name="OBJECT_TYPE" value="Salesproject"/> <column name="GROUPCODE" value="PRODUCTGROUP3"/> <column name="OBJECT_ROWID" value="6d3d16cd-733e-41d1-ab6c-8a6cba63ba4a"/> <column name="INFO" value="fc"/> + <column name="KIND" value="FORECAST"/> </insert> <insert tableName="forecast"> <column name="VOLUME" valueNumeric="100000"/> <column name="FORECASTID" value="44bc5ce9-2456-4e04-8ff1-f35f2a71798f"/> - <column name="DATE_START" valueDate="2020-05-23T12:00:00"/> + <column name="DATE_START" valueDate="2020-05-23T00:00:00"/> <column name="OBJECT_TYPE" value="Salesproject"/> <column name="GROUPCODE" value="PRODUCTSERVICE"/> <column name="OBJECT_ROWID" value="438537db-0dc6-4aed-b1d1-813011baf88c"/> <column name="INFO" value="fc"/> + <column name="KIND" value="FORECAST"/> </insert> <insert tableName="forecast"> <column name="VOLUME" valueNumeric="25000"/> <column name="FORECASTID" value="4cc2db79-5263-4ee7-a651-00e7ecb6cc33"/> - <column name="DATE_START" valueDate="2020-10-22T12:00:00"/> + <column name="DATE_START" valueDate="2020-10-22T00:00:00"/> <column name="OBJECT_TYPE" value="Salesproject"/> <column name="GROUPCODE" value="PRODUCTGROUP3"/> <column name="OBJECT_ROWID" value="6d3d16cd-733e-41d1-ab6c-8a6cba63ba4a"/> <column name="INFO" value="fc"/> + <column name="KIND" value="FORECAST"/> </insert> <insert tableName="forecast"> <column name="VOLUME" valueNumeric="150000"/> <column name="FORECASTID" value="655bf6c0-713a-4738-a649-b1f6e212bd92"/> - <column name="DATE_START" valueDate="2021-01-28T12:00:00"/> + <column name="DATE_START" valueDate="2021-01-28T00:00:00"/> <column name="OBJECT_TYPE" value="Salesproject"/> <column name="GROUPCODE" value="PRODUCTGROUP3"/> <column name="OBJECT_ROWID" value="d422ad81-717f-42b0-bd64-fc892744aac7"/> <column name="INFO" value="fc"/> + <column name="KIND" value="FORECAST"/> </insert> <insert tableName="forecast"> <column name="VOLUME" valueNumeric="100000"/> <column name="FORECASTID" value="74d72ac5-11ba-414f-a8b4-d31481e90e7f"/> - <column name="DATE_START" valueDate="2020-10-29T12:00:00"/> + <column name="DATE_START" valueDate="2020-10-29T00:00:00"/> <column name="OBJECT_TYPE" value="Salesproject"/> <column name="GROUPCODE" value="PRODUCTGROUP3"/> <column name="OBJECT_ROWID" value="ef7f4726-4476-4f59-97c2-706dc1e0046f"/> <column name="INFO" value="W3 "/> + <column name="KIND" value="FORECAST"/> </insert> <insert tableName="forecast"> <column name="VOLUME" valueNumeric="100000"/> <column name="FORECASTID" value="82dccf63-165f-4345-87a6-e3535ae58349"/> - <column name="DATE_START" valueDate="2020-05-22T12:00:00"/> + <column name="DATE_START" valueDate="2020-05-22T00:00:00"/> <column name="OBJECT_TYPE" value="Salesproject"/> <column name="GROUPCODE" value="PRODUCTGROUP1"/> <column name="OBJECT_ROWID" value="438537db-0dc6-4aed-b1d1-813011baf88c"/> <column name="INFO" value="FC"/> + <column name="KIND" value="FORECAST"/> </insert> <insert tableName="forecast"> <column name="VOLUME" valueNumeric="75000"/> <column name="FORECASTID" value="9b3c76ad-5fac-4c26-af9b-3b05f097763f"/> - <column name="DATE_START" valueDate="2020-11-18T12:00:00"/> + <column name="DATE_START" valueDate="2020-11-18T00:00:00"/> <column name="OBJECT_TYPE" value="Salesproject"/> <column name="GROUPCODE" value="PRODUCTGROUP3"/> <column name="OBJECT_ROWID" value="6d3d16cd-733e-41d1-ab6c-8a6cba63ba4a"/> <column name="INFO" value="fc"/> + <column name="KIND" value="FORECAST"/> </insert> <insert tableName="forecast"> <column name="VOLUME" valueNumeric="25000"/> <column name="FORECASTID" value="f87ad5ed-943e-4008-a3fa-291699e3df28"/> - <column name="DATE_START" valueDate="2020-11-19T12:00:00"/> + <column name="DATE_START" valueDate="2020-11-19T00:00:00"/> <column name="OBJECT_TYPE" value="Salesproject"/> <column name="GROUPCODE" value="PRODUCTGROUP3"/> <column name="OBJECT_ROWID" value="7e2680f6-a438-45aa-956a-787363f85923"/> <column name="INFO" value="fc"/> + <column name="KIND" value="FORECAST"/> </insert> </changeSet> </databaseChangeLog> \ No newline at end of file diff --git a/.liquibase/Data_alias/basic/_demoData/generatedData/offeritem.xml b/.liquibase/Data_alias/basic/_demoData/generatedData/offeritem.xml index 06d2014637a63a334113a341736f58795fda6614..6cc33b720c2fdf2b7c09f13c3fe0679154183aa3 100644 --- a/.liquibase/Data_alias/basic/_demoData/generatedData/offeritem.xml +++ b/.liquibase/Data_alias/basic/_demoData/generatedData/offeritem.xml @@ -275,6 +275,7 @@ <column name="ITEMSORT" valueNumeric="1"/> <column name="OFFER_ID" value="2948a9b8-5e81-491f-b741-9b35622f09da"/> <column name="ITEMPOSITION" value="1"/> + <column name="UNIT" value="QUANTITYPIECES"/> <column name="PRICE" valueNumeric="145000.00"/> <column name="PRODUCT_ID" value="993f6294-f1fc-42d2-8786-1c13274fd133"/> </insert> diff --git a/.liquibase/Data_alias/basic/_demoData/generatedData/salesproject.xml b/.liquibase/Data_alias/basic/_demoData/generatedData/salesproject.xml index e974404a483fca6b30869ed902b060c218cfa29b..2f7aec85052da42bdfe0ccac94629992f9b27eee 100644 --- a/.liquibase/Data_alias/basic/_demoData/generatedData/salesproject.xml +++ b/.liquibase/Data_alias/basic/_demoData/generatedData/salesproject.xml @@ -4,7 +4,7 @@ <delete tableName="salesproject"/> <insert tableName="salesproject"> <column name="VOLUME" valueNumeric="200000.00"/> - <column name="PHASE" value="SALPROJPHASESQO"/> + <column name="PHASE" value="SALPROJPHASEOFFER"/> <column name="ENDDATE" valueDate="2021-05-20T12:00:00"/> <column name="SALESPROJECTID" value="438537db-0dc6-4aed-b1d1-813011baf88c"/> <column name="PROBABILITY" valueNumeric="25"/> @@ -17,7 +17,7 @@ </insert> <insert tableName="salesproject"> <column name="VOLUME" valueNumeric="120000.00"/> - <column name="PHASE" value="SALPROJPHASESAL"/> + <column name="PHASE" value="SALPROJPHASELEAD"/> <column name="ENDDATE" valueDate="2021-05-17T12:00:00"/> <column name="SALESPROJECTID" value="6d3d16cd-733e-41d1-ab6c-8a6cba63ba4a"/> <column name="PROBABILITY" valueNumeric="25"/> @@ -43,7 +43,7 @@ </insert> <insert tableName="salesproject"> <column name="VOLUME" valueNumeric="250000.00"/> - <column name="PHASE" value="SALPROJPHASESAL"/> + <column name="PHASE" value="SALPROJPHASELEAD"/> <column name="ENDDATE" valueDate="2022-05-18T12:00:00"/> <column name="SALESPROJECTID" value="d422ad81-717f-42b0-bd64-fc892744aac7"/> <column name="PROBABILITY" valueNumeric="25"/> @@ -55,7 +55,7 @@ <column name="STATUS" value="SALPROJSTATOPEN"/> </insert> <insert tableName="salesproject"> - <column name="PHASE" value="SALPROJPHASENQC"/> + <column name="PHASE" value="SALPROJPHASECONTACT"/> <column name="ENDDATE" valueDate="2021-11-26T12:00:00"/> <column name="SALESPROJECTID" value="ebb04ae2-d1f9-4ef3-bdfa-e9f562d215ba"/> <column name="PROBABILITY" valueNumeric="50"/> @@ -68,7 +68,7 @@ </insert> <insert tableName="salesproject"> <column name="VOLUME" valueNumeric="450000.00"/> - <column name="PHASE" value="SALPROJPHASEMQC"/> + <column name="PHASE" value="SALPROJPHASECONTACT"/> <column name="ENDDATE" valueDate="2022-05-22T12:00:00"/> <column name="SALESPROJECTID" value="ef7f4726-4476-4f59-97c2-706dc1e0046f"/> <column name="PROBABILITY" valueNumeric="25"/> diff --git a/.liquibase/Data_alias/changelog.xml b/.liquibase/Data_alias/changelog.xml index c46a164da2f3cc26f2336d2aba78a1d54067672e..14683de8f2de11bbaf154a98026277bc9c4427fa 100644 --- a/.liquibase/Data_alias/changelog.xml +++ b/.liquibase/Data_alias/changelog.xml @@ -22,6 +22,7 @@ <include relativeToChangelogFile="true" file="basic/2021.0.0/changelog.xml"/> <include relativeToChangelogFile="true" file="basic/2021.0.1/changelog.xml"/> <include relativeToChangelogFile="true" file="basic/2021.0.2/changelog.xml"/> + <include relativeToChangelogFile="true" file="basic/2021.0.3/changelog.xml"/> <!--enable this only when you definetly want to overwrite the existing data with demo records:--> <!--<include relativeToChangelogFile="true" file="basic/_demoData/changelog.xml" context="example"/>--> diff --git a/aliasDefinition/Data_alias/Data_alias.aod b/aliasDefinition/Data_alias/Data_alias.aod index bf89272bc756faa360048b55075e1fde91cf8d9e..52da7066094e0a0c99b4e5df78c7500cb370a432 100644 --- a/aliasDefinition/Data_alias/Data_alias.aod +++ b/aliasDefinition/Data_alias/Data_alias.aod @@ -9966,7 +9966,7 @@ <columnType v="1" /> <size v="36" /> <scale v="0" /> - <notNull v="true" /> + <notNull v="false" /> <isUnique v="false" /> <index v="true" /> <documentation></documentation> @@ -10057,7 +10057,77 @@ <columnType v="12" /> <size v="63" /> <scale v="0" /> - <notNull v="true" /> + <notNull v="false" /> + <isUnique v="false" /> + <index v="false" /> + <documentation></documentation> + <title></title> + <description></description> + </entityFieldDb> + <entityFieldDb> + <name>KIND</name> + <dbName></dbName> + <primaryKey v="false" /> + <columnType v="12" /> + <size v="36" /> + <scale v="0" /> + <notNull v="false" /> + <isUnique v="false" /> + <index v="false" /> + <documentation></documentation> + <title></title> + <description></description> + </entityFieldDb> + <entityFieldDb> + <name>CONTACT_ID</name> + <dbName></dbName> + <primaryKey v="false" /> + <columnType v="1" /> + <size v="36" /> + <scale v="0" /> + <notNull v="false" /> + <isUnique v="false" /> + <index v="false" /> + <documentation></documentation> + <title></title> + <description></description> + </entityFieldDb> + <entityFieldDb> + <name>FORECAST_YEAR</name> + <dbName></dbName> + <primaryKey v="false" /> + <columnType v="4" /> + <size v="10" /> + <scale v="0" /> + <notNull v="false" /> + <isUnique v="false" /> + <index v="false" /> + <documentation></documentation> + <title></title> + <description></description> + </entityFieldDb> + <entityFieldDb> + <name>STATUS</name> + <dbName></dbName> + <primaryKey v="false" /> + <columnType v="12" /> + <size v="36" /> + <scale v="0" /> + <notNull v="false" /> + <isUnique v="false" /> + <index v="false" /> + <documentation></documentation> + <title></title> + <description></description> + </entityFieldDb> + <entityFieldDb> + <name>RESPONSIBLE_CONTACT_ID</name> + <dbName></dbName> + <primaryKey v="false" /> + <columnType v="1" /> + <size v="36" /> + <scale v="0" /> + <notNull v="false" /> <isUnique v="false" /> <index v="false" /> <documentation></documentation> @@ -10193,8 +10263,8 @@ <name>REASON</name> <dbName></dbName> <primaryKey v="false" /> - <columnType v="12" /> - <size v="36" /> + <columnType v="2005" /> + <size v="2147483647" /> <scale v="0" /> <notNull v="false" /> <isUnique v="false" /> @@ -18500,6 +18570,68 @@ </entityFieldDb> </entityFields> </entityDb> + <entityDb> + <name>PLANNING_MONTH</name> + <dbName></dbName> + <idColumn>PLANNING_MONTHID</idColumn> + <idGeneratorType v="0" /> + <idGeneratorInterval v="1" /> + <documentation></documentation> + <title></title> + <description></description> + <auditSyncConfig> + <name>auditSyncConfig</name> + <auditMode v="0" /> + <syncActive v="false" /> + <syncComplete v="true" /> + <syncDirection v="1" /> + <syncIds></syncIds> + </auditSyncConfig> + <entityFields> + <entityFieldDb> + <name>PLANNING_MONTHID</name> + <dbName></dbName> + <primaryKey v="true" /> + <columnType v="1" /> + <size v="36" /> + <scale v="0" /> + <notNull v="true" /> + <isUnique v="true" /> + <index v="true" /> + <documentation></documentation> + <title></title> + <description></description> + </entityFieldDb> + <entityFieldDb> + <name>MONTH_FACTOR</name> + <dbName></dbName> + <primaryKey v="false" /> + <columnType v="4" /> + <size v="10" /> + <scale v="0" /> + <notNull v="false" /> + <isUnique v="false" /> + <index v="false" /> + <documentation></documentation> + <title></title> + <description></description> + </entityFieldDb> + <entityFieldDb> + <name>MONTH_NUMBER</name> + <dbName></dbName> + <primaryKey v="false" /> + <columnType v="4" /> + <size v="10" /> + <scale v="0" /> + <notNull v="false" /> + <isUnique v="false" /> + <index v="false" /> + <documentation></documentation> + <title></title> + <description></description> + </entityFieldDb> + </entityFields> + </entityDb> </entities> </entityGroup> </aliasDefDb> diff --git a/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod b/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod index 56f31da9f97db53dd72583e0cb8631a0a3527050..d67029e7214916e37526a955729915a48c2b80a0 100644 --- a/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod +++ b/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod @@ -57,6 +57,10 @@ <name>Vertriebsdashboard</name> <kind v="10090" /> </entityNode> + <entityNode> + <name>Planning</name> + <kind v="10077" /> + </entityNode> <entityNode> <name>Salesproject</name> <kind v="10077" /> diff --git a/entity/Activity_entity/grantDeleteProcess.js b/entity/Activity_entity/grantDeleteProcess.js index a704528bc95a243ff330ad1ccef6deeb9eaa67ba..929d3d48e9ec2ad7ed7cea376db08f09322c87db 100644 --- a/entity/Activity_entity/grantDeleteProcess.js +++ b/entity/Activity_entity/grantDeleteProcess.js @@ -6,5 +6,7 @@ import("Entity_lib"); var canDelete = new HasLinkedObjectTester() .andNoEntityRows("Document_entity", "Documents", {AssignmentTable_param : "ACTIVITY", AssignmentRowId_param : vars.get("$field.ACTIVITYID")}) //Documents .validate(); + + result.string(canDelete); \ No newline at end of file diff --git a/entity/Appointment_entity/Appointment_entity.aod b/entity/Appointment_entity/Appointment_entity.aod index d615ac8db071653c41b13edc8e574505ab3f4b50..ebfd0f83c692dbda16668ec3f20a2da687b74c0e 100644 --- a/entity/Appointment_entity/Appointment_entity.aod +++ b/entity/Appointment_entity/Appointment_entity.aod @@ -270,6 +270,7 @@ <jDitoRecordAlias>Data_alias</jDitoRecordAlias> <contentProcess>%aditoprj%/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js</contentProcess> <rowCountProcess>%aditoprj%/entity/Appointment_entity/recordcontainers/jdito/rowCountProcess.js</rowCountProcess> + <hasDependentRecords v="true" /> <onInsert>%aditoprj%/entity/Appointment_entity/recordcontainers/jdito/onInsert.js</onInsert> <onUpdate>%aditoprj%/entity/Appointment_entity/recordcontainers/jdito/onUpdate.js</onUpdate> <onDelete>%aditoprj%/entity/Appointment_entity/recordcontainers/jdito/onDelete.js</onDelete> diff --git a/entity/Appointment_entity/afterUiInit.js b/entity/Appointment_entity/afterUiInit.js index 84f0515ebf4c6c9ba00bb4a071bacebe74fbaace..d1a3fedb127f027d614ce245fc9901599743d2a3 100644 --- a/entity/Appointment_entity/afterUiInit.js +++ b/entity/Appointment_entity/afterUiInit.js @@ -2,7 +2,7 @@ import("system.util"); import("system.neon"); import("system.vars"); -if(vars.exists("$param.Entry_param") && vars.get("$param.Entry_param")) +if(vars.get("$param.Entry_param")) { var entry = JSON.parse(vars.getString("$param.Entry_param")); diff --git a/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js b/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js index 709bfac8d00e3b805a383dc0c78c0cb8b91a07d1..a2b8753c1cf9bcd5783b27f12226693770d0e7af 100644 --- a/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js +++ b/entity/Appointment_entity/recordcontainers/jdito/contentProcess.js @@ -18,12 +18,12 @@ var appointmentUids; /** * Will be used, if the user is operating the calendar. */ -if(vars.exists("$param.Entry_param") && vars.get("$param.Entry_param")) +if(vars.get("$param.Entry_param") && JSON.parse(vars.get("$param.Entry_param"))[calendars.ID] != undefined) { var entry = JSON.parse(vars.getString("$param.Entry_param")); var masterEntry = null; - if (vars.exists("$param.MasterEntry_param") && vars.get("$param.MasterEntry_param") != "") { + if (vars.get("$param.MasterEntry_param") != "") { masterEntry = JSON.parse(vars.getString("$param.MasterEntry_param")); } diff --git a/entity/Appointment_entity/recordcontainers/jdito/onInsert.js b/entity/Appointment_entity/recordcontainers/jdito/onInsert.js index 21d79d0f9f82bfa904e33604db62defa2ca9733f..548745a3cf60a6dfa340e0dec3315f2345f18534 100644 --- a/entity/Appointment_entity/recordcontainers/jdito/onInsert.js +++ b/entity/Appointment_entity/recordcontainers/jdito/onInsert.js @@ -8,6 +8,7 @@ import("system.neon"); import("system.vars"); import("system.text"); import("system.db"); +import("system.entities"); var event = JSON.parse(vars.getString("$param.Entry_param")); @@ -22,36 +23,23 @@ event[calendars.LOCATION] = fields["LOCATION.value"]; event[calendars.DESCRIPTION] = fields["DESCRIPTION.value"]; event[calendars.DTSTART] = fields["BEGIN.value"]; event[calendars.DTEND] = fields["END.value"]; -event["X-ADITO-ISALLDAYEVENT"] = fields["ALLDAY.value"]; event[calendars.CLASSIFICATION] = fields["CLASSIFICATION.value"]; event[calendars.TRANSPARENCY] = fields["TRANSPARENCY.value"]; event[calendars.CATEGORIES] = fields["CATEGORIES.value"]; event[calendars.ORGANIZER] = fields["ORGANIZER.value"]; +event["X-ADITO-ISALLDAYEVENT"] = fields["ALLDAY.value"]; if(fields["RRULE.value"]) +{ event[calendars.RRULE] = [fields["RRULE.value"]]; +} if (fields["REMINDER.value"]) { event[calendars.HASREMINDER] = "true"; event[calendars.REMINDER_DURATION] = fields["REMINDER.value"]; } - -var idstringarray = calendars.insert([event]); - -if(event["LINKS"]) -{ - event["LINKS"].forEach(function(pLink){ - neon.addRecord("AppointmentLinks", - { - "OBJECTID" : pLink["OBJECT_ID"], - "OBJECTTYPE" : pLink["OBJECT_TYPE"], - "APPOINTMENT_ID" : idstringarray[0] - }); - }) -} - -event[calendars.ID] = idstringarray[0]; +event[calendars.ID] = calendars.insert([event])[0]; neon.setFieldValue("$field.UID", event[calendars.ID]); vars.set("$context.editmode", calendars.MODE_UPDATE); diff --git a/entity/AttributeRelation_entity/AttributeRelation_entity.aod b/entity/AttributeRelation_entity/AttributeRelation_entity.aod index 05c0bf6f0734e4ea7c8fbbd41efd67172e936955..040e3dfeaeef7181ad13197a1fae39c3d7fd22df 100644 --- a/entity/AttributeRelation_entity/AttributeRelation_entity.aod +++ b/entity/AttributeRelation_entity/AttributeRelation_entity.aod @@ -250,6 +250,7 @@ <children> <entityParameter> <name>GetTree_param</name> + <valueProcess>%aditoprj%/entity/AttributeRelation_entity/entityfields/attributerelations/children/gettree_param/valueProcess.js</valueProcess> <expose v="false" /> </entityParameter> </children> diff --git a/entity/AttributeRelation_entity/entityfields/attributerelations/children/gettree_param/valueProcess.js b/entity/AttributeRelation_entity/entityfields/attributerelations/children/gettree_param/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/entity/AttributeRelation_entity/entityfields/specificattribute/children/attributecount_param/valueProcess.js b/entity/AttributeRelation_entity/entityfields/specificattribute/children/attributecount_param/valueProcess.js index 9c0bc231731f77eee827bad7693c8ce56d7d45d8..0d6de778c4719400e3c4302e1fa4169fd70fd128 100644 --- a/entity/AttributeRelation_entity/entityfields/specificattribute/children/attributecount_param/valueProcess.js +++ b/entity/AttributeRelation_entity/entityfields/specificattribute/children/attributecount_param/valueProcess.js @@ -5,4 +5,6 @@ import("system.vars"); var objectType = vars.exists("$param.ObjectType_param") && vars.get("$param.ObjectType_param"); var rowId = vars.exists("$param.ObjectRowId_param") && vars.get("$param.ObjectRowId_param"); if (vars.get("$param.GetTree_param") == "true" && rowId) - result.object(AttributeRelationUtils.countAttributeRelations(rowId, objectType)); \ No newline at end of file +{ + result.object(AttributeRelationUtils.countAttributeRelations(rowId, objectType)); +} \ No newline at end of file diff --git a/entity/AttributeRelation_entity/entityfields/value/onValidation.js b/entity/AttributeRelation_entity/entityfields/value/onValidation.js index d2f774193b62a68cfde69f37ce3ee9b740f1ac3c..ef3040e48654b8adde21d33bbed134b180a5b504 100644 --- a/entity/AttributeRelation_entity/entityfields/value/onValidation.js +++ b/entity/AttributeRelation_entity/entityfields/value/onValidation.js @@ -8,5 +8,7 @@ if (attributeType && !attributeType.useLookup) { var validationResult = attributeType.validateValue(vars.get("$local.value"), Utils.parseJSON(vars.get("$field.VALIDATIONPARAMETERS"))); if (validationResult && validationResult !== true) + { result.string(validationResult); + } } \ No newline at end of file diff --git a/entity/AttributeRelation_entity/entityfields/value_lookup/onValidation.js b/entity/AttributeRelation_entity/entityfields/value_lookup/onValidation.js index 26590927b278e6a71b75d42c2f5e9d5a4b5da26e..f517b44992fe2d13b2cca675d774dee0028ff7e0 100644 --- a/entity/AttributeRelation_entity/entityfields/value_lookup/onValidation.js +++ b/entity/AttributeRelation_entity/entityfields/value_lookup/onValidation.js @@ -8,5 +8,7 @@ if (attributeType && attributeType.useLookup) { var validationResult = attributeType.validateValue(vars.get("$local.value"), Utils.parseJSON(vars.get("$field.VALIDATIONPARAMETERS"))); if (validationResult && validationResult !== true) + { result.string(validationResult); -} \ No newline at end of file + } +} diff --git a/entity/ChecklistEntryValue_entity/ChecklistEntryValue_entity.aod b/entity/ChecklistEntryValue_entity/ChecklistEntryValue_entity.aod index 307cc1e87027b5757a020bf21e3965c812548a4d..d883abe34f2f787be5becd750d6a0116cb12cbee 100644 --- a/entity/ChecklistEntryValue_entity/ChecklistEntryValue_entity.aod +++ b/entity/ChecklistEntryValue_entity/ChecklistEntryValue_entity.aod @@ -93,11 +93,11 @@ <children> <entityActionField> <name>setCompleted</name> - <title>Set completed</title> <onActionProcess>%aditoprj%/entity/ChecklistEntryValue_entity/entityfields/setchecklistentrycompleted/children/setcompleted/onActionProcess.js</onActionProcess> <isObjectAction v="false" /> <isSelectionAction v="true" /> <iconId>NEON:MQL</iconId> + <titleProcess>%aditoprj%/entity/ChecklistEntryValue_entity/entityfields/setchecklistentrycompleted/children/setcompleted/titleProcess.js</titleProcess> </entityActionField> </children> </entityActionGroup> diff --git a/entity/ChecklistEntryValue_entity/entityfields/setchecklistentrycompleted/children/setcompleted/onActionProcess.js b/entity/ChecklistEntryValue_entity/entityfields/setchecklistentrycompleted/children/setcompleted/onActionProcess.js index 80020200dc6b4dbf08aa00f5c0699d6db47d79e0..86551188b3435613792827d85700777731b72092 100644 --- a/entity/ChecklistEntryValue_entity/entityfields/setchecklistentrycompleted/children/setcompleted/onActionProcess.js +++ b/entity/ChecklistEntryValue_entity/entityfields/setchecklistentrycompleted/children/setcompleted/onActionProcess.js @@ -3,6 +3,5 @@ import("system.neon"); import("Sql_lib"); newWhere("CHECKLISTENTRYVALUE.CHECKLISTENTRYVALUEID", "$field.CHECKLISTENTRYVALUEID") - .updateFields({"IS_FULFILLED":1}); - + .updateFields({"IS_FULFILLED": parseInt(vars.get("$field.IS_FULFILLED")) > 0 ? 0 : 1}); neon.refresh(); \ No newline at end of file diff --git a/entity/ChecklistEntryValue_entity/entityfields/setchecklistentrycompleted/children/setcompleted/titleProcess.js b/entity/ChecklistEntryValue_entity/entityfields/setchecklistentrycompleted/children/setcompleted/titleProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..7a3fbe0a7a5a7bd2743b000c2953487533e4686a --- /dev/null +++ b/entity/ChecklistEntryValue_entity/entityfields/setchecklistentrycompleted/children/setcompleted/titleProcess.js @@ -0,0 +1,8 @@ +import("system.translate"); +import("system.vars"); +import("system.result"); + +result.string(parseInt(vars.get("$field.IS_FULFILLED")) > 0 + ? translate.text("Set not completed") + : translate.text("Set completed") +); diff --git a/entity/ChecklistEntry_entity/entityfields/title/displayValueProcess.js b/entity/ChecklistEntry_entity/entityfields/title/displayValueProcess.js index 8a1672dcd95f28d745482af6021264e667c9abe7..13b9519c0cffd3cb0447a630c74ad989c3e62a41 100644 --- a/entity/ChecklistEntry_entity/entityfields/title/displayValueProcess.js +++ b/entity/ChecklistEntry_entity/entityfields/title/displayValueProcess.js @@ -2,10 +2,15 @@ import("system.result"); import("system.vars"); import("system.translate"); import("KeywordRegistry_basic"); +import("ChecklistEntryRegistry_basic"); var title = vars.get("$field.TITLE"); -if (vars.get("$field.AUTO") != 1) +if (vars.get("$field.AUTO") == 1) +{ + result.string($ChecklistEntryRegistry[title]().title); +} +else { result.string(translate.text(title)); -} \ No newline at end of file +} diff --git a/entity/ClassificationAdmin_entity/ClassificationAdmin_entity.aod b/entity/ClassificationAdmin_entity/ClassificationAdmin_entity.aod index a2ecf6d0ca95c3fa6adb10903a636bc8a28eab8e..b5da465e7f2fe2b3bf84cedd8d80d22a9e991a62 100644 --- a/entity/ClassificationAdmin_entity/ClassificationAdmin_entity.aod +++ b/entity/ClassificationAdmin_entity/ClassificationAdmin_entity.aod @@ -95,14 +95,14 @@ <title>Recalculate Classifications</title> <onActionProcess>%aditoprj%/entity/ClassificationAdmin_entity/entityfields/filterviewactiongroup/children/updateclassification/onActionProcess.js</onActionProcess> <iconId>VAADIN:AUTOMATION</iconId> - <tooltip>Starts the serverprocess manually, which will recalculate all (potentially) outdated classifications. Use this after changes to the configuration of classifications.</tooltip> + <tooltip>Starts the server process manually, which will recalculate all (potentially) outdated classifications. This process should be executed after changes to the classification configuration.</tooltip> </entityActionField> <entityActionField> <name>UpdateAllClassifications</name> <title>Recalculate all Classifications</title> <onActionProcess>%aditoprj%/entity/ClassificationAdmin_entity/entityfields/filterviewactiongroup/children/updateallclassifications/onActionProcess.js</onActionProcess> <iconId>VAADIN:AUTOMATION</iconId> - <tooltip>Starts the serverprocess manually, which will recalculate all classifications from scratch. Only do this after e.g importing data from elsewhere where the outdated flag couldn't been set correctly. Since this can take some time.</tooltip> + <tooltip>Starts the server process manually, which will recalculate all classifications from scratch. This process should only be executed after importing data from elsewhere, where the outdated flag couldn't be set correctly, since this can take some time.</tooltip> </entityActionField> </children> </entityActionGroup> diff --git a/entity/DistrictResponsible_entity/grantDeleteProcess.js b/entity/DistrictResponsible_entity/grantDeleteProcess.js index 7039de6df63613d5985e26ef10ab10e90161e5c9..164a0d74af04ec7f0ad9cc499c8b4fb6b775e031 100644 --- a/entity/DistrictResponsible_entity/grantDeleteProcess.js +++ b/entity/DistrictResponsible_entity/grantDeleteProcess.js @@ -8,6 +8,7 @@ var currentContext = ContextUtils.getCurrentContextId(); var canDelete = new HasLinkedObjectTester() .andNoEntityRows("DistrictContact_entity", "DistrictContacts", {ObjectId_param : currentContext, RowId_param : rowId}) //District Contact + .andNoEntityRows("Document_entity", "Documents", {AssignmentTable_param : "DISTRICTRESPONSIBLE", AssignmentRowId_param : rowId}) //Documents .validate(); result.string(canDelete); \ No newline at end of file diff --git a/entity/District_entity/District_entity.aod b/entity/District_entity/District_entity.aod index 1501adb177652439951bcd1501084f8e55729aa4..a195aacda5cdca59724adce2e23bd420598082f2 100644 --- a/entity/District_entity/District_entity.aod +++ b/entity/District_entity/District_entity.aod @@ -5,7 +5,7 @@ <majorModelMode>DISTRIBUTED</majorModelMode> <documentation>%aditoprj%/entity/District_entity/documentation.adoc</documentation> <icon>VAADIN:GLOBE</icon> - <grantDelete v="false" /> + <grantDelete v="true" /> <grantDeleteProcess>%aditoprj%/entity/District_entity/grantDeleteProcess.js</grantDeleteProcess> <contentTitleProcess>%aditoprj%/entity/District_entity/contentTitleProcess.js</contentTitleProcess> <iconIdProcess>%aditoprj%/entity/District_entity/iconIdProcess.js</iconIdProcess> diff --git a/entity/District_entity/grantDeleteProcess.js b/entity/District_entity/grantDeleteProcess.js index 74e29836785f40313a3ff29d94ae95cf743007df..2aa49f3be4ce09fa49552cf97b5b5ab914774d6d 100644 --- a/entity/District_entity/grantDeleteProcess.js +++ b/entity/District_entity/grantDeleteProcess.js @@ -6,7 +6,11 @@ import("system.vars"); var districtId = vars.get("$field.DISTRICTID"); var count = newSelect("COUNT(*)") .from("DISTRICT") - .where("DISTRICT.PARENTDISTRICT_DISTRICTID", districtId) - .cell(); - -result.string(count == 0); + .where("DISTRICT.PARENTDISTRICT_DISTRICTID", districtId); + +var canDelete = new HasLinkedObjectTester() + .andNoEntityRows("Document_entity", "Documents", {AssignmentTable_param : "DISTRICT", AssignmentRowId_param : districtId}) //Documents + .andSqlYieldsZero(count) + .validate(); + +result.string(canDelete); diff --git a/entity/DocumentTemplate_entity/entityfields/openhtmleditor/stateProcess.js b/entity/DocumentTemplate_entity/entityfields/openhtmleditor/stateProcess.js index c0824ad21cb8d86f3e4cd4b0729d393cb7db7870..718a96109027807c05614a94925ff71302ec524c 100644 --- a/entity/DocumentTemplate_entity/entityfields/openhtmleditor/stateProcess.js +++ b/entity/DocumentTemplate_entity/entityfields/openhtmleditor/stateProcess.js @@ -7,5 +7,12 @@ import("system.neon"); var template = DocumentTemplateUtils.getTemplate(vars.get("$field.DOCUMENTTEMPLATEID"), false); var kind = vars.get("$field.KIND"); -if(template.type == DocumentTemplate.types.HTML && kind == $KeywordRegistry.documentTemplateType$textModular() || kind == $KeywordRegistry.documentTemplateType$mail()) - result.string(neon.COMPONENTSTATE_EDITABLE); +if (template) +{ + if(template.type == DocumentTemplate.types.HTML && + kind == $KeywordRegistry.documentTemplateType$textModular() || + kind == $KeywordRegistry.documentTemplateType$mail()) + { + result.string(neon.COMPONENTSTATE_EDITABLE); + } +} diff --git a/entity/Email_entity/entityfields/sendmail/onActionProcess.js b/entity/Email_entity/entityfields/sendmail/onActionProcess.js index 0ee0af9d3e78ea7027cafebd667d54814c15e43c..8c93bbcfad19c8a77e2d8aa228f336723f2b466c 100644 --- a/entity/Email_entity/entityfields/sendmail/onActionProcess.js +++ b/entity/Email_entity/entityfields/sendmail/onActionProcess.js @@ -30,7 +30,7 @@ if (vars.exists("$param.AdditionalPlaceholders_param") && vars.get("$param.Addit }); } -var eml = EmailWritingUtils.openMailTemplate( +EmailWritingUtils.openMailTemplate( vars.get("$field.RECIPIENT"), EmployeeUtils.getCurrentContactId(), vars.get("$field.DOCUMENT_TEMPLATE"), diff --git a/entity/Employee_entity/Employee_entity.aod b/entity/Employee_entity/Employee_entity.aod index bfd8058aad0b247a60cbaa1f25a8ffe947c08eb4..d5182766d6b8c6d1efd6963ce26fb9a64761077a 100644 --- a/entity/Employee_entity/Employee_entity.aod +++ b/entity/Employee_entity/Employee_entity.aod @@ -297,6 +297,24 @@ <fieldName>Employees</fieldName> <isConsumer v="false" /> </entityDependency> + <entityDependency> + <name>9c38e9ef-6f90-4e57-af45-d82539c57a0e</name> + <entityName>Planning_entity</entityName> + <fieldName>Responsible</fieldName> + <isConsumer v="false" /> + </entityDependency> + <entityDependency> + <name>b49eecba-062b-4658-a3b9-574982536fb1</name> + <entityName>PlanningChangeStatusAndResponsible_entity</entityName> + <fieldName>Responsibles</fieldName> + <isConsumer v="false" /> + </entityDependency> + <entityDependency> + <name>d1736052-573f-4774-b90b-0f8a81083cb6</name> + <entityName>PlanningAddToOrganisations_entity</entityName> + <fieldName>Responsible</fieldName> + <isConsumer v="false" /> + </entityDependency> </dependencies> <children> <entityParameter> diff --git a/entity/Employee_entity/recordcontainers/jdito/contentProcess.js b/entity/Employee_entity/recordcontainers/jdito/contentProcess.js index 8970fd6bd60fb0f744c14a2089ae5a213ef71702..5fabbf72734e00a22b4fb52ad5cb2e3472adcf76 100644 --- a/entity/Employee_entity/recordcontainers/jdito/contentProcess.js +++ b/entity/Employee_entity/recordcontainers/jdito/contentProcess.js @@ -1,6 +1,4 @@ -import("system.logging"); import("Sql_lib"); -import("system.db"); import("Attribute_lib"); import("system.vars"); import("system.result"); diff --git a/entity/Forecast_entity/Forecast_entity.aod b/entity/Forecast_entity/Forecast_entity.aod index d8b6f1c7fe8094323f828a1e133cfa91704bf158..9182cdc2c8fcf6e928dc89de0a768396901706ed 100644 --- a/entity/Forecast_entity/Forecast_entity.aod +++ b/entity/Forecast_entity/Forecast_entity.aod @@ -126,6 +126,10 @@ <name>#PROVIDER_AGGREGATES</name> <useAggregates v="true" /> </entityProvider> + <entityField> + <name>KIND</name> + <valueProcess>%aditoprj%/entity/Forecast_entity/entityfields/kind/valueProcess.js</valueProcess> + </entityField> </entityFields> <recordContainers> <dbRecordContainer> @@ -173,6 +177,10 @@ <name>FORECASTID.value</name> <recordfield>FORECAST.FORECASTID</recordfield> </dbRecordFieldMapping> + <dbRecordFieldMapping> + <name>KIND.value</name> + <recordfield>FORECAST.KIND</recordfield> + </dbRecordFieldMapping> </recordFieldMappings> <linkInformation> <linkInformation> diff --git a/entity/Forecast_entity/entityfields/kind/valueProcess.js b/entity/Forecast_entity/entityfields/kind/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..0c435ef9c8d8c55358dcec3248633382dde57b30 --- /dev/null +++ b/entity/Forecast_entity/entityfields/kind/valueProcess.js @@ -0,0 +1,9 @@ +import("system.vars"); +import("system.result"); +import("KeywordRegistry_basic"); + +if(vars.get("$this.value") == null) +{ + result.string($KeywordRegistry.forecastKind$forecast()); +} + diff --git a/entity/Forecast_entity/recordcontainers/db/conditionProcess.js b/entity/Forecast_entity/recordcontainers/db/conditionProcess.js index 0c0805ca63787abe761e25b34fa860f9cb5c820d..8bdcaacb995af969f571d8c5847671e31caa5c21 100644 --- a/entity/Forecast_entity/recordcontainers/db/conditionProcess.js +++ b/entity/Forecast_entity/recordcontainers/db/conditionProcess.js @@ -1,9 +1,11 @@ +import("KeywordRegistry_basic"); import("system.vars"); import("system.db"); import("system.result"); import("Sql_lib"); var cond = newWhere() + .and("FORECAST.KIND", $KeywordRegistry.forecastKind$forecast()) .andIfSet("FORECAST.OBJECT_ROWID", "$param.ObjectRowId_param") .andIfSet("FORECAST.OBJECT_TYPE", "$param.ObjectType_param"); diff --git a/entity/KeywordCategory_entity/recordcontainers/db/onDBDelete.js b/entity/KeywordCategory_entity/recordcontainers/db/onDBDelete.js index 9fb896f27e82dbcc7f7afcadf277a6a2383d6f24..5d42defb0b26b5b8267b5340c0067bccecf1ecc2 100644 --- a/entity/KeywordCategory_entity/recordcontainers/db/onDBDelete.js +++ b/entity/KeywordCategory_entity/recordcontainers/db/onDBDelete.js @@ -5,11 +5,11 @@ import("Sql_lib"); var categoryId = vars.get("$local.uid"); newWhere("AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ATTRIBUTE_ID", newSelect("AB_KEYWORD_ATTRIBUTE.AB_KEYWORD_ATTRIBUTEID") - .from("AB_KEYWORD_ATTRIBUTE") - .where("AB_KEYWORD_ATTRIBUTE.AB_KEYWORD_CATEGORY_ID", categoryId) - , SqlBuilder.IN()).deleteData(); -newWhere("AB_KEYWORD_ATTRIBUTE.AB_KEYWORD_CATEGORY_ID", categoryId).deleteData(); -newWhere("AB_KEYWORD_ENTRY.AB_KEYWORD_CATEGORY_ID", categoryId).deleteData(); + .from("AB_KEYWORD_ATTRIBUTE") + .where("AB_KEYWORD_ATTRIBUTE.AB_KEYWORD_CATEGORY_ID", categoryId) + , SqlBuilder.IN()).deleteData(true, "AB_KEYWORD_ATTRIBUTERELATION"); +newWhere("AB_KEYWORD_ATTRIBUTE.AB_KEYWORD_CATEGORY_ID", categoryId).deleteData(true, "AB_KEYWORD_ATTRIBUTE"); +newWhere("AB_KEYWORD_ENTRY.AB_KEYWORD_CATEGORY_ID", categoryId).deleteData(true, "AB_KEYWORD_ENTRY"); //dependecies are removed so the cache needs to be updated entities.invalidateCache("KeywordEntry_entity", "db"); \ No newline at end of file diff --git a/entity/KeywordEntry_entity/KeywordEntry_entity.aod b/entity/KeywordEntry_entity/KeywordEntry_entity.aod index 44c798ccabe7ae92fb32abac9855b811f4edcbc7..995222aa8beb491c011f3d9ec0dc3116a4648788 100644 --- a/entity/KeywordEntry_entity/KeywordEntry_entity.aod +++ b/entity/KeywordEntry_entity/KeywordEntry_entity.aod @@ -637,6 +637,42 @@ <fieldName>KeywordPhases</fieldName> <isConsumer v="false" /> </entityDependency> + <entityDependency> + <name>bf774c79-2902-4fdb-a8d2-8a157294bc27</name> + <entityName>Planning_entity</entityName> + <fieldName>KeywordKinds</fieldName> + <isConsumer v="false" /> + </entityDependency> + <entityDependency> + <name>3a570fef-552b-4d94-b010-33a7ffee7a96</name> + <entityName>Planning_entity</entityName> + <fieldName>KeywordStatus</fieldName> + <isConsumer v="false" /> + </entityDependency> + <entityDependency> + <name>5dc1bb58-75cb-4214-b6f5-065e8de26779</name> + <entityName>Planning_entity</entityName> + <fieldName>KeywordGroupcode</fieldName> + <isConsumer v="false" /> + </entityDependency> + <entityDependency> + <name>49358965-6e83-4279-82a8-babf257c3b5f</name> + <entityName>PlanningAddToOrganisations_entity</entityName> + <fieldName>KeywordStatus</fieldName> + <isConsumer v="false" /> + </entityDependency> + <entityDependency> + <name>f7aa1856-6896-4531-8b15-d3c5504172fb</name> + <entityName>PlanningAddToOrganisations_entity</entityName> + <fieldName>KeywordGroupcode</fieldName> + <isConsumer v="false" /> + </entityDependency> + <entityDependency> + <name>12a0dd2c-57f2-4277-b25c-9f824b82308d</name> + <entityName>PlanningChangeStatusAndResponsible_entity</entityName> + <fieldName>KeywordStatus</fieldName> + <isConsumer v="false" /> + </entityDependency> </dependencies> <children> <entityParameter> @@ -652,7 +688,7 @@ </entityProvider> <entityField> <name>TITLE_TRANSLATED</name> - <state>INVISIBLE</state> + <title>Title (translated)</title> <valueProcess>%aditoprj%/entity/KeywordEntry_entity/entityfields/title_translated/valueProcess.js</valueProcess> </entityField> <entityParameter> diff --git a/entity/LeadLog_entity/LeadLog_entity.aod b/entity/LeadLog_entity/LeadLog_entity.aod index 60e321526ff8163355ca475842c04ef2ff6af8aa..6ebe0432210ce13bf1eda860c5496b14cbfa87e1 100644 --- a/entity/LeadLog_entity/LeadLog_entity.aod +++ b/entity/LeadLog_entity/LeadLog_entity.aod @@ -6,7 +6,8 @@ <documentation>%aditoprj%/entity/LeadLog_entity/documentation.adoc</documentation> <grantCreate v="false" /> <grantUpdate v="false" /> - <grantDelete v="false" /> + <grantDelete v="true" /> + <grantDeleteProcess>%aditoprj%/entity/LeadLog_entity/grantDeleteProcess.js</grantDeleteProcess> <recordContainer>db</recordContainer> <entityFields> <entityProvider> diff --git a/entity/LeadLog_entity/grantDeleteProcess.js b/entity/LeadLog_entity/grantDeleteProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..cea08cc1f625bdd4b38ced32dffe9b979c2a0c5b --- /dev/null +++ b/entity/LeadLog_entity/grantDeleteProcess.js @@ -0,0 +1,10 @@ +import("system.vars"); +import("system.result"); + +var leadLogId = vars.get("$field.LEADLOGID"); + +var canDelete = new HasLinkedObjectTester() + .andNoEntityRows("Document_entity", "Documents", {AssignmentTable_param : "LEADLOG", AssignmentRowId_param : leadLogId}) //Documents + .validate(); + +result.string(canDelete); \ No newline at end of file diff --git a/entity/Leadimport_entity/grantDeleteProcess.js b/entity/Leadimport_entity/grantDeleteProcess.js index 416fae60ccb6b7be26ccf428eb9c5f692b18b077..673d09de7739420cae7e94fc8270ceacba96564b 100644 --- a/entity/Leadimport_entity/grantDeleteProcess.js +++ b/entity/Leadimport_entity/grantDeleteProcess.js @@ -8,6 +8,7 @@ var currentContext = ContextUtils.getCurrentContextId(); var canDelete = new HasLinkedObjectTester() .andNoEntityRows("Task_entity", "Tasks", {ObjectId_param : currentContext, RowId_param : rowId}) //Tasks + .andNoEntityRows("Document_entity", "Documents", {AssignmentTable_param : "LEADIMPORT", AssignmentRowId_param : rowId}) //Documents .validate(); result.string(canDelete); diff --git a/entity/Letter_entity/entityfields/downloadletterandcreateactivity/onActionProcess.js b/entity/Letter_entity/entityfields/downloadletterandcreateactivity/onActionProcess.js index 0c453f91c3e8e31847be4c6cca575257597a7650..69b7b7b8cb88c489754264203262574b6ff4e2be 100644 --- a/entity/Letter_entity/entityfields/downloadletterandcreateactivity/onActionProcess.js +++ b/entity/Letter_entity/entityfields/downloadletterandcreateactivity/onActionProcess.js @@ -33,6 +33,4 @@ if (template) } ActivityUtils.createNewActivity(null, links, null, null, translate.text("Letter"), text.parseDocument(content), $KeywordRegistry.activityDirection$outgoing(), [[template.filename, content, false]]); -} -else - throw new Error("Error while using a document template: The provided template does not contain data."); \ No newline at end of file +} \ No newline at end of file diff --git a/entity/Member_entity/recordcontainers/jdito/contentProcess.js b/entity/Member_entity/recordcontainers/jdito/contentProcess.js index 85d651ee76c4f9f5d1898f4a39d2c48644226946..6a0466b6f9cb9866935d6039e83c9f64148033ae 100644 --- a/entity/Member_entity/recordcontainers/jdito/contentProcess.js +++ b/entity/Member_entity/recordcontainers/jdito/contentProcess.js @@ -106,9 +106,16 @@ if (Utils.isNullOrEmpty(idValues) || memberRows.length === 0) .entity("Person_entity") .uids(responsibleUids) .fields(["ORGANISATION_ID", "ORGANISATION_NAME", "CONTACTROLE", "POSITION", - "FIRSTNAME", "LASTNAME", "SALUTATION", "TITLE"]); - - var persRows = entities.getRows(loadingConfPers); + "FIRSTNAME", "LASTNAME", "SALUTATION", "TITLE", "PERSONID", "CONTACTID"]); + var persRowsMap = {}; + entities.getRows(loadingConfPers).forEach(function(item) { + persRowsMap[item["CONTACTID"]] = item; + }); + + var persRows = []; + responsibleUids.forEach(function(uid) { + persRows.push(persRowsMap[uid]); + }); persRows = persRows.map(function(row){ return [row["SALUTATION"], row["TITLE"], row["FIRSTNAME"], row["LASTNAME"], diff --git a/entity/Offer_entity/entityfields/anycontacts/children/contactids_param/valueProcess.js b/entity/Offer_entity/entityfields/anycontacts/children/contactids_param/valueProcess.js index 64ebdd402a070cab2fb3c837720f16423cda76ec..b705ec11cfccaaef8f29c1143c3980d86f028ae2 100644 --- a/entity/Offer_entity/entityfields/anycontacts/children/contactids_param/valueProcess.js +++ b/entity/Offer_entity/entityfields/anycontacts/children/contactids_param/valueProcess.js @@ -1,10 +1,21 @@ import("system.result"); import("system.vars"); +import("Sql_lib"); -var contactIds = ""; -if (vars.exists("$param.ContactIds_param") && vars.get("$param.ContactIds_param")) { +var contactIds = null; +if(vars.exists("$param.ContactIds_param") && vars.get("$param.ContactIds_param")) +{ contactIds = vars.get("$param.ContactIds_param"); } -if (contactIds) - result.string(contactIds); \ No newline at end of file +if(!contactIds && vars.get("$field.CONTACT_ORG_ID")) +{ + var sql = newSelect("CONTACTID").from("CONTACT") + .where("CONTACT.ORGANISATION_ID", vars.get("$field.CONTACT_ORG_ID")); + contactIds = JSON.stringify(sql.arrayColumn()); +} + +if(contactIds) +{ + result.string(contactIds); +} diff --git a/entity/Offer_entity/entityfields/contact_id/stateProcess.js b/entity/Offer_entity/entityfields/contact_id/stateProcess.js index e64c4d20acc8987719c1a474f96da92ddce301e4..0dcccb84c7750c4743ac3fb30a625052af4e8830 100644 --- a/entity/Offer_entity/entityfields/contact_id/stateProcess.js +++ b/entity/Offer_entity/entityfields/contact_id/stateProcess.js @@ -3,8 +3,11 @@ import("system.result"); import("system.neon"); import("system.vars"); -if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT || - (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.exists("$param.ContactId_param") && vars.get("$param.ContactId_param"))) +if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT) +{ result.string(neon.COMPONENTSTATE_READONLY); +} else - result.string(OfferUtils.isEditable(vars.get("$field.STATUS")) ? neon.COMPONENTSTATE_AUTO : neon.COMPONENTSTATE_DISABLED); \ No newline at end of file +{ + result.string(OfferUtils.isEditable(vars.get("$field.STATUS")) ? neon.COMPONENTSTATE_AUTO : neon.COMPONENTSTATE_DISABLED); +} diff --git a/entity/Offer_entity/entityfields/contact_id/valueProcess.js b/entity/Offer_entity/entityfields/contact_id/valueProcess.js index c50907d05b5a89d6a44af670474fff35f2f6c74d..c0b04b66955d098cc77487c068ccbf00045c7b76 100644 --- a/entity/Offer_entity/entityfields/contact_id/valueProcess.js +++ b/entity/Offer_entity/entityfields/contact_id/valueProcess.js @@ -6,27 +6,31 @@ import("Sql_lib"); import("Context_lib"); if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && vars.get("$this.value") == null) -var contactId = ""; -if ((!vars.exists("$param.ContactId_param") || !vars.get("$param.ContactId_param")) - && (vars.exists("$param.ObjectType_param") - && vars.get("$param.ObjectType_param") - && vars.exists("$param.ObjectRowId_param") - && vars.get("$param.ObjectRowId_param"))) { - contactId = ContextUtils.getContactId(vars.get("$param.ObjectType_param"), vars.get("$param.ObjectRowId_param")) -} else if (vars.exists("$param.ContactId_param") && vars.get("$param.ContactId_param")) { - contactId = vars.get("$param.ContactId_param"); -} - -if (contactId) -{ - var lang = newSelect("ISOLANGUAGE") - .from("CONTACT") - .where("CONTACT.CONTACTID", contactId) - .cell(); - - if(lang != "") - neon.setFieldValue("field.ISOLANGUAGE", lang); + var contactId = ""; + if ((!vars.exists("$param.ContactId_param") || !vars.get("$param.ContactId_param")) + && (vars.exists("$param.ObjectType_param") + && vars.get("$param.ObjectType_param") + && vars.exists("$param.ObjectRowId_param") + && vars.get("$param.ObjectRowId_param"))) + { + contactId = ContextUtils.getContactId(vars.get("$param.ObjectType_param"), vars.get("$param.ObjectRowId_param")); + } + else if (vars.exists("$param.ContactId_param") && vars.get("$param.ContactId_param")) + { + contactId = vars.get("$param.ContactId_param"); + } - result.string(contactId); -} \ No newline at end of file + if (contactId) + { + var lang = newSelect("ISOLANGUAGE") + .from("CONTACT") + .where("CONTACT.CONTACTID", contactId) + .cell(); + + if(lang != "") + neon.setFieldValue("field.ISOLANGUAGE", lang); + + result.string(contactId); + } +} diff --git a/entity/Offer_entity/entityfields/currency/stateProcess.js b/entity/Offer_entity/entityfields/currency/stateProcess.js index 3625a84172ccbedf97a4a6aa2c74ff6f9fe83679..20a5979a7502c8f535158aa31c0f850bf2405526 100644 --- a/entity/Offer_entity/entityfields/currency/stateProcess.js +++ b/entity/Offer_entity/entityfields/currency/stateProcess.js @@ -2,5 +2,18 @@ import("system.vars"); import("system.result"); import("system.neon"); import("Offer_lib"); +import("system.entities"); -result.string(OfferUtils.isEditable(vars.get("$field.STATUS")) ? neon.COMPONENTSTATE_AUTO : neon.COMPONENTSTATE_DISABLED); \ No newline at end of file +var loadConfig = entities.createConfigForLoadingRows() + .entity("OfferItem_entity") + .addParameter("OfferId_param", vars.get("$field.OFFERID")); +var offerItemCount = entities.getRowCount(loadConfig); + +if(offerItemCount > 0) +{ + result.string(neon.COMPONENTSTATE_DISABLED); +} +else +{ + result.string(OfferUtils.isEditable(vars.get("$field.STATUS")) ? neon.COMPONENTSTATE_AUTO : neon.COMPONENTSTATE_DISABLED); +} diff --git a/entity/Offer_entity/entityfields/offercode/onValidation.js b/entity/Offer_entity/entityfields/offercode/onValidation.js index 58a3364596c6f0a8f85c3863acf31b877c629f69..63c69739e9c8429c0c1471f30a67781b9db395ae 100644 --- a/entity/Offer_entity/entityfields/offercode/onValidation.js +++ b/entity/Offer_entity/entityfields/offercode/onValidation.js @@ -1,5 +1,9 @@ +import("system.vars"); import("system.neon"); //reload the field on save to make sure the offercode is really unique, otherwise the offercode could be the same for two offers created at //the same time -neon.refresh(["$field.OFFERCODE"]); \ No newline at end of file +if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW) +{ + neon.refresh(["$field.OFFERCODE"]); +} \ No newline at end of file diff --git a/entity/Offer_entity/entityfields/status/stateProcess.js b/entity/Offer_entity/entityfields/status/stateProcess.js index 2f47d5d1011fd2ccbe859630ac7904f21f4c6a09..547c00b1f8ff3f450ee6e9b33fcd7a472dd34d71 100644 --- a/entity/Offer_entity/entityfields/status/stateProcess.js +++ b/entity/Offer_entity/entityfields/status/stateProcess.js @@ -4,4 +4,11 @@ import("system.neon"); import("Offer_lib"); import("KeywordRegistry_basic"); -result.string(OfferUtils.isEditable(vars.get("$field.STATUS")) || vars.get("$field.STATUS") == $KeywordRegistry.offerStatus$sent() ? neon.COMPONENTSTATE_AUTO : neon.COMPONENTSTATE_DISABLED); \ No newline at end of file +if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW) +{ + result.string(neon.COMPONENTSTATE_READONLY); +} +else +{ + result.string(OfferUtils.isEditable(vars.get("$field.STATUS")) || vars.get("$field.STATUS") == $KeywordRegistry.offerStatus$sent() ? neon.COMPONENTSTATE_AUTO : neon.COMPONENTSTATE_DISABLED); +} diff --git a/entity/Offer_entity/grantUpdateProcess.js b/entity/Offer_entity/grantUpdateProcess.js index f022059101691315bf584048dfcd766f0d747cdf..dd8ad2ced390f8db78ba4b8eb638915cfdda25aa 100644 --- a/entity/Offer_entity/grantUpdateProcess.js +++ b/entity/Offer_entity/grantUpdateProcess.js @@ -1,2 +1,14 @@ +import("system.tools"); +import("system.result"); +import("system.vars"); +import("KeywordRegistry_basic"); + // as one field (status) should be editable if status is sent and all other not, it is done by a state process in each field. -// using the grant update would also disable the status field. \ No newline at end of file +// using the grant update would also disable the status field. + +var status = vars.get("$field.STATUS"); +var editable = status != $KeywordRegistry.offerStatus$sent() + && status != $KeywordRegistry.offerStatus$won() + && status != $KeywordRegistry.offerStatus$lost(); + +result.string(editable || tools.hasRole(vars.get("$sys.user"), "INTERNAL_ADMINISTRATOR")); diff --git a/entity/Offeritem_entity/Offeritem_entity.aod b/entity/Offeritem_entity/Offeritem_entity.aod index 002cae927a6f49f5b009e413ce6338fb70b475e3..4b11ba39e18f534dfcccf3a4fe05a4679f04416c 100644 --- a/entity/Offeritem_entity/Offeritem_entity.aod +++ b/entity/Offeritem_entity/Offeritem_entity.aod @@ -73,8 +73,9 @@ <contentType>NUMBER</contentType> <outputFormat>#,##0.00</outputFormat> <inputFormat>#,##0.00</inputFormat> + <mandatory v="true" /> + <valueProcess>%aditoprj%/entity/Offeritem_entity/entityfields/price/valueProcess.js</valueProcess> <displayValueProcess>%aditoprj%/entity/Offeritem_entity/entityfields/price/displayValueProcess.js</displayValueProcess> - <onValidation>%aditoprj%/entity/Offeritem_entity/entityfields/price/onValidation.js</onValidation> </entityField> <entityField> <name>PRODUCT_ID</name> @@ -292,6 +293,10 @@ </entityActionField> </children> </entityActionGroup> + <entityField> + <name>itemInsertStatements</name> + <documentation>%aditoprj%/entity/Offeritem_entity/entityfields/iteminsertstatements/documentation.adoc</documentation> + </entityField> </entityFields> <recordContainers> <dbRecordContainer> diff --git a/entity/Offeritem_entity/entityfields/iteminsertstatements/documentation.adoc b/entity/Offeritem_entity/entityfields/iteminsertstatements/documentation.adoc new file mode 100644 index 0000000000000000000000000000000000000000..483999ea30ce8b8d311f57b6a69113bfa9d9f1e6 --- /dev/null +++ b/entity/Offeritem_entity/entityfields/iteminsertstatements/documentation.adoc @@ -0,0 +1,5 @@ += itemInsertStatements + +Helper field to store the statements for the childitems (statements get built with the correct amounts when changing the product or the quantity). +Statements get stored as stringified object. +And parsed and inserted in the onInsertProcess \ No newline at end of file diff --git a/entity/Offeritem_entity/entityfields/price/onValidation.js b/entity/Offeritem_entity/entityfields/price/onValidation.js deleted file mode 100644 index 20fb049467d74f3d2770187652e1e958bd69a285..0000000000000000000000000000000000000000 --- a/entity/Offeritem_entity/entityfields/price/onValidation.js +++ /dev/null @@ -1,9 +0,0 @@ -import("system.translate"); -import("system.result"); -import("system.vars"); - -var localValue = vars.get("$local.value"); -if(!localValue || parseFloat(localValue) <= 0) -{ - result.string(translate.text("Price could not be determined")); -} diff --git a/entity/Offeritem_entity/entityfields/price/valueProcess.js b/entity/Offeritem_entity/entityfields/price/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/entity/Offeritem_entity/entityfields/product_id/onValueChange.js b/entity/Offeritem_entity/entityfields/product_id/onValueChange.js index 0d52517c981eb2f8832ea8149f8206dae6067d8b..2dc7f5d987c0b34ce0729068c679995626a41707 100644 --- a/entity/Offeritem_entity/entityfields/product_id/onValueChange.js +++ b/entity/Offeritem_entity/entityfields/product_id/onValueChange.js @@ -1,11 +1,35 @@ +import("system.neon"); import("system.vars"); import("OfferOrder_lib"); +import("Offer_lib"); var pId = vars.get("$local.value"); -var uid = vars.get("$field.OFFERITEMID"); -var entity = vars.get("$sys.currententityname"); -if(pId != "") +if(pId != "" && vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW) { + var uid = vars.get("$field.OFFERITEMID"); + var entity = vars.get("$sys.currententityname"); ItemUtils.product_IdOnValueChange(pId, uid, entity); -} \ No newline at end of file + var oiUtils = new OfferItemUtils(vars.get("$field.OFFER_ID")); + var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : ""; + var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : ""; + var language = vars.exists("$param.Language_param") ? vars.get("$param.Language_param") : ""; + var quantity = vars.get("$field.QUANTITY"); + + var sumUpTop = false; + var price = vars.get("$field.PRICE"); + if(!price) + { + sumUpTop = true; + } + + var partsListObject = oiUtils.insertPartsList(pId, vars.get("$field.OFFERITEMID"), curr, contactid, language, quantity, true, vars.get("$field.OFFER_ID"), sumUpTop); + + neon.setFieldValue("$field.itemInsertStatements", JSON.stringify(partsListObject["partsList"])); + + if(sumUpTop && partsListObject["topProductInfo"])//only sum-up this price if there is no valid Price + { + neon.setFieldValue("$field.PRICE", partsListObject["topProductInfo"]["price"]*quantity); + neon.setFieldValue("$field.VAT", partsListObject["topProductInfo"]["vat"]); + } +} diff --git a/entity/Offeritem_entity/entityfields/quantity/onValueChange.js b/entity/Offeritem_entity/entityfields/quantity/onValueChange.js index 051fa52ad7aebb44ad62ec755fa776f4232cc9bd..d7b8bf70c3d2499934263912da05af0dc88a291e 100644 --- a/entity/Offeritem_entity/entityfields/quantity/onValueChange.js +++ b/entity/Offeritem_entity/entityfields/quantity/onValueChange.js @@ -1,36 +1,34 @@ -import("AttributeRegistry_basic"); import("system.vars"); import("system.neon"); -import("Product_lib"); -import("Util_lib"); -import("Entity_lib"); -import("Attribute_lib"); +import("OfferOrder_lib"); +import("Offer_lib"); -var pid = vars.get("$field.PRODUCT_ID"); -var newQuantity = vars.get("local.value"); -if(pid != "" && newQuantity != "") +var pId = vars.get("$field.PRODUCT_ID"); +if(pId != "" && vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW) { + var uid = vars.get("$field.OFFERITEMID"); + var entity = vars.get("$sys.currententityname"); + ItemUtils.product_IdOnValueChange(pId, uid, entity); + + var oiUtils = new OfferItemUtils(vars.get("$field.OFFER_ID")); var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : ""; var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : ""; - var pricelist = new AttributeRelationQuery(contactid, $AttributeRegistry.pricelist()).getSingleAttributeValue() || ""; - - var PriceListFilter = { currency: curr, quantity: newQuantity, relationId: contactid, priceList: pricelist }; + var language = vars.exists("$param.Language_param") ? vars.get("$param.Language_param") : ""; + var quantity = vars.get("$local.value"); + + var sumUpTop = false; + var price = vars.get("$field.PRICE"); + if(!price) + { + sumUpTop = true; + } - var ProductDetails = ProductUtils.getProductDetails(pid, PriceListFilter); + var partsListObject = oiUtils.insertPartsList(pId, vars.get("$field.OFFERITEMID"), curr, contactid, language, quantity, true, vars.get("$field.OFFER_ID"), sumUpTop); + neon.setFieldValue("$field.itemInsertStatements", JSON.stringify(partsListObject["partsList"])); - if(ProductDetails.productId != undefined && ProductDetails.PriceListToUse != null) + if(sumUpTop)//only sum-up this price if there is no valid Price { - neon.setFieldValue("$field.PRICE", ProductDetails.PriceListToUse.price); - neon.setFieldValue("$field.VAT", ProductDetails.PriceListToUse.vat); + neon.setFieldValue("$field.PRICE", partsListObject["topProductInfo"]["price"]); + neon.setFieldValue("$field.VAT", partsListObject["topProductInfo"]["vat"]); } -} - - -//checks if the value is <= 0, if so fallback to 1 -var quatity = vars.get("$local.value") ? vars.get("$local.value") : ""; - -if (parseInt(quatity) <= 0) -{ - neon.setFieldValue("local.value", "1"); -} - \ No newline at end of file +} \ No newline at end of file diff --git a/entity/Offeritem_entity/recordcontainers/db/onDBInsert.js b/entity/Offeritem_entity/recordcontainers/db/onDBInsert.js index ccbec217a9ab2911b54beeaef6e915c64863b14c..7310f91eb38e14a7e2bf37c40acaec12e1e58116 100644 --- a/entity/Offeritem_entity/recordcontainers/db/onDBInsert.js +++ b/entity/Offeritem_entity/recordcontainers/db/onDBInsert.js @@ -1,172 +1,50 @@ -import("system.eMath"); +import("system.db"); +import("OfferOrder_lib"); import("system.entities"); -import("system.datetime"); import("system.neon"); import("system.vars"); -import("system.db"); -import("system.util"); import("Offer_lib"); import("Product_lib"); import("Sql_lib"); var rowdata = vars.get("$local.rowdata"); - var oid = rowdata["OFFERITEM.OFFER_ID"]; if(oid != "") { - var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : ""; - var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : ""; var discount = vars.exists("$param.Discount_param") ? vars.get("$param.Discount_param"): ""; - var quantity = vars.get("$field.QUANTITY"); var oiUtils = new OfferItemUtils(rowdata["OFFERITEM.OFFER_ID"]); - var insertParts = oiUtils.insertPartsList(rowdata["OFFERITEM.PRODUCT_ID"], vars.get("$local.uid"), curr, contactid, vars.get("$param.Language_param"), quantity, true); - oiUtils.reOrgItems(); - var calculatedPrices = {}; - var priceObj = insertParts["priceObject"]; - var treeStructure = insertParts["treeStructure"][rowdata["OFFERITEM.OFFERITEMID"]]; - var productsWithSumUpPrices = insertParts["productsWithSumUpPrices"] - var correctOrder = insertParts["insertedItemIds"]; - _handleSumUpPricesOfItems(correctOrder, treeStructure, productsWithSumUpPrices, priceObj); - var price = rowdata["OFFERITEM.PRICE"]; - if(price === "" || price === undefined || price === null) + + var insertStatements = JSON.parse(vars.get("$field.itemInsertStatements"));//insert statements get set by insertPartsList in the onvalueChanges of product_id and quantity + var statements = []; + if(insertStatements) { - var calcPrice = 0; - var vat = 0; - for(var id in treeStructure) - { - calcPrice = eMath.addDec(priceObj[id]["price"], calcPrice); - if(priceObj[id]["vat"] !== null && priceObj[id]["vat"] !== undefined && priceObj[id]["vat"] > 0) - { - vat = priceObj[id]["vat"]; - } - } - var config = entities.createConfigForUpdatingRows() - .entity("Offeritem_entity") - .addParameter("OfferId_param", oid) - .addParameter("IgnoreOnUpdateProcess_param", true) - .uid(rowdata["OFFERITEM.OFFERITEMID"]) - .fieldValues({ - "PRICE": calcPrice, - "VAT": vat - }); - entities.updateRow(config); + statements = statements.concat(insertStatements); } //update offer price var vals = oiUtils.getNetAndVat(); var discountedVals = OfferItemUtils.getDiscountedNet(null, oid, discount); - - let config = entities.createConfigForUpdatingRows() - config.entity("Offer_entity"); - if(discountedVals) { - config.fieldValues({ - "NET": vals[0], - "VAT": vals[1], - "DISCOUNTED_NET": discountedVals[0], - "DISCOUNTED_VAT": discountedVals[1] - }); + insertStatements.push( + newWhere("OFFERITEM.OFFERITEMID", rowdata["OFFERITEM.OFFERITEMID"]).buildUpdateStatement({ + "NET": vals[0], + "VAT": vals[1], + "DISCOUNTED_NET": discountedVals[0], + "DISCOUNTED_VAT": discountedVals[1] + }) + ) } else { - config.fieldValues({ - "NET": vals[0], - "VAT": vals[1] - }); - - } - config.uid(oid); - entities.updateRow(config); -} - -//We want to sum up the prices directly under the current item to calculate the price if we don't have an valid price for them -function _handleSumUpPricesOfItems(pOrder, pTreestruct, pSumUpPrices, pPriceObj) -{ - - var currentStruc = pTreestruct; - var sumUpPrices = pSumUpPrices; - var order = pOrder; - var summandObject = {}; - for (var i = order.length; i > -1; i--)//we do this backwards because otherwiese we would run into problems when trying to build the sum (we could have items without an price yet) - { - if(sumUpPrices.hasOwnProperty(order[i])) - { - summandObject[order[i]] = _getNode(pTreestruct, order[i], Object.keys(pTreestruct)[0]); - } - } - - for(var offerItem in summandObject) - { - var calcPrice = 0; - var vat = null; - for (var child in summandObject[offerItem]) - { - var childPrice; - if(priceObj[child] != undefined) - { - childPrice = priceObj[child]["price"] - } - else if(summandObject[child][child] != undefined) - { - childPrice = priceObj[Object.keys(summandObject[child][child])[0]]["price"] - vat = priceObj[Object.keys(summandObject[child][child])[0]]["vat"] - } - else - { - childPrice = 0; - vat = 0; - } - calcPrice = eMath.addDec(childPrice, calcPrice); - if(!vat) - { - vat = priceObj[child]["vat"]; - } - } - calculatedPrices[offerItem] = {}; - calculatedPrices[offerItem]["price"] = calcPrice; - calculatedPrices[offerItem]["vat"] = vat; - priceObj[offerItem] = {}; - priceObj[offerItem]["price"] = calcPrice; - priceObj[offerItem]["vat"] = vat; - - } - //ToDo: Document - function _getNode(pObject, pName, pCurrName){ - if(pCurrName == pName) - { - return pObject; - } - else if (pObject != undefined) - { - let x; - let res = null; - for(var obj in pObject) - { - if(res == null) - { - res = _getNode(pObject[obj], pName, obj); - } - else - { - break; - } - } - return res; - } - return null; + insertStatements.push( + newWhere("OFFERITEMID", rowdata["OFFERITEM.OFFERITEMID"]) + .buildUpdateStatement({ + "NET": vals[0], + "VAT": vals[1] + }) + ) } - - var config = entities.createConfigForUpdatingRows().entity("Offeritem_entity").addParameter("OfferId_param", oid).addParameter("IgnoreOnUpdateProcess_param", true); - for(var oiId in productsWithSumUpPrices) - { - config.uid(oiId) - .fieldValues({ - "PRICE": priceObj[oiId]["price"], - "VAT": priceObj[oiId]["vat"] - }); - - entities.updateRow(config); - } + db.execute(statements, "Data_alias", 10000000); } \ No newline at end of file diff --git a/entity/Offeritem_entity/recordcontainers/db/onDBUpdate.js b/entity/Offeritem_entity/recordcontainers/db/onDBUpdate.js index a3e8e2fb33ac86ffe5baad4675c7dba8ab206316..a86dd0453eef51446501a4f8119e4896ee27fa68 100644 --- a/entity/Offeritem_entity/recordcontainers/db/onDBUpdate.js +++ b/entity/Offeritem_entity/recordcontainers/db/onDBUpdate.js @@ -51,10 +51,10 @@ if(oid != "") var potentialAsignees = {}; var offerItemsToUpdate = {}; var stop = false; - while(stop == false) + while(stop == false)//we have too loop forall the rows for each row that needs updating, since those are also pontially asignees { stop = true; - for(var offeritem in rows) + for(var offeritem in rows)//loop trough all the rows and build offerItemsToUpdate { if(!(rows[offeritem]["OFFERITEMID"] in offerItemsToUpdate) &&(rows[offeritem]["ASSIGNEDTO"] == offerItemId || rows[offeritem]["ASSIGNEDTO"] in potentialAsignees)) { diff --git a/entity/Order_entity/Order_entity.aod b/entity/Order_entity/Order_entity.aod index ea20792d664c1f6d3213eaeb1ef3dc411bfc94c2..090bc46b1ac2b2383882f5ccdd94f06126ba58f1 100644 --- a/entity/Order_entity/Order_entity.aod +++ b/entity/Order_entity/Order_entity.aod @@ -4,6 +4,7 @@ <title>Receipt</title> <majorModelMode>DISTRIBUTED</majorModelMode> <documentation>%aditoprj%/entity/Order_entity/documentation.adoc</documentation> + <grantUpdateProcess>%aditoprj%/entity/Order_entity/grantUpdateProcess.js</grantUpdateProcess> <grantDeleteProcess>%aditoprj%/entity/Order_entity/grantDeleteProcess.js</grantDeleteProcess> <contentTitleProcess>%aditoprj%/entity/Order_entity/contentTitleProcess.js</contentTitleProcess> <contentDescriptionProcess>%aditoprj%/entity/Order_entity/contentDescriptionProcess.js</contentDescriptionProcess> diff --git a/entity/Order_entity/entityfields/salesordercode/onValidation.js b/entity/Order_entity/entityfields/salesordercode/onValidation.js index f3e48817277e5545f8b9b6296bd84039c58682bf..7dea3bc9db7862239f4114433c8d7e78ab4e5cd0 100644 --- a/entity/Order_entity/entityfields/salesordercode/onValidation.js +++ b/entity/Order_entity/entityfields/salesordercode/onValidation.js @@ -1,5 +1,9 @@ +import("system.vars"); import("system.neon"); //reload the field on save to make sure the salesordercode is really unique, otherwise the salesordercode could be the same for two salesorders //created at the same time -neon.refresh(["$field.SALESORDERCODE"]); \ No newline at end of file +if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW) +{ + neon.refresh(["$field.SALESORDERCODE"]); +} \ No newline at end of file diff --git a/entity/Order_entity/grantUpdateProcess.js b/entity/Order_entity/grantUpdateProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..1559507308ff05db1a670d59cd825ca8d9d24160 --- /dev/null +++ b/entity/Order_entity/grantUpdateProcess.js @@ -0,0 +1,6 @@ +import("system.tools"); +import("system.result"); +import("system.vars"); + +var editable = !parseInt(vars.get("$field.ORDERSTATUS")); +result.string(editable || tools.hasRole(vars.get("$sys.user"), "INTERNAL_ADMINISTRATOR")); diff --git a/entity/Orderitem_entity/Orderitem_entity.aod b/entity/Orderitem_entity/Orderitem_entity.aod index 7abed959968cbf47b141f802a6c7c240a6f5201d..68999920abfefb7875463dc38a5b1bca18e994dd 100644 --- a/entity/Orderitem_entity/Orderitem_entity.aod +++ b/entity/Orderitem_entity/Orderitem_entity.aod @@ -60,6 +60,7 @@ <contentType>NUMBER</contentType> <outputFormat>#,##0.00</outputFormat> <inputFormat>#,##0.00</inputFormat> + <mandatory v="true" /> <displayValueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/price/displayValueProcess.js</displayValueProcess> </entityField> <entityField> @@ -272,6 +273,15 @@ </entityActionField> </children> </entityActionGroup> + <entityParameter> + <name>IgnoreOnUpdateProcess_param</name> + <expose v="true" /> + <documentation>%aditoprj%/entity/Orderitem_entity/entityfields/ignoreonupdateprocess_param/documentation.adoc</documentation> + </entityParameter> + <entityField> + <name>itemInsertStatements</name> + <documentation>%aditoprj%/entity/Orderitem_entity/entityfields/iteminsertstatements/documentation.adoc</documentation> + </entityField> </entityFields> <recordContainers> <dbRecordContainer> diff --git a/entity/Orderitem_entity/entityfields/ignoreonupdateprocess_param/documentation.adoc b/entity/Orderitem_entity/entityfields/ignoreonupdateprocess_param/documentation.adoc new file mode 100644 index 0000000000000000000000000000000000000000..3b7c3bfb85ecfca60367469d04eb39274a4de3e2 --- /dev/null +++ b/entity/Orderitem_entity/entityfields/ignoreonupdateprocess_param/documentation.adoc @@ -0,0 +1,3 @@ +=IgnoreOnUpdateProcess_param + +This param only exists because we use writeEntiy in the onUpdateProcess and don't want to execute parts of it again for the updates we trigger for the children. \ No newline at end of file diff --git a/entity/Orderitem_entity/entityfields/iteminsertstatements/documentation.adoc b/entity/Orderitem_entity/entityfields/iteminsertstatements/documentation.adoc new file mode 100644 index 0000000000000000000000000000000000000000..483999ea30ce8b8d311f57b6a69113bfa9d9f1e6 --- /dev/null +++ b/entity/Orderitem_entity/entityfields/iteminsertstatements/documentation.adoc @@ -0,0 +1,5 @@ += itemInsertStatements + +Helper field to store the statements for the childitems (statements get built with the correct amounts when changing the product or the quantity). +Statements get stored as stringified object. +And parsed and inserted in the onInsertProcess \ No newline at end of file diff --git a/entity/Orderitem_entity/entityfields/product_id/onValueChange.js b/entity/Orderitem_entity/entityfields/product_id/onValueChange.js index 1996256d8084708c434b34ce31be70a28bb63879..07ed27e6e201cab5dee47355979c9e9f9037c9ac 100644 --- a/entity/Orderitem_entity/entityfields/product_id/onValueChange.js +++ b/entity/Orderitem_entity/entityfields/product_id/onValueChange.js @@ -1,8 +1,34 @@ +import("system.neon"); import("system.vars"); import("OfferOrder_lib"); +import("Order_lib"); var pId = vars.get("$local.value"); -if(pId != "") + +if(pId != "" && vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW) { - ItemUtils.product_IdOnValueChange(pId); -} \ No newline at end of file + var uid = vars.get("$field.SALESORDERITEMID"); + var entity = vars.get("$sys.currententityname"); + + ItemUtils.product_IdOnValueChange(pId, uid, entity); + var oiUtils = new OrderItemUtils(vars.get("$field.SALESORDER_ID")); + var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : ""; + var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : ""; + var quantity = vars.get("$field.QUANTITY"); + + var sumUpTop = false; + var price = vars.get("$field.PRICE"); + if(!price) + { + sumUpTop = true; + } + + var partsListObject = oiUtils.insertPartsList(pId, vars.get("$field.SALESORDERITEMID"), curr, contactid, quantity, true, vars.get("$field.SALESORDER_ID"), sumUpTop); + neon.setFieldValue("$field.itemInsertStatements", JSON.stringify(partsListObject["partsList"])); + if(sumUpTop)//only sum-up this price if there is no valid Price + { + neon.setFieldValue("$field.PRICE", partsListObject["topProductInfo"]["price"]*quantity); + neon.setFieldValue("$field.VAT", partsListObject["topProductInfo"]["vat"]); + } +} + diff --git a/entity/Orderitem_entity/entityfields/quantity/onValueChange.js b/entity/Orderitem_entity/entityfields/quantity/onValueChange.js index 5fbe3952a65b6081c9a845b0ec03e4092303c315..5946e7dffec4186398e7664403a3f9be56bd654b 100644 --- a/entity/Orderitem_entity/entityfields/quantity/onValueChange.js +++ b/entity/Orderitem_entity/entityfields/quantity/onValueChange.js @@ -1,23 +1,33 @@ import("system.vars"); import("system.neon"); -import("Product_lib"); -import("Util_lib"); -import("Entity_lib"); +import("OfferOrder_lib"); +import("Order_lib"); -var pid = vars.get("$field.PRODUCT_ID"); -var newQuantity = vars.get("local.value"); -if(pid != "" && newQuantity != "") +var pId = vars.get("$field.PRODUCT_ID"); +if(pId != "" && vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW) { + var uid = vars.get("$field.SALESORDERITEMID"); + var entity = vars.get("$sys.currententityname"); + ItemUtils.product_IdOnValueChange(pId, uid, entity); + + var oiUtils = new OrderItemUtils(vars.get("$field.SALESORDER_ID")); var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : ""; var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : ""; + var quantity = vars.get("$local.value"); + + var sumUpTop = false; + var price = vars.get("$field.PRICE"); + if(!price) + { + sumUpTop = true; + } - var PriceListFilter = { currency: curr, quantity: newQuantity, relationId: contactid }; - - var ProductDetails = ProductUtils.getProductDetails(pid, PriceListFilter); + var partsListObject = oiUtils.insertPartsList(pId, vars.get("$field.SALESORDERITEMID"), curr, contactid, quantity, true, vars.get("$field.SALESORDER_ID"), sumUpTop); + neon.setFieldValue("$field.itemInsertStatements", JSON.stringify(partsListObject["partsList"])); - if(ProductDetails.productId != undefined && ProductDetails.PriceListToUse != null) + if(sumUpTop)//only sum-up this price if there is no valid Price { - vars.set("$field.PRICE", ProductDetails.PriceListToUse.price); - vars.set("$field.VAT", ProductDetails.PriceListToUse.vat); + neon.setFieldValue("$field.PRICE", partsListObject["topProductInfo"]["price"]); + neon.setFieldValue("$field.VAT", partsListObject["topProductInfo"]["vat"]); } } \ No newline at end of file diff --git a/entity/Orderitem_entity/recordcontainers/db/onDBInsert.js b/entity/Orderitem_entity/recordcontainers/db/onDBInsert.js index 23d5cc030038257a4b6ef7d593867dd0a5a851fd..2c949920f21cecceaf3869b6f81ac6549d18623e 100644 --- a/entity/Orderitem_entity/recordcontainers/db/onDBInsert.js +++ b/entity/Orderitem_entity/recordcontainers/db/onDBInsert.js @@ -1,25 +1,26 @@ +import("system.db"); +import("OfferOrder_lib"); import("system.entities"); -import("system.datetime"); -import("system.neon"); import("system.vars"); -import("system.db"); import("system.util"); import("Order_lib"); import("Product_lib"); import("Sql_lib"); - var rowdata = vars.get("$local.rowdata"); var oid = rowdata["SALESORDERITEM.SALESORDER_ID"]; if(oid != "") { - var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : ""; - var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : ""; var discount = vars.exists("$param.Discount_param") ? vars.get("$param.Discount_param"): ""; var oiUtils = new OrderItemUtils(oid); - oiUtils.insertPartsList(rowdata["SALESORDERITEM.PRODUCT_ID"], vars.get("$local.uid"), curr, contactid, vars.get("$param.Language_param")); - oiUtils.reOrgItems(); + + var insertStatements = JSON.parse(vars.get("$field.itemInsertStatements"));//insert statements get set by insertPartsList in the onvalueChanges of product_id and quantity + + if(insertStatements) + { + db.inserts(insertStatements); + } //update order price var vals = oiUtils.getNetAndVat(); @@ -42,7 +43,6 @@ if(oid != "") "NET": vals[0], "VAT": vals[1] }); - } config.uid(oid); entities.updateRow(config); diff --git a/entity/Orderitem_entity/recordcontainers/db/onDBUpdate.js b/entity/Orderitem_entity/recordcontainers/db/onDBUpdate.js index a763dd4a6bcb8cc0232ef42817f0d777f5cab1ec..55517585ef0974dec7e7964e713775ebf6a944c6 100644 --- a/entity/Orderitem_entity/recordcontainers/db/onDBUpdate.js +++ b/entity/Orderitem_entity/recordcontainers/db/onDBUpdate.js @@ -33,4 +33,44 @@ if(oid != "") } config.uid(oid); entities.updateRow(config); + + + //this process get's executed for every child of this offerItem since we use writeEntiy, so we use the param to make sure we don't execute it for the children + if(vars.getString("$param.IgnoreOnUpdateProcess_param") != "true") + { + var newQuanitity = parseFloat(vars.get("$field.QUANTITY")); + var oldQuantity = parseFloat(vars.get("$local.initialRowdata")["SALESORDERITEM.QUANTITY"]); + var offerItemId = vars.get("$field.SALESORDERITEMID"); + if(newQuanitity != oldQuantity) //quantity changed -> change quantities of the childitems accordingly + { + var multiplier = newQuanitity/oldQuantity; + + var loadConfig = entities.createConfigForLoadingRows().entity("Orderitem_entity").addParameter("OrderId_param", oid).fields(["SALESORDERITEMID", "ASSIGNEDTO", "PRODUCT_ID", "QUANTITY"]) + + var rows = entities.getRows(loadConfig); + + var potentialAsignees = {}; + var offerItemsToUpdate = {}; + var stop = false; + while(stop == false)//we have too loop forall the rows for each row that needs updating, since those are also pontially asignees + { + stop = true; + for(var offeritem in rows)//loop trough all the rows and build offerItemsToUpdate + { + if(!(rows[offeritem]["SALESORDERITEMID"] in offerItemsToUpdate) &&(rows[offeritem]["ASSIGNEDTO"] == offerItemId || rows[offeritem]["ASSIGNEDTO"] in potentialAsignees)) + { + offerItemsToUpdate[rows[offeritem]["SALESORDERITEMID"]] = parseInt(rows[offeritem]["QUANTITY"])*multiplier; + potentialAsignees[rows[offeritem]["SALESORDERITEMID"]] = ""; + stop = false; + } + } + } + + var updateConfig = entities.createConfigForUpdatingRows().entity("Orderitem_entity").addParameter("OrderId_param", oid).addParameter("IgnoreOnUpdateProcess_param", true); + for(var object_Id in offerItemsToUpdate) + { + entities.updateRow(updateConfig.fieldValues({"QUANTITY": offerItemsToUpdate[object_Id]}).uid(object_Id)) + } + } + } } \ No newline at end of file diff --git a/entity/Organisation_entity/Organisation_entity.aod b/entity/Organisation_entity/Organisation_entity.aod index a1c9dc5748145d7807a8927740c9383fa46d735c..be40c333adc19fbc28ccd8715d0596b2f151a47f 100644 --- a/entity/Organisation_entity/Organisation_entity.aod +++ b/entity/Organisation_entity/Organisation_entity.aod @@ -186,6 +186,24 @@ <fieldName>OrganisationConsumer</fieldName> <isConsumer v="false" /> </entityDependency> + <entityDependency> + <name>640a8509-1972-4dc5-980e-68832f1c03c5</name> + <entityName>Planning_entity</entityName> + <fieldName>Organisations</fieldName> + <isConsumer v="false" /> + </entityDependency> + <entityDependency> + <name>3ceb7668-285a-4169-b71a-b64edc206b34</name> + <entityName>OrganisationsMultiEdit_entity</entityName> + <fieldName>Organisations</fieldName> + <isConsumer v="false" /> + </entityDependency> + <entityDependency> + <name>75b4de32-4fd6-4223-80f5-908aeb533577</name> + <entityName>Turnover_entity</entityName> + <fieldName>Organisations</fieldName> + <isConsumer v="false" /> + </entityDependency> </dependencies> <children> <entityParameter> @@ -1418,6 +1436,7 @@ <title>New appointment</title> <onActionProcess>%aditoprj%/entity/Organisation_entity/entityfields/newappointment/onActionProcess.js</onActionProcess> <iconId>VAADIN:CALENDAR</iconId> + <state>EDITABLE</state> <stateProcess>%aditoprj%/entity/Organisation_entity/entityfields/newappointment/stateProcess.js</stateProcess> <tooltip>New Appointment</tooltip> </entityActionField> @@ -1475,6 +1494,14 @@ <isObjectAction v="false" /> <iconId>VAADIN:ENVELOPES</iconId> </entityActionField> + <entityActionField> + <name>addPlanningToOrganisations</name> + <title>Create planning</title> + <onActionProcess>%aditoprj%/entity/Organisation_entity/entityfields/filterviewactiongroup/children/addplanningtoorganisations/onActionProcess.js</onActionProcess> + <isObjectAction v="false" /> + <isSelectionAction v="false" /> + <iconId>VAADIN:MONEY</iconId> + </entityActionField> </children> </entityActionGroup> <entityActionField> @@ -1602,6 +1629,42 @@ <iconId>VAADIN:CURLY_BRACKETS</iconId> <stateProcess>%aditoprj%/entity/Organisation_entity/entityfields/openadminview/stateProcess.js</stateProcess> </entityActionField> + <entityConsumer> + <name>Plannings</name> + <dependency> + <name>dependency</name> + <entityName>Planning_entity</entityName> + <fieldName>Plannings</fieldName> + </dependency> + <children> + <entityParameter> + <name>ContactId_param</name> + <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/plannings/children/contactid_param/valueProcess.js</valueProcess> + </entityParameter> + </children> + </entityConsumer> + <entityConsumer> + <name>Turnovers</name> + <dependency> + <name>dependency</name> + <entityName>Turnover_entity</entityName> + <fieldName>DynamicTurnover</fieldName> + </dependency> + <children> + <entityParameter> + <name>ContactId_param</name> + <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/turnovers/children/contactid_param/valueProcess.js</valueProcess> + </entityParameter> + </children> + </entityConsumer> + <entityConsumer> + <name>conversionrates</name> + <dependency> + <name>dependency</name> + <entityName>SalesprojectConversionRate_entity</entityName> + <fieldName>#PROVIDER</fieldName> + </dependency> + </entityConsumer> </entityFields> <recordContainers> <dbRecordContainer> diff --git a/entity/Organisation_entity/entityfields/360degreeobjects/children/objectrowid_param/valueProcess.js b/entity/Organisation_entity/entityfields/360degreeobjects/children/objectrowid_param/valueProcess.js index 3080fcea47e69e82074e9a6a5d3b9951364aa7fe..aee05ab473a438d99830659e02d26be864a17c3f 100644 --- a/entity/Organisation_entity/entityfields/360degreeobjects/children/objectrowid_param/valueProcess.js +++ b/entity/Organisation_entity/entityfields/360degreeobjects/children/objectrowid_param/valueProcess.js @@ -5,6 +5,6 @@ import("system.result"); var contactids = newSelect( "CONTACTID" ) .from("CONTACT") .where("CONTACT.ORGANISATION_ID", vars.getString("$field.ORGANISATIONID")) - .arrayColumn(); + .orderBy("CONTACT.PERSON_ID DESC").arrayColumn(); result.string( JSON.stringify(contactids) ); \ No newline at end of file diff --git a/entity/Organisation_entity/entityfields/filterviewactiongroup/children/addplanningtoorganisations/onActionProcess.js b/entity/Organisation_entity/entityfields/filterviewactiongroup/children/addplanningtoorganisations/onActionProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..4015c373ea1b0e8eaec6b01b545bcfa496111c96 --- /dev/null +++ b/entity/Organisation_entity/entityfields/filterviewactiongroup/children/addplanningtoorganisations/onActionProcess.js @@ -0,0 +1,17 @@ +import("system.vars"); +import("system.neon"); + +var params = {}; +var selection = vars.get("$sys.selection"); + +if(selection.length > 0) +{ + params["SelectedOrganisations_param"] = JSON.stringify(vars.get("$sys.selection")); +} +else +{ + params["OrganisationsWithFilter_param"] = JSON.stringify(vars.get("$sys.filter")); +} + + +neon.openContext("PlanningAddToOrganisations", "PlanningAddToOrganisations_view", null, neon.OPERATINGSTATE_NEW, params); diff --git a/entity/Organisation_entity/entityfields/plannings/children/contactid_param/valueProcess.js b/entity/Organisation_entity/entityfields/plannings/children/contactid_param/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..7b6137b4d105e9ba592cf8ef6e796fb838a32b09 --- /dev/null +++ b/entity/Organisation_entity/entityfields/plannings/children/contactid_param/valueProcess.js @@ -0,0 +1,4 @@ +import("system.vars"); +import("system.result"); + +result.string(vars.get("$field.CONTACTID")); \ No newline at end of file diff --git a/entity/Organisation_entity/entityfields/turnovers/children/contactid_param/valueProcess.js b/entity/Organisation_entity/entityfields/turnovers/children/contactid_param/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..7b6137b4d105e9ba592cf8ef6e796fb838a32b09 --- /dev/null +++ b/entity/Organisation_entity/entityfields/turnovers/children/contactid_param/valueProcess.js @@ -0,0 +1,4 @@ +import("system.vars"); +import("system.result"); + +result.string(vars.get("$field.CONTACTID")); \ No newline at end of file diff --git a/entity/OrganisationsMultiEdit_entity/OrganisationsMultiEdit_entity.aod b/entity/OrganisationsMultiEdit_entity/OrganisationsMultiEdit_entity.aod new file mode 100644 index 0000000000000000000000000000000000000000..e423affb316335725d90383e14ea11ee28bc6c9f --- /dev/null +++ b/entity/OrganisationsMultiEdit_entity/OrganisationsMultiEdit_entity.aod @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.18" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.18"> + <name>OrganisationsMultiEdit_entity</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <documentation>%aditoprj%/entity/OrganisationsMultiEdit_entity/documentation.adoc</documentation> + <recordContainer>jdito</recordContainer> + <entityFields> + <entityProvider> + <name>#PROVIDER</name> + <dependencies> + <entityDependency> + <name>ce007a14-f543-4959-81d6-145590e12a72</name> + <entityName>PlanningAddToOrganisations_entity</entityName> + <fieldName>Organisations</fieldName> + <isConsumer v="false" /> + </entityDependency> + </dependencies> + </entityProvider> + <entityProvider> + <name>#PROVIDER_AGGREGATES</name> + <useAggregates v="true" /> + </entityProvider> + <entityField> + <name>CONTACT_ID</name> + <title>Organisation</title> + <consumer>Organisations</consumer> + <displayValueProcess>%aditoprj%/entity/OrganisationsMultiEdit_entity/entityfields/contact_id/displayValueProcess.js</displayValueProcess> + </entityField> + <entityConsumer> + <name>Organisations</name> + <dependency> + <name>dependency</name> + <entityName>Organisation_entity</entityName> + <fieldName>Organisations</fieldName> + </dependency> + </entityConsumer> + <entityField> + <name>UID</name> + <state>INVISIBLE</state> + </entityField> + </entityFields> + <recordContainers> + <jDitoRecordContainer> + <name>jdito</name> + <jDitoRecordAlias>Data_alias</jDitoRecordAlias> + <contentProcess>%aditoprj%/entity/OrganisationsMultiEdit_entity/recordcontainers/jdito/contentProcess.js</contentProcess> + <onInsert>%aditoprj%/entity/OrganisationsMultiEdit_entity/recordcontainers/jdito/onInsert.js</onInsert> + <recordFieldMappings> + <jDitoRecordFieldMapping> + <name>UID.value</name> + </jDitoRecordFieldMapping> + </recordFieldMappings> + </jDitoRecordContainer> + </recordContainers> +</entity> diff --git a/entity/OrganisationsMultiEdit_entity/documentation.adoc b/entity/OrganisationsMultiEdit_entity/documentation.adoc new file mode 100644 index 0000000000000000000000000000000000000000..dce629f858c22192f8745e1251d4872dbf655917 --- /dev/null +++ b/entity/OrganisationsMultiEdit_entity/documentation.adoc @@ -0,0 +1,4 @@ += OrganisationsMultiEdit_entity + +This entity is used to have a GenericMultiple selection of organisations. +For example, it is used in the series action "Create planning" in the organisation. \ No newline at end of file diff --git a/entity/OrganisationsMultiEdit_entity/entityfields/contact_id/displayValueProcess.js b/entity/OrganisationsMultiEdit_entity/entityfields/contact_id/displayValueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..9d7be1063f1aba777a205ded715b26133f8144a0 --- /dev/null +++ b/entity/OrganisationsMultiEdit_entity/entityfields/contact_id/displayValueProcess.js @@ -0,0 +1,6 @@ +import("Contact_lib"); +import("system.result"); +import("system.neon"); +import("system.vars"); + +result.string(OrganisationUtils.getNameByContactId(vars.get("$field.CONTACT_ID"))); \ No newline at end of file diff --git a/entity/OrganisationsMultiEdit_entity/recordcontainers/jdito/contentProcess.js b/entity/OrganisationsMultiEdit_entity/recordcontainers/jdito/contentProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..8a8b23ca6e41d5f262b6e6e9d5d47ddb8f0d2c56 --- /dev/null +++ b/entity/OrganisationsMultiEdit_entity/recordcontainers/jdito/contentProcess.js @@ -0,0 +1,7 @@ +import("system.result"); +import("system.vars"); + +if(vars.get("$local.idvalues")) +{ + result.object([vars.get("$local.idvalues")]); +} \ No newline at end of file diff --git a/entity/OrganisationsMultiEdit_entity/recordcontainers/jdito/onInsert.js b/entity/OrganisationsMultiEdit_entity/recordcontainers/jdito/onInsert.js new file mode 100644 index 0000000000000000000000000000000000000000..1b78561c5f27d03689ff51f7b20711a814ae99e1 --- /dev/null +++ b/entity/OrganisationsMultiEdit_entity/recordcontainers/jdito/onInsert.js @@ -0,0 +1 @@ +""; // this line must not be deleted, because there must always be something in that process \ No newline at end of file diff --git a/entity/Person_entity/Person_entity.aod b/entity/Person_entity/Person_entity.aod index f294673d397ad7e5b12ab7f16821daa5d3c0d75b..d318ebbdde32ccfe73c757d1e904246333556526 100644 --- a/entity/Person_entity/Person_entity.aod +++ b/entity/Person_entity/Person_entity.aod @@ -1453,6 +1453,7 @@ <title>New appointment</title> <onActionProcess>%aditoprj%/entity/Person_entity/entityfields/newappointment/onActionProcess.js</onActionProcess> <iconId>VAADIN:CALENDAR</iconId> + <state>EDITABLE</state> <stateProcess>%aditoprj%/entity/Person_entity/entityfields/newappointment/stateProcess.js</stateProcess> <tooltip>New Appointment</tooltip> </entityActionField> diff --git a/entity/PlanningAddToOrganisations_entity/PlanningAddToOrganisations_entity.aod b/entity/PlanningAddToOrganisations_entity/PlanningAddToOrganisations_entity.aod new file mode 100644 index 0000000000000000000000000000000000000000..c6e7d28790268007293d698ed1ed73275e0d1341 --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/PlanningAddToOrganisations_entity.aod @@ -0,0 +1,158 @@ +<?xml version="1.0" encoding="UTF-8"?> +<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.18" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.18"> + <name>PlanningAddToOrganisations_entity</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <documentation>%aditoprj%/entity/PlanningAddToOrganisations_entity/documentation.adoc</documentation> + <afterUiInit>%aditoprj%/entity/PlanningAddToOrganisations_entity/afterUiInit.js</afterUiInit> + <afterSave>%aditoprj%/entity/PlanningAddToOrganisations_entity/afterSave.js</afterSave> + <recordContainer>jdito</recordContainer> + <entityFields> + <entityProvider> + <name>#PROVIDER</name> + </entityProvider> + <entityProvider> + <name>#PROVIDER_AGGREGATES</name> + <useAggregates v="true" /> + </entityProvider> + <entityField> + <name>YEAR</name> + <title>Year</title> + <contentType>DATE</contentType> + <resolution>YEAR</resolution> + <state>EDITABLE</state> + <valueProcess>%aditoprj%/entity/PlanningAddToOrganisations_entity/entityfields/year/valueProcess.js</valueProcess> + </entityField> + <entityField> + <name>VOLUME</name> + <state>EDITABLE</state> + <titleProcess>%aditoprj%/entity/PlanningAddToOrganisations_entity/entityfields/volume/titleProcess.js</titleProcess> + </entityField> + <entityConsumer> + <name>Organisations</name> + <dependency> + <name>dependency</name> + <entityName>OrganisationsMultiEdit_entity</entityName> + <fieldName>#PROVIDER</fieldName> + </dependency> + </entityConsumer> + <entityField> + <name>UID</name> + </entityField> + <entityParameter> + <name>SelectedOrganisations_param</name> + <expose v="true" /> + </entityParameter> + <entityField> + <name>STATUS</name> + <title>Status</title> + <consumer>KeywordStatus</consumer> + <state>READONLY</state> + <valueProcess>%aditoprj%/entity/PlanningAddToOrganisations_entity/entityfields/status/valueProcess.js</valueProcess> + <displayValueProcess>%aditoprj%/entity/PlanningAddToOrganisations_entity/entityfields/status/displayValueProcess.js</displayValueProcess> + </entityField> + <entityField> + <name>RESPONSIBLE_CONTACT_ID</name> + <title>Responsible</title> + <consumer>Responsible</consumer> + <state>EDITABLE</state> + <valueProcess>%aditoprj%/entity/PlanningAddToOrganisations_entity/entityfields/responsible_contact_id/valueProcess.js</valueProcess> + <displayValueProcess>%aditoprj%/entity/PlanningAddToOrganisations_entity/entityfields/responsible_contact_id/displayValueProcess.js</displayValueProcess> + </entityField> + <entityField> + <name>GROUPCODE</name> + <title>Product group</title> + <consumer>KeywordGroupcode</consumer> + <state>EDITABLE</state> + <displayValueProcess>%aditoprj%/entity/PlanningAddToOrganisations_entity/entityfields/groupcode/displayValueProcess.js</displayValueProcess> + </entityField> + <entityConsumer> + <name>KeywordGroupcode</name> + <dependency> + <name>dependency</name> + <entityName>KeywordEntry_entity</entityName> + <fieldName>SpecificContainerKeywords</fieldName> + </dependency> + <children> + <entityParameter> + <name>ContainerName_param</name> + <valueProcess>%aditoprj%/entity/PlanningAddToOrganisations_entity/entityfields/keywordgroupcode/children/containername_param/valueProcess.js</valueProcess> + </entityParameter> + </children> + </entityConsumer> + <entityConsumer> + <name>KeywordStatus</name> + <dependency> + <name>dependency</name> + <entityName>KeywordEntry_entity</entityName> + <fieldName>SpecificContainerKeywords</fieldName> + </dependency> + <children> + <entityParameter> + <name>ContainerName_param</name> + <valueProcess>%aditoprj%/entity/PlanningAddToOrganisations_entity/entityfields/keywordstatus/children/containername_param/valueProcess.js</valueProcess> + </entityParameter> + </children> + </entityConsumer> + <entityConsumer> + <name>Responsible</name> + <dependency> + <name>dependency</name> + <entityName>Employee_entity</entityName> + <fieldName>Employees</fieldName> + </dependency> + </entityConsumer> + <entityConsumer> + <name>PlanningsAlreadyExists</name> + <dependency> + <name>dependency</name> + <entityName>Planning_entity</entityName> + <fieldName>Plannings</fieldName> + </dependency> + <children> + <entityParameter> + <name>PlanningIds_param</name> + <valueProcess>%aditoprj%/entity/PlanningAddToOrganisations_entity/entityfields/planningsalreadyexists/children/planningids_param/valueProcess.js</valueProcess> + </entityParameter> + </children> + </entityConsumer> + <entityConsumer> + <name>PlanningsNew</name> + <dependency> + <name>dependency</name> + <entityName>Planning_entity</entityName> + <fieldName>Plannings</fieldName> + </dependency> + <children> + <entityParameter> + <name>PlanningIds_param</name> + <valueProcess>%aditoprj%/entity/PlanningAddToOrganisations_entity/entityfields/planningsnew/children/planningids_param/valueProcess.js</valueProcess> + </entityParameter> + </children> + </entityConsumer> + <entityParameter> + <name>PlanningIdsNew_param</name> + <expose v="true" /> + </entityParameter> + <entityParameter> + <name>PlanningIdsAlreadyExists_param</name> + <expose v="true" /> + </entityParameter> + <entityParameter> + <name>OrganisationsWithFilter_param</name> + <expose v="true" /> + </entityParameter> + </entityFields> + <recordContainers> + <jDitoRecordContainer> + <name>jdito</name> + <jDitoRecordAlias>Data_alias</jDitoRecordAlias> + <contentProcess>%aditoprj%/entity/PlanningAddToOrganisations_entity/recordcontainers/jdito/contentProcess.js</contentProcess> + <onInsert>%aditoprj%/entity/PlanningAddToOrganisations_entity/recordcontainers/jdito/onInsert.js</onInsert> + <recordFieldMappings> + <jDitoRecordFieldMapping> + <name>UID.value</name> + </jDitoRecordFieldMapping> + </recordFieldMappings> + </jDitoRecordContainer> + </recordContainers> +</entity> diff --git a/entity/PlanningAddToOrganisations_entity/afterSave.js b/entity/PlanningAddToOrganisations_entity/afterSave.js new file mode 100644 index 0000000000000000000000000000000000000000..559470208ca89a3a5a43ca4f2f8c6f06d2fd591b --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/afterSave.js @@ -0,0 +1,14 @@ +import("system.neon"); +import("system.vars"); + + +var instertedPlannings = vars.get("$context.InsertedPlannings"); +var existingPlannings = vars.get("$context.ExistingPlannings"); +var uid = vars.get("$local.entitydata")["UID"]; + +var params = { + "PlanningIdsNew_param": instertedPlannings, + "PlanningIdsAlreadyExists_param": existingPlannings +}; + +neon.openContext("PlanningAddToOrganisations", "PlanningAddToOrganisationOverlay_view", [uid], neon.OPERATINGSTATE_VIEW, params); \ No newline at end of file diff --git a/entity/PlanningAddToOrganisations_entity/afterUiInit.js b/entity/PlanningAddToOrganisations_entity/afterUiInit.js new file mode 100644 index 0000000000000000000000000000000000000000..9d32ea72e6e8350f799fb65c3df5392278e7c690 --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/afterUiInit.js @@ -0,0 +1,39 @@ +import("Sql_lib"); +import("system.util"); +import("system.vars"); +import("system.neon"); + +var selectedOrganisations = JSON.parse(vars.get("$param.SelectedOrganisations_param")); +var organisationsWithFilter = JSON.parse(vars.get("$param.OrganisationsWithFilter_param")); + +// If nothing is selected in the organisation, a filter is provided to limit the companies in the query. +if(organisationsWithFilter) +{ + selectedOrganisations = newSelect("CONTACT.CONTACTID") + .from("ORGANISATION") + .join("CONTACT", "ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID and CONTACT.PERSON_ID is null") + .leftJoin("ADDRESS", "ADDRESS.ADDRESSID = CONTACT.ADDRESS_ID") + .leftJoin("CLASSIFICATIONSTORAGE", "CLASSIFICATIONSTORAGE.OBJECT_ROWID = CONTACT.CONTACTID") + .where(organisationsWithFilter.condition) + .arrayColumn(); +} + +if(selectedOrganisations) +{ + var emptyRows = vars.get("$field.Organisations.insertedRows"); + + // the empty rows of the consumer are deleted + emptyRows.forEach(function(oneRow) + { + neon.deleteRecord("Organisations", oneRow["#UID"]); + }); + + // the sselected organisations are added to the consumer + selectedOrganisations.forEach(function(contactId) + { + neon.addRecord("Organisations", + { + "CONTACT_ID": contactId + }); + }); +} diff --git a/entity/PlanningAddToOrganisations_entity/documentation.adoc b/entity/PlanningAddToOrganisations_entity/documentation.adoc new file mode 100644 index 0000000000000000000000000000000000000000..a6304142ab9fdc5aca689268b5c540f8857a2e5b --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/documentation.adoc @@ -0,0 +1,3 @@ += PlanningAddToOrganisations_entity + +Opens in the series action "Create planning" and creates planning for selected companies. \ No newline at end of file diff --git a/entity/PlanningAddToOrganisations_entity/entityfields/groupcode/displayValueProcess.js b/entity/PlanningAddToOrganisations_entity/entityfields/groupcode/displayValueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..b969a4ff0bee37ef3e8d525de185396c440adf25 --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/entityfields/groupcode/displayValueProcess.js @@ -0,0 +1,6 @@ +import("system.result"); +import("system.vars"); +import("Keyword_lib"); +import("KeywordRegistry_basic"); + +result.string(KeywordUtils.getViewValue($KeywordRegistry.productGroupcode(), vars.get("$field.GROUPCODE"))); diff --git a/entity/PlanningAddToOrganisations_entity/entityfields/keywordgroupcode/children/containername_param/valueProcess.js b/entity/PlanningAddToOrganisations_entity/entityfields/keywordgroupcode/children/containername_param/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..e0b3a6dd6b49bace8935531285f8defc51731f36 --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/entityfields/keywordgroupcode/children/containername_param/valueProcess.js @@ -0,0 +1,5 @@ +import("system.result"); +import("Keyword_lib"); +import("KeywordRegistry_basic"); + +result.string($KeywordRegistry.productGroupcode()); diff --git a/entity/PlanningAddToOrganisations_entity/entityfields/keywordstatus/children/containername_param/valueProcess.js b/entity/PlanningAddToOrganisations_entity/entityfields/keywordstatus/children/containername_param/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..87817cdbaef598656d71e960792d8bb868601bf2 --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/entityfields/keywordstatus/children/containername_param/valueProcess.js @@ -0,0 +1,4 @@ +import("KeywordRegistry_basic"); +import("system.result"); + +result.string($KeywordRegistry.forecastStatus()); \ No newline at end of file diff --git a/entity/PlanningAddToOrganisations_entity/entityfields/planningsalreadyexists/children/planningids_param/valueProcess.js b/entity/PlanningAddToOrganisations_entity/entityfields/planningsalreadyexists/children/planningids_param/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..010d78872bbd3010fe571026492f38c96d2e774d --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/entityfields/planningsalreadyexists/children/planningids_param/valueProcess.js @@ -0,0 +1,9 @@ +import("system.vars"); +import("system.result"); + +var planningIds = vars.get("$param.PlanningIdsAlreadyExists_param"); + +if(planningIds) +{ + result.string(planningIds); +} \ No newline at end of file diff --git a/entity/PlanningAddToOrganisations_entity/entityfields/planningsnew/children/planningids_param/valueProcess.js b/entity/PlanningAddToOrganisations_entity/entityfields/planningsnew/children/planningids_param/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..07283d79208802774a6fadea6166f4d1e739af0f --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/entityfields/planningsnew/children/planningids_param/valueProcess.js @@ -0,0 +1,9 @@ +import("system.vars"); +import("system.result"); + +var planningIds = vars.get("$param.PlanningIdsNew_param"); + +if(planningIds) +{ + result.string(planningIds); +} \ No newline at end of file diff --git a/entity/PlanningAddToOrganisations_entity/entityfields/responsible_contact_id/displayValueProcess.js b/entity/PlanningAddToOrganisations_entity/entityfields/responsible_contact_id/displayValueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..688c1f577469ab057712c28e731741c12d9a2da9 --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/entityfields/responsible_contact_id/displayValueProcess.js @@ -0,0 +1,5 @@ +import("system.vars"); +import("Contact_lib"); +import("system.result"); + +result.string(ContactUtils.getFullTitleByContactId(vars.get("$field.RESPONSIBLE_CONTACT_ID"))); \ No newline at end of file diff --git a/entity/PlanningAddToOrganisations_entity/entityfields/responsible_contact_id/valueProcess.js b/entity/PlanningAddToOrganisations_entity/entityfields/responsible_contact_id/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..a4c7e25a113f238ca83a0e6800afe8b8a061a687 --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/entityfields/responsible_contact_id/valueProcess.js @@ -0,0 +1,10 @@ +import("Employee_lib"); +import("KeywordRegistry_basic"); +import("system.neon"); +import("system.vars"); +import("system.result"); + +if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW && !vars.get("$this.value")) +{ + result.string(EmployeeUtils.getCurrentContactId()); +} \ No newline at end of file diff --git a/entity/PlanningAddToOrganisations_entity/entityfields/status/displayValueProcess.js b/entity/PlanningAddToOrganisations_entity/entityfields/status/displayValueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..f25ee6cc31c469da23ef615a51367848b9da3d37 --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/entityfields/status/displayValueProcess.js @@ -0,0 +1,6 @@ +import("system.result"); +import("system.vars"); +import("Keyword_lib"); +import("KeywordRegistry_basic"); + +result.string(KeywordUtils.getViewValue($KeywordRegistry.forecastStatus(), vars.get("$field.STATUS"))); diff --git a/entity/PlanningAddToOrganisations_entity/entityfields/status/valueProcess.js b/entity/PlanningAddToOrganisations_entity/entityfields/status/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..ec3ba22fcd9f2773e90c85317a86808ff542abce --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/entityfields/status/valueProcess.js @@ -0,0 +1,9 @@ +import("KeywordRegistry_basic"); +import("system.neon"); +import("system.vars"); +import("system.result"); + +if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW && !vars.get("$this.value")) +{ + result.string($KeywordRegistry.forecastStatus$inPlanning()); +} \ No newline at end of file diff --git a/entity/PlanningAddToOrganisations_entity/entityfields/volume/titleProcess.js b/entity/PlanningAddToOrganisations_entity/entityfields/volume/titleProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..f7b76c335483a7410366d5c56db6ae8ba7917091 --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/entityfields/volume/titleProcess.js @@ -0,0 +1,4 @@ +import("system.result"); +import("system.translate"); + +result.string(translate.text("${VOLUME_MONEY}") + " (" + translate.text("${EURO_SIGN}") + ")"); \ No newline at end of file diff --git a/entity/PlanningAddToOrganisations_entity/entityfields/year/valueProcess.js b/entity/PlanningAddToOrganisations_entity/entityfields/year/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..71920b6293bd1f359fb80ff155183ddd35447f23 --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/entityfields/year/valueProcess.js @@ -0,0 +1,8 @@ +import("system.result"); +import("system.neon"); +import("system.vars"); + +if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW && vars.get("$this.value") == null) +{ + result.string(vars.get("$sys.date")); +} \ No newline at end of file diff --git a/entity/PlanningAddToOrganisations_entity/recordcontainers/jdito/contentProcess.js b/entity/PlanningAddToOrganisations_entity/recordcontainers/jdito/contentProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..10ff3a0d5e227a014f34f889dc7442c31715d4da --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/recordcontainers/jdito/contentProcess.js @@ -0,0 +1,8 @@ +import("system.result"); +import("system.vars"); + +if(vars.get("$local.idvalues")) +{ + + result.object([vars.get("$local.idvalues")]); +} \ No newline at end of file diff --git a/entity/PlanningAddToOrganisations_entity/recordcontainers/jdito/onInsert.js b/entity/PlanningAddToOrganisations_entity/recordcontainers/jdito/onInsert.js new file mode 100644 index 0000000000000000000000000000000000000000..e28934ac0d7b9c11d3eaec01521ae960814fc5b4 --- /dev/null +++ b/entity/PlanningAddToOrganisations_entity/recordcontainers/jdito/onInsert.js @@ -0,0 +1,75 @@ +import("system.neon"); +import("Sql_lib"); +import("system.datetime"); +import("system.db"); +import("KeywordRegistry_basic"); +import("system.util"); +import("system.vars"); + +var selectedOrganisations = vars.get("$field.Organisations.insertedRows"); +selectedOrganisations = selectedOrganisations.map(function(row){ + return row["CONTACT_ID"]; +}); + +var year = datetime.toDate(vars.get("$field.YEAR"), "yyyy", "UTC"); +var volume = vars.get("$field.VOLUME"); +var responsible = vars.get("$field.RESPONSIBLE_CONTACT_ID"); +var status = vars.get("$field.STATUS"); +var groupcode = vars.get("$field.GROUPCODE"); +var inserts = []; +var cols = ["FORECASTID", "FORECAST_YEAR", "CONTACT_ID", "VOLUME", "KIND", "RESPONSIBLE_CONTACT_ID", "STATUS"]; +var table = "FORECAST"; +var existingPlanningIds = []; + +if(groupcode) +{ + cols.push("GROUPCODE"); +} + +var existingPlannings = newSelect("FORECAST.CONTACT_ID, FORECAST.FORECASTID") +.from("FORECAST") +.where("FORECAST.CONTACT_ID", selectedOrganisations, SqlBuilder.IN()) +.and("FORECAST.FORECAST_YEAR", year); + +if(!groupcode) +{ + existingPlannings.and("FORECAST.GROUPCODE is null"); +} +else +{ + existingPlannings.and("FORECAST.GROUPCODE", groupcode); +} + +existingPlannings = existingPlannings.table(); + +existingPlannings = existingPlannings.map(function([contactId, planningId]) +{ + existingPlanningIds.push(planningId); + return contactId; +}); + +var insertedPlannings = []; +selectedOrganisations.forEach(function(contactId) +{ + if(!existingPlannings.includes(contactId)) + { + var uid = util.getNewUUID(); + insertedPlannings.push(uid); + var vals = [uid, year, contactId, volume, $KeywordRegistry.forecastKind$planning(), responsible, status]; + + if(groupcode) + { + vals.push(groupcode); + } + + inserts.push([table, cols, null, vals]); + } +}); + + + +vars.set("$context.InsertedPlannings", JSON.stringify(insertedPlannings.length == 0? [""]: insertedPlannings)); +vars.set("$context.ExistingPlannings", JSON.stringify(existingPlanningIds.length == 0? [""]: existingPlanningIds)); + + +db.inserts(inserts); diff --git a/entity/PlanningChangeStatusAndResponsible_entity/PlanningChangeStatusAndResponsible_entity.aod b/entity/PlanningChangeStatusAndResponsible_entity/PlanningChangeStatusAndResponsible_entity.aod new file mode 100644 index 0000000000000000000000000000000000000000..9810a9260ea975aaf566713047ef9db3ba016093 --- /dev/null +++ b/entity/PlanningChangeStatusAndResponsible_entity/PlanningChangeStatusAndResponsible_entity.aod @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.18" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.18"> + <name>PlanningChangeStatusAndResponsible_entity</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <documentation>%aditoprj%/entity/PlanningChangeStatusAndResponsible_entity/documentation.adoc</documentation> + <afterSave>%aditoprj%/entity/PlanningChangeStatusAndResponsible_entity/afterSave.js</afterSave> + <recordContainer>jdito</recordContainer> + <entityFields> + <entityProvider> + <name>#PROVIDER</name> + </entityProvider> + <entityProvider> + <name>#PROVIDER_AGGREGATES</name> + <useAggregates v="true" /> + </entityProvider> + <entityField> + <name>STATUS</name> + <title>Status</title> + <consumer>KeywordStatus</consumer> + <state>EDITABLE</state> + </entityField> + <entityField> + <name>RESPONSIBLE</name> + <title>Responsible</title> + <consumer>Responsibles</consumer> + <state>EDITABLE</state> + </entityField> + <entityConsumer> + <name>Responsibles</name> + <dependency> + <name>dependency</name> + <entityName>Employee_entity</entityName> + <fieldName>Employees</fieldName> + </dependency> + </entityConsumer> + <entityConsumer> + <name>KeywordStatus</name> + <dependency> + <name>dependency</name> + <entityName>KeywordEntry_entity</entityName> + <fieldName>SpecificContainerKeywords</fieldName> + </dependency> + <children> + <entityParameter> + <name>ContainerName_param</name> + <valueProcess>%aditoprj%/entity/PlanningChangeStatusAndResponsible_entity/entityfields/keywordstatus/children/containername_param/valueProcess.js</valueProcess> + </entityParameter> + </children> + </entityConsumer> + <entityParameter> + <name>PlanningIds_param</name> + <expose v="true" /> + </entityParameter> + <entityParameter> + <name>OrganisationContactId_param</name> + <expose v="true" /> + </entityParameter> + <entityField> + <name>UID</name> + </entityField> + </entityFields> + <recordContainers> + <jDitoRecordContainer> + <name>jdito</name> + <jDitoRecordAlias>Data_alias</jDitoRecordAlias> + <contentProcess>%aditoprj%/entity/PlanningChangeStatusAndResponsible_entity/recordcontainers/jdito/contentProcess.js</contentProcess> + <onInsert>%aditoprj%/entity/PlanningChangeStatusAndResponsible_entity/recordcontainers/jdito/onInsert.js</onInsert> + <recordFieldMappings> + <jDitoRecordFieldMapping> + <name>UID.value</name> + </jDitoRecordFieldMapping> + </recordFieldMappings> + </jDitoRecordContainer> + </recordContainers> +</entity> diff --git a/entity/PlanningChangeStatusAndResponsible_entity/afterSave.js b/entity/PlanningChangeStatusAndResponsible_entity/afterSave.js new file mode 100644 index 0000000000000000000000000000000000000000..87b9d67c893c48c3194bc93885b0d2f983204995 --- /dev/null +++ b/entity/PlanningChangeStatusAndResponsible_entity/afterSave.js @@ -0,0 +1,13 @@ +import("system.neon"); +import("system.vars"); + +var orgContactId = vars.get("$param.OrganisationContactId_param"); + +if(orgContactId) +{ + neon.openContext("Organisation", "OrganisationMain_view", [orgContactId], neon.OPERATINGSTATE_VIEW, null, "4c03be39-db8d-4cef-b75c-3325f70101c2"); +} +else +{ + neon.openContext("Planning", "PlanningFilter_view", null, neon.OPERATINGSTATE_SEARCH, null, null); +} diff --git a/entity/PlanningChangeStatusAndResponsible_entity/documentation.adoc b/entity/PlanningChangeStatusAndResponsible_entity/documentation.adoc new file mode 100644 index 0000000000000000000000000000000000000000..7fff46ead5c0c962c1dfb2d6c233674360482ff4 --- /dev/null +++ b/entity/PlanningChangeStatusAndResponsible_entity/documentation.adoc @@ -0,0 +1,7 @@ += PlanningChangeStatusAndResponsible_entity + +This entity is used for the series actions "Change status" and "Change responsible" in the Planning_entity. +When the "Change Status" action is called, the PlanningChangeStatus_view is opened. +In this case, only the STATUS field is filled and it is known that the serial action for status change has been called. +When the serial action "Change responsible" is called, the PlanningChangeResponsible_view is opened. +Here again only the RESPONSIBLE field is filled and it is known that the responsible person has been changed. diff --git a/entity/PlanningChangeStatusAndResponsible_entity/entityfields/keywordstatus/children/containername_param/valueProcess.js b/entity/PlanningChangeStatusAndResponsible_entity/entityfields/keywordstatus/children/containername_param/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..87817cdbaef598656d71e960792d8bb868601bf2 --- /dev/null +++ b/entity/PlanningChangeStatusAndResponsible_entity/entityfields/keywordstatus/children/containername_param/valueProcess.js @@ -0,0 +1,4 @@ +import("KeywordRegistry_basic"); +import("system.result"); + +result.string($KeywordRegistry.forecastStatus()); \ No newline at end of file diff --git a/entity/PlanningChangeStatusAndResponsible_entity/recordcontainers/jdito/contentProcess.js b/entity/PlanningChangeStatusAndResponsible_entity/recordcontainers/jdito/contentProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..5de89893d6ba5c0db535dbb63b3a6694a1630a27 --- /dev/null +++ b/entity/PlanningChangeStatusAndResponsible_entity/recordcontainers/jdito/contentProcess.js @@ -0,0 +1,7 @@ +import("system.result"); +import("system.vars"); + +if(vars.get("$local.idvalues")) +{ + result.object(vars.get("$local.idvalues")); +} \ No newline at end of file diff --git a/entity/PlanningChangeStatusAndResponsible_entity/recordcontainers/jdito/onInsert.js b/entity/PlanningChangeStatusAndResponsible_entity/recordcontainers/jdito/onInsert.js new file mode 100644 index 0000000000000000000000000000000000000000..14addd0dc1415ae52b7c7d3a9fb6a9576cc0aa1b --- /dev/null +++ b/entity/PlanningChangeStatusAndResponsible_entity/recordcontainers/jdito/onInsert.js @@ -0,0 +1,83 @@ +import("Contact_lib"); +import("Keyword_lib"); +import("Employee_lib"); +import("system.translate"); +import("system.notification"); +import("KeywordRegistry_basic"); +import("Sql_lib"); +import("system.db"); +import("system.vars"); +import("system.neon"); +import("system.tools"); + +var planningObj = JSON.parse(vars.get("$param.PlanningIds_param")); +var status = vars.get("$field.STATUS"); +var responsible = vars.get("$field.RESPONSIBLE"); +var table = "FORECAST"; +var cols; +var vals; +var planningIds; + + +planningIds = planningObj.filter(function(oneObj){ + + var cond = oneObj["STATUS"] != $KeywordRegistry.forecastStatus$locked(); + + if(status) + { + cond = cond || tools.currentUserHasRole("INTERNAL_ADMINISTRATOR"); + } + + return cond; +}).map(function(oneObj) +{ + return oneObj["FORECASTID"]; +}); + + +if(status) +{ + cols = ["STATUS"]; + vals = [status]; + +} +else if(responsible) +{ + cols = ["RESPONSIBLE_CONTACT_ID"]; + vals = [responsible]; +} + +if(planningIds.length > 0) +{ + db.updateData(table, cols, null, vals, newWhere("FORECAST.FORECASTID", planningIds, SqlBuilder.IN()).toString()); +} + +var notUpdatedRecordsLength = (planningObj.length - planningIds.length); +var descriptionText = "%0 out of %1 records were changed to \"%2\".\n %3 record/s could not be updated."; + +var captionStatus = translate.withArguments("%0 status was/were changed", [planningIds.length]); +var captionResponsible = translate.withArguments("%0 responsilbe/s was/were changed", [planningIds.length]); +var descriptionStatus = translate.withArguments(descriptionText, [planningIds.length, planningObj.length, KeywordUtils.getViewValue($KeywordRegistry.forecastStatus(), status), notUpdatedRecordsLength]); +var descriptionResponsible = translate.withArguments(descriptionText, [planningIds.length, planningObj.length, ContactUtils.getFullTitleByContactId(responsible), notUpdatedRecordsLength]); + +var notificationConfig = notification.createConfig() + .addUserWithId(EmployeeUtils.getCurrentUserId()) + .forcedPriority(notification.PRIO_NONE) + .notificationType("_____SYSTEM_NOTIFICATION_MESSAGE") + .initialState(notification.STATE_UNSEEN) + .daysToLive(1); + +if(status) +{ + notificationConfig.caption(captionStatus) + .description(descriptionStatus); +} +else if(responsible) +{ + notificationConfig.caption(captionResponsible) + .description(descriptionResponsible); +} + +notification.addNotificationWith(notificationConfig); + + diff --git a/entity/Planning_entity/Planning_entity.aod b/entity/Planning_entity/Planning_entity.aod new file mode 100644 index 0000000000000000000000000000000000000000..d398750ab2f311e3ff30b101d4c691a9c11af698 --- /dev/null +++ b/entity/Planning_entity/Planning_entity.aod @@ -0,0 +1,302 @@ +<?xml version="1.0" encoding="UTF-8"?> +<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.18" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.18"> + <name>Planning_entity</name> + <title>Planning</title> + <majorModelMode>DISTRIBUTED</majorModelMode> + <documentation>%aditoprj%/entity/Planning_entity/documentation.adoc</documentation> + <icon>VAADIN:MONEY</icon> + <grantUpdate v="true" /> + <grantUpdateProcess>%aditoprj%/entity/Planning_entity/grantUpdateProcess.js</grantUpdateProcess> + <grantDeleteProcess>%aditoprj%/entity/Planning_entity/grantDeleteProcess.js</grantDeleteProcess> + <onValidation>%aditoprj%/entity/Planning_entity/onValidation.js</onValidation> + <titlePlural>Plannings</titlePlural> + <recordContainer>db</recordContainer> + <entityFields> + <entityProvider> + <name>#PROVIDER</name> + </entityProvider> + <entityProvider> + <name>#PROVIDER_AGGREGATES</name> + <useAggregates v="true" /> + </entityProvider> + <entityField> + <name>FORECASTID</name> + </entityField> + <entityField> + <name>INFO</name> + <title>Information</title> + <contentType>LONG_TEXT</contentType> + </entityField> + <entityField> + <name>VOLUME</name> + <title>Volume</title> + <contentType>NUMBER</contentType> + <outputFormat>#,##0.00</outputFormat> + <inputFormat>#,##0.00</inputFormat> + <groupable v="true" /> + <mandatory v="true" /> + </entityField> + <entityField> + <name>FORECAST_YEAR</name> + <title>Year</title> + <contentType>NUMBER</contentType> + <outputFormat>####</outputFormat> + <groupable v="true" /> + <state>EDITABLE</state> + <onValueChangeTypes> + <element>MASK</element> + </onValueChangeTypes> + </entityField> + <entityField> + <name>GROUPCODE</name> + <title>Product Group</title> + <consumer>KeywordGroupcode</consumer> + <groupable v="true" /> + <stateProcess>%aditoprj%/entity/Planning_entity/entityfields/groupcode/stateProcess.js</stateProcess> + <displayValueProcess>%aditoprj%/entity/Planning_entity/entityfields/groupcode/displayValueProcess.js</displayValueProcess> + </entityField> + <entityField> + <name>CONTACT_ID</name> + <title>Organisation</title> + <consumer>Organisations</consumer> + <groupable v="true" /> + <linkedContext>Organisation</linkedContext> + <mandatory v="true" /> + <stateProcess>%aditoprj%/entity/Planning_entity/entityfields/contact_id/stateProcess.js</stateProcess> + <displayValueProcess>%aditoprj%/entity/Planning_entity/entityfields/contact_id/displayValueProcess.js</displayValueProcess> + </entityField> + <entityField> + <name>KIND</name> + <consumer>KeywordKinds</consumer> + <valueProcess>%aditoprj%/entity/Planning_entity/entityfields/kind/valueProcess.js</valueProcess> + </entityField> + <entityConsumer> + <name>KeywordKinds</name> + <dependency> + <name>dependency</name> + <entityName>KeywordEntry_entity</entityName> + <fieldName>SpecificContainerKeywords</fieldName> + </dependency> + <children> + <entityParameter> + <name>ContainerName_param</name> + <valueProcess>%aditoprj%/entity/Planning_entity/entityfields/keywordkinds/children/containername_param/valueProcess.js</valueProcess> + </entityParameter> + </children> + </entityConsumer> + <entityConsumer> + <name>Organisations</name> + <dependency> + <name>dependency</name> + <entityName>Organisation_entity</entityName> + <fieldName>Organisations</fieldName> + </dependency> + </entityConsumer> + <entityField> + <name>YEAR_DATETIME</name> + <title>Year</title> + <contentType>DATE</contentType> + <resolution>YEAR</resolution> + <mandatory v="true" /> + <state>EDITABLE</state> + <stateProcess>%aditoprj%/entity/Planning_entity/entityfields/year_datetime/stateProcess.js</stateProcess> + <valueProcess>%aditoprj%/entity/Planning_entity/entityfields/year_datetime/valueProcess.js</valueProcess> + <onValueChange>%aditoprj%/entity/Planning_entity/entityfields/year_datetime/onValueChange.js</onValueChange> + <onValueChangeTypes> + <element>MASK</element> + </onValueChangeTypes> + </entityField> + <entityProvider> + <name>Plannings</name> + <dependencies> + <entityDependency> + <name>73fab37a-74bc-452d-a1ec-ea1c53204468</name> + <entityName>Organisation_entity</entityName> + <fieldName>Plannings</fieldName> + <isConsumer v="false" /> + </entityDependency> + <entityDependency> + <name>9ddd5d69-72df-46f7-b42a-f08f08a2c8cd</name> + <entityName>PlanningAddToOrganisations_entity</entityName> + <fieldName>PlanningsAlreadyExists</fieldName> + <isConsumer v="false" /> + </entityDependency> + <entityDependency> + <name>c022c816-85eb-4112-95fe-7cbcab96e128</name> + <entityName>PlanningAddToOrganisations_entity</entityName> + <fieldName>PlanningsNew</fieldName> + <isConsumer v="false" /> + </entityDependency> + </dependencies> + </entityProvider> + <entityParameter> + <name>ContactId_param</name> + <expose v="true" /> + </entityParameter> + <entityField> + <name>STATUS</name> + <title>Status</title> + <consumer>KeywordStatus</consumer> + <groupable v="true" /> + <stateProcess>%aditoprj%/entity/Planning_entity/entityfields/status/stateProcess.js</stateProcess> + <valueProcess>%aditoprj%/entity/Planning_entity/entityfields/status/valueProcess.js</valueProcess> + <displayValueProcess>%aditoprj%/entity/Planning_entity/entityfields/status/displayValueProcess.js</displayValueProcess> + </entityField> + <entityField> + <name>RESPONSIBLE_CONTACT_ID</name> + <title>Responsible</title> + <consumer>Responsible</consumer> + <groupable v="true" /> + <stateProcess>%aditoprj%/entity/Planning_entity/entityfields/responsible_contact_id/stateProcess.js</stateProcess> + <valueProcess>%aditoprj%/entity/Planning_entity/entityfields/responsible_contact_id/valueProcess.js</valueProcess> + <displayValueProcess>%aditoprj%/entity/Planning_entity/entityfields/responsible_contact_id/displayValueProcess.js</displayValueProcess> + </entityField> + <entityConsumer> + <name>KeywordStatus</name> + <dependency> + <name>dependency</name> + <entityName>KeywordEntry_entity</entityName> + <fieldName>SpecificContainerKeywords</fieldName> + </dependency> + <children> + <entityParameter> + <name>ContainerName_param</name> + <valueProcess>%aditoprj%/entity/Planning_entity/entityfields/keywordstatus/children/containername_param/valueProcess.js</valueProcess> + </entityParameter> + </children> + </entityConsumer> + <entityConsumer> + <name>KeywordGroupcode</name> + <dependency> + <name>dependency</name> + <entityName>KeywordEntry_entity</entityName> + <fieldName>SpecificContainerKeywords</fieldName> + </dependency> + <children> + <entityParameter> + <name>ContainerName_param</name> + <valueProcess>%aditoprj%/entity/Planning_entity/entityfields/keywordgroupcode/children/containername_param/valueProcess.js</valueProcess> + </entityParameter> + </children> + </entityConsumer> + <entityConsumer> + <name>Responsible</name> + <dependency> + <name>dependency</name> + <entityName>Employee_entity</entityName> + <fieldName>Employees</fieldName> + </dependency> + </entityConsumer> + <entityActionGroup> + <name>FilterViewActions</name> + <children> + <entityActionField> + <name>ChangeResponsible</name> + <title>Change responsible</title> + <onActionProcess>%aditoprj%/entity/Planning_entity/entityfields/filterviewactions/children/changeresponsible/onActionProcess.js</onActionProcess> + <isObjectAction v="false" /> + <isSelectionAction v="true" /> + <iconId>VAADIN:USER</iconId> + </entityActionField> + <entityActionField> + <name>ChangeStatus</name> + <title>Change status</title> + <onActionProcess>%aditoprj%/entity/Planning_entity/entityfields/filterviewactions/children/changestatus/onActionProcess.js</onActionProcess> + <isObjectAction v="false" /> + <isSelectionAction v="true" /> + <iconId>VAADIN:CHECK_SQUARE_O</iconId> + </entityActionField> + </children> + </entityActionGroup> + <entityParameter> + <name>SerialActionAddPlanning_param</name> + <expose v="true" /> + </entityParameter> + <entityParameter> + <name>PlanningIds_param</name> + <expose v="true" /> + </entityParameter> + </entityFields> + <recordContainers> + <dbRecordContainer> + <name>db</name> + <conditionProcess>%aditoprj%/entity/Planning_entity/recordcontainers/db/conditionProcess.js</conditionProcess> + <alias>Data_alias</alias> + <recordFieldMappings> + <dbRecordFieldMapping> + <name>FORECASTID.value</name> + <recordfield>FORECAST.FORECASTID</recordfield> + </dbRecordFieldMapping> + <dbRecordFieldMapping> + <name>GROUPCODE.value</name> + <recordfield>FORECAST.GROUPCODE</recordfield> + </dbRecordFieldMapping> + <dbRecordFieldMapping> + <name>INFO.value</name> + <recordfield>FORECAST.INFO</recordfield> + <isFilterable v="true" /> + </dbRecordFieldMapping> + <dbRecordFieldMapping> + <name>VOLUME.value</name> + <recordfield>FORECAST.VOLUME</recordfield> + <isFilterable v="true" /> + </dbRecordFieldMapping> + <dbRecordFieldMapping> + <name>KIND.value</name> + <recordfield>FORECAST.KIND</recordfield> + </dbRecordFieldMapping> + <dbRecordFieldMapping> + <name>FORECAST_YEAR.value</name> + <recordfield>FORECAST.FORECAST_YEAR</recordfield> + <isFilterable v="true" /> + </dbRecordFieldMapping> + <dbRecordFieldMapping> + <name>CONTACT_ID.value</name> + <recordfield>FORECAST.CONTACT_ID</recordfield> + <isFilterable v="true" /> + </dbRecordFieldMapping> + <consumerMapping> + <name>Organisations</name> + <filterConditionProcess>%aditoprj%/entity/Planning_entity/recordcontainers/db/recordfieldmappings/organisations/filterConditionProcess.js</filterConditionProcess> + <isFilterable v="true" /> + <filtertype>EXTENDED</filtertype> + </consumerMapping> + <dbRecordFieldMapping> + <name>STATUS.value</name> + <recordfield>FORECAST.STATUS</recordfield> + </dbRecordFieldMapping> + <dbRecordFieldMapping> + <name>RESPONSIBLE_CONTACT_ID.value</name> + <recordfield>FORECAST.RESPONSIBLE_CONTACT_ID</recordfield> + <isFilterable v="true" /> + </dbRecordFieldMapping> + <dbRecordFieldMapping> + <name>STATUS.displayValue</name> + <expression>%aditoprj%/entity/Planning_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js</expression> + </dbRecordFieldMapping> + <dbRecordFieldMapping> + <name>GROUPCODE.displayValue</name> + <expression>%aditoprj%/entity/Planning_entity/recordcontainers/db/recordfieldmappings/groupcode.displayvalue/expression.js</expression> + </dbRecordFieldMapping> + </recordFieldMappings> + <linkInformation> + <linkInformation> + <name>52c342ed-8a01-4d01-80b6-d9b74e9e66ab</name> + <tableName>FORECAST</tableName> + <primaryKey>FORECASTID</primaryKey> + <isUIDTable v="true" /> + <readonly v="false" /> + </linkInformation> + </linkInformation> + <filterExtensions> + <filterExtensionSet> + <name>OrganisationAttributes_filter</name> + <filterFieldsProcess>%aditoprj%/entity/Planning_entity/recordcontainers/db/filterextensions/organisationattributes_filter/filterFieldsProcess.js</filterFieldsProcess> + <filterValuesProcess>%aditoprj%/entity/Planning_entity/recordcontainers/db/filterextensions/organisationattributes_filter/filterValuesProcess.js</filterValuesProcess> + <filterConditionProcess>%aditoprj%/entity/Planning_entity/recordcontainers/db/filterextensions/organisationattributes_filter/filterConditionProcess.js</filterConditionProcess> + <filtertype>EXTENDED</filtertype> + </filterExtensionSet> + </filterExtensions> + </dbRecordContainer> + </recordContainers> +</entity> diff --git a/entity/Planning_entity/documentation.adoc b/entity/Planning_entity/documentation.adoc new file mode 100644 index 0000000000000000000000000000000000000000..29fb921f7f52b2dc0e6c3ee1b4c22807aad7df4f --- /dev/null +++ b/entity/Planning_entity/documentation.adoc @@ -0,0 +1,4 @@ += Planning_entity + +An entity for handling Plannings. +A planning is a forecast that is not yet realistic. diff --git a/entity/Planning_entity/entityfields/contact_id/displayValueProcess.js b/entity/Planning_entity/entityfields/contact_id/displayValueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..9d7be1063f1aba777a205ded715b26133f8144a0 --- /dev/null +++ b/entity/Planning_entity/entityfields/contact_id/displayValueProcess.js @@ -0,0 +1,6 @@ +import("Contact_lib"); +import("system.result"); +import("system.neon"); +import("system.vars"); + +result.string(OrganisationUtils.getNameByContactId(vars.get("$field.CONTACT_ID"))); \ No newline at end of file diff --git a/entity/Planning_entity/entityfields/contact_id/stateProcess.js b/entity/Planning_entity/entityfields/contact_id/stateProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..e00d986e700ae99be24e13b62ec5f88affba025b --- /dev/null +++ b/entity/Planning_entity/entityfields/contact_id/stateProcess.js @@ -0,0 +1,8 @@ +import("system.vars"); +import("system.neon"); +import("system.result"); + +if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_EDIT) +{ + result.string(neon.COMPONENTSTATE_READONLY); +} \ No newline at end of file diff --git a/entity/Planning_entity/entityfields/filterviewactions/children/changeresponsible/onActionProcess.js b/entity/Planning_entity/entityfields/filterviewactions/children/changeresponsible/onActionProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..dc355adfad0f5c6dd5e131d51fb14ddadea9c051 --- /dev/null +++ b/entity/Planning_entity/entityfields/filterviewactions/children/changeresponsible/onActionProcess.js @@ -0,0 +1,13 @@ +import("system.vars"); +import("system.neon"); + +var params = { + "PlanningIds_param": JSON.stringify(vars.get("$sys.selectionRows")) +}; + +if(vars.get("$param.ContactId_param")) +{ + params["OrganisationContactId_param"] = vars.get("$param.ContactId_param"); +} + +neon.openContext("PlanningChangeStatusAndResponsible", "PlanningChangeResponsible_view", null, neon.OPERATINGSTATE_NEW, params); \ No newline at end of file diff --git a/entity/Planning_entity/entityfields/filterviewactions/children/changestatus/onActionProcess.js b/entity/Planning_entity/entityfields/filterviewactions/children/changestatus/onActionProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..c3e1224d7beec61e97ade927146387bcddff6942 --- /dev/null +++ b/entity/Planning_entity/entityfields/filterviewactions/children/changestatus/onActionProcess.js @@ -0,0 +1,13 @@ +import("system.vars"); +import("system.neon"); + +var params = { + "PlanningIds_param": JSON.stringify(vars.get("$sys.selectionRows")) +}; + +if(vars.get("$param.ContactId_param")) +{ + params["OrganisationContactId_param"] = vars.get("$param.ContactId_param"); +} + +neon.openContext("PlanningChangeStatusAndResponsible", "PlanningChangeStatus_view", null, neon.OPERATINGSTATE_NEW, params); \ No newline at end of file diff --git a/entity/Planning_entity/entityfields/groupcode/displayValueProcess.js b/entity/Planning_entity/entityfields/groupcode/displayValueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..b969a4ff0bee37ef3e8d525de185396c440adf25 --- /dev/null +++ b/entity/Planning_entity/entityfields/groupcode/displayValueProcess.js @@ -0,0 +1,6 @@ +import("system.result"); +import("system.vars"); +import("Keyword_lib"); +import("KeywordRegistry_basic"); + +result.string(KeywordUtils.getViewValue($KeywordRegistry.productGroupcode(), vars.get("$field.GROUPCODE"))); diff --git a/entity/Planning_entity/entityfields/groupcode/stateProcess.js b/entity/Planning_entity/entityfields/groupcode/stateProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..e00d986e700ae99be24e13b62ec5f88affba025b --- /dev/null +++ b/entity/Planning_entity/entityfields/groupcode/stateProcess.js @@ -0,0 +1,8 @@ +import("system.vars"); +import("system.neon"); +import("system.result"); + +if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_EDIT) +{ + result.string(neon.COMPONENTSTATE_READONLY); +} \ No newline at end of file diff --git a/entity/Planning_entity/entityfields/keywordgroupcode/children/containername_param/valueProcess.js b/entity/Planning_entity/entityfields/keywordgroupcode/children/containername_param/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..e0b3a6dd6b49bace8935531285f8defc51731f36 --- /dev/null +++ b/entity/Planning_entity/entityfields/keywordgroupcode/children/containername_param/valueProcess.js @@ -0,0 +1,5 @@ +import("system.result"); +import("Keyword_lib"); +import("KeywordRegistry_basic"); + +result.string($KeywordRegistry.productGroupcode()); diff --git a/entity/Planning_entity/entityfields/keywordkinds/children/containername_param/valueProcess.js b/entity/Planning_entity/entityfields/keywordkinds/children/containername_param/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..7dd10c8e07794e1ee9aade2bb0babf386d08573d --- /dev/null +++ b/entity/Planning_entity/entityfields/keywordkinds/children/containername_param/valueProcess.js @@ -0,0 +1,4 @@ +import("KeywordRegistry_basic"); +import("system.result"); + +result.string($KeywordRegistry.forecastKind()); \ No newline at end of file diff --git a/entity/Planning_entity/entityfields/keywordstatus/children/containername_param/valueProcess.js b/entity/Planning_entity/entityfields/keywordstatus/children/containername_param/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..87817cdbaef598656d71e960792d8bb868601bf2 --- /dev/null +++ b/entity/Planning_entity/entityfields/keywordstatus/children/containername_param/valueProcess.js @@ -0,0 +1,4 @@ +import("KeywordRegistry_basic"); +import("system.result"); + +result.string($KeywordRegistry.forecastStatus()); \ No newline at end of file diff --git a/entity/Planning_entity/entityfields/kind/valueProcess.js b/entity/Planning_entity/entityfields/kind/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..9c3cc5fe072b13dc822063ffd8d69c53e6dfa88f --- /dev/null +++ b/entity/Planning_entity/entityfields/kind/valueProcess.js @@ -0,0 +1,9 @@ +import("KeywordRegistry_basic"); +import("system.result"); +import("system.neon"); +import("system.vars"); + +if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW) +{ + result.string($KeywordRegistry.forecastKind$planning()); +} \ No newline at end of file diff --git a/entity/Planning_entity/entityfields/responsible_contact_id/displayValueProcess.js b/entity/Planning_entity/entityfields/responsible_contact_id/displayValueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..688c1f577469ab057712c28e731741c12d9a2da9 --- /dev/null +++ b/entity/Planning_entity/entityfields/responsible_contact_id/displayValueProcess.js @@ -0,0 +1,5 @@ +import("system.vars"); +import("Contact_lib"); +import("system.result"); + +result.string(ContactUtils.getFullTitleByContactId(vars.get("$field.RESPONSIBLE_CONTACT_ID"))); \ No newline at end of file diff --git a/entity/Planning_entity/entityfields/responsible_contact_id/stateProcess.js b/entity/Planning_entity/entityfields/responsible_contact_id/stateProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..e00d986e700ae99be24e13b62ec5f88affba025b --- /dev/null +++ b/entity/Planning_entity/entityfields/responsible_contact_id/stateProcess.js @@ -0,0 +1,8 @@ +import("system.vars"); +import("system.neon"); +import("system.result"); + +if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_EDIT) +{ + result.string(neon.COMPONENTSTATE_READONLY); +} \ No newline at end of file diff --git a/entity/Planning_entity/entityfields/responsible_contact_id/valueProcess.js b/entity/Planning_entity/entityfields/responsible_contact_id/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..a4c7e25a113f238ca83a0e6800afe8b8a061a687 --- /dev/null +++ b/entity/Planning_entity/entityfields/responsible_contact_id/valueProcess.js @@ -0,0 +1,10 @@ +import("Employee_lib"); +import("KeywordRegistry_basic"); +import("system.neon"); +import("system.vars"); +import("system.result"); + +if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW && !vars.get("$this.value")) +{ + result.string(EmployeeUtils.getCurrentContactId()); +} \ No newline at end of file diff --git a/entity/Planning_entity/entityfields/status/displayValueProcess.js b/entity/Planning_entity/entityfields/status/displayValueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..f25ee6cc31c469da23ef615a51367848b9da3d37 --- /dev/null +++ b/entity/Planning_entity/entityfields/status/displayValueProcess.js @@ -0,0 +1,6 @@ +import("system.result"); +import("system.vars"); +import("Keyword_lib"); +import("KeywordRegistry_basic"); + +result.string(KeywordUtils.getViewValue($KeywordRegistry.forecastStatus(), vars.get("$field.STATUS"))); diff --git a/entity/Planning_entity/entityfields/status/stateProcess.js b/entity/Planning_entity/entityfields/status/stateProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..ae436c75973b625076a73472675414be0c9687c7 --- /dev/null +++ b/entity/Planning_entity/entityfields/status/stateProcess.js @@ -0,0 +1,10 @@ +import("system.neon"); +import("system.vars"); +import("system.result"); + +var operatingstate = vars.get("$sys.operatingstate"); + +if(operatingstate == neon.OPERATINGSTATE_NEW || operatingstate == neon.OPERATINGSTATE_EDIT) +{ + result.string(neon.COMPONENTSTATE_READONLY); +} \ No newline at end of file diff --git a/entity/Planning_entity/entityfields/status/valueProcess.js b/entity/Planning_entity/entityfields/status/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..ec3ba22fcd9f2773e90c85317a86808ff542abce --- /dev/null +++ b/entity/Planning_entity/entityfields/status/valueProcess.js @@ -0,0 +1,9 @@ +import("KeywordRegistry_basic"); +import("system.neon"); +import("system.vars"); +import("system.result"); + +if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW && !vars.get("$this.value")) +{ + result.string($KeywordRegistry.forecastStatus$inPlanning()); +} \ No newline at end of file diff --git a/entity/Planning_entity/entityfields/year_datetime/onValueChange.js b/entity/Planning_entity/entityfields/year_datetime/onValueChange.js new file mode 100644 index 0000000000000000000000000000000000000000..33c75c30f93eb29f2c67415ccca75b994d88fa74 --- /dev/null +++ b/entity/Planning_entity/entityfields/year_datetime/onValueChange.js @@ -0,0 +1,10 @@ +import("system.datetime"); +import("system.neon"); +import("system.vars"); + +var yearDatetime = vars.get("$local.value"); + +if(yearDatetime) +{ + neon.setFieldValue("$field.FORECAST_YEAR", datetime.toDate(yearDatetime, "yyyy", "UTC")); +} \ No newline at end of file diff --git a/entity/Planning_entity/entityfields/year_datetime/stateProcess.js b/entity/Planning_entity/entityfields/year_datetime/stateProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..d5b44033c15b257a0ccbf07443098ecbade16ee4 --- /dev/null +++ b/entity/Planning_entity/entityfields/year_datetime/stateProcess.js @@ -0,0 +1,14 @@ +import("system.result"); +import("system.neon"); +import("system.vars"); + +var operatingstate = vars.get("$sys.operatingstate"); + +if(operatingstate == neon.OPERATINGSTATE_EDIT) +{ + result.string(neon.COMPONENTSTATE_READONLY); +} +else if(operatingstate == neon.OPERATINGSTATE_VIEW && vars.get("$sys.recordstate") == neon.OPERATINGSTATE_VIEW) +{ + result.string(neon.COMPONENTSTATE_INVISIBLE); +} \ No newline at end of file diff --git a/entity/Planning_entity/entityfields/year_datetime/valueProcess.js b/entity/Planning_entity/entityfields/year_datetime/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..1f2d4b665b8a9e079f379c194dc2d84ac47537b7 --- /dev/null +++ b/entity/Planning_entity/entityfields/year_datetime/valueProcess.js @@ -0,0 +1,17 @@ +import("system.neon"); +import("system.vars"); +import("system.result"); +import("system.datetime"); + +var yearDate = vars.get("$field.FORECAST_YEAR"); +var operatingstate = vars.get("$sys.operatingstate"); +var thisValue = vars.get("$this.value"); + +if(operatingstate == neon.OPERATINGSTATE_NEW && thisValue == null) +{ + result.string(vars.get("$sys.date")); +} +else if(yearDate && operatingstate == neon.OPERATINGSTATE_EDIT && thisValue == null) +{ + result.string(datetime.toLong(yearDate, "yyyy", "UTC")); +} \ No newline at end of file diff --git a/entity/Planning_entity/grantDeleteProcess.js b/entity/Planning_entity/grantDeleteProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..a6ac3b38ec75bda6924c8fe3c0c738c787d69655 --- /dev/null +++ b/entity/Planning_entity/grantDeleteProcess.js @@ -0,0 +1,8 @@ +import("system.result"); +import("KeywordRegistry_basic"); +import("system.vars"); + +if(vars.get("$field.STATUS") == $KeywordRegistry.forecastStatus$locked()) +{ + result.string(false); +} \ No newline at end of file diff --git a/entity/Planning_entity/grantUpdateProcess.js b/entity/Planning_entity/grantUpdateProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..a6ac3b38ec75bda6924c8fe3c0c738c787d69655 --- /dev/null +++ b/entity/Planning_entity/grantUpdateProcess.js @@ -0,0 +1,8 @@ +import("system.result"); +import("KeywordRegistry_basic"); +import("system.vars"); + +if(vars.get("$field.STATUS") == $KeywordRegistry.forecastStatus$locked()) +{ + result.string(false); +} \ No newline at end of file diff --git a/entity/Planning_entity/onValidation.js b/entity/Planning_entity/onValidation.js new file mode 100644 index 0000000000000000000000000000000000000000..047915d05fafd8a5103104a807e57842e9fdf6b9 --- /dev/null +++ b/entity/Planning_entity/onValidation.js @@ -0,0 +1,37 @@ +import("system.neon"); +import("system.translate"); +import("system.result"); +import("Sql_lib"); +import("system.vars"); + +if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW) +{ + var contact_id = vars.get("$field.CONTACT_ID"); + var year = vars.get("$field.FORECAST_YEAR"); + var groupcode = vars.get("$field.GROUPCODE"); + + if(contact_id && year) + { + var plannings = newSelect("FORECAST.FORECASTID") + .from("FORECAST") + .where("FORECAST.CONTACT_ID", contact_id) + .and("FORECAST.FORECAST_YEAR", year); + + + if(!groupcode) + { + plannings.and("FORECAST.GROUPCODE is null"); + } + else + { + plannings.and("FORECAST.GROUPCODE", groupcode); + } + + plannings = plannings.cell(); + + if(plannings) + { + result.string(translate.text("The combination of organisation, product group and year already exists.")); + } + } +} \ No newline at end of file diff --git a/entity/Planning_entity/recordcontainers/db/conditionProcess.js b/entity/Planning_entity/recordcontainers/db/conditionProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..7241ab84dcb6128aefd11daf0b2407de72695f8f --- /dev/null +++ b/entity/Planning_entity/recordcontainers/db/conditionProcess.js @@ -0,0 +1,11 @@ +import("system.vars"); +import("KeywordRegistry_basic"); +import("system.result"); +import("Sql_lib"); + +var cond = newWhere() + .and("FORECAST.KIND", $KeywordRegistry.forecastKind$planning()) + .andIfSet("FORECAST.CONTACT_ID", "$param.ContactId_param") + .andIfSet("FORECAST.FORECASTID", JSON.parse(vars.get("$param.PlanningIds_param")), SqlBuilder.IN()); + +result.string(cond.toString()); \ No newline at end of file diff --git a/entity/Planning_entity/recordcontainers/db/filterextensions/organisationattributes_filter/filterConditionProcess.js b/entity/Planning_entity/recordcontainers/db/filterextensions/organisationattributes_filter/filterConditionProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..50f428b461f003b03cfc7e6cc151773dc8306319 --- /dev/null +++ b/entity/Planning_entity/recordcontainers/db/filterextensions/organisationattributes_filter/filterConditionProcess.js @@ -0,0 +1,6 @@ +import("system.result"); +import("AttributeFilter_lib"); + +var sqlCond = AttributeFilterExtensionMaker.makeFilterConditionSql("CONTACT_ID", "Organisation"); + +result.string(sqlCond); \ No newline at end of file diff --git a/entity/Planning_entity/recordcontainers/db/filterextensions/organisationattributes_filter/filterFieldsProcess.js b/entity/Planning_entity/recordcontainers/db/filterextensions/organisationattributes_filter/filterFieldsProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..105c59dca1f529f109664b425b83d8de93041f00 --- /dev/null +++ b/entity/Planning_entity/recordcontainers/db/filterextensions/organisationattributes_filter/filterFieldsProcess.js @@ -0,0 +1,5 @@ +import("system.result"); +import("AttributeFilter_lib"); + +var fields = AttributeFilterExtensionMaker.makeFilterFields("Organisation"); +result.string(fields); \ No newline at end of file diff --git a/entity/Planning_entity/recordcontainers/db/filterextensions/organisationattributes_filter/filterValuesProcess.js b/entity/Planning_entity/recordcontainers/db/filterextensions/organisationattributes_filter/filterValuesProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..942b0a0495a179f9c25d19330bb8cd59c5563ec0 --- /dev/null +++ b/entity/Planning_entity/recordcontainers/db/filterextensions/organisationattributes_filter/filterValuesProcess.js @@ -0,0 +1,5 @@ +import("system.result"); +import("AttributeFilter_lib"); + +var values = AttributeFilterExtensionMaker.makeFilterValues(); +result.object(values); \ No newline at end of file diff --git a/entity/Planning_entity/recordcontainers/db/recordfieldmappings/groupcode.displayvalue/expression.js b/entity/Planning_entity/recordcontainers/db/recordfieldmappings/groupcode.displayvalue/expression.js new file mode 100644 index 0000000000000000000000000000000000000000..24e9e9e299565f26fa9151cdda86f2c73c7c102b --- /dev/null +++ b/entity/Planning_entity/recordcontainers/db/recordfieldmappings/groupcode.displayvalue/expression.js @@ -0,0 +1,5 @@ +import("KeywordRegistry_basic"); +import("Keyword_lib"); +import("system.result"); + +result.string(KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.productGroupcode(), "FORECAST.GROUPCODE")); \ No newline at end of file diff --git a/entity/Planning_entity/recordcontainers/db/recordfieldmappings/organisations/filterConditionProcess.js b/entity/Planning_entity/recordcontainers/db/recordfieldmappings/organisations/filterConditionProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..8e208adfb692eded396d7ddcd4a46a66cb5e825b --- /dev/null +++ b/entity/Planning_entity/recordcontainers/db/recordfieldmappings/organisations/filterConditionProcess.js @@ -0,0 +1,13 @@ +import("Sql_lib"); +import("system.vars"); +import("system.result"); + + +var subSql = newSelect("CONTACT.CONTACTID") +.from("CONTACT") +.join("ORGANISATION", "ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID and CONTACT.PERSON_ID is null") +.leftJoin("ADDRESS", "ADDRESS.ADDRESSID = CONTACT.ADDRESS_ID") +.leftJoin("CLASSIFICATIONSTORAGE", "CLASSIFICATIONSTORAGE.OBJECT_ROWID = CONTACT.CONTACTID") +.where(vars.get("$local.condition")).toString(); + +result.string(newWhere("FORECAST.CONTACT_ID in (" + subSql + ")").toString()); \ No newline at end of file diff --git a/entity/Planning_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js b/entity/Planning_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js new file mode 100644 index 0000000000000000000000000000000000000000..c13a0a906da9ffc60b722608fd8ea32a086d4003 --- /dev/null +++ b/entity/Planning_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js @@ -0,0 +1,5 @@ +import("KeywordRegistry_basic"); +import("Keyword_lib"); +import("system.result"); + +result.string(KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.forecastStatus(), "FORECAST.STATUS")); \ No newline at end of file diff --git a/entity/Productprice_entity/Productprice_entity.aod b/entity/Productprice_entity/Productprice_entity.aod index db95abf550f0eb6f8be509961236a026edce225b..d886179ed2215e5441f060fdf457548a9b4774fa 100644 --- a/entity/Productprice_entity/Productprice_entity.aod +++ b/entity/Productprice_entity/Productprice_entity.aod @@ -20,6 +20,7 @@ <dropDownProcess>%aditoprj%/entity/Productprice_entity/entityfields/buysell/dropDownProcess.js</dropDownProcess> <stateProcess>%aditoprj%/entity/Productprice_entity/entityfields/buysell/stateProcess.js</stateProcess> <valueProcess>%aditoprj%/entity/Productprice_entity/entityfields/buysell/valueProcess.js</valueProcess> + <onValueChange>%aditoprj%/entity/Productprice_entity/entityfields/buysell/onValueChange.js</onValueChange> </entityField> <entityField> <name>CURRENCY</name> @@ -112,6 +113,7 @@ <titleProcess>%aditoprj%/entity/Productprice_entity/entityfields/pricelist/titleProcess.js</titleProcess> <valueProcess>%aditoprj%/entity/Productprice_entity/entityfields/pricelist/valueProcess.js</valueProcess> <displayValueProcess>%aditoprj%/entity/Productprice_entity/entityfields/pricelist/displayValueProcess.js</displayValueProcess> + <onValueChange>%aditoprj%/entity/Productprice_entity/entityfields/pricelist/onValueChange.js</onValueChange> </entityField> <entityParameter> <name>ProductId_param</name> diff --git a/entity/Productprice_entity/entityfields/buysell/onValueChange.js b/entity/Productprice_entity/entityfields/buysell/onValueChange.js new file mode 100644 index 0000000000000000000000000000000000000000..b9fbc8bb8696d58f2540bb8a93d6a6464adedfea --- /dev/null +++ b/entity/Productprice_entity/entityfields/buysell/onValueChange.js @@ -0,0 +1,9 @@ +import("system.neon"); +import("Product_lib"); +import("system.vars"); + +if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_EDIT) +{ + var productId = vars.get("$field.PRODUCT_ID"); + ProductUtils.presetPriceAndVat(vars.get("$field.PRODUCT_ID"), vars.get("$field.VAT"),vars.get("$field.PRICELIST") , vars.get("$this.value")); +} \ No newline at end of file diff --git a/entity/Productprice_entity/entityfields/pricelist/onValueChange.js b/entity/Productprice_entity/entityfields/pricelist/onValueChange.js new file mode 100644 index 0000000000000000000000000000000000000000..190d27786a2d386cdb57927e6c422d1ff16716fd --- /dev/null +++ b/entity/Productprice_entity/entityfields/pricelist/onValueChange.js @@ -0,0 +1,9 @@ +import("system.neon"); +import("Product_lib"); +import("system.vars"); + +if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_EDIT) +{ + var productId = vars.get("$field.PRODUCT_ID"); + ProductUtils.presetPriceAndVat(vars.get("$field.PRODUCT_ID"), vars.get("$field.VAT"), vars.get("$this.value"), vars.get("$field.BUYSELL")); +} \ No newline at end of file diff --git a/entity/Productprice_entity/onValidation.js b/entity/Productprice_entity/onValidation.js index 2bfd42916247e16b08a7d6d09da372ed9bef0449..2d96e9b5c19b0e339f8845561d5d4dac4de746e4 100644 --- a/entity/Productprice_entity/onValidation.js +++ b/entity/Productprice_entity/onValidation.js @@ -1,3 +1,8 @@ +import("system.datetime"); +import("system.eMath"); +import("system.translate"); +import("system.neon"); +import("Product_lib"); import("Date_lib"); import("system.result"); import("system.vars"); @@ -11,4 +16,67 @@ if(vars.getString("$param.IgnoreOnValidation_param") != "true") { result.string(DateUtils.getValidationFailString()); } + //The logic for creating a new priceA is the following: + //If there already exists the same priceB (-> same pricelist, buySell, fromQuantity and currency) + // and the validFrom of priceB is before the validFrom of priceA + // ->change the validTo of priceB to one date prior the validFrom of priceA. + // (A)|-------| -> |---| + // (B) |-----------| -> |-----------| + // + // and the validTo of priceB is after the validTo of priceA + // ->change the validFrom of priceB to one date after the validTo of priceA. + // (A) |-------| -> |-----| + // (B) |---------| -> |---------| + // + //There is another case we cannot handle as easy: + // if priceB's validFrom is after the validFrom of priceA and it's validTo is also before the validTo of priceA + // -> catch this case in the onValidation, since the only solution would be to delete priceB + // (A) |----| -> handle in onValidation + // (B) |-------------| -> handle in onValidation + else if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW) + { + var priceList = vars.get("$field.PRICELIST"); + var productId = vars.get("$field.PRODUCT_ID"); + var buySell = vars.get("$field.BUYSELL"); + var validFrom = vars.get("$field.VALID_FROM"); + var validTo = vars.get("$field.VALID_TO"); + var currency = vars.get("$field.CURRENCY"); + var productPriceListId = vars.get("$field.PRODUCTPRICEID"); + + var priceListFilter = { currency: currency + , quantity: vars.get("$field.FROMQUANTITY") + , priceList: priceList + , buySell: buySell + , dateFrom: validFrom + , dateTo: validTo}; + var ProductDetails = ProductUtils.getProductDetails(productId, priceListFilter); + + var priceListsToPotentiallyReplace = ProductDetails.CurrentValidPriceLists; + var priceListsToReplace1 = []; + var priceListsToReplace2 = []; + + var showMessage = false; + for (var valPriceList in priceListsToPotentiallyReplace) + { + var currPriceList = priceListsToPotentiallyReplace[valPriceList]; + if(currPriceList["priceList"] == priceList && currPriceList["buySell"] == buySell) + { + if(currPriceList["validFrom"] > validFrom && ((validTo == undefined || validTo == "") || + (currPriceList["validTo"] != undefined && currPriceList["validTo"] != "" && currPriceList["validTo"] < validTo))) + { + showMessage = true; + break; + } + else if(eMath.addInt(currPriceList["validFrom"], datetime.ONE_DAY) == currPriceList["validTo"]) + { + showMessage = true; + break; + } + } + } + if(showMessage) + { + result.string(translate.withArguments("There already exists a %0 price with the same type of pricelist, quantity and currency in the defined range.", [vars.get("$field.BUYSELL")])); + } + } } \ No newline at end of file diff --git a/entity/Productprice_entity/recordcontainers/db/onDBInsert.js b/entity/Productprice_entity/recordcontainers/db/onDBInsert.js index 5d9ed76f358f35176af7e052e4630a14b9774255..62b572aaab1fd35c0b53c327d4d4f9a9b174d3dd 100644 --- a/entity/Productprice_entity/recordcontainers/db/onDBInsert.js +++ b/entity/Productprice_entity/recordcontainers/db/onDBInsert.js @@ -4,28 +4,70 @@ import("system.datetime"); import("system.entities"); import("Sql_lib"); import("system.vars"); +import("Product_lib"); +//The logic for creating a new priceA is the following: +//If there already exists the same priceB (-> same pricelist, buySell, fromQuantity and currency) +// and the validFrom of priceB is before the validFrom of priceA +// ->change the validTo of priceB to one date prior the validFrom of priceA. +// (A)|-------| -> |---| +// (B) |-----------| -> |-----------| +// +// and the validTo of priceB is after the validTo of priceA +// ->change the validFrom of priceB to one date after the validTo of priceA. +// (A) |-------| -> |-----| +// (B) |---------| -> |---------| +// +//There is another case we cannot handle as easy: +// if priceB's validFrom is after the validFrom of priceA and it's validTo is also before the validTo of priceA +// -> catch this case in the onValidation, since the only solution would be to delete priceB +// (A) |----| -> handle in onValidation +// (B) |-------------| -> handle in onValidation +// +var priceListId = vars.get("$field.PRODUCTPRICEID"); var priceList = vars.get("$field.PRICELIST"); var productId = vars.get("$field.PRODUCT_ID"); var buySell = vars.get("$field.BUYSELL"); var validFrom = vars.get("$field.VALID_FROM"); +var validTo = vars.get("$field.VALID_TO"); +var currency = vars.get("$field.CURRENCY"); var oneDayPrior = eMath.subInt(validFrom, datetime.ONE_DAY); +var oneDayAfter = eMath.addInt(validTo, datetime.ONE_DAY); var productPriceListId = vars.get("$field.PRODUCTPRICEID"); -var validPriceLists = newSelect("PRODUCTPRICE.PRODUCTPRICEID") - .from("PRODUCTPRICE") - .where("PRODUCTPRICE.PRICELIST", priceList) - .and("PRODUCTPRICE.PRODUCTPRICEID", productPriceListId, SqlBuilder.NOT_EQUAL()) - .and("PRODUCTPRICE.PRODUCT_ID", productId) - .and("PRODUCTPRICE.BUYSELL", buySell) - .and("PRODUCTPRICE.FROMQUANTITY", validFrom, SqlBuilder.LESS_OR_EQUAL()) - .and(newWhere("PRODUCTPRICE.VALID_TO", validFrom, SqlBuilder.GREATER_OR_EQUAL()).or("PRODUCTPRICE.VALID_TO is null")) - .arrayColumn(); +var PriceListFilter = { currency: currency, quantity: vars.get("$field.FROMQUANTITY"), priceList: priceList, buySell: buySell, dateFrom: validFrom, dateTo: validTo}; +var ProductDetails = ProductUtils.getProductDetails(productId, PriceListFilter); -var config = entities.createConfigForUpdatingRows().entity("Productprice_entity").fieldValues({"VALID_TO": oneDayPrior}).addParameter("IgnoreOnValidation_param", true); +var priceListsToPotentiallyReplace = ProductDetails.CurrentValidPriceLists; +var priceListsUpdateValidTo = []; +var priceListsUpdateValidFrom = []; +var configValidTo = entities.createConfigForUpdatingRows().entity("Productprice_entity") + .fieldValues({"VALID_TO": oneDayPrior}).addParameter("IgnoreOnValidation_param", true); +var configValidFrom = entities.createConfigForUpdatingRows().entity("Productprice_entity") + .fieldValues({"VALID_FROM": oneDayAfter}).addParameter("IgnoreOnValidation_param", true); + +for (var valPriceList in priceListsToPotentiallyReplace) +{ + var currPriceList = priceListsToPotentiallyReplace[valPriceList]; + if(currPriceList["priceListId"] != priceListId && currPriceList["priceList"] == priceList && currPriceList["buySell"] == buySell) + { + if(currPriceList["validFrom"] < validFrom && (!currPriceList["validTo"] || currPriceList["validTo"] > validFrom)) + { + priceListsUpdateValidTo.push(currPriceList["priceListId"]); + } + else if(currPriceList["validFrom"] < validTo && (!currPriceList["validTo"] || currPriceList["validTo"] > validTo)) + { + priceListsUpdateValidFrom.push(currPriceList["priceListId"]); + } + } +} -for (i = 0; i < validPriceLists.length; i++) { - - entities.updateRow(config.uid(validPriceLists[i])) +for (let i = 0; i < priceListsUpdateValidTo.length; i++) +{ + entities.updateRow(configValidTo.uid(priceListsUpdateValidTo[i])); } +for (let i = 0; i < priceListsUpdateValidFrom.length; i++) +{ + entities.updateRow(configValidFrom.uid(priceListsUpdateValidFrom[i])); +} \ No newline at end of file diff --git a/entity/SalesprojectAnalyses_entity/SalesprojectAnalyses_entity.aod b/entity/SalesprojectAnalyses_entity/SalesprojectAnalyses_entity.aod index 153d97d7307a0475640a7ed9cbb61dee68cdb2ba..1411e096a87c88026fbb8dde8a4ea90e73fdc0ec 100644 --- a/entity/SalesprojectAnalyses_entity/SalesprojectAnalyses_entity.aod +++ b/entity/SalesprojectAnalyses_entity/SalesprojectAnalyses_entity.aod @@ -91,6 +91,26 @@ <name>#PROVIDER_AGGREGATES</name> <useAggregates v="true" /> </entityProvider> + <entityField> + <name>OVERALL_PLANNING</name> + <contentType>NUMBER</contentType> + <titleProcess>%aditoprj%/entity/SalesprojectAnalyses_entity/entityfields/overall_planning/titleProcess.js</titleProcess> + <valueProcess>%aditoprj%/entity/SalesprojectAnalyses_entity/entityfields/overall_planning/valueProcess.js</valueProcess> + </entityField> + <entityField> + <name>OVERALL_FORECAST_weighted</name> + <contentType>NUMBER</contentType> + <titleProcess>%aditoprj%/entity/SalesprojectAnalyses_entity/entityfields/overall_forecast_weighted/titleProcess.js</titleProcess> + <valueProcess>%aditoprj%/entity/SalesprojectAnalyses_entity/entityfields/overall_forecast_weighted/valueProcess.js</valueProcess> + </entityField> + <entityActionField> + <name>openPlanning</name> + <onActionProcess>%aditoprj%/entity/SalesprojectAnalyses_entity/entityfields/openplanning/onActionProcess.js</onActionProcess> + </entityActionField> + <entityActionField> + <name>openForecastWeighted</name> + <onActionProcess>%aditoprj%/entity/SalesprojectAnalyses_entity/entityfields/openforecastweighted/onActionProcess.js</onActionProcess> + </entityActionField> </entityFields> <recordContainers> <jDitoRecordContainer> diff --git a/entity/SalesprojectAnalyses_entity/entityfields/my_forecast/valueProcess.js b/entity/SalesprojectAnalyses_entity/entityfields/my_forecast/valueProcess.js index b42db4e92b2f1cd8d5c2c26e12119155191db777..294c23f1c5e14e44b189997f12792b7edfa9ebd2 100644 --- a/entity/SalesprojectAnalyses_entity/entityfields/my_forecast/valueProcess.js +++ b/entity/SalesprojectAnalyses_entity/entityfields/my_forecast/valueProcess.js @@ -1,3 +1,4 @@ +import("KeywordRegistry_basic"); import("system.result"); import("system.SQLTYPES"); import("system.vars"); @@ -13,6 +14,7 @@ var forecast = newSelect("SUM(VOLUME)") .where("FORECAST.DATE_START", datetime.toDate(vars.get("$sys.date"), "yyyy"), "year(#) = ?", SQLTYPES.INTEGER) .and("OBJECTMEMBER.OBJECT_TYPE", 'Salesproject') .and("OBJECTMEMBER.CONTACT_ID", myContactId) + .and("FORECAST.KIND", $KeywordRegistry.forecastKind$forecast()) .cell(); result.string(forecast); \ No newline at end of file diff --git a/entity/SalesprojectAnalyses_entity/entityfields/openforecast/onActionProcess.js b/entity/SalesprojectAnalyses_entity/entityfields/openforecast/onActionProcess.js index a4f17e146fc1bc27447f0f53818616a254bcf6d1..9fefbbb1bd449bb98340f8e877b522be8474e48e 100644 --- a/entity/SalesprojectAnalyses_entity/entityfields/openforecast/onActionProcess.js +++ b/entity/SalesprojectAnalyses_entity/entityfields/openforecast/onActionProcess.js @@ -1,7 +1,4 @@ import("KeywordRegistry_basic"); import("system.neon"); -neon.openContext("Turnover", null, null, neon.OPERATINGSTATE_SEARCH, { - "ShowForecast_param": "true", - "ShowTurnover_param": "false" -}); +neon.openContext("Turnover", null, null, neon.OPERATINGSTATE_SEARCH, null); \ No newline at end of file diff --git a/entity/SalesprojectAnalyses_entity/entityfields/openforecastweighted/onActionProcess.js b/entity/SalesprojectAnalyses_entity/entityfields/openforecastweighted/onActionProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..9fefbbb1bd449bb98340f8e877b522be8474e48e --- /dev/null +++ b/entity/SalesprojectAnalyses_entity/entityfields/openforecastweighted/onActionProcess.js @@ -0,0 +1,4 @@ +import("KeywordRegistry_basic"); +import("system.neon"); + +neon.openContext("Turnover", null, null, neon.OPERATINGSTATE_SEARCH, null); \ No newline at end of file diff --git a/entity/SalesprojectAnalyses_entity/entityfields/openplanning/onActionProcess.js b/entity/SalesprojectAnalyses_entity/entityfields/openplanning/onActionProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..9fefbbb1bd449bb98340f8e877b522be8474e48e --- /dev/null +++ b/entity/SalesprojectAnalyses_entity/entityfields/openplanning/onActionProcess.js @@ -0,0 +1,4 @@ +import("KeywordRegistry_basic"); +import("system.neon"); + +neon.openContext("Turnover", null, null, neon.OPERATINGSTATE_SEARCH, null); \ No newline at end of file diff --git a/entity/SalesprojectAnalyses_entity/entityfields/openturnover/onActionProcess.js b/entity/SalesprojectAnalyses_entity/entityfields/openturnover/onActionProcess.js index b278ec2dce925c93c0fcccbd8689f8ad68f7c781..9fefbbb1bd449bb98340f8e877b522be8474e48e 100644 --- a/entity/SalesprojectAnalyses_entity/entityfields/openturnover/onActionProcess.js +++ b/entity/SalesprojectAnalyses_entity/entityfields/openturnover/onActionProcess.js @@ -1,7 +1,4 @@ import("KeywordRegistry_basic"); import("system.neon"); -neon.openContext("Turnover", null, null, neon.OPERATINGSTATE_SEARCH, { - "ShowForecast_param": "false", - "ShowTurnover_param": "true" -}); +neon.openContext("Turnover", null, null, neon.OPERATINGSTATE_SEARCH, null); \ No newline at end of file diff --git a/entity/SalesprojectAnalyses_entity/entityfields/overall_forecast/valueProcess.js b/entity/SalesprojectAnalyses_entity/entityfields/overall_forecast/valueProcess.js index 11bf47828e54c9717e4be2002742fd632e42f3e7..6fc6fe33750bbc53c98debb67d376a87ae05d68b 100644 --- a/entity/SalesprojectAnalyses_entity/entityfields/overall_forecast/valueProcess.js +++ b/entity/SalesprojectAnalyses_entity/entityfields/overall_forecast/valueProcess.js @@ -1,3 +1,4 @@ +import("KeywordRegistry_basic"); import("system.datetime"); import("system.db"); import("system.result"); @@ -9,6 +10,7 @@ import("system.SQLTYPES") var forecast = newSelect("sum(VOLUME)") .from("FORECAST") .where("FORECAST.DATE_START", datetime.toDate(vars.get("$sys.date"), "yyyy"), "year(#) = ?", SQLTYPES.INTEGER) + .and("FORECAST.KIND", $KeywordRegistry.forecastKind$forecast()) .cell(); result.string(forecast); \ No newline at end of file diff --git a/entity/SalesprojectAnalyses_entity/entityfields/overall_forecast_weighted/titleProcess.js b/entity/SalesprojectAnalyses_entity/entityfields/overall_forecast_weighted/titleProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..5597a3a86393359f334f257db8a9cccbdbebc391 --- /dev/null +++ b/entity/SalesprojectAnalyses_entity/entityfields/overall_forecast_weighted/titleProcess.js @@ -0,0 +1,6 @@ +import("system.vars"); +import("system.result"); +import("system.translate"); +import("system.datetime"); + +result.string(translate.text("Forecast weighted") + " " + datetime.toDate(vars.get("$sys.date"), "yyyy")); \ No newline at end of file diff --git a/entity/SalesprojectAnalyses_entity/entityfields/overall_forecast_weighted/valueProcess.js b/entity/SalesprojectAnalyses_entity/entityfields/overall_forecast_weighted/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..feeaefb3bd905925bbbc32e4ea240279862db0fc --- /dev/null +++ b/entity/SalesprojectAnalyses_entity/entityfields/overall_forecast_weighted/valueProcess.js @@ -0,0 +1,17 @@ +import("KeywordRegistry_basic"); +import("system.datetime"); +import("system.db"); +import("system.result"); +import("system.vars"); +import("Date_lib"); +import("Sql_lib"); +import("system.SQLTYPES") + +var forecast = newSelect("sum(FORECAST.VOLUME/100*SALESPROJECT.PROBABILITY)") + .from("FORECAST") + .join("SALESPROJECT", "OBJECT_TYPE = 'Salesproject' and OBJECT_ROWID = SALESPROJECTID") + .where("FORECAST.DATE_START", datetime.toDate(vars.get("$sys.date"), "yyyy"), "year(#) = ?", SQLTYPES.INTEGER) + .and("FORECAST.KIND", $KeywordRegistry.forecastKind$forecast()) + .cell(); + +result.string(forecast); \ No newline at end of file diff --git a/entity/SalesprojectAnalyses_entity/entityfields/overall_planning/titleProcess.js b/entity/SalesprojectAnalyses_entity/entityfields/overall_planning/titleProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..10c0846daeb8fbdc1eca20617a2e69ba3d9a0e59 --- /dev/null +++ b/entity/SalesprojectAnalyses_entity/entityfields/overall_planning/titleProcess.js @@ -0,0 +1,6 @@ +import("system.vars"); +import("system.result"); +import("system.translate"); +import("system.datetime"); + +result.string(translate.text("Planning") + " " + datetime.toDate(vars.get("$sys.date"), "yyyy")); \ No newline at end of file diff --git a/entity/SalesprojectAnalyses_entity/entityfields/overall_planning/valueProcess.js b/entity/SalesprojectAnalyses_entity/entityfields/overall_planning/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..090e68361372538732d3d2e9851581657afd9e63 --- /dev/null +++ b/entity/SalesprojectAnalyses_entity/entityfields/overall_planning/valueProcess.js @@ -0,0 +1,16 @@ +import("KeywordRegistry_basic"); +import("system.datetime"); +import("system.db"); +import("system.result"); +import("system.vars"); +import("Date_lib"); +import("Sql_lib"); +import("system.SQLTYPES") + +var forecast = newSelect("sum(FORECAST.VOLUME)") + .from("FORECAST") + .where("FORECAST.FORECAST_YEAR", datetime.toDate(vars.get("$sys.date"), "yyyy")) + .and("FORECAST.KIND", $KeywordRegistry.forecastKind$planning()) + .cell(); + +result.string(forecast); \ No newline at end of file diff --git a/entity/SalesprojectAnalyses_entity/entityfields/overall_turnover/valueProcess.js b/entity/SalesprojectAnalyses_entity/entityfields/overall_turnover/valueProcess.js index fb9181d479ded05d017fa498a37642d570c9e70f..9e90122f8d0c2cfaf927bb627e9f0852d0314dc6 100644 --- a/entity/SalesprojectAnalyses_entity/entityfields/overall_turnover/valueProcess.js +++ b/entity/SalesprojectAnalyses_entity/entityfields/overall_turnover/valueProcess.js @@ -4,7 +4,10 @@ import("system.vars"); import("system.datetime"); import("Sql_lib"); -var turnover = newSelect("sum(NET + VAT)") +var sqlHelper = new SqlMaskingUtils(); + + +var turnover = newSelect(sqlHelper.cast("sum(NET + VAT)", SQLTYPES.INTEGER)) .from("SALESORDER") .where("SALESORDER.SALESORDERDATE", datetime.toDate(vars.get("$sys.date"), "yyyy"), "year(#) = ?", SQLTYPES.INTEGER) .cell(); diff --git a/entity/SalesprojectConversionRate_entity/SalesprojectConversionRate_entity.aod b/entity/SalesprojectConversionRate_entity/SalesprojectConversionRate_entity.aod index 834661f182666bfb72d744ba2a9e67ae4185900f..cc131683a1feb211ede261efd5b24770ed159b43 100644 --- a/entity/SalesprojectConversionRate_entity/SalesprojectConversionRate_entity.aod +++ b/entity/SalesprojectConversionRate_entity/SalesprojectConversionRate_entity.aod @@ -10,6 +10,14 @@ <entityFields> <entityProvider> <name>#PROVIDER</name> + <dependencies> + <entityDependency> + <name>34de2519-ae79-4092-9f10-29727239804d</name> + <entityName>Organisation_entity</entityName> + <fieldName>conversionrates</fieldName> + <isConsumer v="false" /> + </entityDependency> + </dependencies> </entityProvider> <entityField> <name>UID</name> diff --git a/entity/SalesprojectConversionRate_entity/recordcontainers/jdito/contentProcess.js b/entity/SalesprojectConversionRate_entity/recordcontainers/jdito/contentProcess.js index d178c9b6a5223ada92f5560f27deb405e65543e9..d089bda4986c95444506a3c9a76a783579a71d9e 100644 --- a/entity/SalesprojectConversionRate_entity/recordcontainers/jdito/contentProcess.js +++ b/entity/SalesprojectConversionRate_entity/recordcontainers/jdito/contentProcess.js @@ -62,4 +62,4 @@ else sql.select(["AB_KEYWORD_ENTRY.AB_KEYWORD_ENTRYID", "AB_KEYWORD_ENTRY.KEYID", "AB_KEYWORD_ENTRY.TITLE"]) .orderBy("AB_KEYWORD_ENTRY.SORTING"); result.object(sql.table()); -} \ No newline at end of file +} diff --git a/entity/SalesprojectConversionRate_entity/recordcontainers/jdito/rowCountProcess.js b/entity/SalesprojectConversionRate_entity/recordcontainers/jdito/rowCountProcess.js index 60aed2227590efc2bded1bbfc77689af0c89e0fc..b118d35605a04e93448f89038190d574a59a8b58 100644 --- a/entity/SalesprojectConversionRate_entity/recordcontainers/jdito/rowCountProcess.js +++ b/entity/SalesprojectConversionRate_entity/recordcontainers/jdito/rowCountProcess.js @@ -1,3 +1,4 @@ +import("Observation_lib"); import("Keyword_lib"); import("system.result"); import("JditoFilter_lib"); diff --git a/entity/SalesprojectMilestone_entity/SalesprojectMilestone_entity.aod b/entity/SalesprojectMilestone_entity/SalesprojectMilestone_entity.aod index 9b33104d183410e5faf5ea980bc1ced20093efd5..e8af3acf65ceae7f227545812be139a5e11565fc 100644 --- a/entity/SalesprojectMilestone_entity/SalesprojectMilestone_entity.aod +++ b/entity/SalesprojectMilestone_entity/SalesprojectMilestone_entity.aod @@ -139,10 +139,6 @@ <name>dateEndGantt</name> <valueProcess>%aditoprj%/entity/SalesprojectMilestone_entity/entityfields/dateendgantt/valueProcess.js</valueProcess> </entityField> - <entityField> - <name>valueLongName</name> - <valueProcess>%aditoprj%/entity/SalesprojectMilestone_entity/entityfields/valuelongname/valueProcess.js</valueProcess> - </entityField> <entityProvider> <name>#PROVIDER_AGGREGATES</name> <useAggregates v="true" /> diff --git a/entity/SalesprojectMilestone_entity/entityfields/valuelongname/valueProcess.js b/entity/SalesprojectMilestone_entity/entityfields/valuelongname/valueProcess.js deleted file mode 100644 index b153ca0c6bd48838fbd12bef7a2cb820d3f05e19..0000000000000000000000000000000000000000 --- a/entity/SalesprojectMilestone_entity/entityfields/valuelongname/valueProcess.js +++ /dev/null @@ -1,8 +0,0 @@ -import("system.translate"); -import("system.vars"); -import("system.result"); -import("Keyword_lib") - -var keywordAttr = new KeywordAttribute(vars.get("$field.KIND"), "longName", vars.get("$field.MILESTONEVALUE.displayValue")) - -result.string(translate.text(keywordAttr.getValue(vars.get("$field.MILESTONEVALUE")))) \ No newline at end of file diff --git a/entity/SalesprojectPhaseDefinition_entity/SalesprojectPhaseDefinition_entity.aod b/entity/SalesprojectPhaseDefinition_entity/SalesprojectPhaseDefinition_entity.aod index 29cb770c0a049830e8884a6a41d1dcd3c5e5290b..a237428017ad212e1fd457d7982bb1bd5e3d35d9 100644 --- a/entity/SalesprojectPhaseDefinition_entity/SalesprojectPhaseDefinition_entity.aod +++ b/entity/SalesprojectPhaseDefinition_entity/SalesprojectPhaseDefinition_entity.aod @@ -60,13 +60,6 @@ </entityDependency> </dependencies> </entityProvider> - <entityFieldGroup> - <name>SalesprojectPhaseFullname</name> - <valueProcess>%aditoprj%/entity/SalesprojectPhaseDefinition_entity/entityfields/salesprojectphasefullname/valueProcess.js</valueProcess> - <fields> - <element>PHASE</element> - </fields> - </entityFieldGroup> <entityConsumer> <name>ChecklistEntries</name> <dependency> diff --git a/entity/SalesprojectPhaseDefinition_entity/entityfields/salesprojectphasefullname/valueProcess.js b/entity/SalesprojectPhaseDefinition_entity/entityfields/salesprojectphasefullname/valueProcess.js deleted file mode 100644 index 75192dbbe5da1c412c31fb25d1849b2b6572b455..0000000000000000000000000000000000000000 --- a/entity/SalesprojectPhaseDefinition_entity/entityfields/salesprojectphasefullname/valueProcess.js +++ /dev/null @@ -1,36 +0,0 @@ -import("system.result"); -import("system.vars"); -import("KeywordRegistry_basic"); - - -var salesprojectPhase = vars.get("$field.PHASE"); -var longForm = ""; - -switch(salesprojectPhase){ - case $KeywordRegistry.salesprojectPhase$mal(): - longForm = "Marketing Accepted Lead"; - break; - case $KeywordRegistry.salesprojectPhase$mql(): - longForm = "Marketing Qualified Lead"; - break; - case $KeywordRegistry.salesprojectPhase$nego(): - longForm = "Negotiation"; - break; - case $KeywordRegistry.salesprojectPhase$nqc(): - longForm = "Non Qualified Contact"; - break; - case $KeywordRegistry.salesprojectPhase$offer(): - longForm = "Offer"; - break; - case $KeywordRegistry.salesprojectPhase$sal(): - longForm = "Sales Accepted Lead"; - break; - case $KeywordRegistry.salesprojectPhase$sqo(): - longForm = "Sales Qualified Offer"; - break; - case $KeywordRegistry.salesprojectPhase$mqc(): - longForm = "Marketing Qualified Contact"; - break; -} - -result.string(longForm); diff --git a/entity/Salesproject_entity/Salesproject_entity.aod b/entity/Salesproject_entity/Salesproject_entity.aod index d567ac3a36efcd8d474b14981641eb0eda498497..c55710d2e8104b1c34dadf75455035043648e687 100644 --- a/entity/Salesproject_entity/Salesproject_entity.aod +++ b/entity/Salesproject_entity/Salesproject_entity.aod @@ -868,6 +868,20 @@ <parentField>VOLUME</parentField> <title>Volume</title> </entityAggregateField> + <entityConsumer> + <name>Turnovers</name> + <dependency> + <name>dependency</name> + <entityName>Turnover_entity</entityName> + <fieldName>DynamicTurnover</fieldName> + </dependency> + <children> + <entityParameter> + <name>SalesprojectIdDynamicChart_param</name> + <valueProcess>%aditoprj%/entity/Salesproject_entity/entityfields/turnovers/children/salesprojectiddynamicchart_param/valueProcess.js</valueProcess> + </entityParameter> + </children> + </entityConsumer> </entityFields> <recordContainers> <dbRecordContainer> @@ -1106,7 +1120,7 @@ </filterExtension> <filterExtension> <name>Competitor_filterExtension</name> - <title>Competitor</title> + <title>Competitions/Competitor</title> <contentType>TEXT</contentType> <filterValuesProcess>%aditoprj%/entity/Salesproject_entity/recordcontainers/db/filterextensions/competitor_filterextension/filterValuesProcess.js</filterValuesProcess> <filterConditionProcess>%aditoprj%/entity/Salesproject_entity/recordcontainers/db/filterextensions/competitor_filterextension/filterConditionProcess.js</filterConditionProcess> diff --git a/entity/Salesproject_entity/entityfields/turnovers/children/salesprojectiddynamicchart_param/valueProcess.js b/entity/Salesproject_entity/entityfields/turnovers/children/salesprojectiddynamicchart_param/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..2b119ebfa1944164fd2a1cb645511740bec9015e --- /dev/null +++ b/entity/Salesproject_entity/entityfields/turnovers/children/salesprojectiddynamicchart_param/valueProcess.js @@ -0,0 +1,4 @@ +import("system.vars"); +import("system.result"); + +result.string(vars.get("$field.SALESPROJECTID")); \ No newline at end of file diff --git a/entity/SupportTicket_entity/SupportTicket_entity.aod b/entity/SupportTicket_entity/SupportTicket_entity.aod index 18411b1b108aadcd8107ce353aed8febb31b5fc8..a82e8b8219ed27ae068e6c3630c6b37cc1deaa28 100644 --- a/entity/SupportTicket_entity/SupportTicket_entity.aod +++ b/entity/SupportTicket_entity/SupportTicket_entity.aod @@ -4,6 +4,7 @@ <title>Support Ticket</title> <majorModelMode>DISTRIBUTED</majorModelMode> <documentation>%aditoprj%/entity/SupportTicket_entity/documentation.adoc</documentation> + <grantDeleteProcess>%aditoprj%/entity/SupportTicket_entity/grantDeleteProcess.js</grantDeleteProcess> <contentTitleProcess>%aditoprj%/entity/SupportTicket_entity/contentTitleProcess.js</contentTitleProcess> <contentDescriptionProcess>%aditoprj%/entity/SupportTicket_entity/contentDescriptionProcess.js</contentDescriptionProcess> <afterUiInit>%aditoprj%/entity/SupportTicket_entity/afterUiInit.js</afterUiInit> diff --git a/entity/SupportTicket_entity/grantDeleteProcess.js b/entity/SupportTicket_entity/grantDeleteProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..1300a4f0d525e6083e9f8dc6df280f802ef813c2 --- /dev/null +++ b/entity/SupportTicket_entity/grantDeleteProcess.js @@ -0,0 +1,10 @@ +import("system.vars"); +import("system.result"); + +var uid = vars.get("$sys.uid"); + +var canDelete = new HasLinkedObjectTester() + .andNoEntityRows("Document_entity", "Documents", {AssignmentTable_param : "TICKET", AssignmentRowId_param : uid}) //Documents + .validate(); + +result.string(canDelete); \ No newline at end of file diff --git a/entity/Turnover_entity/Turnover_entity.aod b/entity/Turnover_entity/Turnover_entity.aod index 5949a1679dc99db0137406414b81cb4b22c7d8e8..e61b1a3a96ce5cd498aabf87c946dd0a0ca9785c 100644 --- a/entity/Turnover_entity/Turnover_entity.aod +++ b/entity/Turnover_entity/Turnover_entity.aod @@ -1,18 +1,18 @@ <?xml version="1.0" encoding="UTF-8"?> <entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.18" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.18"> <name>Turnover_entity</name> - <title>Turnover</title> + <title>Sales forecast</title> <majorModelMode>DISTRIBUTED</majorModelMode> <documentation>%aditoprj%/entity/Turnover_entity/documentation.adoc</documentation> <siblings> <element>Forecast_entity</element> </siblings> + <initFilterProcess>%aditoprj%/entity/Turnover_entity/initFilterProcess.js</initFilterProcess> <iconId>VAADIN:CHART</iconId> - <recordContainer>jdito</recordContainer> + <recordContainer>jditoDynamicMultiDataChart</recordContainer> <entityFields> <entityProvider> <name>#PROVIDER</name> - <recordContainer>jdito</recordContainer> </entityProvider> <entityField> <name>UID</name> @@ -54,6 +54,7 @@ <entityProvider> <name>FilteredTurnovers</name> <documentation>%aditoprj%/entity/Turnover_entity/entityfields/filteredturnovers/documentation.adoc</documentation> + <recordContainer>jdito</recordContainer> <dependencies> <entityDependency> <name>51106aba-bd82-4ac5-8de6-fc56d53c6117</name> @@ -117,11 +118,125 @@ <name>#PROVIDER_AGGREGATES</name> <useAggregates v="true" /> </entityProvider> + <entityField> + <name>GroupField</name> + <title>Year</title> + </entityField> + <entityField> + <name>FORECAST_VOLUME</name> + <title>Forecast</title> + <contentType>NUMBER</contentType> + </entityField> + <entityField> + <name>PLANNING_VOLUME</name> + <title>Planning</title> + <contentType>NUMBER</contentType> + </entityField> + <entityField> + <name>TURNOVER_VOLUME</name> + <title>Turnover</title> + <contentType>NUMBER</contentType> + </entityField> + <entityAggregateField> + <name>ForecastVolume_aggregate</name> + <parentField>FORECAST_VOLUME</parentField> + </entityAggregateField> + <entityAggregateField> + <name>TurnoverVolume_aggregate</name> + <parentField>TURNOVER_VOLUME</parentField> + </entityAggregateField> + <entityAggregateField> + <name>PlanningVolume_aggregate</name> + <parentField>PLANNING_VOLUME</parentField> + </entityAggregateField> + <entityField> + <name>ORGANISATION_ID</name> + <title>Organisation</title> + <consumer>Organisations</consumer> + <groupable v="true" /> + </entityField> + <entityConsumer> + <name>Organisations</name> + <refreshParent v="false" /> + <dependency> + <name>dependency</name> + <entityName>Organisation_entity</entityName> + <fieldName>Organisations</fieldName> + </dependency> + </entityConsumer> + <entityField> + <name>TURNOVER_YEAR</name> + <title>Year</title> + <contentType>NUMBER</contentType> + <groupable v="true" /> + </entityField> + <entityField> + <name>emptyField</name> + <contentType>NUMBER</contentType> + </entityField> + <entityField> + <name>FORECAST_VOLUME_weighted</name> + <title>Forecast weighted</title> + <contentType>NUMBER</contentType> + </entityField> + <entityAggregateField> + <name>ForecastVolumeWeighted_aggregate</name> + <parentField>FORECAST_VOLUME_weighted</parentField> + </entityAggregateField> + <entityProvider> + <name>DynamicTurnover</name> + <dependencies> + <entityDependency> + <name>d20b815b-0c36-4e7c-b114-9a8bfba77c96</name> + <entityName>Organisation_entity</entityName> + <fieldName>Turnovers</fieldName> + <isConsumer v="false" /> + </entityDependency> + <entityDependency> + <name>341bcc89-313f-43eb-94ef-b9a934fe7f1e</name> + <entityName>Salesproject_entity</entityName> + <fieldName>Turnovers</fieldName> + <isConsumer v="false" /> + </entityDependency> + </dependencies> + <children> + <entityParameter> + <name>MaxYear_param</name> + <expose v="false" /> + </entityParameter> + <entityParameter> + <name>ShowTurnover_param</name> + <expose v="false" /> + </entityParameter> + <entityParameter> + <name>ShowForecast_param</name> + <expose v="false" /> + </entityParameter> + <entityParameter> + <name>SalesprojectId_param</name> + <expose v="false" /> + </entityParameter> + <entityParameter> + <name>YearCountToShow_param</name> + <expose v="false" /> + </entityParameter> + </children> + </entityProvider> + <entityParameter> + <name>ContactId_param</name> + <expose v="true" /> + </entityParameter> + <entityParameter> + <name>SalesprojectIdDynamicChart_param</name> + <expose v="true" /> + </entityParameter> </entityFields> <recordContainers> <jDitoRecordContainer> <name>jdito</name> <jDitoRecordAlias>Data_alias</jDitoRecordAlias> + <isFilterable v="true" /> + <isGroupable v="true" /> <contentProcess>%aditoprj%/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js</contentProcess> <recordFieldMappings> <jDitoRecordFieldMapping> @@ -141,5 +256,167 @@ </jDitoRecordFieldMapping> </recordFieldMappings> </jDitoRecordContainer> + <jDitoRecordContainer> + <name>jditoDynamicMultiDataChart</name> + <jDitoRecordAlias>Data_alias</jDitoRecordAlias> + <isPageable v="true" /> + <isFilterable v="true" /> + <isGroupable v="true" /> + <contentProcess>%aditoprj%/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/contentProcess.js</contentProcess> + <rowCountProcess>%aditoprj%/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/rowCountProcess.js</rowCountProcess> + <description></description> + <recordFieldMappings> + <jDitoRecordFieldMapping> + <name>UID.value</name> + </jDitoRecordFieldMapping> + <jDitoRecordFieldMapping> + <name>GroupField.value</name> + </jDitoRecordFieldMapping> + <jDitoRecordFieldMapping> + <name>ORGANISATION_ID.value</name> + <isFilterable v="true" /> + </jDitoRecordFieldMapping> + <jDitoRecordFieldMapping> + <name>TURNOVER_YEAR.value</name> + <isFilterable v="true" /> + </jDitoRecordFieldMapping> + <jDitoRecordFieldMapping> + <name>PLANNING_VOLUME.value</name> + </jDitoRecordFieldMapping> + <jDitoRecordFieldMapping> + <name>FORECAST_VOLUME.value</name> + </jDitoRecordFieldMapping> + <jDitoRecordFieldMapping> + <name>TURNOVER_VOLUME.value</name> + </jDitoRecordFieldMapping> + <jDitoRecordFieldMapping> + <name>FORECAST_VOLUME_weighted.value</name> + </jDitoRecordFieldMapping> + </recordFieldMappings> + <aggregateFieldMappings> + <jDitoRecordFieldMapping> + <name>PlanningVolume_aggregate.value</name> + </jDitoRecordFieldMapping> + <jDitoRecordFieldMapping> + <name>ForecastVolume_aggregate.value</name> + </jDitoRecordFieldMapping> + <jDitoRecordFieldMapping> + <name>TurnoverVolume_aggregate.value</name> + </jDitoRecordFieldMapping> + <jDitoRecordFieldMapping> + <name>ForecastVolumeWeighted_aggregate.value</name> + </jDitoRecordFieldMapping> + </aggregateFieldMappings> + <filterExtensions> + <filterExtension> + <name>Groupcode_filter</name> + <title>Product group</title> + <contentType>TEXT</contentType> + <filterValuesProcess>%aditoprj%/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/groupcode_filter/filterValuesProcess.js</filterValuesProcess> + <isGroupable v="true" /> + <filtertype>BASIC</filtertype> + </filterExtension> + <filterExtension> + <name>Month_filter</name> + <title>Month</title> + <contentType>TEXT</contentType> + <filterValuesProcess>%aditoprj%/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/month_filter/filterValuesProcess.js</filterValuesProcess> + <isFilterable v="true" /> + <isGroupable v="true" /> + <filtertype>BASIC</filtertype> + </filterExtension> + <filterExtensionSet> + <name>ClassificationGroup_filter</name> + <filterFieldsProcess>%aditoprj%/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/classificationgroup_filter/filterFieldsProcess.js</filterFieldsProcess> + <filterValuesProcess>%aditoprj%/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/classificationgroup_filter/filterValuesProcess.js</filterValuesProcess> + <isGroupable v="false" /> + <filtertype>EXTENDED</filtertype> + </filterExtensionSet> + <filterExtensionSet> + <name>ClassificationType_filter</name> + <filterFieldsProcess>%aditoprj%/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/classificationtype_filter/filterFieldsProcess.js</filterFieldsProcess> + <filterValuesProcess>%aditoprj%/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/classificationtype_filter/filterValuesProcess.js</filterValuesProcess> + <isGroupable v="false" /> + <filtertype>EXTENDED</filtertype> + </filterExtensionSet> + <filterExtension> + <name>OrgCountry_filter</name> + <title>Organisation Country</title> + <contentType>TEXT</contentType> + <filterValuesProcess>%aditoprj%/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgcountry_filter/filterValuesProcess.js</filterValuesProcess> + <filtertype>BASIC</filtertype> + </filterExtension> + <filterExtension> + <name>OrgAddress_filter</name> + <title>Organisation Address</title> + <contentType>TEXT</contentType> + <filtertype>BASIC</filtertype> + </filterExtension> + <filterExtension> + <name>OrgDistrict_filter</name> + <title>Organisation District</title> + <contentType>TEXT</contentType> + <filtertype>BASIC</filtertype> + </filterExtension> + <filterExtension> + <name>OrgState_filter</name> + <title>Organisation State</title> + <contentType>TEXT</contentType> + <filtertype>BASIC</filtertype> + </filterExtension> + <filterExtension> + <name>OrgZip_filter</name> + <title>Organisation Zip</title> + <contentType>TEXT</contentType> + <filtertype>BASIC</filtertype> + </filterExtension> + <filterExtension> + <name>OrgCity_filter</name> + <title>Organisation City</title> + <contentType>TEXT</contentType> + <filtertype>BASIC</filtertype> + </filterExtension> + <filterExtension> + <name>OrgRegion_filter</name> + <title>Organisation Region</title> + <contentType>TEXT</contentType> + <filtertype>BASIC</filtertype> + </filterExtension> + <filterExtension> + <name>OrgType_filter</name> + <title>Organisation Type</title> + <contentType>TEXT</contentType> + <filterValuesProcess>%aditoprj%/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgtype_filter/filterValuesProcess.js</filterValuesProcess> + <filtertype>BASIC</filtertype> + </filterExtension> + <filterExtension> + <name>OrgClassification_filter</name> + <title>Organisation Classification</title> + <contentType>TEXT</contentType> + <filterValuesProcess>%aditoprj%/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgclassification_filter/filterValuesProcess.js</filterValuesProcess> + <filtertype>BASIC</filtertype> + </filterExtension> + <filterExtension> + <name>OrgLanguage_filter</name> + <title>Organisation Language</title> + <contentType>TEXT</contentType> + <filterValuesProcess>%aditoprj%/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orglanguage_filter/filterValuesProcess.js</filterValuesProcess> + <filtertype>BASIC</filtertype> + </filterExtension> + <filterExtensionSet> + <name>OrgAttribute_filter</name> + <filterFieldsProcess>%aditoprj%/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgattribute_filter/filterFieldsProcess.js</filterFieldsProcess> + <filterValuesProcess>%aditoprj%/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgattribute_filter/filterValuesProcess.js</filterValuesProcess> + <filtertype>EXTENDED</filtertype> + </filterExtensionSet> + <filterExtension> + <name>Salesproject_filter</name> + <title>Salesproject</title> + <contentType>TEXT</contentType> + <filterValuesProcess>%aditoprj%/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/salesproject_filter/filterValuesProcess.js</filterValuesProcess> + <filtertype>BASIC</filtertype> + </filterExtension> + </filterExtensions> + </jDitoRecordContainer> </recordContainers> </entity> diff --git a/entity/Turnover_entity/documentation.adoc b/entity/Turnover_entity/documentation.adoc index c369458ae651df5cf5b04e813fc3cbe93c66a6e4..4198a9d4a298a1caad40904d697560266da8b2df 100644 --- a/entity/Turnover_entity/documentation.adoc +++ b/entity/Turnover_entity/documentation.adoc @@ -1,6 +1,45 @@ = Turnover_entity +General explanation of MultiDataChart: For technical docu see the contentProcess of the jdito-record container of this entityThis entity provides charts to display the Turnover. This chart can show any data in a cumulative way: * It loads the most specific data (e.g. Productgroups) and calculates the layers above (e.g. Productgroups -> Months -> years) - * And then it shows the most top layer (years) at the top. If you click on it, it drills down to the more specific layer (Months / Productgroups) \ No newline at end of file + * And then it shows the most top layer (years) at the top. If you click on it, it drills down to the more specific layer (Months / Productgroups) + + +General explanation of DynamicMultiDataChart: +The fields FORECAST_VOLUME, GroupField, MONTH, ORGANISATION_ID, PLANNING_VOLUME, TURNOVER_VOLUME and TURNOVER_YEAR are only used +for the jditoDynamicMultiDataChart-RecordContainer. +To be able to group this RecordContainer the properties isPageable and isGroupable must be set and the rowCountProcess must be filled. +If you specify these settings for a jditoRecordContainer and you want to group them, certain things have to be considered +when they are returned in the contentProcess. +If grouping is selected, the array returned in the contentProcess must have the following structure: +[[NumberOfUnderlyingRecords, UID, ValueGrouping, AggregateField1, AggregateField2, AggregateFieldx]]. +The first position of the array must always be the number of underlying records. +After that always comes the UID and after that the value of the grouping. +These fields must be specified like this. After that, any number of aggregate fields can be specified. +Therefore, if you specify more than two fields in the recordFieldMappings, the rest will be ignored. +That means, if a grouping exists, then only the fields UID and GroupField in the recordFieldMappings +and all fields in the aggregateFieldMappings are considered. +If no grouping exists, the fields in aggregateFieldMappings are ignored and all fields in recordFieldMappings are used. +So if no grouping is selected, the array returned must match the recordFieldMappings. +To get a lookup when filtering on the company, a field was created and no FilterExtension was used. +The year was also not created as a FilterExtension, because it must be stored as a default grouping in the view +and no FilterExtension can be selected there. + +Extend filter: +To add a new FilterExtension the following steps have to be done: +- Create new FilterExtension +- check isFilterable +- In the Turnover_lib extend the object in the function TurnoverDynamicChart.getFilterMapping(). + Structure of the object is described in the function and can be done analog to the existing filter fields. + +Expand grouping: +If you want to group by another field the following steps have to be done: +- Create new FilterExtension +- check isGroupable +- In the Turnover_lib extend the object in the function TurnoverDynamicChart.getFilterMapping(). + Structure of the object is described in the function and can be extended analog to the existing ones. +- In Turnover_lib the switch case must be extended in the function TurnoverDynamicChart.prototype.getGroupFieldDisplayValue(). + The titles used in the case are defined in the grouping object under the key fieldName. + diff --git a/entity/Turnover_entity/initFilterProcess.js b/entity/Turnover_entity/initFilterProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..b7905f93bee903ee6fcf57f098aab5f024c94796 --- /dev/null +++ b/entity/Turnover_entity/initFilterProcess.js @@ -0,0 +1,53 @@ +import("Sql_lib"); +import("Contact_lib"); +import("system.neon"); +import("system.vars"); +import("Keyword_lib"); +import("KeywordRegistry_basic"); +import("system.result"); + +var contactId = vars.get("$param.ContactId_param"); +var salesprojectId = vars.get("$param.SalesprojectIdDynamicChart_param"); + +if(contactId || salesprojectId) +{ + var filter = { + type: "group", + operator: "AND", + childs: [{ + type: "row", + name: null, + operator: "EQUAL", + contenttype: "TEXT", + key: null, + value: null + }] + }; + + if(contactId) + { + filter.childs[0].name = "ORGANISATION_ID"; + filter.childs[0].key = contactId; + filter.childs[0].value = OrganisationUtils.getNameByContactId(contactId); + } + else if(salesprojectId) + { + var salesprojectTitle = newSelect("PROJECTCODE, PROJECTTITLE") + .from("SALESPROJECT") + .where("SALESPROJECT.SALESPROJECTID", salesprojectId) + .arrayColumn(); + salesprojectTitle = salesprojectTitle[0] + " | " + salesprojectTitle[1]; + + filter.childs[0].name = "#EXTENSION.Salesproject_filter.Salesproject_filter#TEXT"; + filter.childs[0].key = salesprojectId; + filter.childs[0].value = salesprojectTitle; + } + + res = JSON.stringify(filter); + + if (res) + { + result.string(res); + } +} + diff --git a/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js b/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js index fd0e3bd7a6f2c7518d54d02f9351a842f3d25d9b..ad9b4204f6e6c67c2ca3a1dd03883f10f801dba9 100644 --- a/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js +++ b/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js @@ -206,4 +206,4 @@ function _addCount(pKeys, pValue) { countData[key].count += parseFloat(pValue); } } -} \ No newline at end of file +} diff --git a/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/contentProcess.js b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/contentProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..80bd839c8ebb81497dfd61842259cfd26ce3071e --- /dev/null +++ b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/contentProcess.js @@ -0,0 +1,41 @@ +import("system.SQLTYPES"); +import("Contact_lib"); +import("KeywordRegistry_basic"); +import("Keyword_lib"); +import("system.datetime"); +import("JditoFilter_lib"); +import("system.vars"); +import("system.result"); +import("Sql_lib"); +import("Turnover_lib"); + + + +var filter = vars.get("$local.filters"); +var dynamicChart = new TurnoverDynamicChart(filter); +var fromSql; + +if( vars.exists("$local.grouped")) +{ + + var groupedField = vars.get("$local.grouped"); + dynamicChart.groupedField = groupedField; + + fromSql = dynamicChart.getFromSql(); + + var sqlHelper = new SqlMaskingUtils(); + + + var select = newSelect("count(*), results.uid, results.groupField, sum(results.sum_planning), " + + "sum(results.sum_forecast), sum(results.sum_turnover), sum(results.sum_forecast_weighted) ") + .from("(" + fromSql.toString() + ") results") + .groupBy("results.uid, results.groupField"); + + var dataResult = select.table(); + result.object(dataResult); +} +else +{ + fromSql = dynamicChart.getFromSql(); + result.object(fromSql.table()); +} \ No newline at end of file diff --git a/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/classificationgroup_filter/filterFieldsProcess.js b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/classificationgroup_filter/filterFieldsProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..2a00071eedf9ebb4dbce585f63f92e2839f57ae7 --- /dev/null +++ b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/classificationgroup_filter/filterFieldsProcess.js @@ -0,0 +1,6 @@ +import("system.result"); +import("ClassificationFilter_lib"); + +var fields = ClassificationGroupFilterUtils.makeFilterFields("Organisation"); + +result.string(fields); \ No newline at end of file diff --git a/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/classificationgroup_filter/filterValuesProcess.js b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/classificationgroup_filter/filterValuesProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..1b8a9b50976e699ff763ca7856c501df123ca054 --- /dev/null +++ b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/classificationgroup_filter/filterValuesProcess.js @@ -0,0 +1,6 @@ +import("system.result"); +import("ClassificationFilter_lib"); + +var values = ClassificationGroupFilterUtils.makeFilterValues(); + +result.object(values); \ No newline at end of file diff --git a/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/classificationtype_filter/filterFieldsProcess.js b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/classificationtype_filter/filterFieldsProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..973583180e1c02048afa5b4ca6641e8c13ac2bf9 --- /dev/null +++ b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/classificationtype_filter/filterFieldsProcess.js @@ -0,0 +1,6 @@ +import("system.vars"); +import("system.result"); +import("ClassificationFilter_lib"); + +var fields = ClassificationTypeFilterUtils.getFilterFields("Organisation"); +result.string(fields); \ No newline at end of file diff --git a/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/classificationtype_filter/filterValuesProcess.js b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/classificationtype_filter/filterValuesProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..488499064a9bdd69b939b834b9a8c642bae09484 --- /dev/null +++ b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/classificationtype_filter/filterValuesProcess.js @@ -0,0 +1,5 @@ +import("system.result"); +import("ClassificationFilter_lib"); + +var values = ClassificationTypeFilterUtils.makeFilterFields(); +result.object(values); \ No newline at end of file diff --git a/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/groupcode_filter/filterValuesProcess.js b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/groupcode_filter/filterValuesProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..e36045723141095186b689258098409dedadeb49 --- /dev/null +++ b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/groupcode_filter/filterValuesProcess.js @@ -0,0 +1,12 @@ +import("KeywordRegistry_basic"); +import("system.result"); +import("Keyword_lib"); +import("Sql_lib"); + + + +result.object(newSelect("KEYID, " + KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.productGroupcode(), "AB_KEYWORD_ENTRY.KEYID")) + .from("AB_KEYWORD_ENTRY") + .join("AB_KEYWORD_CATEGORY", "AB_KEYWORD_CATEGORY_ID = AB_KEYWORD_CATEGORYID") + .where("AB_KEYWORD_CATEGORY.NAME", $KeywordRegistry.productGroupcode()) + .table()); \ No newline at end of file diff --git a/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/month_filter/filterValuesProcess.js b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/month_filter/filterValuesProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..8dd51ba80ba9d3230e7316be92bd79a03edb8abd --- /dev/null +++ b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/month_filter/filterValuesProcess.js @@ -0,0 +1,17 @@ +import("system.result"); +import("system.translate"); + +result.object([ + ["1", translate.text("January")], + ["2", translate.text("February")], + ["3", translate.text("March")], + ["4", translate.text("April")], + ["5", translate.text("May")], + ["6", translate.text("June")], + ["7", translate.text("July")], + ["8", translate.text("August")], + ["9", translate.text("September")], + ["10", translate.text("October")], + ["11", translate.text("November")], + ["12", translate.text("December")] +]); \ No newline at end of file diff --git a/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgattribute_filter/filterFieldsProcess.js b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgattribute_filter/filterFieldsProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..105c59dca1f529f109664b425b83d8de93041f00 --- /dev/null +++ b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgattribute_filter/filterFieldsProcess.js @@ -0,0 +1,5 @@ +import("system.result"); +import("AttributeFilter_lib"); + +var fields = AttributeFilterExtensionMaker.makeFilterFields("Organisation"); +result.string(fields); \ No newline at end of file diff --git a/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgattribute_filter/filterValuesProcess.js b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgattribute_filter/filterValuesProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..942b0a0495a179f9c25d19330bb8cd59c5563ec0 --- /dev/null +++ b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgattribute_filter/filterValuesProcess.js @@ -0,0 +1,5 @@ +import("system.result"); +import("AttributeFilter_lib"); + +var values = AttributeFilterExtensionMaker.makeFilterValues(); +result.object(values); \ No newline at end of file diff --git a/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgclassification_filter/filterValuesProcess.js b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgclassification_filter/filterValuesProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..b8ebaf03a411092da7ddd03166632c4820f9b3a4 --- /dev/null +++ b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgclassification_filter/filterValuesProcess.js @@ -0,0 +1,9 @@ +import("system.result"); +import("Sql_lib"); + +var resultData = newSelect("distinct CLASSIFICATIONVALUE, CLASSIFICATIONVALUE") +.from("CLASSIFICATIONSTORAGE") +.orderBy("CLASSIFICATIONVALUE") +.table(); + +result.object(resultData); \ No newline at end of file diff --git a/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgcountry_filter/filterValuesProcess.js b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgcountry_filter/filterValuesProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..0a0ee5818385a190191326efad26abc14e018e48 --- /dev/null +++ b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgcountry_filter/filterValuesProcess.js @@ -0,0 +1,15 @@ +import("system.result"); +import("system.entities"); + +var entityConfig = entities.createConfigForLoadingRows() + .entity("Countries_Entity") + .fields(["ISO2", "#CONTENTTITLE"]); + +var entityRow = entities.getRows(entityConfig); + +entityRow = entityRow.map(function(row) +{ + return [row["ISO2"], row["#CONTENTTITLE"]]; +}); + +result.object(entityRow); \ No newline at end of file diff --git a/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orglanguage_filter/filterValuesProcess.js b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orglanguage_filter/filterValuesProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..a8b5a7d0f10dcd75c459519259381d8dc0184955 --- /dev/null +++ b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orglanguage_filter/filterValuesProcess.js @@ -0,0 +1,15 @@ +import("system.result"); +import("system.entities"); + +var entityConfig = entities.createConfigForLoadingRows() + .entity("Language_entity") + .fields(["ISO3", "#CONTENTTITLE"]); + +var entityRow = entities.getRows(entityConfig); + +entityRow = entityRow.map(function(row) +{ + return [row["ISO3"], row["#CONTENTTITLE"]]; +}); + +result.object(entityRow); \ No newline at end of file diff --git a/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgtype_filter/filterValuesProcess.js b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgtype_filter/filterValuesProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..4742b4b09934c6676734a4f3d40e40124d37a259 --- /dev/null +++ b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/orgtype_filter/filterValuesProcess.js @@ -0,0 +1,17 @@ +import("KeywordRegistry_basic"); +import("system.result"); +import("system.entities"); + +var entityConfig = entities.createConfigForLoadingRows() + .entity("KeywordEntry_entity") + .fields(["KEYID", "TITLE_TRANSLATED"]) + .addParameter("ContainerName_param", $KeywordRegistry.organisationType()); + +var entityRow = entities.getRows(entityConfig); + +entityRow = entityRow.map(function(row) +{ + return [row["KEYID"], row["TITLE_TRANSLATED"]]; +}); + +result.object(entityRow); \ No newline at end of file diff --git a/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/salesproject_filter/filterValuesProcess.js b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/salesproject_filter/filterValuesProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..9391c3e568a387b764bf9c2755be6aae9b6ef8c5 --- /dev/null +++ b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/filterextensions/salesproject_filter/filterValuesProcess.js @@ -0,0 +1,13 @@ +import("Sql_lib"); +import("system.result"); + +var sqlHelper = new SqlMaskingUtils(); +var dataResult = newSelect("SALESPROJECTID, PROJECTCODE, PROJECTTITLE") + .from("SALESPROJECT") + .table(); + +dataResult = dataResult.map(function(row) +{ + return [row[0], row[1] + " | " + row[2]]; +}); +result.object(dataResult); \ No newline at end of file diff --git a/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/rowCountProcess.js b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/rowCountProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..4dda5fa2a6d783c577d9c0397464fbebccf441f7 --- /dev/null +++ b/entity/Turnover_entity/recordcontainers/jditodynamicmultidatachart/rowCountProcess.js @@ -0,0 +1,39 @@ +import("system.SQLTYPES"); +import("Contact_lib"); +import("KeywordRegistry_basic"); +import("Keyword_lib"); +import("system.datetime"); +import("JditoFilter_lib"); +import("system.vars"); +import("system.result"); +import("Sql_lib"); +import("Turnover_lib"); + +var filter = vars.get("$local.filters"); +var dynamicChart = new TurnoverDynamicChart(filter); +var fromSql; + +if( vars.exists("$local.grouped")) +{ + + var groupedField = vars.get("$local.grouped"); + dynamicChart.groupedField = groupedField; + + fromSql = dynamicChart.getFromSql(); + + var sqlHelper = new SqlMaskingUtils(); + + var select = newSelect("count(*), results.uid, results.groupField, sum(results.sum_planning), " + + "sum(results.sum_forecast), sum(results.sum_turnover), sum(results.sum_forecast_weighted) ") + .from("(" + fromSql.toString() + ") results") + .groupBy("results.uid, results.groupField"); + + var dataResult = select.table(); + + result.string(dataResult.length); +} +else +{ + fromSql = dynamicChart.getFromSql(); + result.string(fromSql.table().length); +} \ No newline at end of file diff --git a/entity/VisitPlanEntry_entity/entityfields/entityactiongroup/children/newappointment/onActionProcess.js b/entity/VisitPlanEntry_entity/entityfields/entityactiongroup/children/newappointment/onActionProcess.js index b760e1613d9594960cabd2067bade94a03105560..6de5e67211d4a10723765b058e83b58c8cdf6530 100644 --- a/entity/VisitPlanEntry_entity/entityfields/entityactiongroup/children/newappointment/onActionProcess.js +++ b/entity/VisitPlanEntry_entity/entityfields/entityactiongroup/children/newappointment/onActionProcess.js @@ -25,12 +25,10 @@ var summary = translate.text("Site visit") + " || " + fullName; var description = fullName; var standardMail = CommUtil.getStandardMail(selectionRowData[0].CONTACT_ID); -var startTime = selectionRowData[0].BEGIN_TIME; -var endTime = selectionRowData[0].END_TIME; -var duration = eMath.subInt(endTime, startTime); -var entryDate = datetime.toLocaleDate(selectionRowData[0].ENTRYDATE, "dd-MM-yyyy"); -startTime = entryDate + " " + datetime.toLocaleDate(selectionRowData[0].BEGIN_TIME, "HH:mm:ss.S"); -startTime = datetime.toLong(startTime, "dd-MM-yyyy HH:mm:ss.S", "UTC"); // #1076044 set tz to prevent time gaps. +//creates an js date object with the current utc time and adds the appointment begin/end time. +//necessary for CalendarUtil.createEntry() +var start = new Date(datetime.today(vars.get("$sys.timezone"))+Number(selectionRowData[0].BEGIN_TIME)); +var end = new Date(datetime.today(vars.get("$sys.timezone"))+Number(selectionRowData[0].END_TIME)); var links = [ { @@ -44,8 +42,8 @@ var links = [ ]; var params = { - "Entry_param": JSON.stringify(CalendarUtil.createEntry(summary, description, links, undefined, undefined, Date(Date.toExponential(startTime)), - Date(Date.toExponential(endTime)), undefined, undefined, undefined, [standardMail], + "Entry_param": JSON.stringify(CalendarUtil.createEntry(summary, description, links, undefined, undefined, start, + end, undefined, undefined, undefined, [standardMail], undefined, undefined, undefined)) }; diff --git a/entity/VisitPlanEntry_entity/entityfields/entityactiongroup/children/newappointment/stateProcess.js b/entity/VisitPlanEntry_entity/entityfields/entityactiongroup/children/newappointment/stateProcess.js index 3f986eb99cdd8c56ea85788bc2ab0f547f172b25..181e70bbeca24bebbcad6595818e49b2e55484ad 100644 --- a/entity/VisitPlanEntry_entity/entityfields/entityactiongroup/children/newappointment/stateProcess.js +++ b/entity/VisitPlanEntry_entity/entityfields/entityactiongroup/children/newappointment/stateProcess.js @@ -2,9 +2,14 @@ import("system.logging"); import("system.result"); import("system.vars"); import("system.neon"); +import("Util_lib"); -if (vars.get("$field.ISGROUP") == "false" && vars.get("$sys.selectionRows") != "" +if (Utils.toBoolean(vars.get("$field.ISGROUP")) && (vars.get("$field.STATUS") == "VISITSTATUSAPPPLANED" - || vars.get("$field.STATUS_APPOINTMENT") == "VISITSTATUSAPPOINTMENTCONFIRMED ")) - result.string(neon.COMPONENTSTATE_DISABLED); + || vars.get("$field.STATUS_APPOINTMENT") == "VISITSTATUSAPPOINTMENTCONFIRMED ") + || Utils.isNullOrEmpty(vars.get("$sys.selectionRows")) + || Utils.isNullOrEmpty(vars.get("$field.PARENT_ID"))) +{ + result.string(neon.COMPONENTSTATE_DISABLED); +} diff --git a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod index a147fbceb5578dc7cc49da5e3b1f6488d401059e..7a23534af0c82d7804e1c40ff68e48726a0aee77 100644 --- a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod +++ b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod @@ -8062,7 +8062,7 @@ <key>by sorting</key> </entry> <entry> - <key>Starts the serverprocess manually, which will recalculate all (potentially) outdated classifications. Use this after changes to the configuration of classifications.</key> + <key>Starts the server process manually, which will recalculate all (potentially) outdated classifications. This process should be executed after changes to the classification configuration.</key> </entry> <entry> <key>Recalculate Classifications</key> @@ -8071,7 +8071,7 @@ <key>Are you sure you want to recalculate all classifications using the current classificationgradings? This can take some time, since ALL classifications will get freshly calculated and updated if needed.</key> </entry> <entry> - <key>Starts the serverprocess manually, which will recalculate all classifications from scratch. Only do this after e.g importing data from elsewhere where the outdated flag couldn't been set correctly. Since this can take some time.</key> + <key>Starts the server process manually, which will recalculate all classifications from scratch. This process should only be executed after importing data from elsewhere, where the outdated flag couldn't be set correctly, since this can take some time.</key> </entry> <entry> <key>EML files can't be edited here. You can download, edit and reupload the template to change the content.</key> @@ -8166,6 +8166,261 @@ <entry> <key>Value must be an integer</key> </entry> + <entry> + <key>Buyer</key> + </entry> + <entry> + <key>Internal responsible</key> + </entry> + <entry> + <key>Initiator</key> + </entry> + <entry> + <key>Internal Sales</key> + </entry> + <entry> + <key>Influencer</key> + </entry> + <entry> + <key>Set not completed</key> + </entry> + <entry> + <key>Add planning to organisations</key> + </entry> + <entry> + <key>Planning</key> + </entry> + <entry> + <key>Create planning</key> + </entry> + <entry> + <key>The combination of organisation, product group and year already exists.</key> + </entry> + <entry> + <key>Change responsible</key> + </entry> + <entry> + <key>Plannings</key> + </entry> + <entry> + <key>Save</key> + </entry> + <entry> + <key>%0 status was/were changed</key> + </entry> + <entry> + <key>Change status</key> + </entry> + <entry> + <key>%0 out of %1 records were changed to \"%2\".\n %3 record/s could not be updated.</key> + </entry> + <entry> + <key>%0 responsilbe/s was/were changed</key> + </entry> + <entry> + <key>Already existing</key> + </entry> + <entry> + <key>Forecast weighted</key> + </entry> + <entry> + <key>Turnover, Forecast, Planning</key> + </entry> + <entry> + <key>Unchanged plan values</key> + </entry> + <entry> + <key>New created plan values</key> + </entry> + <entry> + <key>Fixed</key> + </entry> + <entry> + <key>Sales forecast</key> + </entry> + <entry> + <key>Planning/Forecast/Turnover</key> + </entry> + <entry> + <key>Organisation Zip</key> + </entry> + <entry> + <key>Organisation City</key> + </entry> + <entry> + <key>Organisation Classification</key> + </entry> + <entry> + <key>Organisation District</key> + </entry> + <entry> + <key>Organisation Type</key> + </entry> + <entry> + <key>Organisation Language</key> + </entry> + <entry> + <key>Organisation Region</key> + </entry> + <entry> + <key>Organisation Address</key> + </entry> + <entry> + <key>Organisation Country</key> + </entry> + <entry> + <key>Organisation State</key> + </entry> + <entry> + <key>Shows the global Covid Cases in a Table</key> + </entry> + <entry> + <key>Buyer</key> + </entry> + <entry> + <key>Internal responsible</key> + </entry> + <entry> + <key>Global Cases Table</key> + </entry> + <entry> + <key>Global Cases</key> + </entry> + <entry> + <key>Initiator</key> + </entry> + <entry> + <key>New Cases</key> + </entry> + <entry> + <key>Internal Sales</key> + </entry> + <entry> + <key>Influencer</key> + </entry> + <entry> + <key>Shows the new daily Covid Cases</key> + </entry> + <entry> + <key>Shows the global Covid Cases in a Table</key> + </entry> + <entry> + <key>Buyer</key> + </entry> + <entry> + <key>Internal responsible</key> + </entry> + <entry> + <key>Global Cases Table</key> + </entry> + <entry> + <key>Global Cases</key> + </entry> + <entry> + <key>Initiator</key> + </entry> + <entry> + <key>New Cases</key> + </entry> + <entry> + <key>Internal Sales</key> + </entry> + <entry> + <key>Influencer</key> + </entry> + <entry> + <key>Shows the new daily Covid Cases</key> + </entry> + <entry> + <key>Event Data</key> + </entry> + <entry> + <key>On Site</key> + </entry> + <entry> + <key>Event Type</key> + </entry> + <entry> + <key>New child product</key> + </entry> + <entry> + <key>Communication: Link</key> + </entry> + <entry> + <key>Event Begin</key> + </entry> + <entry> + <key>Communication: Phone</key> + </entry> + <entry> + <key>Event</key> + </entry> + <entry> + <key>other</key> + </entry> + <entry> + <key>Communication: Mail</key> + </entry> + <entry> + <key>Vacation</key> + </entry> + <entry> + <key>Event End</key> + </entry> + <entry> + <key>On site</key> + </entry> + <entry> + <key>Event Data</key> + </entry> + <entry> + <key>On Site</key> + </entry> + <entry> + <key>Event Type</key> + </entry> + <entry> + <key>New child product</key> + </entry> + <entry> + <key>Communication: Link</key> + </entry> + <entry> + <key>Event Begin</key> + </entry> + <entry> + <key>Buying center and internal project team</key> + </entry> + <entry> + <key>Communication: Phone</key> + </entry> + <entry> + <key>Event</key> + </entry> + <entry> + <key>other</key> + </entry> + <entry> + <key>Communication: Mail</key> + </entry> + <entry> + <key>Vacation</key> + </entry> + <entry> + <key>Event End</key> + </entry> + <entry> + <key>On site</key> + </entry> + <entry> + <key>${SALESPROJECT_PROSPECT}</key> + </entry> + <entry> + <key>${SALESPROJECT_LEAD}</key> + </entry> + <entry> + <key>${SALESPROJECT_CONTACT}</key> + </entry> </keyValueMap> <font name="Dialog" style="0" size="11" /> <sqlModels> diff --git a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod index e58f48ed810e3e924239be23397a809edc0303bc..e452e7706338b32c9653d260c13643d774291c76 100644 --- a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod +++ b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod @@ -10,6 +10,10 @@ <key>Event End</key> <value>Veranstaltungs Ende</value> </entry> + <entry> + <key>%0 out of %1 records were changed to \"%2\".\n %3 record/s could not be updated.</key> + <value>%0 von %1 Datensätze wurden auf \"%2\" geändert.\n%3 Datensätze konnten nicht akutualisiert werden.</value> + </entry> <entry> <key>Value is too big, the maximum is %0</key> <value>Wert ist zu groß, das Maximum ist %0</value> @@ -27,14 +31,58 @@ <value>Objekt nicht gefunden </value> </entry> + <entry> + <key>Change responsible</key> + <value>Verantwortlichen wechseln</value> + </entry> + <entry> + <key>Already existing</key> + <value>Bereits existierende</value> + </entry> <entry> <key>discounted Vat</key> <value>Rbt. Mehrwertssteuer</value> </entry> + <entry> + <key>Organisation Country</key> + <value>Firma Land</value> + </entry> + <entry> + <key>Planning</key> + <value>Planung</value> + </entry> + <entry> + <key>Add planning to organisations</key> + <value>Planung der Firma hinzufügen</value> + </entry> + <entry> + <key>New created plan values</key> + <value>Neu erstellte Planwerte</value> + </entry> <entry> <key>Illegal Parent Operator in buildFilterObj-Function:</key> <value>Übergebener Operator ungültig in Funktion "buildFilterObj"</value> </entry> + <entry> + <key>Organisation Language</key> + <value>Firma Sprache</value> + </entry> + <entry> + <key>The combination of organisation, product group and year already exists.</key> + <value>Die Kombination aus Firma, Produktgruppe und Jahr existiert bereits.</value> + </entry> + <entry> + <key>Title (translated)</key> + <value>Titel (übersetzt)</value> + </entry> + <entry> + <key>Organisation State</key> + <value>Firma Staat</value> + </entry> + <entry> + <key>Organisation Zip</key> + <value>Firma PLZ</value> + </entry> <entry> <key>EML files can't be edited here. You can download, edit and reupload the template to change the content.</key> <value>Das Bearbeiten von EML-Dateien ist hier nicht möglich. Um den Inhalt zu ändern, können Sie die Vorlage herunterladen, bearbeiten und erneut hochladen.</value> @@ -43,18 +91,46 @@ <key>Value must be an integer</key> <value>Wert muss eine Ganzzahl sein</value> </entry> + <entry> + <key>Organisation Address</key> + <value>Firma Straße</value> + </entry> + <entry> + <key>Organisation Classification</key> + <value>Firma Klassifizierung</value> + </entry> <entry> <key>Checklist entries</key> <value>Checklisteneinträge</value> </entry> + <entry> + <key>Organisation Region</key> + <value>Firma Kreis</value> + </entry> + <entry> + <key>Organisation Type</key> + <value>Firma Typ</value> + </entry> + <entry> + <key>Organisation City</key> + <value>Firma Ort</value> + </entry> <entry> <key>Project team: \"Project manager\"</key> <value>Projektteam: \"Projektmanager\"</value> </entry> + <entry> + <key>Organisation District</key> + <value>Firma Gebiet</value> + </entry> <entry> <key>Checklist entry</key> <value>Checklisteneintrag</value> </entry> + <entry> + <key>Create planning</key> + <value>Planung erstellen</value> + </entry> <entry> <key>descending</key> <value>absteigend</value> @@ -423,6 +499,10 @@ <key>My Contacts</key> <value>Meine Kontakte</value> </entry> + <entry> + <key>%0 status was/were changed</key> + <value>%0 Status wurde/n geändert</value> + </entry> <entry> <key>Workflow definition</key> <value>Workflowdefinition</value> @@ -439,6 +519,10 @@ <key>${ORDER_CANCELLED}</key> <value>Storniert</value> </entry> + <entry> + <key>Plannings</key> + <value>Planungen</value> + </entry> <entry> <key>CONFIRMED</key> <value>Gelesen</value> @@ -459,6 +543,10 @@ <key>Deletion</key> <value>Löschung</value> </entry> + <entry> + <key>%0 responsilbe/s was/were changed</key> + <value>%0 Verantwortliche/r wurde/n geändert</value> + </entry> <entry> <key>Please check if the following fields are filled correctly</key> <value>Bitte überprüfen Sie ob folgende Felder richtig befüllt sind</value> @@ -1711,6 +1799,10 @@ <key>Checked</key> <value>Geprüft</value> </entry> + <entry> + <key>Save</key> + <value>Speichern</value> + </entry> <entry> <key>Sent</key> <value>Versendet</value> @@ -4047,6 +4139,10 @@ <entry> <key>25%</key> </entry> + <entry> + <key>Sales forecast</key> + <value>Umsatzprognose</value> + </entry> <entry> <key>50%</key> </entry> @@ -4657,7 +4753,7 @@ </entry> <entry> <key>Locked</key> - <value>Gelocked</value> + <value>Gesperrt </value> </entry> <entry> <key>Timetracking Id</key> @@ -5974,6 +6070,10 @@ <key>Away travel</key> <value>Fernreisen</value> </entry> + <entry> + <key>Unchanged plan values</key> + <value>Unveränderte Planwerte</value> + </entry> <entry> <key>Partial calculation</key> <value>Teilberechnung</value> @@ -7229,6 +7329,10 @@ <key>Offer exists</key> <value>Angebot existiert</value> </entry> + <entry> + <key>Fixed</key> + <value>Fixiert</value> + </entry> <entry> <key>Salesproject member Id</key> <value>VertriebsprojektsteilnehmerId</value> @@ -7257,6 +7361,10 @@ <key>Ignore series</key> <value>Serie ignorieren</value> </entry> + <entry> + <key>Change status</key> + <value>Status wechseln</value> + </entry> <entry> <key>Organisation name</key> <value>Firmenname</value> @@ -9663,12 +9771,12 @@ Bitte Datumseingabe prüfen</value> <value>Klassifizierungen neuberechnen</value> </entry> <entry> - <key>Starts the serverprocess manually, which will recalculate all (potentially) outdated classifications. Use this after changes to the configuration of classifications.</key> - <value>Startet den Serverprozess Manuell. Berechnet alle (potenziell) veralteten Klassifizierungen. Benutze dies nach Änderungen an den Klassifizierungseinstellungen.</value> + <key>Starts the server process manually, which will recalculate all (potentially) outdated classifications. This process should be executed after changes to the classification configuration.</key> + <value>Startet den Serverprozess manuell, wodurch alle (möglicherweise) veralteten Klassifizierungen neu berechnet werden. Dieser Prozess sollte nach Änderungen an der Klassifizierungskonfiguration ausgeführt werden.</value> </entry> <entry> - <key>Starts the serverprocess manually, which will recalculate all classifications from scratch. Only do this after e.g importing data from elsewhere where the outdated flag couldn't been set correctly. Since this can take some time.</key> - <value>Startet den Serverprozess Manuell. Berechnet alle Klassifizierungen neu. Benutze dies nur nach z.B dem Importieren von Daten von ausserhalb des Systems bei denen der outdated flag nciht richtig gesetzt wurde, da dieser Durchlauf länger dauen kann</value> + <key>Starts the server process manually, which will recalculate all classifications from scratch. This process should only be executed after importing data from elsewhere, where the outdated flag couldn't be set correctly, since this can take some time.</key> + <value>Startet den Serverprozess manuell, wodurch alle Klassifizierungen von Grund auf neu berechnet werden. Dieser Vorgang sollte nur ausgeführt werden, nachdem externe Daten importiert wurden, an denen der outdated flag nicht richtig gesetzt werden konnte, da dies einige Zeit dauern kann.</value> </entry> <entry> <key>Are you sure you want to recalculate all classifications using the current classificationgradings? This can take some time, since ALL classifications will get freshly calculated and updated if needed.</key> @@ -10092,6 +10200,10 @@ Bitte Datumseingabe prüfen</value> <key>#login</key> <value>Login Token</value> </entry> + <entry> + <key>Forecast weighted</key> + <value>Prognose gewichtet</value> + </entry> <entry> <key>Rechnungsbetrag</key> </entry> @@ -10147,6 +10259,10 @@ Bitte Datumseingabe prüfen</value> <entry> <key>Channel Name</key> </entry> + <entry> + <key>Planning/Forecast/Turnover</key> + <value>Planung/Prognose/Umsatz</value> + </entry> <entry> <key>Sales Project Phases</key> </entry> @@ -10789,6 +10905,34 @@ Bitte Datumseingabe prüfen</value> <key>Internal responsible</key> <value>Intern: Gebietsverantwortlich</value> </entry> + <entry> + <key>Invalid attribute count</key> + <value>Unzulässige Attributanzahl</value> + </entry> + <entry> + <key>Set not completed</key> + <value>Nicht erledigt setzen</value> + </entry> + <entry> + <key>There already exists a %0 price with the same type of pricelist, quantity and currency in the defined range.</key> + <value>Es gibt bereits einen %0 Preis mit der selben Preisliste, Menge und Einheit im festgeleten Bereich.</value> + </entry> + <entry> + <key>${SALESPROJECT_PROSPECT}</key> + <value>Prospect</value> + </entry> + <entry> + <key>${SALESPROJECT_LEAD}</key> + <value>Lead</value> + </entry> + <entry> + <key>${SALESPROJECT_CONTACT}</key> + <value>Contact</value> + </entry> + <entry> + <key>Competitions/Competitor</key> + <value>Mitbewerber/Wettbewerber</value> + </entry> </keyValueMap> <font name="Dialog" style="0" size="11" /> </language> diff --git a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod index bd409fc49c98727cb2474505aa5ed41cd131d72e..bdbd5793b38747eeaea0d20b38e287484ea5c9cd 100644 --- a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod +++ b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod @@ -8247,6 +8247,192 @@ <entry> <key>Value must be an integer</key> </entry> + <entry> + <key>Buyer</key> + </entry> + <entry> + <key>Internal responsible</key> + </entry> + <entry> + <key>Initiator</key> + </entry> + <entry> + <key>Internal Sales</key> + </entry> + <entry> + <key>Influencer</key> + </entry> + <entry> + <key>Set not completed</key> + </entry> + <entry> + <key>Add planning to organisations</key> + </entry> + <entry> + <key>Planning</key> + </entry> + <entry> + <key>Create planning</key> + </entry> + <entry> + <key>The combination of organisation, product group and year already exists.</key> + </entry> + <entry> + <key>Change responsible</key> + </entry> + <entry> + <key>Plannings</key> + </entry> + <entry> + <key>Save</key> + </entry> + <entry> + <key>%0 status was/were changed</key> + </entry> + <entry> + <key>Change status</key> + </entry> + <entry> + <key>%0 out of %1 records were changed to \"%2\".\n %3 record/s could not be updated.</key> + </entry> + <entry> + <key>%0 responsilbe/s was/were changed</key> + </entry> + <entry> + <key>Already existing</key> + </entry> + <entry> + <key>Forecast weighted</key> + </entry> + <entry> + <key>Turnover, Forecast, Planning</key> + </entry> + <entry> + <key>Unchanged plan values</key> + </entry> + <entry> + <key>New created plan values</key> + </entry> + <entry> + <key>Fixed</key> + </entry> + <entry> + <key>Sales forecast</key> + </entry> + <entry> + <key>Planning/Forecast/Turnover</key> + </entry> + <entry> + <key>Organisation Zip</key> + </entry> + <entry> + <key>Organisation City</key> + </entry> + <entry> + <key>Organisation Classification</key> + </entry> + <entry> + <key>Organisation District</key> + </entry> + <entry> + <key>Organisation Type</key> + </entry> + <entry> + <key>Organisation Language</key> + </entry> + <entry> + <key>Organisation Region</key> + </entry> + <entry> + <key>Organisation Address</key> + </entry> + <entry> + <key>Organisation Country</key> + </entry> + <entry> + <key>Organisation State</key> + </entry> + <entry> + <key>Shows the global Covid Cases in a Table</key> + </entry> + <entry> + <key>Buyer</key> + </entry> + <entry> + <key>Internal responsible</key> + </entry> + <entry> + <key>Global Cases Table</key> + </entry> + <entry> + <key>Global Cases</key> + </entry> + <entry> + <key>Initiator</key> + </entry> + <entry> + <key>New Cases</key> + </entry> + <entry> + <key>Internal Sales</key> + </entry> + <entry> + <key>Influencer</key> + </entry> + <entry> + <key>Shows the new daily Covid Cases</key> + </entry> + <entry> + <key>On Site</key> + </entry> + <entry> + <key>New child product</key> + </entry> + <entry> + <key>Communication: Link</key> + </entry> + <entry> + <key>Communication: Phone</key> + </entry> + <entry> + <key>Communication: Mail</key> + </entry> + <entry> + <key>Vacation</key> + </entry> + <entry> + <key>On Site</key> + </entry> + <entry> + <key>New child product</key> + </entry> + <entry> + <key>Communication: Link</key> + </entry> + <entry> + <key>Buying center and internal project team</key> + </entry> + <entry> + <key>Communication: Phone</key> + </entry> + <entry> + <key>Communication: Mail</key> + </entry> + <entry> + <key>Vacation</key> + </entry> + <entry> + <key>${SALESPROJECT_PROSPECT}</key> + <value>Prospect</value> + </entry> + <entry> + <key>${SALESPROJECT_LEAD}</key> + <value>Lead</value> + </entry> + <entry> + <key>${SALESPROJECT_CONTACT}</key> + <value>Contact</value> + </entry> </keyValueMap> <font name="Dialog" style="0" size="11" /> </language> diff --git a/neonContext/Orderitem/Orderitem.aod b/neonContext/Orderitem/Orderitem.aod index 7f83b02e3c96c59afcef3fcd95509ab6950e035e..7317e72be684374f98fb8797603cf4d6a3ec1819 100644 --- a/neonContext/Orderitem/Orderitem.aod +++ b/neonContext/Orderitem/Orderitem.aod @@ -4,6 +4,7 @@ <majorModelMode>DISTRIBUTED</majorModelMode> <filterView>OrderitemFilter_view</filterView> <editView>OrderitemEdit_view</editView> + <previewView>OrderitemPreview_view</previewView> <entity>Orderitem_entity</entity> <references> <neonViewReference> diff --git a/neonContext/Organisation/Organisation.aod b/neonContext/Organisation/Organisation.aod index 87f1786ecea40ec5b4903385bde15598fa3f9489..f3e985e7707b9387eb3b2ff38bf51ae6cb2a2bc2 100644 --- a/neonContext/Organisation/Organisation.aod +++ b/neonContext/Organisation/Organisation.aod @@ -67,5 +67,9 @@ <name>0b052872-d6b4-41ac-ad0b-580575893e1b</name> <view>OrganisationLesserNoiseTable_view</view> </neonViewReference> + <neonViewReference> + <name>d9091127-4ad7-46bb-ba5f-988aa84c52b5</name> + <view>OrganisationPlanningTurnoverChart_view</view> + </neonViewReference> </references> </neonContext> diff --git a/neonContext/OrganisationsMultiEdit/OrganisationsMultiEdit.aod b/neonContext/OrganisationsMultiEdit/OrganisationsMultiEdit.aod new file mode 100644 index 0000000000000000000000000000000000000000..6861aac96fd603b6795210ea41fa7369f4a70cb0 --- /dev/null +++ b/neonContext/OrganisationsMultiEdit/OrganisationsMultiEdit.aod @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.1"> + <name>OrganisationsMultiEdit</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <entity>OrganisationsMultiEdit_entity</entity> + <references> + <neonViewReference> + <name>c42551af-ccfd-4a13-a795-8acbf4fac82e</name> + <view>OrganisationsMultiEdit_view</view> + </neonViewReference> + </references> +</neonContext> diff --git a/neonContext/Planning/Planning.aod b/neonContext/Planning/Planning.aod new file mode 100644 index 0000000000000000000000000000000000000000..387221c361acd05e48468ec96feb73ea5bdb25d4 --- /dev/null +++ b/neonContext/Planning/Planning.aod @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.1"> + <name>Planning</name> + <title>Planning</title> + <majorModelMode>DISTRIBUTED</majorModelMode> + <icon>VAADIN:MONEY</icon> + <filterView>PlanningFilter_view</filterView> + <editView>PlanningEdit_view</editView> + <lookupView>PlanningFilter_view</lookupView> + <entity>Planning_entity</entity> + <references> + <neonViewReference> + <name>6751a02c-2614-41aa-bb69-c471184b77be</name> + <view>PlanningFilter_view</view> + </neonViewReference> + <neonViewReference> + <name>360005f9-0f0a-41dc-b7c8-3f8b2e947d98</name> + <view>PlanningEdit_view</view> + </neonViewReference> + <neonViewReference> + <name>87ed8e38-7591-404e-b57a-b1268db6a777</name> + </neonViewReference> + <neonViewReference> + <name>1a7e2b28-65ee-4620-88b7-c8f38b69d2c5</name> + </neonViewReference> + <neonViewReference> + <name>e12da517-cd75-4665-a4cd-c9a2643dc0c1</name> + <view>PlanningOrganisationFilter_view</view> + </neonViewReference> + <neonViewReference> + <name>d7be79c9-fc8b-4b3a-98ee-2c2b93766bbb</name> + <view>PlanningMultiEditOverlay_view</view> + </neonViewReference> + </references> +</neonContext> diff --git a/neonContext/PlanningAddToOrganisations/PlanningAddToOrganisations.aod b/neonContext/PlanningAddToOrganisations/PlanningAddToOrganisations.aod new file mode 100644 index 0000000000000000000000000000000000000000..8b02af1a9e8b8e991e4b17c72042323d156e1f64 --- /dev/null +++ b/neonContext/PlanningAddToOrganisations/PlanningAddToOrganisations.aod @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.1"> + <name>PlanningAddToOrganisations</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <filterView>PlanningAddToOrganisations_view</filterView> + <editView>PlanningAddToOrganisations_view</editView> + <entity>PlanningAddToOrganisations_entity</entity> + <references> + <neonViewReference> + <name>0583b894-7d37-41af-923d-1e25c41b375b</name> + <view>PlanningAddToOrganisations_view</view> + </neonViewReference> + <neonViewReference> + <name>97d65606-07b2-4597-bff0-02353b1b77a3</name> + <view>PlanningAddToOrganisationOverlay_view</view> + </neonViewReference> + <neonViewReference> + <name>956879d0-f8ea-480d-b5c2-aa01cd35b331</name> + <view>PlanningAddToOrganisationsExistingPlannings_view</view> + </neonViewReference> + <neonViewReference> + <name>7dd047c4-f672-4eeb-b0de-6a80b4014ee6</name> + <view>PlanningAddToOrganisationsNewPlannings_view</view> + </neonViewReference> + </references> +</neonContext> diff --git a/neonContext/PlanningChangeStatusAndResponsible/PlanningChangeStatusAndResponsible.aod b/neonContext/PlanningChangeStatusAndResponsible/PlanningChangeStatusAndResponsible.aod new file mode 100644 index 0000000000000000000000000000000000000000..3e7cb8a0d19a3ff6bf077bc94f7d7ccf186794df --- /dev/null +++ b/neonContext/PlanningChangeStatusAndResponsible/PlanningChangeStatusAndResponsible.aod @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.1"> + <name>PlanningChangeStatusAndResponsible</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <entity>PlanningChangeStatusAndResponsible_entity</entity> + <references> + <neonViewReference> + <name>aded48b1-7b16-4ef8-a7b8-0679846d888f</name> + <view>PlanningChangeStatus_view</view> + </neonViewReference> + <neonViewReference> + <name>519a7687-db30-4f6b-83f3-f228e96ef19a</name> + <view>PlanningChangeResponsible_view</view> + </neonViewReference> + </references> +</neonContext> diff --git a/neonContext/Salesproject/Salesproject.aod b/neonContext/Salesproject/Salesproject.aod index 92def56f1a35869471d27551d86b8e0b6362c374..9b93a07f221f0722a90b60601aeac8e4032fefa2 100644 --- a/neonContext/Salesproject/Salesproject.aod +++ b/neonContext/Salesproject/Salesproject.aod @@ -80,5 +80,9 @@ <name>407d9b32-c379-428b-b1e1-d92a820971fd</name> <view>SalesprojectPreviewMultiple_view</view> </neonViewReference> + <neonViewReference> + <name>c860de14-8ebe-438f-92c3-cba727a15690</name> + <view>SalesprojectAttribute_view</view> + </neonViewReference> </references> </neonContext> diff --git a/neonContext/Turnover/Turnover.aod b/neonContext/Turnover/Turnover.aod index 1973598c84fcc7f4092662bd6f72493b54047005..b1da34ccaf6098ce619d7dc851f91219b4710972 100644 --- a/neonContext/Turnover/Turnover.aod +++ b/neonContext/Turnover/Turnover.aod @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.1"> <name>Turnover</name> - <title>Turnover</title> + <title>Sales forecast</title> <majorModelMode>DISTRIBUTED</majorModelMode> - <filterView>TurnoverChart_view</filterView> + <filterView>TurnoverDynamicMultiDataChart_view</filterView> <entity>Turnover_entity</entity> <references> <neonViewReference> @@ -18,5 +18,9 @@ <name>29a44f69-d9a5-4916-8242-4ba470506d92</name> <view>TurnoverChartForcastDrawer_view</view> </neonViewReference> + <neonViewReference> + <name>d54348be-db01-4f89-ad3f-99ef35fa7e32</name> + <view>TurnoverDynamicMultiDataChart_view</view> + </neonViewReference> </references> </neonContext> diff --git a/neonView/KeywordEntryFilter_view/KeywordEntryFilter_view.aod b/neonView/KeywordEntryFilter_view/KeywordEntryFilter_view.aod index efd8bf78f7c8605f00de542b3b0eddc416218d00..cd94859acb44e7dab7270bf26ae412f7611608c8 100644 --- a/neonView/KeywordEntryFilter_view/KeywordEntryFilter_view.aod +++ b/neonView/KeywordEntryFilter_view/KeywordEntryFilter_view.aod @@ -31,6 +31,10 @@ <name>aa5612b4-997e-4f0f-8fb1-91e18e32051d</name> <entityField>TITLE</entityField> </neonTreeTableColumn> + <neonTreeTableColumn> + <name>e56e22ec-258f-4438-85a9-940cffd2a3ec</name> + <entityField>TITLE_TRANSLATED</entityField> + </neonTreeTableColumn> <neonTreeTableColumn> <name>eea7891c-81bd-4c1b-9d9b-fd81c6bc49b2</name> <entityField>ISACTIVE</entityField> @@ -65,6 +69,10 @@ <name>42d1d488-8739-4101-9aee-087dcc34d51a</name> <entityField>TITLE</entityField> </neonTableColumn> + <neonTableColumn> + <name>92e1fe00-be4a-47fe-8d85-27576942bde3</name> + <entityField>TITLE_TRANSLATED</entityField> + </neonTableColumn> <neonTableColumn> <name>f4241fa3-907e-4542-b01d-6efa95ac4d0f</name> <entityField>ISACTIVE</entityField> diff --git a/neonView/OrganisationMain_view/OrganisationMain_view.aod b/neonView/OrganisationMain_view/OrganisationMain_view.aod index 53376c617bb547c3fcc917315abe17927716bd90..67ceac6a5cdafeb611c83c06583b634263c4b921 100644 --- a/neonView/OrganisationMain_view/OrganisationMain_view.aod +++ b/neonView/OrganisationMain_view/OrganisationMain_view.aod @@ -65,6 +65,11 @@ <entityField>Documents</entityField> <view>DocumentFilter_view</view> </neonViewReference> + <neonViewReference> + <name>b6e7ad76-511f-46c4-b47c-b2e56825331b</name> + <entityField>#ENTITY</entityField> + <view>OrganisationPlanningTurnoverChart_view</view> + </neonViewReference> <neonViewReference> <name>0686ad7e-8dc7-4b10-9df2-bf066ae3a310</name> <entityField>LogHistories</entityField> diff --git a/neonView/OrganisationPlanningTurnoverChart_view/OrganisationPlanningTurnoverChart_view.aod b/neonView/OrganisationPlanningTurnoverChart_view/OrganisationPlanningTurnoverChart_view.aod new file mode 100644 index 0000000000000000000000000000000000000000..a506d247ca30f7379f96bba44cdf5f858459578e --- /dev/null +++ b/neonView/OrganisationPlanningTurnoverChart_view/OrganisationPlanningTurnoverChart_view.aod @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.8"> + <name>OrganisationPlanningTurnoverChart_view</name> + <title>Planning</title> + <majorModelMode>DISTRIBUTED</majorModelMode> + <layout> + <boxLayout> + <name>layout</name> + </boxLayout> + </layout> + <children> + <neonViewReference> + <name>b830d3cf-fffc-408d-89c1-5e4219311045</name> + <entityField>Plannings</entityField> + <view>PlanningOrganisationFilter_view</view> + </neonViewReference> + <neonViewReference> + <name>95d12cd1-8b3d-42b0-b9b3-363a9599e555</name> + <entityField>Turnovers</entityField> + <view>TurnoverDynamicMultiDataChart_view</view> + </neonViewReference> + </children> +</neonView> diff --git a/neonView/OrganisationsMultiEdit_view/OrganisationsMultiEdit_view.aod b/neonView/OrganisationsMultiEdit_view/OrganisationsMultiEdit_view.aod new file mode 100644 index 0000000000000000000000000000000000000000..e016aea0aa032a71a7cb5a8ec54ac4ecad9ca5fc --- /dev/null +++ b/neonView/OrganisationsMultiEdit_view/OrganisationsMultiEdit_view.aod @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.8"> + <name>OrganisationsMultiEdit_view</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <layout> + <noneLayout> + <name>layout</name> + </noneLayout> + </layout> + <children> + <genericMultipleViewTemplate> + <name>GenericMultiple</name> + <columns> + <neonGenericMultipleTableColumn> + <name>210f77fd-4b41-4efc-87c0-b5ab7720648b</name> + <entityField>CONTACT_ID</entityField> + <fullWidth v="true" /> + </neonGenericMultipleTableColumn> + </columns> + </genericMultipleViewTemplate> + </children> +</neonView> diff --git a/neonView/PlanningAddToOrganisationOverlay_view/PlanningAddToOrganisationOverlay_view.aod b/neonView/PlanningAddToOrganisationOverlay_view/PlanningAddToOrganisationOverlay_view.aod new file mode 100644 index 0000000000000000000000000000000000000000..1f4b1f97ea7e2c576a537733d1d1b057df0946e2 --- /dev/null +++ b/neonView/PlanningAddToOrganisationOverlay_view/PlanningAddToOrganisationOverlay_view.aod @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.8"> + <name>PlanningAddToOrganisationOverlay_view</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <isOverlay v="true" /> + <layout> + <boxLayout> + <name>layout</name> + </boxLayout> + </layout> + <children> + <neonViewReference> + <name>26e207f5-f69c-4ec3-8b29-7baae3476542</name> + <entityField>#ENTITY</entityField> + <view>PlanningAddToOrganisationsNewPlannings_view</view> + </neonViewReference> + <genericViewTemplate> + <name>Generic</name> + </genericViewTemplate> + <neonViewReference> + <name>9a9578d0-d925-4f9a-94a8-c7b8b50c1fa7</name> + <entityField>#ENTITY</entityField> + <view>PlanningAddToOrganisationsExistingPlannings_view</view> + </neonViewReference> + </children> +</neonView> diff --git a/neonView/PlanningAddToOrganisationsExistingPlannings_view/PlanningAddToOrganisationsExistingPlannings_view.aod b/neonView/PlanningAddToOrganisationsExistingPlannings_view/PlanningAddToOrganisationsExistingPlannings_view.aod new file mode 100644 index 0000000000000000000000000000000000000000..0d5eba2523f50a1925ab0f802c8ce3427bd00de4 --- /dev/null +++ b/neonView/PlanningAddToOrganisationsExistingPlannings_view/PlanningAddToOrganisationsExistingPlannings_view.aod @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.8"> + <name>PlanningAddToOrganisationsExistingPlannings_view</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <layout> + <drawerLayout> + <name>layout</name> + <layoutCaption>Unchanged plan values</layoutCaption> + </drawerLayout> + </layout> + <children> + <neonViewReference> + <name>50a592ce-97ca-4f59-be35-5ba47a246b6f</name> + <entityField>PlanningsAlreadyExists</entityField> + <view>PlanningMultiEditOverlay_view</view> + </neonViewReference> + </children> +</neonView> diff --git a/neonView/PlanningAddToOrganisationsNewPlannings_view/PlanningAddToOrganisationsNewPlannings_view.aod b/neonView/PlanningAddToOrganisationsNewPlannings_view/PlanningAddToOrganisationsNewPlannings_view.aod new file mode 100644 index 0000000000000000000000000000000000000000..173de0924d9336e7a796523180a631bbb8a8447d --- /dev/null +++ b/neonView/PlanningAddToOrganisationsNewPlannings_view/PlanningAddToOrganisationsNewPlannings_view.aod @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.8"> + <name>PlanningAddToOrganisationsNewPlannings_view</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <layout> + <drawerLayout> + <name>layout</name> + <layoutCaption>New created plan values</layoutCaption> + </drawerLayout> + </layout> + <children> + <neonViewReference> + <name>8c27b321-68ce-4979-9185-4f7472883ba2</name> + <entityField>PlanningsNew</entityField> + <view>PlanningMultiEditOverlay_view</view> + </neonViewReference> + </children> +</neonView> diff --git a/neonView/PlanningAddToOrganisations_view/PlanningAddToOrganisations_view.aod b/neonView/PlanningAddToOrganisations_view/PlanningAddToOrganisations_view.aod new file mode 100644 index 0000000000000000000000000000000000000000..af062e3c59220fa5fd5c579745875db1d2897502 --- /dev/null +++ b/neonView/PlanningAddToOrganisations_view/PlanningAddToOrganisations_view.aod @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.8"> + <name>PlanningAddToOrganisations_view</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <size>SMALL</size> + <isOverlay v="false" /> + <overlayOrientation>PORTRAIT</overlayOrientation> + <layout> + <boxLayout> + <name>layout</name> + </boxLayout> + </layout> + <children> + <genericViewTemplate> + <name>Generic</name> + <editMode v="true" /> + <fields> + <entityFieldLink> + <name>5e4b29ff-2a7a-4558-aa64-903372c10bfc</name> + <entityField>VOLUME</entityField> + </entityFieldLink> + <entityFieldLink> + <name>ee165810-35e2-4238-9080-bd7a476ab9d5</name> + <entityField>YEAR</entityField> + </entityFieldLink> + <entityFieldLink> + <name>602e99fd-ee67-4609-a5cd-f6c82e48a6c0</name> + <entityField>STATUS</entityField> + </entityFieldLink> + <entityFieldLink> + <name>04c59ecc-9bdc-4ab8-bd10-3a559f680f3f</name> + <entityField>RESPONSIBLE_CONTACT_ID</entityField> + </entityFieldLink> + <entityFieldLink> + <name>3842c2c8-cbb1-4506-bbc2-1c05e898791f</name> + <entityField>GROUPCODE</entityField> + </entityFieldLink> + </fields> + </genericViewTemplate> + <neonViewReference> + <name>d2a119e0-5b04-44b0-bc10-23ff56b3a27d</name> + <entityField>Organisations</entityField> + <view>OrganisationsMultiEdit_view</view> + </neonViewReference> + </children> +</neonView> diff --git a/neonView/PlanningChangeResponsible_view/PlanningChangeResponsible_view.aod b/neonView/PlanningChangeResponsible_view/PlanningChangeResponsible_view.aod new file mode 100644 index 0000000000000000000000000000000000000000..de3b597b0c2372a583613a506fb5c42aded1730e --- /dev/null +++ b/neonView/PlanningChangeResponsible_view/PlanningChangeResponsible_view.aod @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.8"> + <name>PlanningChangeResponsible_view</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <size>SMALL</size> + <layout> + <noneLayout> + <name>layout</name> + </noneLayout> + </layout> + <children> + <genericViewTemplate> + <name>Generic</name> + <editMode v="true" /> + <fields> + <entityFieldLink> + <name>008e9611-1f57-45c8-ab1c-ce4c161aad2d</name> + <entityField>RESPONSIBLE</entityField> + </entityFieldLink> + </fields> + </genericViewTemplate> + </children> +</neonView> diff --git a/neonView/PlanningChangeStatus_view/PlanningChangeStatus_view.aod b/neonView/PlanningChangeStatus_view/PlanningChangeStatus_view.aod new file mode 100644 index 0000000000000000000000000000000000000000..3b962389e8ec2d5e5b9f68e38ed5c55d955c0758 --- /dev/null +++ b/neonView/PlanningChangeStatus_view/PlanningChangeStatus_view.aod @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.8"> + <name>PlanningChangeStatus_view</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <size>SMALL</size> + <layout> + <noneLayout> + <name>layout</name> + </noneLayout> + </layout> + <children> + <genericViewTemplate> + <name>Generic</name> + <editMode v="true" /> + <fields> + <entityFieldLink> + <name>dc185280-5c42-4c69-904c-6c5a2a7efec8</name> + <entityField>STATUS</entityField> + </entityFieldLink> + </fields> + </genericViewTemplate> + </children> +</neonView> diff --git a/neonView/PlanningEdit_view/PlanningEdit_view.aod b/neonView/PlanningEdit_view/PlanningEdit_view.aod new file mode 100644 index 0000000000000000000000000000000000000000..aef83d5201b8e5036cc3f27c7af4893c9df1f1e2 --- /dev/null +++ b/neonView/PlanningEdit_view/PlanningEdit_view.aod @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.8"> + <name>PlanningEdit_view</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <size>SMALL</size> + <layout> + <boxLayout> + <name>layout</name> + </boxLayout> + </layout> + <children> + <genericViewTemplate> + <name>Generic</name> + <editMode v="true" /> + <fields> + <entityFieldLink> + <name>ea73371d-a0d9-46e3-bc59-aa03d2cab163</name> + <entityField>CONTACT_ID</entityField> + </entityFieldLink> + <entityFieldLink> + <name>a3206d87-1d66-42b8-b1b9-608533eb6f98</name> + <entityField>VOLUME</entityField> + </entityFieldLink> + <entityFieldLink> + <name>89ec3f79-b840-434f-8059-1ccfacbaa518</name> + <entityField>YEAR_DATETIME</entityField> + </entityFieldLink> + <entityFieldLink> + <name>4142072e-10f3-4868-8b5e-8199d851680d</name> + <entityField>STATUS</entityField> + </entityFieldLink> + <entityFieldLink> + <name>8ce415e3-e810-4567-bc9e-d367f50af474</name> + <entityField>RESPONSIBLE_CONTACT_ID</entityField> + </entityFieldLink> + <entityFieldLink> + <name>76d5f780-ff48-4872-a450-a05d0853bcee</name> + <entityField>GROUPCODE</entityField> + </entityFieldLink> + <entityFieldLink> + <name>9fb31b2e-363a-431a-8126-5c23a4b6c452</name> + <entityField>INFO</entityField> + </entityFieldLink> + </fields> + </genericViewTemplate> + </children> +</neonView> diff --git a/neonView/PlanningFilter_view/PlanningFilter_view.aod b/neonView/PlanningFilter_view/PlanningFilter_view.aod new file mode 100644 index 0000000000000000000000000000000000000000..93e3ba9a59aed53b4e78fa48b2fecd3ff94338e4 --- /dev/null +++ b/neonView/PlanningFilter_view/PlanningFilter_view.aod @@ -0,0 +1,132 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.8"> + <name>PlanningFilter_view</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <filterable v="true" /> + <layout> + <groupLayout> + <name>layout</name> + </groupLayout> + </layout> + <children> + <tableViewTemplate> + <name>Table</name> + <favoriteActionGroup1>FilterViewActions</favoriteActionGroup1> + <columns> + <neonTableColumn> + <name>2024c784-29c3-498b-80b3-f2e378f25773</name> + <entityField>CONTACT_ID</entityField> + </neonTableColumn> + <neonTableColumn> + <name>2e953e44-4bc5-4faa-9f4b-24067e547948</name> + <entityField>GROUPCODE</entityField> + </neonTableColumn> + <neonTableColumn> + <name>e4291f04-8c2b-4098-a50e-596c8475307d</name> + <entityField>FORECAST_YEAR</entityField> + </neonTableColumn> + <neonTableColumn> + <name>5151f716-d93d-4131-a19e-9935cd7ef6a4</name> + <entityField>VOLUME</entityField> + </neonTableColumn> + <neonTableColumn> + <name>befc56f1-8681-4f08-8d94-e1971de8e7c3</name> + <entityField>STATUS</entityField> + </neonTableColumn> + <neonTableColumn> + <name>21f5c228-b2eb-4e66-8112-5814b32d1fba</name> + <entityField>INFO</entityField> + </neonTableColumn> + <neonTableColumn> + <name>4a354a6b-87c9-4cf5-89e1-c5eb99aa2c07</name> + <entityField>RESPONSIBLE_CONTACT_ID</entityField> + </neonTableColumn> + </columns> + </tableViewTemplate> + <treeTableViewTemplate> + <name>TreeTable</name> + <favoriteActionGroup1>FilterViewActions</favoriteActionGroup1> + <columns> + <neonTreeTableColumn> + <name>9664cd27-0bd3-48e1-bc4e-b80e8ce52c64</name> + <entityField>CONTACT_ID</entityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>cf434d69-e808-474d-b14a-7cf1f71858e3</name> + <entityField>GROUPCODE</entityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>e43c6e75-4dc6-4506-b34f-146dc5762633</name> + <entityField>FORECAST_YEAR</entityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>ba9ed9ef-1492-4a56-a8fa-ec1ce58c95c9</name> + <entityField>VOLUME</entityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>2a65c747-1624-4c58-8a17-1d60c79826ac</name> + <entityField>STATUS</entityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>804e6425-30b1-47a0-8851-730e72af3937</name> + <entityField>INFO</entityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>b58a1b6d-8824-4122-a616-42dcb5a50fef</name> + <entityField>RESPONSIBLE_CONTACT_ID</entityField> + </neonTreeTableColumn> + </columns> + </treeTableViewTemplate> + <multiEditTableViewTemplate> + <name>MultiEditTable</name> + <editableColumns> + <element>VOLUME</element> + </editableColumns> + <favoriteActionGroup1>FilterViewActions</favoriteActionGroup1> + <columns> + <neonTableColumn> + <name>9dc22f85-20d3-4891-810e-74570c1faf80</name> + <entityField>FORECAST_YEAR</entityField> + </neonTableColumn> + <neonTableColumn> + <name>bb541f09-5a3c-4905-a73e-4a94b8dd4aba</name> + <entityField>CONTACT_ID</entityField> + </neonTableColumn> + <neonTableColumn> + <name>93f37300-6859-4860-a246-e0f282377b54</name> + <entityField>GROUPCODE</entityField> + </neonTableColumn> + <neonTableColumn> + <name>54abb536-db50-49c6-b70a-41779a66b977</name> + <entityField>VOLUME</entityField> + </neonTableColumn> + <neonTableColumn> + <name>8996ce6a-582c-4caa-9515-9615561e4d1a</name> + <entityField>STATUS</entityField> + </neonTableColumn> + <neonTableColumn> + <name>9dbb7180-33a7-4d3e-b750-93ee3234fde7</name> + <entityField>INFO</entityField> + </neonTableColumn> + <neonTableColumn> + <name>0215f710-cac1-474b-9ecf-418c6877076d</name> + <entityField>RESPONSIBLE_CONTACT_ID</entityField> + </neonTableColumn> + </columns> + <editRendererMapping> + <rendererMappingEntry> + <name>476f5047-9632-4b02-a018-9a8465340f26</name> + <fieldName>VOLUME</fieldName> + <renderer>numberPlus1000</renderer> + </rendererMappingEntry> + </editRendererMapping> + <viewRendererMapping> + <rendererMappingEntry> + <name>a681d707-affa-4ca9-ad41-28b9dce029c6</name> + <fieldName>STATUS</fieldName> + <renderer>badge</renderer> + </rendererMappingEntry> + </viewRendererMapping> + </multiEditTableViewTemplate> + </children> +</neonView> diff --git a/neonView/PlanningMultiEditOverlay_view/PlanningMultiEditOverlay_view.aod b/neonView/PlanningMultiEditOverlay_view/PlanningMultiEditOverlay_view.aod new file mode 100644 index 0000000000000000000000000000000000000000..e190fa525c288644ad81925452f92cdf6353e12e --- /dev/null +++ b/neonView/PlanningMultiEditOverlay_view/PlanningMultiEditOverlay_view.aod @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.8"> + <name>PlanningMultiEditOverlay_view</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <isOverlay v="false" /> + <layout> + <noneLayout> + <name>layout</name> + </noneLayout> + </layout> + <children> + <multiEditTableViewTemplate> + <name>MultiEditTable</name> + <editableColumns> + <element>VOLUME</element> + </editableColumns> + <hideHeader v="false" /> + <isCreatable v="false" /> + <isDeletable v="false" /> + <isEditable v="false" /> + <columns> + <neonTableColumn> + <name>bb541f09-5a3c-4905-a73e-4a94b8dd4aba</name> + <entityField>CONTACT_ID</entityField> + </neonTableColumn> + <neonTableColumn> + <name>93f37300-6859-4860-a246-e0f282377b54</name> + <entityField>GROUPCODE</entityField> + </neonTableColumn> + <neonTableColumn> + <name>9dc22f85-20d3-4891-810e-74570c1faf80</name> + <entityField>FORECAST_YEAR</entityField> + </neonTableColumn> + <neonTableColumn> + <name>54abb536-db50-49c6-b70a-41779a66b977</name> + <entityField>VOLUME</entityField> + </neonTableColumn> + <neonTableColumn> + <name>8996ce6a-582c-4caa-9515-9615561e4d1a</name> + <entityField>STATUS</entityField> + </neonTableColumn> + <neonTableColumn> + <name>9dbb7180-33a7-4d3e-b750-93ee3234fde7</name> + <entityField>INFO</entityField> + </neonTableColumn> + <neonTableColumn> + <name>0215f710-cac1-474b-9ecf-418c6877076d</name> + <entityField>RESPONSIBLE_CONTACT_ID</entityField> + </neonTableColumn> + </columns> + <editRendererMapping> + <rendererMappingEntry> + <name>d0c0badc-a365-41fc-bb18-493e3c8340d9</name> + <fieldName>VOLUME</fieldName> + <renderer>numberPlus1000</renderer> + </rendererMappingEntry> + </editRendererMapping> + <viewRendererMapping> + <rendererMappingEntry> + <name>a681d707-affa-4ca9-ad41-28b9dce029c6</name> + <fieldName>STATUS</fieldName> + <renderer>badge</renderer> + </rendererMappingEntry> + </viewRendererMapping> + </multiEditTableViewTemplate> + </children> +</neonView> diff --git a/neonView/PlanningOrganisationFilter_view/PlanningOrganisationFilter_view.aod b/neonView/PlanningOrganisationFilter_view/PlanningOrganisationFilter_view.aod new file mode 100644 index 0000000000000000000000000000000000000000..ed4339a63e0f6aea64875454565d42f8c3f56cfb --- /dev/null +++ b/neonView/PlanningOrganisationFilter_view/PlanningOrganisationFilter_view.aod @@ -0,0 +1,132 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.8"> + <name>PlanningOrganisationFilter_view</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <filterable v="true" /> + <layout> + <groupLayout> + <name>layout</name> + </groupLayout> + </layout> + <children> + <multiEditTableViewTemplate> + <name>MultiEditTable</name> + <editableColumns> + <element>VOLUME</element> + </editableColumns> + <favoriteActionGroup1>FilterViewActions</favoriteActionGroup1> + <columns> + <neonTableColumn> + <name>9dc22f85-20d3-4891-810e-74570c1faf80</name> + <entityField>FORECAST_YEAR</entityField> + </neonTableColumn> + <neonTableColumn> + <name>bb541f09-5a3c-4905-a73e-4a94b8dd4aba</name> + <entityField>CONTACT_ID</entityField> + </neonTableColumn> + <neonTableColumn> + <name>93f37300-6859-4860-a246-e0f282377b54</name> + <entityField>GROUPCODE</entityField> + </neonTableColumn> + <neonTableColumn> + <name>54abb536-db50-49c6-b70a-41779a66b977</name> + <entityField>VOLUME</entityField> + </neonTableColumn> + <neonTableColumn> + <name>8996ce6a-582c-4caa-9515-9615561e4d1a</name> + <entityField>STATUS</entityField> + </neonTableColumn> + <neonTableColumn> + <name>9dbb7180-33a7-4d3e-b750-93ee3234fde7</name> + <entityField>INFO</entityField> + </neonTableColumn> + <neonTableColumn> + <name>0215f710-cac1-474b-9ecf-418c6877076d</name> + <entityField>RESPONSIBLE_CONTACT_ID</entityField> + </neonTableColumn> + </columns> + <editRendererMapping> + <rendererMappingEntry> + <name>2d22888b-24f1-42b4-9573-1a294a342dc4</name> + <fieldName>VOLUME</fieldName> + <renderer>numberPlus1000</renderer> + </rendererMappingEntry> + </editRendererMapping> + <viewRendererMapping> + <rendererMappingEntry> + <name>a681d707-affa-4ca9-ad41-28b9dce029c6</name> + <fieldName>STATUS</fieldName> + <renderer>badge</renderer> + </rendererMappingEntry> + </viewRendererMapping> + </multiEditTableViewTemplate> + <tableViewTemplate> + <name>Table</name> + <favoriteActionGroup1>FilterViewActions</favoriteActionGroup1> + <columns> + <neonTableColumn> + <name>2024c784-29c3-498b-80b3-f2e378f25773</name> + <entityField>CONTACT_ID</entityField> + </neonTableColumn> + <neonTableColumn> + <name>2e953e44-4bc5-4faa-9f4b-24067e547948</name> + <entityField>GROUPCODE</entityField> + </neonTableColumn> + <neonTableColumn> + <name>e4291f04-8c2b-4098-a50e-596c8475307d</name> + <entityField>FORECAST_YEAR</entityField> + </neonTableColumn> + <neonTableColumn> + <name>5151f716-d93d-4131-a19e-9935cd7ef6a4</name> + <entityField>VOLUME</entityField> + </neonTableColumn> + <neonTableColumn> + <name>befc56f1-8681-4f08-8d94-e1971de8e7c3</name> + <entityField>STATUS</entityField> + </neonTableColumn> + <neonTableColumn> + <name>21f5c228-b2eb-4e66-8112-5814b32d1fba</name> + <entityField>INFO</entityField> + </neonTableColumn> + <neonTableColumn> + <name>4a354a6b-87c9-4cf5-89e1-c5eb99aa2c07</name> + <entityField>RESPONSIBLE_CONTACT_ID</entityField> + </neonTableColumn> + </columns> + </tableViewTemplate> + <treeTableViewTemplate> + <name>TreeTable</name> + <favoriteActionGroup1>FilterViewActions</favoriteActionGroup1> + <columns> + <neonTreeTableColumn> + <name>9664cd27-0bd3-48e1-bc4e-b80e8ce52c64</name> + <entityField>CONTACT_ID</entityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>cf434d69-e808-474d-b14a-7cf1f71858e3</name> + <entityField>GROUPCODE</entityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>e43c6e75-4dc6-4506-b34f-146dc5762633</name> + <entityField>FORECAST_YEAR</entityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>ba9ed9ef-1492-4a56-a8fa-ec1ce58c95c9</name> + <entityField>VOLUME</entityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>2a65c747-1624-4c58-8a17-1d60c79826ac</name> + <entityField>STATUS</entityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>804e6425-30b1-47a0-8851-730e72af3937</name> + <entityField>INFO</entityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>b58a1b6d-8824-4122-a616-42dcb5a50fef</name> + <entityField>RESPONSIBLE_CONTACT_ID</entityField> + </neonTreeTableColumn> + </columns> + </treeTableViewTemplate> + </children> +</neonView> diff --git a/neonView/SalesprojectMain_view/SalesprojectMain_view.aod b/neonView/SalesprojectMain_view/SalesprojectMain_view.aod index 43368c01548b156b25d2389c85c30878e3a071c1..95fc6da52400e9b0dc53d2d2bba8123349600be5 100644 --- a/neonView/SalesprojectMain_view/SalesprojectMain_view.aod +++ b/neonView/SalesprojectMain_view/SalesprojectMain_view.aod @@ -25,8 +25,8 @@ <view>SalesprojectActivity_view</view> </neonViewReference> <neonViewReference> - <name>7ac103ea-1131-41e0-85ce-e7d2fc86dfd8</name> - <entityField>Attributes</entityField> + <name>107b20e3-6326-498a-968b-ac09257981fc</name> + <entityField>AttributeTree</entityField> <view>AttributeRelationTree_view</view> </neonViewReference> <neonViewReference> diff --git a/neonView/SalesprojectMilestoneInfo_view/SalesprojectMilestoneInfo_view.aod b/neonView/SalesprojectMilestoneInfo_view/SalesprojectMilestoneInfo_view.aod index 965ca73b487c64db86d0d42be802d619a6b1041e..0fe777d742fb9efff898ee891b27270c5b5e7ddd 100644 --- a/neonView/SalesprojectMilestoneInfo_view/SalesprojectMilestoneInfo_view.aod +++ b/neonView/SalesprojectMilestoneInfo_view/SalesprojectMilestoneInfo_view.aod @@ -12,8 +12,8 @@ <ganttViewTemplate> <name>MilestoneGantt</name> <uidField>SALESPROJECT_MILESTONEID</uidField> - <titleField>valueLongName</titleField> - <descriptionField>valueLongName</descriptionField> + <titleField>MILESTONEVALUE</titleField> + <descriptionField>MILESTONEVALUE</descriptionField> <beginDateField>DATE_START</beginDateField> <endDateField>dateEndGantt</endDateField> <predecessorIdField>PARENT_ID</predecessorIdField> diff --git a/neonView/SalesprojectOfferForecast_view/SalesprojectOfferForecast_view.aod b/neonView/SalesprojectOfferForecast_view/SalesprojectOfferForecast_view.aod index 6d39b58450421b59183f1a9945e59d49b3830270..46035190b079baa6b2cc1f04a2b47664cc649587 100644 --- a/neonView/SalesprojectOfferForecast_view/SalesprojectOfferForecast_view.aod +++ b/neonView/SalesprojectOfferForecast_view/SalesprojectOfferForecast_view.aod @@ -17,9 +17,9 @@ <view>ForecastFilter_view</view> </neonViewReference> <neonViewReference> - <name>ca2581ac-0987-4fa4-a45a-c33ea4cd61e1</name> - <entityField>SalesprojectForecastCharts</entityField> - <view>TurnoverChartForecast_view</view> + <name>aeb63483-3e44-4fcb-885d-48c6d7d193ac</name> + <entityField>Turnovers</entityField> + <view>TurnoverDynamicMultiDataChart_view</view> </neonViewReference> </children> </neonView> diff --git a/neonView/SalesprojectPhaseDefinitionPreview_view/SalesprojectPhaseDefinitionPreview_view.aod b/neonView/SalesprojectPhaseDefinitionPreview_view/SalesprojectPhaseDefinitionPreview_view.aod index a2fe192db764301468d9b71198c550cc677cf3de..25f7dc657276031896bbb3329b0c962bdd1c2f40 100644 --- a/neonView/SalesprojectPhaseDefinitionPreview_view/SalesprojectPhaseDefinitionPreview_view.aod +++ b/neonView/SalesprojectPhaseDefinitionPreview_view/SalesprojectPhaseDefinitionPreview_view.aod @@ -14,7 +14,6 @@ <name>cardViewTemplate</name> <iconField>#ICON</iconField> <titleField>PHASE</titleField> - <subtitleField>SalesprojectPhaseFullname</subtitleField> <entityField>#ENTITY</entityField> </cardViewTemplate> <neonViewReference> diff --git a/neonView/SalesprojectScoreCard_view/SalesprojectScoreCard_view.aod b/neonView/SalesprojectScoreCard_view/SalesprojectScoreCard_view.aod index 6ab33f8dae76b440a0e06de971c0cb3e01e275cc..73440be89f0f0da0add22c6c1dc51542be009400 100644 --- a/neonView/SalesprojectScoreCard_view/SalesprojectScoreCard_view.aod +++ b/neonView/SalesprojectScoreCard_view/SalesprojectScoreCard_view.aod @@ -31,17 +31,27 @@ <scoreCardViewTemplate> <name>KeyFigures</name> <fieldActions> + <element>openPlanning</element> <element>openForecast</element> + <element>openForecastWeighted</element> <element>openTurnover</element> <element>openSalesprojects</element> <element>sentOffers</element> </fieldActions> <entityField>#ENTITY</entityField> <fields> + <entityFieldLink> + <name>0c68c50c-bb6b-4450-a53e-2bbfbb4ee8b5</name> + <entityField>OVERALL_PLANNING</entityField> + </entityFieldLink> <entityFieldLink> <name>3377fe1b-1f29-4c49-88c8-7a1b1ee6d0ce</name> <entityField>OVERALL_FORECAST</entityField> </entityFieldLink> + <entityFieldLink> + <name>5d85e400-1d16-4ec0-977a-ddd76eac4ed9</name> + <entityField>OVERALL_FORECAST_weighted</entityField> + </entityFieldLink> <entityFieldLink> <name>44449f24-ed9d-4053-8202-db4b43032067</name> <entityField>OVERALL_TURNOVER</entityField> diff --git a/neonView/TurnoverDynamicMultiDataChart_view/TurnoverDynamicMultiDataChart_view.aod b/neonView/TurnoverDynamicMultiDataChart_view/TurnoverDynamicMultiDataChart_view.aod new file mode 100644 index 0000000000000000000000000000000000000000..37ac78294393862d6fd6f9c34c58c58d16ab3077 --- /dev/null +++ b/neonView/TurnoverDynamicMultiDataChart_view/TurnoverDynamicMultiDataChart_view.aod @@ -0,0 +1,208 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.8"> + <name>TurnoverDynamicMultiDataChart_view</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <filterable v="true" /> + <layout> + <groupLayout> + <name>layout</name> + </groupLayout> + </layout> + <children> + <dynamicMultiDataChartViewTemplate> + <name>ColumnChart</name> + <chartType>COLUMN</chartType> + <yAxisLabel>Volume</yAxisLabel> + <defaultGroupFields> + <element>TURNOVER_YEAR</element> + </defaultGroupFields> + <maxDBRow v="1000" /> + <columns> + <neonDynamicMultiDataChartColumn> + <name>7709c61e-76a5-482a-b2e6-c29ff74c9bf0</name> + <entityField>PLANNING_VOLUME</entityField> + <aggregateEntityField>PlanningVolume_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + <neonDynamicMultiDataChartColumn> + <name>04e3d31a-b4ca-404a-b308-eaa01abd2a99</name> + <entityField>FORECAST_VOLUME</entityField> + <aggregateEntityField>ForecastVolume_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + <neonDynamicMultiDataChartColumn> + <name>71bfb28b-0eb7-418f-b700-534a631bdad4</name> + <entityField>FORECAST_VOLUME_weighted</entityField> + <aggregateEntityField>ForecastVolumeWeighted_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + <neonDynamicMultiDataChartColumn> + <name>9a3b65fd-5bd3-41a2-9cc6-8dca5acb3367</name> + <entityField>TURNOVER_VOLUME</entityField> + <aggregateEntityField>TurnoverVolume_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + </columns> + </dynamicMultiDataChartViewTemplate> + <dynamicMultiDataChartViewTemplate> + <name>LineChart</name> + <chartType>LINE</chartType> + <yAxisLabel>Volume</yAxisLabel> + <defaultGroupFields> + <element>TURNOVER_YEAR</element> + </defaultGroupFields> + <maxDBRow v="1000" /> + <columns> + <neonDynamicMultiDataChartColumn> + <name>72f5cc43-cec3-4718-94cd-99f587607293</name> + <entityField>PLANNING_VOLUME</entityField> + <aggregateEntityField>PlanningVolume_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + <neonDynamicMultiDataChartColumn> + <name>d4437b51-9e40-4fa7-94bc-28f2ea59e966</name> + <entityField>FORECAST_VOLUME</entityField> + <aggregateEntityField>ForecastVolume_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + <neonDynamicMultiDataChartColumn> + <name>71bfb28b-0eb7-418f-b700-534a631bdad4</name> + <entityField>FORECAST_VOLUME_weighted</entityField> + <aggregateEntityField>ForecastVolumeWeighted_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + <neonDynamicMultiDataChartColumn> + <name>41eba6de-a6a4-4ee2-a0c6-d38ee57e5188</name> + <entityField>TURNOVER_VOLUME</entityField> + <aggregateEntityField>TurnoverVolume_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + </columns> + </dynamicMultiDataChartViewTemplate> + <dynamicMultiDataChartViewTemplate> + <name>AreaChart</name> + <chartType>AREA</chartType> + <yAxisLabel>Volume</yAxisLabel> + <defaultGroupFields> + <element>TURNOVER_YEAR</element> + </defaultGroupFields> + <maxDBRow v="1000" /> + <columns> + <neonDynamicMultiDataChartColumn> + <name>1585e8fd-b76f-44b9-9d44-27a639570140</name> + <entityField>PLANNING_VOLUME</entityField> + <aggregateEntityField>PlanningVolume_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + <neonDynamicMultiDataChartColumn> + <name>ea8a897f-a2ae-4c92-bb91-0b0e9f65614c</name> + <entityField>FORECAST_VOLUME</entityField> + <aggregateEntityField>ForecastVolume_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + <neonDynamicMultiDataChartColumn> + <name>71bfb28b-0eb7-418f-b700-534a631bdad4</name> + <entityField>FORECAST_VOLUME_weighted</entityField> + <aggregateEntityField>ForecastVolumeWeighted_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + <neonDynamicMultiDataChartColumn> + <name>ad2f7c63-e91e-4aeb-ad18-6c46a1550826</name> + <entityField>TURNOVER_VOLUME</entityField> + <aggregateEntityField>TurnoverVolume_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + </columns> + </dynamicMultiDataChartViewTemplate> + <dynamicMultiDataChartViewTemplate> + <name>BarChart</name> + <chartType>BAR</chartType> + <yAxisLabel>Volume</yAxisLabel> + <defaultGroupFields> + <element>TURNOVER_YEAR</element> + </defaultGroupFields> + <maxDBRow v="1000" /> + <columns> + <neonDynamicMultiDataChartColumn> + <name>7f45aa1c-cd85-42f6-86fb-7507be02f77b</name> + <entityField>PLANNING_VOLUME</entityField> + <aggregateEntityField>PlanningVolume_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + <neonDynamicMultiDataChartColumn> + <name>65847c02-460d-45dd-b8b4-d4cd957bba73</name> + <entityField>FORECAST_VOLUME</entityField> + <aggregateEntityField>ForecastVolume_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + <neonDynamicMultiDataChartColumn> + <name>71bfb28b-0eb7-418f-b700-534a631bdad4</name> + <entityField>FORECAST_VOLUME_weighted</entityField> + <aggregateEntityField>ForecastVolumeWeighted_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + <neonDynamicMultiDataChartColumn> + <name>7ad4c50f-8f47-43a0-8791-3eb778c0d6fd</name> + <entityField>TURNOVER_VOLUME</entityField> + <aggregateEntityField>TurnoverVolume_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + </columns> + </dynamicMultiDataChartViewTemplate> + <dynamicMultiDataChartViewTemplate> + <name>SplineChart</name> + <chartType>SPLINE</chartType> + <yAxisLabel>Volume</yAxisLabel> + <defaultGroupFields> + <element>TURNOVER_YEAR</element> + </defaultGroupFields> + <maxDBRow v="1000" /> + <columns> + <neonDynamicMultiDataChartColumn> + <name>913e241e-382d-46dd-9aa8-944603e0b3ce</name> + <entityField>PLANNING_VOLUME</entityField> + <aggregateEntityField>PlanningVolume_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + <neonDynamicMultiDataChartColumn> + <name>03c8beba-08c8-4395-bf10-a8068f7f580b</name> + <entityField>FORECAST_VOLUME</entityField> + <aggregateEntityField>ForecastVolume_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + <neonDynamicMultiDataChartColumn> + <name>71bfb28b-0eb7-418f-b700-534a631bdad4</name> + <entityField>FORECAST_VOLUME_weighted</entityField> + <aggregateEntityField>ForecastVolumeWeighted_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + <neonDynamicMultiDataChartColumn> + <name>18d8478b-4e5e-4c4c-86f4-0f0ea16cc423</name> + <entityField>TURNOVER_VOLUME</entityField> + <aggregateEntityField>TurnoverVolume_aggregate</aggregateEntityField> + </neonDynamicMultiDataChartColumn> + </columns> + </dynamicMultiDataChartViewTemplate> + <treeTableViewTemplate> + <name>TreeTable</name> + <showChildrenCount v="false" /> + <defaultGroupFields> + <element>TURNOVER_YEAR</element> + </defaultGroupFields> + <isCreatable v="false" /> + <isDeletable v="false" /> + <isEditable v="false" /> + <columns> + <neonTreeTableColumn> + <name>a4f9a077-a90a-483b-af60-f8768f5f44b7</name> + <entityField>GroupField</entityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>177d07d7-cf46-410a-b9d4-840ca24a0623</name> + <entityField>PLANNING_VOLUME</entityField> + <aggregateEntityField>PlanningVolume_aggregate</aggregateEntityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>b18fd75b-b15e-4752-a6d8-60f068ccf0fe</name> + <entityField>FORECAST_VOLUME</entityField> + <aggregateEntityField>ForecastVolume_aggregate</aggregateEntityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>b4f0d966-e1cb-4b03-99cc-057f7a525b46</name> + <entityField>FORECAST_VOLUME_weighted</entityField> + <aggregateEntityField>ForecastVolumeWeighted_aggregate</aggregateEntityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>ed226e68-be2a-45d8-9c00-072f97a79dc3</name> + <entityField>TURNOVER_VOLUME</entityField> + <aggregateEntityField>TurnoverVolume_aggregate</aggregateEntityField> + </neonTreeTableColumn> + <neonTreeTableColumn> + <name>54f705d0-ecf6-4408-b962-835df01fb245</name> + <entityField>emptyField</entityField> + </neonTreeTableColumn> + </columns> + </treeTableViewTemplate> + </children> +</neonView> diff --git a/process/AttributeFilter_lib/process.js b/process/AttributeFilter_lib/process.js index 0e9a44920eed7e6875ee71fec0b1f268187ee71d..eebe63683c593ed8588e5a0ad2891c947b1d9de0 100644 --- a/process/AttributeFilter_lib/process.js +++ b/process/AttributeFilter_lib/process.js @@ -138,12 +138,15 @@ AttributeFilterExtensionMaker.getFilterFields = function(pObjectType) /** * fetches attributes that are filterable and transforms them into filter fields for the current context * + * @param {String} pAlternativeContext If anoter context instead of the current context should be used, the context can be specified with this parameter. + * * @see AttributeFilterExtensionMaker.getFilterFields for more details * @static */ -AttributeFilterExtensionMaker.makeFilterFields = function() +AttributeFilterExtensionMaker.makeFilterFields = function(pAlternativeContext) { - var objectType = ContextUtils.getCurrentContextId(); + var objectType = pAlternativeContext || ContextUtils.getCurrentContextId(); + var res = AttributeFilterExtensionMaker.getFilterFields(objectType); return res; }; @@ -257,12 +260,15 @@ AttributeFilterExtensionMaker.getFilterCondition = function(pObjectType, pFilter /** * Builds a Sql-condition for a attribute filter extension set. This allows to filter for attributes within a db-table * + * @param {String} pAlternativeColumn If anoter column instead of the UID of the table should be used, the column can be specified with this parameter. + * @param {String} pAlternativeContext If anoter context instead of the current context should be used, the context can be specified with this parameter. + * * @see AttributeFilterExtensionMaker.getFilterCondition for more details * @static */ -AttributeFilterExtensionMaker.makeFilterConditionSql = function() +AttributeFilterExtensionMaker.makeFilterConditionSql = function(pAlternativeColumn, pAlternativeContext) { - var objectType = ContextUtils.getCurrentContextId(); + var objectType = pAlternativeContext || ContextUtils.getCurrentContextId(); var filterName = vars.get("$local.name"); var filterCond = vars.get("$local.condition"); var filterRawValue = vars.get("$local.rawvalue"); @@ -270,7 +276,7 @@ AttributeFilterExtensionMaker.makeFilterConditionSql = function() var uidInfo = EntityUtils.parseUidColumn(vars.get("$sys.uidcolumn")); var columnPlaceholder = vars.get("$local.columnPlaceholder"); var res = AttributeFilterExtensionMaker.getFilterCondition(objectType, filterName, filterCond, filterRawValue, filterOpratorName, - uidInfo.table, uidInfo.column, columnPlaceholder); + uidInfo.table, pAlternativeColumn || uidInfo.column, columnPlaceholder); return res; }; diff --git a/process/Attribute_lib/process.js b/process/Attribute_lib/process.js index b6f4f0380639ea5cce991ad0f9fc62065b3c8cf5..98ff92d9eb3f27b726c777f1ed7aa3dc026bdfb8 100644 --- a/process/Attribute_lib/process.js +++ b/process/Attribute_lib/process.js @@ -692,6 +692,16 @@ AttributeRelationUtils.validateAttributeCount = function (pRowId, pObjectType, p this[row.AB_ATTRIBUTE_ID] = (this[row.AB_ATTRIBUTE_ID] || 0) + 1; }, countObj); } + if (changedRows) //append the new rows (if they are added by default but not filled with a value) + { + changedRows.forEach(function (row) + { + if(!row.DATE_NEW && !row.USER_NEW) + { + this[row.AB_ATTRIBUTE_ID] = (this[row.AB_ATTRIBUTE_ID] || 0) + 1; + } + }, countObj); + } var possibleAttributes = AttributeUtil.getPossibleAttributes(pObjectType, undefined, pFilteredAttributeIds); var minMaxCounts = []; @@ -798,6 +808,7 @@ AttributeRelationUtils.countAttributeRelations = function (pRowId, pObjectType, return countObj; } + /*********************************************************************************************************************/ diff --git a/process/CalendarUtil_test/CalendarUtil_test.aod b/process/CalendarUtil_test/CalendarUtil_test.aod new file mode 100644 index 0000000000000000000000000000000000000000..003d70031c462bade2eda8dbf49aa510a48faf9f --- /dev/null +++ b/process/CalendarUtil_test/CalendarUtil_test.aod @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.2" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.2"> + <name>CalendarUtil_test</name> + <title>[TEST] Calendar_lib</title> + <majorModelMode>DISTRIBUTED</majorModelMode> + <icon>VAADIN:CHECK_CIRCLE</icon> + <process>%aditoprj%/process/CalendarUtil_test/process.js</process> + <alias>Data_alias</alias> + <variants> + <element>EXECUTABLE</element> + </variants> +</process> diff --git a/process/CalendarUtil_test/process.js b/process/CalendarUtil_test/process.js new file mode 100644 index 0000000000000000000000000000000000000000..6c1808870af916388b07ef1d865e2658de2ff71f --- /dev/null +++ b/process/CalendarUtil_test/process.js @@ -0,0 +1,82 @@ +import("system.calendars"); +import("system.result"); +import("system.db"); +import("UnitTest_lib"); +import("Calendar_lib"); +import("Sql_lib"); + + +var testUids = []; +var tester = new Tester("Test Calendar_lib"); +var newSilentEvent = new TestSuite("CalendarUtil.newSilentEvent", [ + new Test("Should create an appointment without graphical user interaction.", function(pTester, pDataProvider){ + var uid = CalendarUtil.newSilentEvent(pDataProvider[0], pDataProvider[1], pDataProvider[2], pDataProvider[3], pDataProvider[4], + pDataProvider[5], pDataProvider[6], pDataProvider[7], pDataProvider[8], pDataProvider[9], pDataProvider[10], pDataProvider[11], + pDataProvider[12], pDataProvider[13]); + + var doesLinksExists; + var doesExists = Number(newSelect("count(*)", SqlUtils.getSystemAlias()) + .from("asys_calendarbackend") + .where("asys_calendarbackend.elementuid", uid) + .cell()); + + pTester.expectThat(doesExists).isGreaterEqual(1).assert(); + + if(pDataProvider[2] && doesExists) + { + doesLinksExists = newSelect("ab_appointmentlink_id") + .from("ab_appointmentlink") + .where("ab_appointmentlink.appointment_id", uid) + .arrayColumn(); + + pTester.expectThat(doesLinksExists).hasMinLength(1).assert(); + } + + doesLinksExists.length > 0 ? testUids.push([uid, doesLinksExists]) : testUids.push([uid]); + }, function(){ + return [ + ["Testtermin 1","Testbeschreibung",[{"OBJECT_ID":"c7ddf982-0e58-4152-b82b-8f5673b0b729", "OBJECT_TYPE":"Person"}], "Admin", ["Admin"], + new Date("2021", "02", "29", "08", "30"), new Date("2021", "02", "29", "08", "45"), ["Meeting"], undefined, undefined, undefined, + "Microsoft Teams", false, calendars.CLASSIFICATION_PUBLIC], + ["Testtermin 2","Testbeschreibung", + [{"OBJECT_ID":"c7ddf982-0e58-4152-b82b-8f5673b0b729", "OBJECT_TYPE":"Person"}, + {"OBJECT_ID":"18ed06df-30b2-4d59-a4b4-a6e646f6f05a", "OBJECT_TYPE":"Activity"}, + {"OBJECT_ID":"449080f6-b714-4189-a261-37439d0d4010", "OBJECT_TYPE":"Organisation"}, + {"OBJECT_ID":"e9cb198d-c420-4192-9c29-b23682457d8e", "OBJECT_TYPE":"Task"}], + "Admin", ["Admin"], new Date("2021", "03", "08", "14", "30"), new Date("2021", "03", "08", "15", "45"), ["Meeting", "OutOfOffice"], + calendars.STATUS_ACCEPTED, new Date("2021", "03", "08", "14", "15"), + ["herbert.obermaier@hotmail.de", "lisa.lustig@yahoo.com"], "Microsoft Teams", false, calendars.CLASSIFICATION_PUBLIC], + ["Testtermin 3","Testbeschreibung",null, "Admin", ["Admin"], + new Date("2021", "03", "29", "10", "00"), new Date("2021", "03", "29", "11", "00"), ["Vacation"], undefined, undefined, undefined, + "Microsoft Teams", false, calendars.CLASSIFICATION_PUBLIC], + ["Testtermin 4","Testbeschreibung",[{"OBJECTID": "d8f35764-2c56-45be-93c7-f1e0695e2417", "OBJECT_TYPE":"Task"}], "Admin", ["Admin"], + new Date("2021", "03", "29", "10", "00"), new Date("2021", "03", "29", "11", "00"), ["Vacation"], undefined, undefined, undefined, + "Microsoft Teams", false, calendars.CLASSIFICATION_PUBLIC], + ]; + }) +], null, null, function(){ + for (i = 0; i < testUids.length; i++) + { + if(testUids[i].length > 1) + { + newWhere("asys_calendarbackend.elementuid", testUids[i][0], null, null, SqlUtils.getSystemAlias()) + .deleteData(); + testUids[i][1].forEach(function(pLinkUid){ + newWhere("ab_appointmentlink.ab_appointmentlink_id", pLinkUid, null, null, db.getCurrentAlias()) + .deleteData(); + }); + } + else + { + newWhere("asys_calendarbackend.elementuid", testUids[i][0], null, null, SqlUtils.getSystemAlias()) + .deleteData(); + } + } +}); + +tester.initCoverage(CalendarUtil); +tester.test(newSilentEvent); + +tester.summary(); + +result.object(tester.getResults()); \ No newline at end of file diff --git a/process/Calendar_lib/process.js b/process/Calendar_lib/process.js index 455b28d263c1e6def680391206245b213240c4e8..de9bc373d0fee6098f61111dfa3ae96f8c5ab735 100644 --- a/process/Calendar_lib/process.js +++ b/process/Calendar_lib/process.js @@ -1,657 +1,658 @@ -import("system.translate"); -import("system.datetime"); -import("system.neon"); -import("system.calendars"); -import("system.vars"); -import("system.db"); -import("system.swing"); -import("system.eMath"); -import("system.logging"); -import("system.tools"); -import("system.text"); -import("system.question"); -import("system.SQLTYPES"); -import("system.result"); -import("system.util"); -import("system.entities"); -import("Util_lib"); -import("Sql_lib"); - - -/** - * Functions for the calendar. - * <p> - * <b><u>Do not create an instance of this!</u></b> - * @class - */ -function CalendarUtil(){} - - -/* - * Creates and opens an new task object (with link). - * - * @param {String} pSummary (optional) <p> - * The summary.<br> - * @param {String} pDescription (optional) <p> - * The description.<br> - * @param {Boolean} pWithLink (optional) Case if its true, then an a shortcut to $image.frametable will created.<br> - * @param {String[][]} pWithLink (optional) <p> - * The required informations:<br> - * <ul> - * <li>pWithLink[0]: Name of the frame.</li> - * <li>pWithLink[1]: Id of the shown record.</li> - * <li>pWithLink[2]: Linking title.</li> - * @param {String} pUser (optional) <p> - * The user (login).<br> - * @param {[]} pAffectedUsers (optional) <p> - * The affected users. (login)<br> - * @param {date} pStart (optional) <p> - * Start of the task.<br> - * @param {date} pDuration (optional) <p> - * Duration of the task.<br> - * @param {integer} pCategory (optional) <p> - * calendars.CATEGORIES , encoded(String) (e.g.: text.encodeMS(["Service"])) - * @param {String} pStatus (optional) <p> - * Status of the appointment. (calendars.STATUS_TENTATIVE, <br> - * calendars.STATUS_CONFIRMED, calendars.STATUS_CANCELLED)<br> - * @param {Array{[]} pComps4Refresh (optional) <p> - * The component which will be updated.<br> - * - * @return {void} - */ -CalendarUtil.newTodo = function(pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus, pComps4Refresh) -{ - var todo = CalendarUtil.createEntry( calendars.VTODO, pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus ); - var prompts = []; - prompts["comp4refresh"] = []; - - if (pComps4Refresh == undefined) - pComps4Refresh = ["$comp.Aufgabe", "$comp.tbl_Aufgabe"]; - - for (var i = 0; i < pComps4Refresh.length; i++) - { - if ( vars.exists(pComps4Refresh[i])) prompts["comp4refresh"].push(pComps4Refresh[i]); - } - if(vars.getString("$sys.scope") == "vaadin") - neon.openCalendarEntry([todo], null, neon.OPERATINGSTATE_NEW, null) - else - { - if (vars.exists("$sys.currentwindow")) - prompts["window"] = vars.getString("$sys.currentwindow"); - if (vars.exists("$sys.currentimage")) - prompts["image"] = vars.getString("$sys.currentimage"); - - swing.openCalendarEntry([todo], null, false, prompts); - } -} - - -/** - * Finds the effective calendarId of an user in the same <br> - * attribute order like the ADITO core, which is:<br> - * <p> - * exchangeEmail -> calendarID -> email<br> - * <p> - * <b><u>DO NOT CHANGE THIS ORDER!</u></b> - * - * @param {String} pUser <p> - * To check. - * @return <p> - * Effective calendar id.<br> - */ -CalendarUtil.getEffectiveCalendarIdFromUser = function(pUser) -{ - var userParams = pUser["params"]; - - var resolvedCurrentUser; - var exchangeEmail = userParams["exchangeEMail"]; - var calendarId = userParams["calendarID"]; - var email = userParams["email"]; - - if(exchangeEmail) - return exchangeEmail; - else if(calendarId) - return calendarId; - else if(email) - return email; - else - return ""; -} - - -/* - * Creates and opens an new appointment object (with link). - * - * @param {String} pSummary (optional) <p> - * The summary.<br> - * @param {String} pDescription (optional) <p> - * The description.<br> - * @param {Boolean} pWithLink (optional) <p> - * True sets an link to $image.frametable<br> - * @param {String[][]} pWithLink (optional) Description:<br> - * <ul> - * <li>pWithLink[0]: Name of the frame</li> - * <li>pWithLink[1]: Id of the shown record</li> - * <li>pWithLink[2]: linking title</li> - * </ul> - * @param {String} pUser (optional) <p> - * The user (login). - * @param {[]} pAffectedUsers (optional) <p> - * The affected users (login). - * @param {Date} pStart (optional) <p> - * Begin of the task.<br> - * @param {Date} pDuration (optional) <p> - * Duration.<br> - * @param {Number} pCategory (optional) <p> - * calendars.CATEGORIES , encoded(String) (z.B.: text.encodeMS(["Service"])).<br> - * @param {String} pStatus (optional) <p> - * Status of the appointment:<br> - * <ul> - * <li>calendars.STATUS_TENTATIVE</li> - * <li>calendars.STATUS_CONFIRMED</li> - * <li>calendars.STATUS_CANCELLED</li> - * </ul> - * @param {Array{[]} pComps4Refresh (optional) <p> - * The component which will be updated.<br> - * @param {Array{[]} pWorklistId (optional) <p> - * The worklist id.<br> - * - * @return {void} - */ -CalendarUtil.newEvent = function( pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus, pComps4Refresh, pWorklistId) -{ - var event = CalendarUtil.createEntry( calendars.VEVENT, pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus ); - - var prompts = []; - prompts["comp4refresh"] = []; - if (pComps4Refresh == undefined) - pComps4Refresh = ["$comp.Aufgabe", "$comp.tbl_Termine"]; - for (let i = 0; i < pComps4Refresh.length; i++) - { - if ( vars.exists(pComps4Refresh[i])) prompts["comp4refresh"].push(pComps4Refresh[i]); - } - - if(vars.getString("$sys.scope") == "vaadin") - neon.openCalendarEntry([event],"", neon.OPERATINGSTATE_NEW, null) - else - { - prompts["window"] = vars.getString("$sys.currentwindow"); - prompts["image"] = vars.getString("$sys.currentimage"); - if (pWorklistId != undefined) - prompts["worklistId"] = pWorklistId; - swing.openCalendarEntry([event], null, false, prompts); - } -} - - -/* - * Creates an new appointment entry. - * - * @param {String} pSummary (optional) <p> - * The summary/title of the appointment. - * @param {String} pDescription (optional) <p> - * The appointment description. - * @param {String} pLinks (optional) <p> - * The links as objects <u>(key: "OBJECT_ID" & "OBJECT_TYPE")</u> in an array. - * @param {String} pOwner (optional) <p> - * The calendar-user (username) which will be specified as entry-owner. - * @param {String[]} pAffectedUsers (optional) <p> - * The affected users (username). - * @param {Date} pStart (optional) <p> - * The start of the appointment. - * @param {Date} pEnd (optional) <p> - * The end of the appointment. - * @param {String[]} pCategories (optional) <p> - * The categories of the appointment, the default ones are:<br> - * <ul> - * <li>Meeting</li> - * <li>Organisation</li> - * <li>OutOfOffice</li> - * <li>Vacation</li> - * </ul> - * @param {String} pStatus (optional) <p> - * Status of the appointment:<br> - * <ul> - * <li>calendars.STATUS_TENTATIVE</li> - * <li>calendars.STATUS_CONFIRMED</li> - * <li>calendars.STATUS_CANCELLED</li> - * </ul> - * @param {Date} pReminder (optional) <p> - * Date of the reminder for the appointment. - * @param {String[]} pExternalAttendees (optional) <p> - * External attendees. - * @param {String} pLocation (optional) <p> - * The location of the appointment. - * @param {Boolean} pIsAllDay (optional) <p> - * Whether if it is an all-day appointment or not. - * @param {String} pClassification (optional) <p> - * The classification of the appointment:<br> - * <ul> - * <li>calendars.CLASSIFICATION_PUBLIC</li> - * <li>calendars.CLASSIFICATION_PRIVATE</li> - * </ul> - * @return {void} - */ -CalendarUtil.newSilentEvent = function(pSummary, pDescription, pLinks, pOwner, pAffectedUsers, pStart, pEnd, pCategories, pStatus, - pReminder, pExternalAttendees, pLocation, pIsAllDay, pClassification) -{ - var event = CalendarUtil.createEntry(pSummary, pDescription, pLinks, pOwner, pAffectedUsers, pStart, pEnd, pCategories, pStatus, pReminder, - pExternalAttendees, pLocation, pIsAllDay, pClassification); - - var ids = calendars.insert([event], calendars.GROUP_SINGLE); - - if(pLinks) - { - var conf; - - pLinks.forEach(function(pLink){ - conf = entities.createConfigForAddingRows().entity("AppointmentLink_entity").fieldValues({ - "APPOINTMENT_ID" : ids[0], - "OBJECTID" : pLink["OBJECT_ID"], - "OBJECTTYPE" : pLink["OBJECT_TYPE"] - }); - - entities.createRow(conf); - }); - } -} - -/* - * Creates an new appointment object, which is responsible for holding the data<br> - * till it's used to insert with: calendars.insert (e.g.: in Appointment_entity). - * - * @param {String} pSummary (optional) <p> - * The summary/title of the appointment. - * @param {String} pDescription (optional) <p> - * The description of the appointment. - * @param {Object[]} pLinks (optional) <p> - * The links as objects <u>(key: "OBJECT_ID" & "OBJECT_TYPE")</u> in an array. - * @param {String} pOwner (optional) <p> - * The calendar-user (username) which will be specified as entry-owner. - * @param {String[]} pAffectedUsers (optional) <p> - * The affected users (usernames), which will be added to the appointment. - * @param {Date} pStart (optional) <p> - * Start of the appointment. - * @param {Date} pEnd (optional) <p> - * Duration of the appointment. - * @param {String[]} pCategories (optional) <p> - * The categories of the appointment, the default ones are:<br> - * <ul> - * <li>Meeting</li> - * <li>Organisation</li> - * <li>OutOfOffice</li> - * <li>Vacation</li> - * </ul> - * @param {String} pStatus (optional) Status of the appointment:<br> - * <ul> - * <li>calendars.STATUS_TENTATIVE</li> - * <li>calendars.STATUS_CONFIRMED</li> - * <li>calendars.STATUS_CANCELLED</li> - * </ul> - * @param {Date} pReminder (optional) <p> - * Date of reminder. - * @param {String[]} pExternalAttendees (optional) <p> - * External attendes (e-mail addresses). - * @param {String} pLocation (optional) <p> - * The locations of the appointment. - * @param {Boolean} pIsAllDay (optional) <p> - * Whether if it is an all-day appointment or not. - * @param {String} pClassification (optional) <p> - * The classification of the appointment: - * <ul> - * <li>calendars.CLASSIFICATION_PUBLIC</li> - * <li>calendars.CLASSIFICATION_PRIVATE</li> - * </ul> - * @return {Object} - */ -CalendarUtil.createEntry = function(pSummary, pDescription, pLinks, pOwner, pAffectedUsers, pStart, pEnd, pCategories, pStatus, - pReminder, pExternalAttendees, pLocation, pIsAllDay, pClassification) -{ - var entry = {}; - - entry[calendars.TYPE] = calendars.VEVENT; // hardcoded, cause only other option would be calendars.VTODO for an task - // since tasks are handled via. Task_entity there is no need for the calendars.VTODO option. - - if (!pDescription) - { - if(vars.getString("$sys.scope") == "vaadin") - { - pDescription = neon.getImageContent(vars.getString("$sys.currententityname")); - } - else - { - pDescription = swing.getImageContent(); //todo: check whether it's necessary or not. #1047482 - } - } - - if (!pOwner) - { - pOwner = vars.getString("$sys.user"); - } - - if (!pStart) - { - entry[calendars.DTSTART] = Date.now(); - } - else - { - entry[calendars.DTSTART] = pStart.getTime(); - } - - if (!pEnd) - { - let tempStartdate = entry[calendars.DTSTART]; - entry[calendars.DTEND] = tempStartdate.setHours(tempStartdate.getHours()+1); - } - else - { - entry[calendars.DTEND] = pEnd.getTime().toString(); - } - - if (!pCategories || pCategories == []) - { - pCategories = ""; - } - else - { - for (i = 0; i < pCategories.length; i++) - { - pCategories[i] = translate.text(pCategories[i]); - } - - pCategories = text.encodeMS(pCategories); - } - - if ((pAffectedUsers == null || pAffectedUsers == undefined) && (pExternalAttendees == null || pExternalAttendees == undefined)) - { - entry[calendars.AFFECTEDUSERS] = ""; - } - else - { - var affectedUsers = []; - - if(pAffectedUsers && pAffectedUsers != []) - { - affectedUsers = calendars.getCalendarUsers(pAffectedUsers); - } - - if(pExternalAttendees && pExternalAttendees != []) - { - for(let i = 0; i < pExternalAttendees.length; i++) - { - affectedUsers.push("; mailto:" + pExternalAttendees[i] + "; CN:" + pExternalAttendees[i] + "; ") - } - } - - entry[calendars.AFFECTEDUSERS] = text.encodeMS(affectedUsers); - } - - if (!pStatus) - { - pStatus = calendars.STATUS_CONFIRMED; - } - - if(!pReminder) - { - entry[calendars.HASREMINDER] = "true"; - entry[calendars.REMINDER_DURATION] = pReminder.getTime().toString(); - } - else - { - entry[calendars.HASREMINDER] = "false"; - } - - if(pLinks) - { - entry["LINKS"] = pLinks; - } - - entry[calendars.USER] = calendars.getCalendarUser(pOwner); - entry[calendars.DESCRIPTION] = pDescription; - entry[calendars.SUMMARY] = pSummary || ""; - entry[calendars.STATUS] = CalendarUtil.mapCalendarStatus(pStatus, calendars.getBackendType()); - entry[calendars.CLASSIFICATION] = pClassification || calendars.CLASSIFICATION_PUBLIC; - entry[calendars.CATEGORIES] = pCategories; - entry[calendars.TRANSPARENCY] = "OPAQUE"; - entry[calendars.LOCATION] = pLocation || ""; - entry["X-ADITO-ISALLDAYEVENT"] = pIsAllDay ? "TRUE" : "FALSE"; - entry[calendars.DTSTART] = entry[calendars.DTSTART].toString(); - - return entry; -} - -/* - * Add an condition.<br> - * - * @param {[]} pConditions <p> - * The condition.<br> - * @param {Integer} pIndex <p> - * Index of the condition.<br> - * @param {Object} pValues <p> - * The values.<br> - * @return {void} - */ -CalendarUtil.addEntryCondition = function(pConditions, pIndex, pValues) -{ - var params = ["TYPE", "START", "END", "USER", "STATUS", "UID"]; - - for (var i = 0; i < params.length; i++) - if (pValues[params[i]] != undefined) pConditions[params[i] + "_" + pIndex] = pValues[params[i]]; -} - -/* - * Returns the date without the time.<br> - * - * @param {String} datetimeIn <p> - * Datetime.<br> - * @return {Date} <p> - * The desired date.<br> - */ -CalendarUtil.getDate = function(datetimeIn) -{ - if ( datetimeIn != "") - return datetime.clearTime(datetimeIn); - else return ""; -} - -/* - * Resets the event filter.<br> - * - * @return {Object} - */ -CalendarUtil.reset_filterEvent = function() -{ - var today = CalendarUtil.getDate(vars.getString("$sys.date")); - - return pFilter = { - user: vars.getString("$sys.user"), - datefrom: String(today), //nur die Termine ab heute anzeigen, - //die von vor einer Woche sind uninteressant - dateto: String(eMath.addInt(eMath.addInt(today, datetime.ONE_WEEK) - ,datetime.ONE_DAY - datetime.ONE_MINUTE)), - category: "", - tentative: "true", - confirmed: "true", - cancelled: "", - free: "true" - }; -} - -/* - * Gibt den richtigen Status zum Prüfen je nach Backend zurück - * Returns the matching status, to the corresponding backend. - * - * - * @param {String} pStatus req die konstante für den zu prüfenden status, - * z.B. calendars.STATUS_INPROCESS - * - * @param {String} pCalendarType req die konstante für den typen des Termin- oder Aufgabenbackends, - * z.B. calendars.BACKEND_DB - * - * @return {String} Konstanten für den Kalender (Backend-Typen), gibt es den status im backend nicht - * wird null geliefert - */ -CalendarUtil.mapCalendarStatus = function(pStatus, pCalendarType) -{ - switch (pCalendarType) - { - //case calendars.BACKEND_EXCHANGE: - case calendars.BACKEND_EXCHANGEWS: - if (pStatus == calendars.STATUS_CONFIRMED) - return calendars.STATUS_BUSY; - else - return pStatus; - default: - if (pStatus == calendars.STATUS_OOF)//nur bei exchange - return null; - else - return pStatus; - } -} - -/** - * Returns the "real" calendar system/backend type<br> - * (e.g.: BackendType & SyncBackendType) - * - * @param {Number} pScope <p> - * The needed scope:<br> - * <ul> - * <li>calendars.VEVENT</li> - * <li>calendars.VTODO</li> - * </ul> - * @return {Number} <p> - * The backend type (e.g.: calendars.BACKEND_*).<br> - */ -CalendarUtil.getCalendarSystemType = function(pScope) -{ - // Check sync backend type - if (calendars.getSyncBackendType() != calendars.BACKEND_NONE && calendars.getSyncBackendType() != 3) - { - var scope = calendars.getSyncBackendTypeScope(); - if (scope.length == 1 && scope[0] == pScope) // Scope.length = 1 -> VEVENT *OR* VTODO - return calendars.getSyncBackendType(); - else if (scope.length == 2) // Scope.length = 2 -> Both - return calendars.getSyncBackendType(); - // Scope.length = 0 -> Nothing selected -> Skip this block - } - - // Fallback to backend type (event) - if (calendars.getBackendType() != calendars.BACKEND_NONE && pScope === calendars.VEVENT) - return calendars.getBackendType(); - - // Second fallback to backend type (todo) - if (calendars.getBackendTypeTasks() != calendars.BACKEND_NONE && pScope === calendars.VTODO) - return calendars.getBackendTypeTasks(); - - // Everything is none - return calendars.BACKEND_NONE; -} - -CalendarUtil.buildEntriesFromUids = function(appointmentUids) -{ - var entryArray = new Array(appointmentUids.length); - - for(var i = 0; i < appointmentUids.length; i++) - { - var hasPermission = true; - - if(vars.get("$param.ErrorOnPermissionDenied") == "false" || vars.getString("$param.LinkedAppointmentsFromDashlet_param")) - hasPermission = hasUserPermissionForReadingEntry(getEntryOwnerCn(appointmentUids[i])); - - if(hasPermission) - entryArray[i] = CalendarUtil.buildEntry(calendars.getEntry(appointmentUids[i], null, null), null); - } - - //filter out all null - var filteredEntryArray = entryArray.filter(function (el) { - return el != null; - }); - - return filteredEntryArray; -} - - -CalendarUtil.countEntriesFromUids = function(appointmentUids) -{ - return CalendarUtil.buildEntriesFromUids(appointmentUids).length; -} - -CalendarUtil.buildEntry = function (pEntry, pMasterentry) -{ - var uid = pEntry[calendars.ID]; - var summary = pEntry[calendars.SUMMARY]; - var attendees = pEntry[calendars.AFFECTEDUSERS]; - var startdate = pEntry[calendars.DTSTART]; - var enddate = pEntry[calendars.DTEND]; - var links = pEntry[calendars.LINKS]; - var description = pEntry[calendars.DESCRIPTION]; - if(pEntry[calendars.ORGANIZER2] != undefined) - var organizer = pEntry[calendars.ORGANIZER2]["paramvalue"]; - if(pEntry[calendars.USER2] != undefined) - var owner = JSON.stringify(pEntry[calendars.USER2]); - var status = pEntry[calendars.STATUS]; - var location = pEntry[calendars.LOCATION]; - var reminder = pEntry[calendars.REMINDER_DURATION]; - var remindercheck = pEntry[calendars.HASREMINDER] - var classification = pEntry[calendars.CLASSIFICATION]; - var transparency = pEntry[calendars.TRANSPARENCY]; - var categories = pEntry[calendars.CATEGORIES]; - var isAllDay = pEntry["X-ADITO-ISALLDAYEVENT"] != null ? pEntry["X-ADITO-ISALLDAYEVENT"] : "FALSE"; - - var masterBegin = pMasterentry != null ? pMasterentry[calendars.DTSTART] : null - var masterEnd = pMasterentry != null ? pMasterentry[calendars.DTEND] : null - - // Recurrence - var recurrenceID = pEntry[calendars.RECURRENCEID]; - var rrule = null; - if (pMasterentry != null) { // Entry is a recurrence exception, therefore get rrule from master - rrule = pMasterentry[calendars.RRULE] != null ? pMasterentry[calendars.RRULE][0] : null; - } else { - rrule = pEntry[calendars.RRULE] != null ? pEntry[calendars.RRULE][0] : null; - } - - return [ - uid, - attendees.length, - startdate, - enddate, - summary, - organizer, - owner, - attendees, - status, - description, - location, - '', - isAllDay, - classification, - transparency, - categories, - reminder, - remindercheck, - rrule, - recurrenceID, - null, - masterBegin, - masterEnd, - null - ]; -} - - -function hasUserPermissionForReadingEntry(calUserCn) -{ - return calendars.hasPermission(calUserCn, calendars.VEVENT, "READ"); -} - -function getEntryOwnerCn(appointmentUid) -{ - - var owner = newSelect("ASYS_CALENDARBACKEND.OWNER", "_____SYSTEMALIAS") - .from("ASYS_CALENDARBACKEND") - .whereIfSet("ASYS_CALENDARBACKEND.ELEMENTUID", appointmentUid) - .cell(true); - - var ownerArr = text.decodeMS(owner); - return ownerArr[1].split(":")[1]; +import("system.translate"); +import("system.datetime"); +import("system.neon"); +import("system.calendars"); +import("system.vars"); +import("system.db"); +import("system.swing"); +import("system.eMath"); +import("system.logging"); +import("system.tools"); +import("system.text"); +import("system.question"); +import("system.SQLTYPES"); +import("system.result"); +import("system.util"); +import("system.entities"); +import("Util_lib"); +import("Sql_lib"); + + +/** + * Functions for the calendar. + * <p> + * <b><u>Do not create an instance of this!</u></b> + * @class + */ +function CalendarUtil(){} + + +/* + * Creates and opens an new task object (with link). + * + * @param {String} pSummary (optional) <p> + * The summary.<br> + * @param {String} pDescription (optional) <p> + * The description.<br> + * @param {Boolean} pWithLink (optional) Case if its true, then an a shortcut to $image.frametable will created.<br> + * @param {String[][]} pWithLink (optional) <p> + * The required informations:<br> + * <ul> + * <li>pWithLink[0]: Name of the frame.</li> + * <li>pWithLink[1]: Id of the shown record.</li> + * <li>pWithLink[2]: Linking title.</li> + * @param {String} pUser (optional) <p> + * The user (login).<br> + * @param {[]} pAffectedUsers (optional) <p> + * The affected users. (login)<br> + * @param {date} pStart (optional) <p> + * Start of the task.<br> + * @param {date} pDuration (optional) <p> + * Duration of the task.<br> + * @param {integer} pCategory (optional) <p> + * calendars.CATEGORIES , encoded(String) (e.g.: text.encodeMS(["Service"])) + * @param {String} pStatus (optional) <p> + * Status of the appointment. (calendars.STATUS_TENTATIVE, <br> + * calendars.STATUS_CONFIRMED, calendars.STATUS_CANCELLED)<br> + * @param {Array{[]} pComps4Refresh (optional) <p> + * The component which will be updated.<br> + * + * @return {void} + */ +CalendarUtil.newTodo = function(pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus, pComps4Refresh) +{ + var todo = CalendarUtil.createEntry( calendars.VTODO, pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus ); + var prompts = []; + prompts["comp4refresh"] = []; + + if (pComps4Refresh == undefined) + pComps4Refresh = ["$comp.Aufgabe", "$comp.tbl_Aufgabe"]; + + for (var i = 0; i < pComps4Refresh.length; i++) + { + if ( vars.exists(pComps4Refresh[i])) prompts["comp4refresh"].push(pComps4Refresh[i]); + } + if(vars.getString("$sys.scope") == "vaadin") + neon.openCalendarEntry([todo], null, neon.OPERATINGSTATE_NEW, null) + else + { + if (vars.exists("$sys.currentwindow")) + prompts["window"] = vars.getString("$sys.currentwindow"); + if (vars.exists("$sys.currentimage")) + prompts["image"] = vars.getString("$sys.currentimage"); + + swing.openCalendarEntry([todo], null, false, prompts); + } +} + + +/** + * Finds the effective calendarId of an user in the same <br> + * attribute order like the ADITO core, which is:<br> + * <p> + * exchangeEmail -> calendarID -> email<br> + * <p> + * <b><u>DO NOT CHANGE THIS ORDER!</u></b> + * + * @param {String} pUser <p> + * To check. + * @return <p> + * Effective calendar id.<br> + */ +CalendarUtil.getEffectiveCalendarIdFromUser = function(pUser) +{ + var userParams = pUser["params"]; + + var resolvedCurrentUser; + var exchangeEmail = userParams["exchangeEMail"]; + var calendarId = userParams["calendarID"]; + var email = userParams["email"]; + + if(exchangeEmail) + return exchangeEmail; + else if(calendarId) + return calendarId; + else if(email) + return email; + else + return ""; +} + + +/* + * Creates and opens an new appointment object (with link). + * + * @param {String} pSummary (optional) <p> + * The summary.<br> + * @param {String} pDescription (optional) <p> + * The description.<br> + * @param {Boolean} pWithLink (optional) <p> + * True sets an link to $image.frametable<br> + * @param {String[][]} pWithLink (optional) Description:<br> + * <ul> + * <li>pWithLink[0]: Name of the frame</li> + * <li>pWithLink[1]: Id of the shown record</li> + * <li>pWithLink[2]: linking title</li> + * </ul> + * @param {String} pUser (optional) <p> + * The user (login). + * @param {[]} pAffectedUsers (optional) <p> + * The affected users (login). + * @param {Date} pStart (optional) <p> + * Begin of the task.<br> + * @param {Date} pDuration (optional) <p> + * Duration.<br> + * @param {Number} pCategory (optional) <p> + * calendars.CATEGORIES , encoded(String) (z.B.: text.encodeMS(["Service"])).<br> + * @param {String} pStatus (optional) <p> + * Status of the appointment:<br> + * <ul> + * <li>calendars.STATUS_TENTATIVE</li> + * <li>calendars.STATUS_CONFIRMED</li> + * <li>calendars.STATUS_CANCELLED</li> + * </ul> + * @param {Array{[]} pComps4Refresh (optional) <p> + * The component which will be updated.<br> + * @param {Array{[]} pWorklistId (optional) <p> + * The worklist id.<br> + * + * @return {void} + */ +CalendarUtil.newEvent = function( pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus, pComps4Refresh, pWorklistId) +{ + var event = CalendarUtil.createEntry( calendars.VEVENT, pSummary, pDescription, pWithLink, pUser, pAffectedUsers, pStart, pDuration, pCategory, pStatus ); + + var prompts = []; + prompts["comp4refresh"] = []; + if (pComps4Refresh == undefined) + pComps4Refresh = ["$comp.Aufgabe", "$comp.tbl_Termine"]; + for (let i = 0; i < pComps4Refresh.length; i++) + { + if ( vars.exists(pComps4Refresh[i])) prompts["comp4refresh"].push(pComps4Refresh[i]); + } + + if(vars.getString("$sys.scope") == "vaadin") + neon.openCalendarEntry([event],"", neon.OPERATINGSTATE_NEW, null) + else + { + prompts["window"] = vars.getString("$sys.currentwindow"); + prompts["image"] = vars.getString("$sys.currentimage"); + if (pWorklistId != undefined) + prompts["worklistId"] = pWorklistId; + swing.openCalendarEntry([event], null, false, prompts); + } +} + + +/* + * Creates an new appointment entry. + * + * @param {String} pSummary (optional) <p> + * The summary/title of the appointment. + * @param {String} pDescription (optional) <p> + * The appointment description. + * @param {String} pLinks (optional) <p> + * The links as objects <u>(key: "OBJECT_ID" & "OBJECT_TYPE")</u> in an array. + * @param {String} pOwner (optional) <p> + * The calendar-user (username) which will be specified as entry-owner. + * @param {String[]} pAffectedUsers (optional) <p> + * The affected users (username). + * @param {Date} pStart (optional) <p> + * The start of the appointment. + * @param {Date} pEnd (optional) <p> + * The end of the appointment. + * @param {String[]} pCategories (optional) <p> + * The categories of the appointment, the default ones are:<br> + * <ul> + * <li>Meeting</li> + * <li>Organisation</li> + * <li>OutOfOffice</li> + * <li>Vacation</li> + * </ul> + * @param {String} pStatus (optional) <p> + * Status of the appointment:<br> + * <ul> + * <li>calendars.STATUS_TENTATIVE</li> + * <li>calendars.STATUS_CONFIRMED</li> + * <li>calendars.STATUS_CANCELLED</li> + * </ul> + * @param {Date} pReminder (optional) <p> + * Date of the reminder for the appointment. + * @param {String[]} pExternalAttendees (optional) <p> + * External attendees. + * @param {String} pLocation (optional) <p> + * The location of the appointment. + * @param {Boolean} pIsAllDay (optional) <p> + * Whether if it is an all-day appointment or not. + * @param {String} pClassification (optional) <p> + * The classification of the appointment:<br> + * <ul> + * <li>calendars.CLASSIFICATION_PUBLIC</li> + * <li>calendars.CLASSIFICATION_PRIVATE</li> + * </ul> + * @return {void} + */ +CalendarUtil.newSilentEvent = function(pSummary, pDescription, pLinks, pOwner, pAffectedUsers, pStart, pEnd, pCategories, pStatus, + pReminder, pExternalAttendees, pLocation, pIsAllDay, pClassification) +{ + var event = CalendarUtil.createEntry(pSummary, pDescription, pLinks, pOwner, pAffectedUsers, pStart, pEnd, pCategories, pStatus, pReminder, + pExternalAttendees, pLocation, pIsAllDay, pClassification); + + var ids = calendars.insert([event], calendars.GROUP_SINGLE); + + if(pLinks) + { + var conf; + + pLinks.forEach(function(pLink){ + conf = entities.createConfigForAddingRows().entity("AppointmentLink_entity").fieldValues({ + "APPOINTMENT_ID" : ids[0], + "OBJECTID" : pLink["OBJECT_ID"], + "OBJECTTYPE" : pLink["OBJECT_TYPE"] + }); + + entities.createRow(conf); + }); + } +} + +/* + * Creates an new appointment object, which is responsible for holding the data<br> + * till it's used to insert with: calendars.insert (e.g.: in Appointment_entity). + * + * @param {String} pSummary (optional) <p> + * The summary/title of the appointment. + * @param {String} pDescription (optional) <p> + * The description of the appointment. + * @param {Object[]} pLinks (optional) <p> + * The links as objects <u>(key: "OBJECT_ID" & "OBJECT_TYPE")</u> in an array. + * @param {String} pOwner (optional) <p> + * The calendar-user (username) which will be specified as entry-owner. + * @param {String[]} pAffectedUsers (optional) <p> + * The affected users (usernames), which will be added to the appointment. + * @param {Date} pStart (optional) <p> + * Start of the appointment. + * @param {Date} pEnd (optional) <p> + * Duration of the appointment. + * @param {String[]} pCategories (optional) <p> + * The categories of the appointment, the default ones are:<br> + * <ul> + * <li>Meeting</li> + * <li>Organisation</li> + * <li>OutOfOffice</li> + * <li>Vacation</li> + * </ul> + * @param {String} pStatus (optional) Status of the appointment:<br> + * <ul> + * <li>calendars.STATUS_TENTATIVE</li> + * <li>calendars.STATUS_CONFIRMED</li> + * <li>calendars.STATUS_CANCELLED</li> + * </ul> + * @param {Date} pReminder (optional) <p> + * Date of reminder. + * @param {String[]} pExternalAttendees (optional) <p> + * External attendes (e-mail addresses). + * @param {String} pLocation (optional) <p> + * The locations of the appointment. + * @param {Boolean} pIsAllDay (optional) <p> + * Whether if it is an all-day appointment or not. + * @param {String} pClassification (optional) <p> + * The classification of the appointment: + * <ul> + * <li>calendars.CLASSIFICATION_PUBLIC</li> + * <li>calendars.CLASSIFICATION_PRIVATE</li> + * </ul> + * @return {Object} + */ +CalendarUtil.createEntry = function(pSummary, pDescription, pLinks, pOwner, pAffectedUsers, pStart, pEnd, pCategories, pStatus, + pReminder, pExternalAttendees, pLocation, pIsAllDay, pClassification) +{ + var entry = {}; + + entry[calendars.TYPE] = calendars.VEVENT; // hardcoded, cause only other option would be calendars.VTODO for an task + // since tasks are handled via. Task_entity there is no need for the calendars.VTODO option. + + if (!pDescription) + { + if(vars.getString("$sys.scope") == "vaadin") + { + pDescription = neon.getImageContent(vars.getString("$sys.currententityname")); + } + else + { + pDescription = swing.getImageContent(); //todo: check whether it's necessary or not. #1047482 + } + } + + if (!pOwner) + { + pOwner = vars.getString("$sys.user"); + } + + if (!pStart) + { + entry[calendars.DTSTART] = Date.now(); + } + else + { + entry[calendars.DTSTART] = pStart.getTime(); + } + + if (!pEnd) + { + let tempStartdate = entry[calendars.DTSTART]; + entry[calendars.DTEND] = tempStartdate + datetime.ONE_HOUR; + } + else + { + entry[calendars.DTEND] = pEnd.getTime().toString(); + } + + if (!pCategories || pCategories == []) + { + pCategories = ""; + } + else + { + for (i = 0; i < pCategories.length; i++) + { + pCategories[i] = translate.text(pCategories[i]); + } + + pCategories = text.encodeMS(pCategories); + } + + if ((pAffectedUsers == null || pAffectedUsers == undefined) && (pExternalAttendees == null || pExternalAttendees == undefined)) + { + entry[calendars.AFFECTEDUSERS] = ""; + } + else + { + var affectedUsers = []; + affectedUsers.push(calendars.getCalendarUser(vars.get("$sys.user"))); + + if(pAffectedUsers && pAffectedUsers != []) + { + affectedUsers = calendars.getCalendarUsers(pAffectedUsers); + } + + if(pExternalAttendees && pExternalAttendees != []) + { + for(let i = 0; i < pExternalAttendees.length; i++) + { + affectedUsers.push("; mailto:" + pExternalAttendees[i] + "; CN:" + pExternalAttendees[i] + "; ") + } + } + + entry[calendars.AFFECTEDUSERS] = text.encodeMS(affectedUsers); + } + + if (!pStatus) + { + pStatus = calendars.STATUS_CONFIRMED; + } + + if(pReminder) + { + entry[calendars.HASREMINDER] = "true"; + entry[calendars.REMINDER_DURATION] = pReminder.getTime().toString(); + } + else + { + entry[calendars.HASREMINDER] = "false"; + } + + if(pLinks) + { + entry["LINKS"] = pLinks; + } + + entry[calendars.USER] = calendars.getCalendarUser(pOwner); + entry[calendars.DESCRIPTION] = pDescription; + entry[calendars.SUMMARY] = pSummary || ""; + entry[calendars.STATUS] = CalendarUtil.mapCalendarStatus(pStatus, calendars.getBackendType()); + entry[calendars.CLASSIFICATION] = pClassification || calendars.CLASSIFICATION_PUBLIC; + entry[calendars.CATEGORIES] = pCategories; + entry[calendars.TRANSPARENCY] = "OPAQUE"; + entry[calendars.LOCATION] = pLocation || ""; + entry["X-ADITO-ISALLDAYEVENT"] = pIsAllDay ? "TRUE" : "FALSE"; + entry[calendars.DTSTART] = entry[calendars.DTSTART].toString(); + + return entry; +} + +/* + * Add an condition.<br> + * + * @param {[]} pConditions <p> + * The condition.<br> + * @param {Integer} pIndex <p> + * Index of the condition.<br> + * @param {Object} pValues <p> + * The values.<br> + * @return {void} + */ +CalendarUtil.addEntryCondition = function(pConditions, pIndex, pValues) +{ + var params = ["TYPE", "START", "END", "USER", "STATUS", "UID"]; + + for (var i = 0; i < params.length; i++) + if (pValues[params[i]] != undefined) pConditions[params[i] + "_" + pIndex] = pValues[params[i]]; +} + +/* + * Returns the date without the time.<br> + * + * @param {String} datetimeIn <p> + * Datetime.<br> + * @return {Date} <p> + * The desired date.<br> + */ +CalendarUtil.getDate = function(datetimeIn) +{ + if ( datetimeIn != "") + return datetime.clearTime(datetimeIn); + else return ""; +} + +/* + * Resets the event filter.<br> + * + * @return {Object} + */ +CalendarUtil.reset_filterEvent = function() +{ + var today = CalendarUtil.getDate(vars.getString("$sys.date")); + + return pFilter = { + user: vars.getString("$sys.user"), + datefrom: String(today), //nur die Termine ab heute anzeigen, + //die von vor einer Woche sind uninteressant + dateto: String(eMath.addInt(eMath.addInt(today, datetime.ONE_WEEK) + ,datetime.ONE_DAY - datetime.ONE_MINUTE)), + category: "", + tentative: "true", + confirmed: "true", + cancelled: "", + free: "true" + }; +} + +/* + * Gibt den richtigen Status zum Prüfen je nach Backend zurück + * Returns the matching status, to the corresponding backend. + * + * + * @param {String} pStatus req die konstante für den zu prüfenden status, + * z.B. calendars.STATUS_INPROCESS + * + * @param {String} pCalendarType req die konstante für den typen des Termin- oder Aufgabenbackends, + * z.B. calendars.BACKEND_DB + * + * @return {String} Konstanten für den Kalender (Backend-Typen), gibt es den status im backend nicht + * wird null geliefert + */ +CalendarUtil.mapCalendarStatus = function(pStatus, pCalendarType) +{ + switch (pCalendarType) + { + //case calendars.BACKEND_EXCHANGE: + case calendars.BACKEND_EXCHANGEWS: + if (pStatus == calendars.STATUS_CONFIRMED) + return calendars.STATUS_BUSY; + else + return pStatus; + default: + if (pStatus == calendars.STATUS_OOF)//nur bei exchange + return null; + else + return pStatus; + } +} + +/** + * Returns the "real" calendar system/backend type<br> + * (e.g.: BackendType & SyncBackendType) + * + * @param {Number} pScope <p> + * The needed scope:<br> + * <ul> + * <li>calendars.VEVENT</li> + * <li>calendars.VTODO</li> + * </ul> + * @return {Number} <p> + * The backend type (e.g.: calendars.BACKEND_*).<br> + */ +CalendarUtil.getCalendarSystemType = function(pScope) +{ + // Check sync backend type + if (calendars.getSyncBackendType() != calendars.BACKEND_NONE && calendars.getSyncBackendType() != 3) + { + var scope = calendars.getSyncBackendTypeScope(); + if (scope.length == 1 && scope[0] == pScope) // Scope.length = 1 -> VEVENT *OR* VTODO + return calendars.getSyncBackendType(); + else if (scope.length == 2) // Scope.length = 2 -> Both + return calendars.getSyncBackendType(); + // Scope.length = 0 -> Nothing selected -> Skip this block + } + + // Fallback to backend type (event) + if (calendars.getBackendType() != calendars.BACKEND_NONE && pScope === calendars.VEVENT) + return calendars.getBackendType(); + + // Second fallback to backend type (todo) + if (calendars.getBackendTypeTasks() != calendars.BACKEND_NONE && pScope === calendars.VTODO) + return calendars.getBackendTypeTasks(); + + // Everything is none + return calendars.BACKEND_NONE; +} + +CalendarUtil.buildEntriesFromUids = function(appointmentUids) +{ + var entryArray = new Array(appointmentUids.length); + + for(var i = 0; i < appointmentUids.length; i++) + { + var hasPermission = true; + + if(vars.get("$param.ErrorOnPermissionDenied") == "false" || vars.getString("$param.LinkedAppointmentsFromDashlet_param")) + hasPermission = hasUserPermissionForReadingEntry(getEntryOwnerCn(appointmentUids[i])); + + if(hasPermission) + entryArray[i] = CalendarUtil.buildEntry(calendars.getEntry(appointmentUids[i], null, null), null); + } + + //filter out all null + var filteredEntryArray = entryArray.filter(function (el) { + return el != null; + }); + + return filteredEntryArray; +} + + +CalendarUtil.countEntriesFromUids = function(appointmentUids) +{ + return CalendarUtil.buildEntriesFromUids(appointmentUids).length; +} + +CalendarUtil.buildEntry = function (pEntry, pMasterentry) +{ + var uid = pEntry[calendars.ID]; + var summary = pEntry[calendars.SUMMARY]; + var attendees = pEntry[calendars.AFFECTEDUSERS]; + var startdate = pEntry[calendars.DTSTART]; + var enddate = pEntry[calendars.DTEND]; + var links = pEntry[calendars.LINKS]; + var description = pEntry[calendars.DESCRIPTION]; + if(pEntry[calendars.ORGANIZER2] != undefined) + var organizer = pEntry[calendars.ORGANIZER2]["paramvalue"]; + if(pEntry[calendars.USER2] != undefined) + var owner = JSON.stringify(pEntry[calendars.USER2]); + var status = pEntry[calendars.STATUS]; + var location = pEntry[calendars.LOCATION]; + var reminder = pEntry[calendars.REMINDER_DURATION]; + var remindercheck = pEntry[calendars.HASREMINDER] + var classification = pEntry[calendars.CLASSIFICATION]; + var transparency = pEntry[calendars.TRANSPARENCY]; + var categories = pEntry[calendars.CATEGORIES]; + var isAllDay = pEntry["X-ADITO-ISALLDAYEVENT"] != null ? pEntry["X-ADITO-ISALLDAYEVENT"] : "FALSE"; + + var masterBegin = pMasterentry != null ? pMasterentry[calendars.DTSTART] : null + var masterEnd = pMasterentry != null ? pMasterentry[calendars.DTEND] : null + + // Recurrence + var recurrenceID = pEntry[calendars.RECURRENCEID]; + var rrule = null; + if (pMasterentry != null) { // Entry is a recurrence exception, therefore get rrule from master + rrule = pMasterentry[calendars.RRULE] != null ? pMasterentry[calendars.RRULE][0] : null; + } else { + rrule = pEntry[calendars.RRULE] != null ? pEntry[calendars.RRULE][0] : null; + } + + return [ + uid, + attendees.length, + startdate, + enddate, + summary, + organizer, + owner, + attendees, + status, + description, + location, + '', + isAllDay, + classification, + transparency, + categories, + reminder, + remindercheck, + rrule, + recurrenceID, + null, + masterBegin, + masterEnd, + null + ]; +} + + +function hasUserPermissionForReadingEntry(calUserCn) +{ + return calendars.hasPermission(calUserCn, calendars.VEVENT, "READ"); +} + +function getEntryOwnerCn(appointmentUid) +{ + + var owner = newSelect("ASYS_CALENDARBACKEND.OWNER", "_____SYSTEMALIAS") + .from("ASYS_CALENDARBACKEND") + .whereIfSet("ASYS_CALENDARBACKEND.ELEMENTUID", appointmentUid) + .cell(true); + + var ownerArr = text.decodeMS(owner); + return ownerArr[1].split(":")[1]; } \ No newline at end of file diff --git a/process/ChecklistEntryRegistry_basic/process.js b/process/ChecklistEntryRegistry_basic/process.js index 6c0844894e10196c30f9f3ea2dddedcf782f65be..50d93855904af185fe9bce7b36dfa55ad59f2e6a 100644 --- a/process/ChecklistEntryRegistry_basic/process.js +++ b/process/ChecklistEntryRegistry_basic/process.js @@ -1,5 +1,5 @@ +import("Attribute_lib"); import("Keyword_lib"); -import("system.logging"); import("system.eMath"); import("system.datetime"); import("system.translate"); @@ -407,3 +407,118 @@ $ChecklistEntryRegistry.salesprojectContractExists = function(){ } }; } + +/* + * Checks whether the project team roles: + * Initiator, Decition Maker, Influencer, User, Buyer + * are filled for the given salesproject. + */ +$ChecklistEntryRegistry.salesprojectRoleProjectteam = function(){ + return{ + title: translate.text("Project team"), + verifierFn: function(pSalesprojectId){ + var spRows = $ChecklistEntryRegistry._getRows(pSalesprojectId, "Salesproject_entity", ["SALESPROJECTID", "MST_TEAM_ID", "PROJECTCODE"], null, "NoPhaseRequirementLoading"); + var memberRows = $ChecklistEntryRegistry._getRows(null, "Member_entity", ["MEMBERROLE"], [["EnableMSTeams_param", spRows[0]["MST_TEAM_ID"]], + ["ObjectRowId_param", spRows[0]["SALESPROJECTID"]]], "WithDistrictResponsibles"); + var roles = ["MEMROLEINITIATOR", "MEMROLEDECISIONMAKER", "MEMROLEADVISE", "MEMROLEUSER", "MEMROLEEXSALEMANAG"]; + + for (let i = 0; i < memberRows.length; i++) + { + var role = memberRows[i]["MEMBERROLE"]; + var index = roles.indexOf(role); + if (index !== -1) + { + roles.splice(index, 1); + } + } + return roles.length == 0; + } + }; +} + +/* + * Further customer discussions + * (= activity for the category visit, telephone or online meeting has been created) + */ +$ChecklistEntryRegistry.salesprojectFurtherCustomerMeetings = function(){ + return{ + title: translate.text("Further customer meetings"), + verifierFn: function(pSalesprojectId){ + var activityCount = newSelect("count(*)").from("ACTIVITYLINK") + .join("ACTIVITY", newWhere("ACTIVITY.ACTIVITYID = ACTIVITYLINK.ACTIVITY_ID")) + .where("ACTIVITYLINK.OBJECT_TYPE", "Salesproject") + .and("ACTIVITYLINK.OBJECT_ROWID", pSalesprojectId) + .and("ACTIVITY.CATEGORY", [ + $KeywordRegistry.activityCategory$visit(), + $KeywordRegistry.activityCategory$phone(), + $KeywordRegistry.activityCategory$onlineMeeting() + ], SqlBuilder.IN()).cell(); + return parseInt(activityCount) > 0; + } + }; +} + +/* + * Prioritization based on segmentation parameters + * (Explanation: there are 4 segmentation parameters in the standard: + * Industry, company size, country, feasibility assessment. + * These 4 parameters prioritize the project as A, B, C, D project. In the lead phase, + * the segmentation must be supplemented by the feasibility the result is the segmentation A, B, C, D). + */ +$ChecklistEntryRegistry.salesprojectSegmentPrio = function(){ + return{ + title: translate.text("Prioritization based on segmentation parameters"), + verifierFn: function(pSalesprojectId){ + var classificStr = newSelect("CLASSIFICATIONVALUE") + .from("CLASSIFICATIONSTORAGE") + .where("CLASSIFICATIONSTORAGE.OBJECT_TYPE", "Salesproject") + .and("CLASSIFICATIONSTORAGE.OBJECT_ROWID", pSalesprojectId).cell() || "-"; + return classificStr.indexOf("-") === -1; + } + }; +} + +/** + * First customer conversation: Activity for personal contact created + * (= activity for the category visit, telephone or online meeting is created) + */ +$ChecklistEntryRegistry.salesprojectFirstCustConv = function(){ + return{ + title: translate.text("First customer conversation"), + verifierFn: function(pSalesprojectId){ + var activitiesSubSql = newSelect("ACTIVITY.ACTIVITYID").from("ACTIVITYLINK") + .join("ACTIVITY", newWhere("ACTIVITY.ACTIVITYID = ACTIVITYLINK.ACTIVITY_ID")) + .where("ACTIVITYLINK.OBJECT_TYPE", "Salesproject") + .and("ACTIVITYLINK.OBJECT_ROWID", pSalesprojectId) + .and("ACTIVITY.CATEGORY", [ + $KeywordRegistry.activityCategory$visit(), + $KeywordRegistry.activityCategory$phone(), + $KeywordRegistry.activityCategory$onlineMeeting() + ], SqlBuilder.IN()); + + var activityCount = newSelect("count(*)").from("ACTIVITYLINK") + .where("ACTIVITYLINK.ACTIVITY_ID", activitiesSubSql, SqlBuilder.IN()); + return parseInt(activityCount.cell()) > 0; + } + }; +} + +/** + * Automatic: Source / origin of the generation of contacts is known + * and stored as a property for a new sales project (e.g. website, recommendation, etc.) + */ +$ChecklistEntryRegistry.salesprojectContactsGenerationSource = function(){ + return{ + title: translate.text("Source / origin of the generation of contacts"), + verifierFn: function(pSalesprojectId){ + return parseInt(AttributeRelationUtils.getAttributeSqlBuilder( + ["count(*)"], + pSalesprojectId, + "Salesproject" + ) + .and("AB_ATTRIBUTE.ATTRIBUTE_PARENT_ID", "d0ae40d2-1a7f-45f6-bb0c-20ce6ae7efe2") + .cell() + ) > 0; + } + }; +} diff --git a/process/ClassificationFilter_lib/process.js b/process/ClassificationFilter_lib/process.js index d99652fcf5c671b48ff348ea8cc7b6d9c9a1a7bc..bf51b65574f70c95dfa2efeaa3bceb561751dbc5 100644 --- a/process/ClassificationFilter_lib/process.js +++ b/process/ClassificationFilter_lib/process.js @@ -270,10 +270,12 @@ ClassificationGroupFilterUtils.getFilterFields = function(pObjectType) }); return JSON.stringify(res); }; - -ClassificationGroupFilterUtils.makeFilterFields = function() +/* +*@param {String} pAlternativeContext If anoter context instead of the current context should be used, the context can be specified with this parameter. +*/ +ClassificationGroupFilterUtils.makeFilterFields = function(pAlternativeContext) { - var objectType = ContextUtils.getCurrentContextId(); + var objectType = pAlternativeContext || ContextUtils.getCurrentContextId(); var res = ClassificationGroupFilterUtils.getFilterFields(objectType); return res; }; diff --git a/process/Email_lib/process.js b/process/Email_lib/process.js index 8f560c533ad7994e8b1896715b41ee6aabb311b6..61787a5d831ae07d315df9530951b04849e2b560 100644 --- a/process/Email_lib/process.js +++ b/process/Email_lib/process.js @@ -34,7 +34,8 @@ function EmailWritingUtils () {} * @param {Placeholder[]} [pAdditionalPlaceholders] additional placeholders * @return {Array} the eml document as array with [filename, base64] */ -EmailWritingUtils.openMailTemplate = function (pToRecipients, pSenderContactId, pTemplateId, pRecipientContactId, pBindata, pAttachments, pSubject, pEmailFilename, pAdditionalPlaceholders) +EmailWritingUtils.openMailTemplate = function (pToRecipients, pSenderContactId, pTemplateId, pRecipientContactId, pBindata, pAttachments, pSubject, + pEmailFilename, pAdditionalPlaceholders) { if (pToRecipients && typeof(pToRecipients) == "string") pToRecipients = [pToRecipients]; @@ -66,9 +67,13 @@ EmailWritingUtils.openMailTemplate = function (pToRecipients, pSenderContactId, } if (pSubject) + { email.subject = pSubject; + } + + var isBinaryExistent = db.getBinaryCount("DOCUMENTTEMPLATE", "DOCUMENT", pTemplateId, SqlUtils.getBinariesAlias(), null); - return email.downloadEML(pEmailFilename); + return isBinaryExistent > 0 ? email.downloadEML(pEmailFilename) : []; } diff --git a/process/Employee_lib/process.js b/process/Employee_lib/process.js index df1b7707c20e30fab92f0310813fd2a1f88cba02..2cc4dad6f527ad35e895fb83433d76dc19ecef8e 100644 --- a/process/Employee_lib/process.js +++ b/process/Employee_lib/process.js @@ -1,3 +1,4 @@ +import("system.vars"); import("system.tools"); import("system.vars"); import("system.db"); diff --git a/process/IncomingEmailExecutor_lib/process.js b/process/IncomingEmailExecutor_lib/process.js index 18756c30f4dfb3005f0f0d06f5ea3ab27797acde..acd4c707cd7141cea4d447a432df02e3a9adec54 100644 --- a/process/IncomingEmailExecutor_lib/process.js +++ b/process/IncomingEmailExecutor_lib/process.js @@ -153,11 +153,13 @@ IncomingEmailExecutor.prototype.isUnlinkable = function () IncomingEmailExecutor.getContactDataByEmail = function (pMailAddress, pAlias) { var mailAddress = EmailUtils.extractAddress(pMailAddress).toUpperCase(); - return newSelect("CONTACT.CONTACTID, CONTACT.STATUS, CONTACT.PERSON_ID, CONTACT.ISOLANGUAGE", pAlias) - .from("COMMUNICATION") - .join("CONTACT", "COMMUNICATION.CONTACT_ID = CONTACT.CONTACTID") - .where("COMMUNICATION.ADDR", mailAddress, "upper(#) = ?") - .table(); + return mailAddress + ? newSelect("CONTACT.CONTACTID, CONTACT.STATUS, CONTACT.PERSON_ID, CONTACT.ISOLANGUAGE", pAlias) + .from("COMMUNICATION") + .join("CONTACT", "COMMUNICATION.CONTACT_ID = CONTACT.CONTACTID") + .where("COMMUNICATION.ADDR", mailAddress, "upper(#) = ?") + .table() + : []; } IncomingEmailExecutor.prototype.createActivity = function(pAdditionalLinks) diff --git a/process/KeywordRegistry_basic/process.js b/process/KeywordRegistry_basic/process.js index 6a21f8cc5cb43534a0b56ab98cc8fd27245ff627..2ae0206e4c39a9c54e875dee258ac76d8b3fb761 100644 --- a/process/KeywordRegistry_basic/process.js +++ b/process/KeywordRegistry_basic/process.js @@ -111,6 +111,8 @@ $KeywordRegistry.activityCategory = function(){return "ActivityCategory";}; $KeywordRegistry.activityCategory$mail = function(){return "MAIL";}; $KeywordRegistry.activityCategory$letter = function(){return "LETTER";}; $KeywordRegistry.activityCategory$visit = function(){return "VISIT";}; +$KeywordRegistry.activityCategory$phone = function(){return "PHONE";}; +$KeywordRegistry.activityCategory$onlineMeeting = function(){return "ONLINE-MEETING";}; $KeywordRegistry.addressType = function(){return "AddressType";}; $KeywordRegistry.addressType$private = function(){return "HOMEADDR";}; @@ -352,4 +354,13 @@ $KeywordRegistry.notificationPriority$max = function(){ return "MAX";}; $KeywordRegistry.checklistEntryType = function(){return "ChecklistEntryType";} $KeywordRegistry.checklistEntryType$manual = function(){return "MANUAL";} -$KeywordRegistry.checklistEntryType$auto = function(){return "AUTO";} \ No newline at end of file +$KeywordRegistry.checklistEntryType$auto = function(){return "AUTO";} + +$KeywordRegistry.forecastKind = function(){return "ForecastKind";} +$KeywordRegistry.forecastKind$forecast = function(){return "FORECAST";} +$KeywordRegistry.forecastKind$planning = function(){return "PLANNING";} + +$KeywordRegistry.forecastStatus = function(){return "ForecastStatus";} +$KeywordRegistry.forecastStatus$inPlanning = function(){return "IN_PLANNING";} +$KeywordRegistry.forecastStatus$locked = function(){return "LOCKED";} +$KeywordRegistry.forecastStatus$planned = function(){return "PLANNED";} \ No newline at end of file diff --git a/process/Liquibase_lib/process.js b/process/Liquibase_lib/process.js index dc12de6cc2530f6df82778c8644d4add36b1ad65..733bfa14a3686d5aa328709d8db2f888f4c2233d 100644 --- a/process/Liquibase_lib/process.js +++ b/process/Liquibase_lib/process.js @@ -111,7 +111,7 @@ LiquiUtils.exportTableAsLiquibaseFiles = function(pPath, pTableName, pColumns, p LiquiUtils.getDataXmlFromDB = function(pAuthor, pLobPath, pTableName, pColumns, pCondition, pIncludeClearTableDirective, pAlias, pGenerateChangeSetIdFromArguments, pBlobCallbackFn) { var alias = pAlias || db.getCurrentAlias(); - var dbData = db.table("select " + columns.join(", ") + " from " + pTableName + " " + (pCondition ? "where " + pCondition : ""), alias); + var dbData = db.table("select " + pColumns.join(", ") + " from " + pTableName + " " + (pCondition ? "where " + pCondition : ""), alias); return LiquiUtils.getDataXml(pAuthor, pLobPath, pTableName, pColumns, dbData, pIncludeClearTableDirective, pAlias, pGenerateChangeSetIdFromArguments, pBlobCallbackFn); } diff --git a/process/OfferOrder_lib/process.js b/process/OfferOrder_lib/process.js index edecfffa185bb9a53bfa1339ff401b086bfe6c73..656902d6552080485721888117b0092791db81a1 100644 --- a/process/OfferOrder_lib/process.js +++ b/process/OfferOrder_lib/process.js @@ -117,6 +117,7 @@ ItemUtils.prototype.getNetAndVat = function(pExcludedItemIds) { var orderItems = newSelect(columns) .from(this.tableName + "ITEM") .where(this.tableName + "ITEM." + this.tableName + "_ID", this.offerOrderId) + .and(this.tableName + "ITEM.ASSIGNEDTO is null") .andIfSet(this.tableName + "ITEM." + this.tableName + "ITEMID", pExcludedItemIds, SqlBuilder.NOT_IN()) .table(); @@ -196,6 +197,11 @@ ItemUtils.prototype.roundPrice = function(pPrice) { /** * Inserts parts list of the passed product into database. * + * If pSumUpPrices is set to true the following logic applies: <br> + * If one of the items doesn't have a valid price we calculate it by summing up all the prices of the items directly underneath it + * (only the ones which have takePrice set to true and are not optional.) + * + * * @param {String[]} columns req Array of Item DB Columns * @param {String} productId req UID of root product (selected product) * @param {String} assignedTo opt UID of parent item @@ -204,17 +210,23 @@ ItemUtils.prototype.roundPrice = function(pPrice) { * @param {String[][]} additionalProductInfo additional product info, which has to be copied from the product. (e.g. INFO field is only used by offer) * has to be in the form: [[["identifier1", "DESTINATION-DB-FIELD"], ["identifier2", "PRODUCT-DB-SUBSELECT-OR-FIELD"]], ...] * @param {String} pQuantity opt quantity - * @param {Boolean} pSumUpPrices If true: Prices of items get summed up if no valid price exists - * @return {String[]} Array of inserted ItemIDs + * @param {Boolean} pSumUpPrices opt If true: Prices of items get summed up if no valid price exists + * @param {String} pObjectType opt objectType (e.g: "Order", "Offer") + * @param {String} pObjectRowId opt objectRowId + * @param {String} pTopItemId opt offeritemId/orderItemId of the first item (the one we want to insert the partslist of) + * @param {boolean} pSumUpTopPrice opt whether or not the top price should get a sumUpPrice aswell + * @param {boolean} pReturnPartsListInsteadOfInserting opt if true: doesn't actually inserts the parts list, instead it just returns an object: <br> + * {"topProductInfo": {"price": price, "vat: vat"}, "partsList": [partsListAsArray]} + * + * @return {String[]} Array of inserted ItemIds * * @abstract */ -ItemUtils.prototype.insertPartsList = function(columns, productId, assignedTo, currency, contactId, additionalProductInfo, pQuantity, pSumUpPrices) { +ItemUtils.prototype.insertPartsList = function(columns, productId, assignedTo, currency, contactId, additionalProductInfo, pQuantity, pSumUpPrices, pObjectType, pObjectRowId, pTopItemId, pSumUpTopPrice, pReturnPartsListInsteadOfInserting) { if (additionalProductInfo == undefined) { additionalProductInfo = [] } - var insertedItemIds = []; //save address for this here to call methods in recursive sub function __itemInsertStatement var self = this; @@ -231,7 +243,7 @@ ItemUtils.prototype.insertPartsList = function(columns, productId, assignedTo, c if (contactId == undefined) { contactId = ""; - } + } var rootProdId = productId; if (rootProdId != "") @@ -260,16 +272,23 @@ ItemUtils.prototype.insertPartsList = function(columns, productId, assignedTo, c { __itemInsertStatement(partsList.root, assignedTo, currency, contactId); } + if (statements.length > 0) - db.inserts(statements); + { + if(pSumUpPrices) + { + var topPriceObj = ItemUtils.sumUpPricesWhenInserting(statements, insertedItemIds, treeStructure, productsWithSumUpPrices, priceObject, pQuantity, pObjectType, pObjectRowId, pTopItemId, pSumUpTopPrice, pReturnPartsListInsteadOfInserting); + } + if(pReturnPartsListInsteadOfInserting != true) + { + db.inserts(statements); + } + } } - if(pSumUpPrices == true) + if(pReturnPartsListInsteadOfInserting == true) { - return{"insertedItemIds": insertedItemIds, - "treeStructure": treeStructure, - "productsWithSumUpPrices": productsWithSumUpPrices, - "priceObject": priceObject} + return {"topProductInfo": topPriceObj, "partsList": statements}; } else { @@ -300,17 +319,17 @@ ItemUtils.prototype.insertPartsList = function(columns, productId, assignedTo, c { price = ProductDetails.PriceListToUse.price; vat = ProductDetails.PriceListToUse.vat; - if(pSumUpPrices) + if(pSumUpPrices)//also build priceObject if pSumUpPrices is set to true { priceObject[newid] = {}; - priceObject[newid]["price"] = price; + priceObject[newid]["price"] = price*P2pObject["quantity"]; priceObject[newid]["vat"] = vat; } } - else if(pSumUpPrices) + else if(pSumUpPrices)//also build priceObject if pSumUpPrices is set to true { - productsWithSumUpPrices[newid] = ""; + productsWithSumUpPrices[newid] = P2pObject["quantity"]; } } var stop = false; @@ -318,9 +337,9 @@ ItemUtils.prototype.insertPartsList = function(columns, productId, assignedTo, c var amuntOfKeys; var itemAdded; - if(pSumUpPrices) + if(pSumUpPrices)//also build treeStructure if pSumUpPrices is set to true { - treeStructure = _buildTreeStructure(treeStructure, assignedTo, newid); + treeStructure = ItemUtils.buildTreeStructure(treeStructure, assignedTo, newid); } var vals = [newid @@ -331,47 +350,37 @@ ItemUtils.prototype.insertPartsList = function(columns, productId, assignedTo, c , ProductDetails.productName , ProductDetails.unit , price - , vat - , P2pObject.quantity - , P2pObject.optional - , pos - , itemsort] - // add aditional details - .concat(additionalProductInfo.map(function(item) {return ProductDetails[item[1][0]]})); + , vat == null || vat == undefined || vat == "" ? 0 : vat + , P2pObject.quantity]; + + + if(_optionalIsIncluded(columns) == true)//add optional if needed + { + vals = vals.concat(P2pObject.optional) + } + vals = vals.concat([pos, itemsort]); + + // add aditional details + vals = vals.concat(additionalProductInfo.map(function(item) {return ProductDetails[item[1][0]]})); statements.push([table, columns, null, vals]); insertedItemIds.push(newid); __itemInsertStatement(partsList[p2pid], newid, currency, contactId); + } - // helper function to build the tree structure so we can later sum up the prices accordingly - function _buildTreeStructure(treeObj, assignedTo, newid) - { - for (var id in treeObj) + //small helper function for better code read-ability + function _optionalIsIncluded(pColumns) { - if (typeof treeObj[id] == "object" && treeObj[id] !== null && id != assignedTo) - _buildTreeStructure(treeObj[id], assignedTo, newid); - else + for (let i = 0; i < pColumns.length; i++) { - if(id == assignedTo) + if(pColumns[i] == "OPTIONAL") { - if(!treeObj.hasOwnProperty(assignedTo)) - { - treeObj[assignedTo] = {}; - } - treeObj[assignedTo][newid] = {}; - - return treeObj; + return true; } } + return false; } - if(Utils.isEmpty(treeObj)) - { - treeObj[assignedTo] = {}; - treeObj[assignedTo][newid] = {}; - } - return treeObj; - } } } @@ -476,16 +485,53 @@ ItemUtils.prototype.getNextItemPosition = function(assignedTo, tree, ids) { ids = this.ItemIds; var maxPos = ["0"]; - if (assignedTo) { - if (tree[assignedTo].ids.length < 1) { //first item in this level + if (assignedTo) + { + //when using insertPartsList with pReturnPartsListInsteadOfInserting set to true: The tree doesn't have the item yet (so tree[assignedTo] is undefined) + //So we add it ourselves so we can use the tree logic and add the childitems to it + if(tree[assignedTo] == undefined) + { + var lastItem = tree[Object.keys(tree)[Object.keys(tree).length - 1]]; + tree[assignedTo] = {}; + tree[assignedTo]["ids"] = []; + tree[assignedTo]["assignedTo"] = ""; + + var thisItemPos; + var thisItemSort; + //lastItem is undefined if we don't have any item yet -> position and sort are both '1'' + if(lastItem == undefined) + { + thisItemPos = 1; + thisItemSort = 1; + } + else + { + let lastItemPos = lastItem["pos"]; + thisItemPos = eMath.addInt(parseInt(lastItemPos.split(".")[0]), 1);//previous position plus 1 (the position can be something like "7.1.1.1" so we use split to get the "7" + let lastItemSort = lastItem["itemsort"]; + thisItemSort = eMath.addInt(parseInt(lastItemSort), 2);//previous itemsort plus 2 + } + tree[assignedTo]["pos"] = JSON.stringify(thisItemPos); + + tree[assignedTo]["itemsort"] = JSON.stringify(thisItemSort); + this.ItemIds.push(assignedTo) + } + + if (tree[assignedTo].ids.length < 1) //first item in this level + { maxPos = tree[assignedTo].pos.split("."); maxPos = maxPos.concat(["0"]); //next level pos - } else { + } + else + { var childIds = tree[assignedTo].ids; maxPos = tree[childIds[childIds.length-1]].pos.split("."); } - } else { - if (ids.length > 0) { + } + else + { + if (ids.length > 0) + { maxPos[0] = tree[ids[ids.length-1]].pos.split(".")[0]; } } @@ -581,5 +627,220 @@ ItemUtils.product_IdOnValueChange = function (pProductId, pUid, pEntity) neon.setFieldValue("$field.PRICE", ProductDetails.PriceListToUse.price); neon.setFieldValue("$field.VAT", ProductDetails.PriceListToUse.vat); } + } +}; + +/** + * This code is exactly the same for both Offeritem and Orderitem which is why it has it's own Function. <br><br> + * + * The Logic for summing up Prices: <br> + * If a product doesnt have a price: sum up all the prices of the the products directly beneath it that have takePrice set to true and are not optional. <br> + * This means we have to start from bottum up to calculate the prices. + * + * + * @param {Array} pStatements <p/> insertStatements (we modify them if needed so we insert the items with the correct prices instead of updating them later + * @param {Array} pCorrectOrder <p/> the items in the correct Order (top-down), important so we calculate the prices in the correct order + * @param {Object} pTreeStructure <p/> the Treestructure as object tree we got from using ItemUtils.buildTreeStructure() + * @param {Object} pProductsWithSumUpPrices <p/> products with sumupPrices (id as key, quantity as value) + * @param {Object} pPriceObj <p/> products with prices in object with id as key and prices and vat in an array as value + * @param {String} pQuantity <p/> the quantity of out topItem + * @param {String} pObjectType <p/> object type (eg. Offer or Order) + * @param {String} pObjectRowId <p/> object row i + * @param {String} pTopItemId <p/> item id of the topitem + * @param {Boolean} pSumUpTopPrice <p/> whether or not the price of the top item should get summed up aswell + * @param {Boolean} pReturnTopPrice opt <p/> if true: return price and vat as object isntead of updating the row + * @return {void} + * @static + */ +ItemUtils.sumUpPricesWhenInserting = function (pStatements, pCorrectOrder, pTreeStructure, pProductsWithSumUpPrices, pPriceObj, pQuantity, pObjectType, pObjectRowId, pTopItemId, pSumUpTopPrice, pReturnTopPrice) +{ + //private function for better code readability + _handleSumUpPricesOfItems(pCorrectOrder, pTreeStructure, pProductsWithSumUpPrices, pPriceObj, pQuantity, pStatements); + + var price; + var sumUpTopPrice = pSumUpTopPrice; + if(sumUpTopPrice === true) + { + var calcPrice = 0; + var vat = 0; + for(var id in pTreeStructure[pTopItemId]) + { + calcPrice = eMath.addDec(pPriceObj[id]["price"], calcPrice); + if(pPriceObj[id]["vat"] !== null && pPriceObj[id]["vat"] !== undefined && pPriceObj[id]["vat"] > 0) + { + vat = pPriceObj[id]["vat"]; + } + } + sumUpTopPrice = calcPrice/pQuantity; + if(pReturnTopPrice) + { + return {"price": sumUpTopPrice, "vat": vat}; + } + var config = entities.createConfigForUpdatingRows() + .uid(pTopItemId) + .fieldValues({ + "PRICE": sumUpTopPrice, + "VAT": vat + }); + if(pObjectType == "Offer") + { + config = config.entity("Offeritem_entity") + .addParameter("IgnoreOnUpdateProcess_param", true) + } + else if(pObjectType == "Order") + { + config = config.entity("Orderitem_entity") + .addParameter("IgnoreOnUpdateProcess_param", true) + } + entities.updateRow(config); + } + return sumUpTopPrice; + + //We want to sum up the prices directly under the current item to calculate the price if we don't have an valid price for them + function _handleSumUpPricesOfItems(pOrder, pTreestruct, pSumUpPrices, pPriceObj, pQuantity, pStatements) + { + + var currentStruc = pTreestruct; + var sumUpPrices = pSumUpPrices; + var quantity = pQuantity; + var order = pOrder; + var summandObject = {}; + var calculatedPrices = {}; + var priceObj = pPriceObj; + for (var i = order.length; i > -1; i--)//we do this backwards because otherwiese we would run into problems when trying to build the sum (we could have items without an price yet) + { + if(sumUpPrices.hasOwnProperty(order[i])) + { + summandObject[order[i]] = ItemUtils.getNode(pTreestruct, order[i], Object.keys(pTreestruct)[0]); + var calcPrice = 0; + var vat = 0; + for (var child in summandObject[order[i]]) + { + var childPrice; + if(pPriceObj[child] != undefined) + { + childPrice = pPriceObj[child]["price"] + } + else if(summandObject[child][child] != undefined) + { + childPrice = pPriceObj[Object.keys(summandObject[child][child])[0]]["price"] + vat = pPriceObj[Object.keys(summandObject[child][child])[0]]["vat"] + } + else + { + childPrice = 0; + vat = 0; + } + calcPrice = eMath.addDec(childPrice, calcPrice); + if(pPriceObj[child]["vat"] !== null && pPriceObj[child]["vat"] !== undefined && pPriceObj[child]["vat"] > 0) + { + vat = pPriceObj[child]["vat"]; + } + } + calcPrice = calcPrice/quantity; + calculatedPrices[order[i]] = {}; + calculatedPrices[order[i]]["price"] = calcPrice; + calculatedPrices[order[i]]["vat"] = vat; + priceObj[order[i]] = {}; + priceObj[order[i]]["price"] = calcPrice*sumUpPrices[order[i]]; + priceObj[order[i]]["vat"] = vat; + + + } + } + + var config = entities.createConfigForUpdatingRows(); + + for(var statement in pStatements) + { + if(calculatedPrices[pStatements[statement][3][0]] != undefined)//[3][0] = OfferItemId/SalesOrderItemId + { + pStatements[statement][3][7] = calculatedPrices[pStatements[statement][3][0]]["price"] //price + pStatements[statement][3][8] = calculatedPrices[pStatements[statement][3][0]]["vat"] //vat + } + else + { + pStatements[statement][3][7] = priceObj[pStatements[statement][3][0]]["price"] //price + pStatements[statement][3][8] = priceObj[pStatements[statement][3][0]]["vat"] //vat + } + } + } +}; + +/** + * Recursive function to build the tree structure so we can later sum up the prices accordingly (call for every item (top-down)) + * + * @param {Object} pTreeObj <p/> the already existing tree structure (empty object if first time calling this function) + * @param {String} pAssignedTo <p/> id the current one is assigned to + * @param {String} pNewid <p/> current id we want to add to the tree + * + * + * @return {Object} treeStructure with the pNewid added the correct position + * @static + */ +ItemUtils.buildTreeStructure = function (pTreeObj, pAssignedTo, pNewid) +{ + var treeObj = pTreeObj; + var assignedTo = pAssignedTo; + var newid = pNewid; + for (var id in treeObj) + { + if (typeof treeObj[id] == "object" && treeObj[id] !== null && id != assignedTo) + { + ItemUtils.buildTreeStructure(treeObj[id], assignedTo, newid); + } + else + { + if(id == assignedTo) + { + if(!treeObj.hasOwnProperty(assignedTo)) + { + treeObj[assignedTo] = {}; + } + treeObj[assignedTo][newid] = {}; + return treeObj; + } + } + } + if(Utils.isEmpty(treeObj)) + { + treeObj[assignedTo] = {}; + treeObj[assignedTo][newid] = {}; + } + return treeObj; +} + +/** + * Recursive function to return a specific "node" of the tree structure with the specified pName + * + * @param {Object} pObject <p/> the objectTree + * @param {String} pName <p/> the name of the node we want + * @param {String} pCurrName <p/> current node name + * + * + * @return {Object} treeStructure with the pNewid added the correct position + * @static + */ +ItemUtils.getNode = function (pObject, pName, pCurrName){ + if(pCurrName == pName) + { + return pObject; + } + else if (pObject != undefined) + { + let res = null; + for(var obj in pObject) + { + if(res == null) + { + res = ItemUtils.getNode(pObject[obj], pName, obj); + } + else + { + break; + } + } + return res; } -}; \ No newline at end of file + return null; + } \ No newline at end of file diff --git a/process/Offer_lib/process.js b/process/Offer_lib/process.js index 777a0a8412dbc453cc525c1f09ba6bcd7f03aa68..1fb67604ae5cdb6dd7491ed489ead8af5a800e39 100644 --- a/process/Offer_lib/process.js +++ b/process/Offer_lib/process.js @@ -266,7 +266,7 @@ OfferUtils.buildOfferReport = function (pOfferID, pExclDiscountGroupcodes) item[0], //info item[1], //assignedTo item[3], //itemname - item[4], //optional + parseInt(item[4]) ? translate.text("Yes", language) : translate.text("No", language), //optional item[5], //itemposition item[6], //productcode header, //header @@ -324,7 +324,8 @@ OfferUtils.buildOfferReport = function (pOfferID, pExclDiscountGroupcodes) "InvoiceDiscount": translate.text("Invoice Discount", language), "TotalWithoutVat": translate.text("without Vat", language), "TotalWithVat": translate.text("incl. Vat", language), - "printHeadDiscount": printHeadDiscount ? "1" : "0" + "printHeadDiscount": printHeadDiscount ? "1" : "0", + "Optional": translate.text("Optional", language) }; @@ -557,7 +558,7 @@ OfferItemUtils.prototype.roundPrice = function(pPrice) { /** * For documentation, see class ItemUtils. */ -OfferItemUtils.prototype.insertPartsList = function(pProductId, pAssignedTo, pCurrency, pContactId, pLanguage, pQuantity, pSumUpPrices) { +OfferItemUtils.prototype.insertPartsList = function(pProductId, pAssignedTo, pCurrency, pContactId, pLanguage, pQuantity, pSumUpPrices, pOfferId, pSumUpTopPrice) { this.initItemTree(); var cols = ["OFFERITEMID" @@ -580,7 +581,7 @@ OfferItemUtils.prototype.insertPartsList = function(pProductId, pAssignedTo, pCu .where("DESCRIPTIONTRANSLATION.OBJECT_ROWID = PRODUCT.PRODUCTID") .and("DESCRIPTIONTRANSLATION.OBJECT_TYPE", "Product") .andIfSet("DESCRIPTIONTRANSLATION.LANG", pLanguage) - .toString() + ")"]]], pQuantity, pSumUpPrices]); + .toString() + ")"]]], pQuantity, pSumUpPrices, "Offer", pOfferId, pAssignedTo, pSumUpTopPrice, true]); } @@ -635,6 +636,7 @@ OfferItemUtils.getDiscountedNet = function(pExcludedIs, pOfferId, pDiscount, pEx .where("OFFERITEM.OFFER_ID", pOfferId) .andIfSet("OFFERITEM.GROUPCODEID", pExcludedProductgroups, SqlBuilder.NOT_IN()) .andIfSet("OFFERITEM.OFFERITEMID", pExcludedIs, SqlBuilder.NOT_IN()) + .and("OFFERITEM.ASSIGNEDTO is null") .table(); for (var i = 0; i < offeritemData.length; i++) { diff --git a/process/Order_lib/process.js b/process/Order_lib/process.js index fedf40ca93d861e251fd79498aab5579fa5f2b84..8dfe4b4d5e5b23c1659e8cd1a1c096dc0777d8cc 100644 --- a/process/Order_lib/process.js +++ b/process/Order_lib/process.js @@ -703,7 +703,7 @@ OrderItemUtils.prototype.roundPrice = function(pPrice) { /** * For documentation, see class ItemUtils. */ -OrderItemUtils.prototype.insertPartsList = function(pProductId, pAssignedTo, pCurrency, pContactId) { +OrderItemUtils.prototype.insertPartsList = function(pProductId, pAssignedTo, pCurrency, pContactId, pQuantity, pSumUpPrices, pOrderId, pSumUpTopPrice) { this.initItemTree(); var cols = ["SALESORDERITEMID" @@ -719,7 +719,7 @@ OrderItemUtils.prototype.insertPartsList = function(pProductId, pAssignedTo, pCu , "ITEMPOSITION" , "ITEMSORT"]; - return ItemUtils.prototype.insertPartsList.apply(this, [cols, pProductId, pAssignedTo, pCurrency, pContactId]); + return ItemUtils.prototype.insertPartsList.apply(this, [cols, pProductId, pAssignedTo, pCurrency, pContactId, undefined, pQuantity, pSumUpPrices, "Order", pOrderId, pAssignedTo, pSumUpTopPrice, true]); } /** diff --git a/process/Product_lib/process.js b/process/Product_lib/process.js index db6b5fe287338675341282aa80d1660560886bec..cf20a1cf64911ee631f8de66c69d0ee86a2e135b 100644 --- a/process/Product_lib/process.js +++ b/process/Product_lib/process.js @@ -1,3 +1,7 @@ +import("OfferOrder_lib"); +import("system.neon"); +import("system.eMath"); +import("system.entities"); import("system.util"); import("system.SQLTYPES"); import("system.datetime"); @@ -155,6 +159,17 @@ ProductUtils.getStockCount = function(pid) { ProductUtils.getProductDetails = function(pid, pPriceListFilter, pAdditionalProductInfoSubselects) { var priceListFilter = pPriceListFilter; + var dateFrom; + if(priceListFilter.dateFrom != undefined) + { + dateFrom = priceListFilter.dateFrom; + } + var dateTo; + if(priceListFilter.dateTo != undefined) + { + dateTo = priceListFilter.dateTo; + } + var additionalProductInfoSubselects = pAdditionalProductInfoSubselects; if (additionalProductInfoSubselects == undefined) { @@ -185,19 +200,44 @@ ProductUtils.getProductDetails = function(pid, pPriceListFilter, pAdditionalProd && priceListFilter.currency != undefined && priceListFilter.currency != "" && priceListFilter.quantity != undefined && priceListFilter.quantity != "") { + if(priceListFilter.relationId == undefined) + { + priceListFilter.relationId = ""; + } validPriceLists = true; var colsPricelistValid = ["validPP.PRODUCTPRICEID", "validPP.CONTACT_ID", "validPP.PRICELIST", "validPP.PRICE", "validPP.VAT" , "validPP.VALID_FROM", "validPP.VALID_TO", "validPP.BUYSELL", "validPP.FROMQUANTITY", "validPP.CURRENCY"]; orderBy = orderBy.concat(["validPP.VALID_FROM desc", "validPP.FROMQUANTITY desc"]); cols = cols.concat(colsPricelistValid); + var cond; + if(dateFrom != undefined) + { + var secondCond; + if(dateTo) + { + secondCond = newWhere(["PRODUCTPRICE", "VALID_FROM", "validPP"], dateTo, SqlBuilder.LESS_OR_EQUAL()) + } + else + { + secondCond = newWhere(["PRODUCTPRICE", "VALID_FROM", "validPP"], dateFrom, SqlBuilder.LESS_OR_EQUAL()) + } + cond = newWhere().and(newWhere() + .or(["PRODUCTPRICE", "VALID_TO", "validPP"], dateFrom, SqlBuilder.GREATER_OR_EQUAL()) + .or("validPP.VALID_TO is null")) + .and(secondCond) + } + else + { + cond = newWhere().and(["PRODUCTPRICE", "VALID_FROM", "validPP"], datetime.date().toString(), SqlBuilder.LESS_OR_EQUAL()) + .and(newWhere() + .or(["PRODUCTPRICE", "VALID_TO", "validPP"], datetime.today().toString(), SqlBuilder.GREATER_OR_EQUAL()) + .or("validPP.VALID_TO is null")) + } joins.push(["left", "PRODUCTPRICE", "validPP", newWhere("validPP.PRODUCT_ID = PRODUCTID") .and(["PRODUCTPRICE", "CURRENCY", "validPP"], priceListFilter.currency) - .and(["PRODUCTPRICE", "VALID_FROM", "validPP"], datetime.date().toString(), SqlBuilder.LESS_OR_EQUAL()) - .and(newWhere() - .or(["PRODUCTPRICE", "VALID_TO", "validPP"], datetime.today().toString(), SqlBuilder.GREATER_OR_EQUAL()) - .or("validPP.VALID_TO is null")) + .and(cond) .and(["PRODUCTPRICE", "FROMQUANTITY", "validPP"], priceListFilter.quantity, SqlBuilder.LESS_OR_EQUAL()) .and(newWhere() .or(["PRODUCTPRICE", "CONTACT_ID", "validPP"], priceListFilter.relationId) @@ -243,12 +283,6 @@ ProductUtils.getProductDetails = function(pid, pPriceListFilter, pAdditionalProd countPos++; }, ProductDetails); } - //Pricelist (all) - var colIdx = colsProduct.length; - if (ProductData[i][colIdx] != "" && ProductDetails.PriceLists[ProductData[i][colIdx]] == undefined) //Pricelist found - { - ProductDetails.PriceLists[ProductData[i][colIdx]] = _getPriceListObject(); - } //Pricelist (currently valid) colIdx = colsProduct.length + colsPricelistAll.length; @@ -287,7 +321,7 @@ ProductUtils.getProductDetails = function(pid, pPriceListFilter, pAdditionalProd //infividual pricelists always have the highest priority, so we loop trough and use the first one we find regardles of the rest for (var indivList in priceLists) { - if(priceLists[indivList]["priceList"] == $KeywordRegistry.productPricelist$specialList()) + if(priceLists[indivList]["priceList"] == "") { return priceLists[indivList]; } @@ -653,4 +687,144 @@ Prod2ProdUtils.prototype._relateParents = function() } } } +} + +/** + * utility functions for productprices + * Do not create an instance of this! + * + * @class + */ +function ProductPriceUtils() {} + +/** + * Used for presetting the price of a product by summing up the valid prices of the partslist of said product + * + * Logic is as followed: <br> + * If a product doesnt have a price: sum up all the prices of the the products directly beneath it that have takePrice set to true and are not optional. <br> + * This means we have to start from bottum up to calculate the prices. + * + * @param {String} pProductId ProductID of the product we want to set the fields for + * @param {String} pVat opt vat + * @param {String} pPriceList opt priceList(-"type") + * @param {String} pBuySell opt possible values: PP, SP + * + * @example productUtils.getCurrentProductPrice(vars.get("$field.PRODUCTID"), "PP") + * + * @return {void} uses neon.setFieldValues({"$field.PRICE": priceObj[oItem]["price"],"$field.VAT": priceObj[oItem]["vat"]}) + */ +ProductUtils.presetPriceAndVat = function(pProductId, pVat, pPriceList, pBuySell) { + + + var vat = pVat; + var productId = pProductId; + var priceList = pPriceList; + var buySell = pBuySell; + var config = entities.createConfigForLoadingRows() + .entity("Prod2prod_entity") + .addParameter("ProductId_param", productId) + .fields(["PROD2PRODID", + "DEST_ID", + "SOURCE_ID", + "QUANTITY", + "OPTIONAL", + "unit", + "TAKEPRICE", + "currentPurchasePrice", + "currentSalesPrice"]); + var products = entities.getRows(config);//source_id = product_id + var treestructure = {}; + var curr = vars.get("$field.CURRENCY"); + var priceObj = {}; + var sumUpPrices = {}; + _handleProducts(products, treestructure, curr, buySell, priceObj, 1, priceList, productId); //build treeStructure and priceObj + var summandObject = {}; + + for (var i = products.length-1; i > -1; i--)//we do this backwards because otherwiese we would run into problems when trying to build the sum (we could have items without an price yet) + { + if(sumUpPrices.hasOwnProperty(products[i]["SOURCE_ID"])) + { + summandObject[products[i]["PROD2PRODID"]] = ItemUtils.getNode(treestructure[productId], products[i]["PROD2PRODID"], Object.keys(treestructure)[0]); + } + } + + + for(var oItem in summandObject) + { + var calcPrice = 0; + var vat = null; + for (var child in summandObject[oItem]) + { + var childPrice; + if(priceObj[child] != undefined) + { + childPrice = priceObj[child]["price"] + } + else if(summandObject[child][child] != undefined) + { + childPrice = priceObj[Object.keys(summandObject[child][child])[0]]["price"] + vat = priceObj[Object.keys(summandObject[child][child])[0]]["vat"] + } + else + { + childPrice = 0; + vat = 0; + } + let quantity = 1; + for (i = 0; i < products.length; i++) + { + if(products[i]["PROD2PRODID"] == oItem) + { + quantity = products[i]["QUANTITY"]; + break; + } + } + + calcPrice = eMath.addDec(childPrice, calcPrice)*quantity; + if(!vat) + { + vat = priceObj[child]["vat"]; + } + } + priceObj[oItem] = {}; + priceObj[oItem]["price"] = calcPrice; + priceObj[oItem]["vat"] = vat; + } + + var price = 0; + for (var item in treestructure[productId]) + { + price += parseInt(priceObj[item]["price"]); + if(vat == null && priceObj[item]["vat"]) + { + vat = parseInt(priceObj[item]["vat"]); + } + } + + neon.setFieldValues({"$field.PRICE": price, "$field.VAT": vat}) + + //private function for better code-readability + function _handleProducts(products, treestructure, curr, buySell, priceObj, pQuantity, pPriceList, pProductId){ + + for(var product in products) + { + var productDetails = ProductUtils.getProductDetails( + products[product]["SOURCE_ID"], + { currency: curr, quantity: pQuantity, relationId: "", priceList: pPriceList}); + + if(!Utils.isEmpty(productDetails["PriceListToUse"])) + { + priceObj[products[product]["PROD2PRODID"]] = {}; + priceObj[products[product]["PROD2PRODID"]]["price"] = productDetails["PriceListToUse"]["price"]*products[product]["QUANTITY"]; + priceObj[products[product]["PROD2PRODID"]]["vat"] = productDetails["PriceListToUse"]["vat"]; + } + else + { + sumUpPrices[products[product]["SOURCE_ID"]] = {}; + } + + var assignedTo = products[product]["DEST_ID"] != "" ? JSON.parse(products[product]["DEST_ID"])[1] : pProductId; + treestructure = ItemUtils.buildTreeStructure(treestructure, assignedTo, products[product]["PROD2PRODID"]); + } + } } \ No newline at end of file diff --git a/process/Turnover_lib/process.js b/process/Turnover_lib/process.js index c2f5c6c9de86aaacfe8646551301282a2b085ce7..4ce2665e3283ec9b2f8fd170794efe4b5c97ff95 100644 --- a/process/Turnover_lib/process.js +++ b/process/Turnover_lib/process.js @@ -1,3 +1,11 @@ +import("Attribute_lib"); +import("AttributeFilter_lib"); +import("Util_lib"); +import("system.util"); +import("ClassificationFilter_lib"); +import("system.vars"); +import("system.datetime"); +import("JditoFilter_lib"); import("Sql_lib"); import("system.translate"); import("KeywordRegistry_basic"); @@ -95,7 +103,8 @@ TurnoverUtil.getForecastData = function (pMaxYear, pYearCount, pSalesprojectId) ]) .from("FORECAST") .where("FORECAST.DATE_START", pMaxYear, sqlMask.yearFromDate("#") + " <= ?", SQLTYPES.INTEGER) - .and("FORECAST.DATE_START", minYear, sqlMask.yearFromDate("#") + " >= ?", SQLTYPES.INTEGER); + .and("FORECAST.DATE_START", minYear, sqlMask.yearFromDate("#") + " >= ?", SQLTYPES.INTEGER) + .and("FORECAST.KIND", $KeywordRegistry.forecastKind$forecast()); if (pSalesprojectId) { @@ -103,9 +112,9 @@ TurnoverUtil.getForecastData = function (pMaxYear, pYearCount, pSalesprojectId) .and("FORECAST.OBJECT_ROWID", pSalesprojectId) } - forecastSelect.groupBy([sqlMask.yearFromDate("DATE_START"), sqlMask.monthFromDate("DATE_START"), "GROUPCODE"]) + forecastSelect.groupBy([sqlMask.yearFromDate("DATE_START"), sqlMask.monthFromDate("DATE_START"), "GROUPCODE", "KIND"]) .orderBy("yearNum, monthNum"); - + return forecastSelect.table(); } @@ -129,4 +138,638 @@ TurnoverUtil.getTurnoverAndForecastData = function (pMaxYear, pYearCount, pShowF if (pShowForecast) data = data.concat(TurnoverUtil.getForecastData(pMaxYear, pYearCount, pSalesprojectId)); return data; -} \ No newline at end of file +} + + + + +/** + * + * An TurnoverDynamicChart can be used for the dynamic chart turnover<br> + * <i><u>You have to instanciate it with "new".</u></i> + * <p> + * There are also functions where it is not necessary to instantiate it. + * + * @param {Object} pFilter <p> + * The current filter object. <br> + * @class + */ +function TurnoverDynamicChart(pFilter) { + this.groupMapping = TurnoverDynamicChart.getGroupMapping(); + + this.filterMappingPlanning = TurnoverDynamicChart.getFilterMapping("Planning"); + this.filterMappingForecast = TurnoverDynamicChart.getFilterMapping("Forecast"); + this.filterMappingTurnover = TurnoverDynamicChart.getFilterMapping("Turnover"); + + this.filter = pFilter; + + this.idxPlanning = 0; + this.idxForecast = 1; + this.idxTurnover = 2; + this.groupedField = null; + + var thisYear = parseInt(datetime.toDate(vars.get("$sys.date"), "yyyy", "UTC")); + + this.firstYear = thisYear - 2; + this.lastYear = thisYear + 1; + + +} + +/** + * Returns the planning query. + * + */ +TurnoverDynamicChart.prototype.getPlanningFromSql = function () +{ + var sqlHelper = new SqlMaskingUtils(); + + var select = sqlHelper.concatenate(["FORECAST.FORECASTID", "PLANNING_MONTHID"]) + ", '', '', '', "; + + if(this.groupedField) + { + select = this.groupMapping[this.groupedField]["forGrouping"][this.idxPlanning] + " as uid," + + " (" + this.getGroupFieldDisplayValue(this.idxPlanning) + ") as groupField, "; + } + + select += sqlHelper.cast("FORECAST.VOLUME/100*PLANNING_MONTH.MONTH_FACTOR", SQLTYPES.INTEGER) + " as sum_planning, " + + "0 as sum_forecast, 0 as sum_turnover, 0 as sum_forecast_weighted "; + + return newSelect(select) + .from("FORECAST") + .join("PLANNING_MONTH", null, null, "cross") + .leftJoin("CONTACT", "FORECAST.CONTACT_ID = CONTACT.CONTACTID and PERSON_ID is null") + .leftJoin("ORGANISATION", "CONTACT.ORGANISATION_ID = ORGANISATION.ORGANISATIONID") + .leftJoin("ADDRESS", "CONTACT.ADDRESS_ID = ADDRESS.ADDRESSID") + .leftJoin("CLASSIFICATIONSTORAGE", "CLASSIFICATIONSTORAGE.OBJECT_ROWID = CONTACT.CONTACTID") + .where("FORECAST.KIND", $KeywordRegistry.forecastKind$planning()) + .and("FORECAST.FORECAST_YEAR", this.firstYear, SqlBuilder.GREATER_OR_EQUAL()) + .and("FORECAST.FORECAST_YEAR", this.lastYear, SqlBuilder.LESS_OR_EQUAL()); + +} + + +/** + * Returns the forecast query. + * + * @param {Boolean} pIsWeighted <p> + * If the forecast should be weighted the value of the parameter is true.<br> + */ +TurnoverDynamicChart.prototype.getForecastFromSql = function (pIsWeighted) +{ + var sqlHelper = new SqlMaskingUtils(); + + var select = "FORECAST.FORECASTID, '', '', '', "; + + if(this.groupedField) + { + select = this.groupMapping[this.groupedField]["forGrouping"][this.idxForecast] + " as uid, " + + "(" + this.getGroupFieldDisplayValue(this.idxForecast) + ") as groupField,"; + } + var volumeColumns = " 0 as sum_planning, " + sqlHelper.cast("FORECAST.VOLUME", SQLTYPES.INTEGER) + + " as sum_forecast, 0 as sum_turnover, 0 as sum_forecast_weighted"; + + if(pIsWeighted) + { + if(!this.groupedField) + { + select = sqlHelper.concatenate(["FORECAST.FORECASTID", sqlHelper.cast("SALESPROJECT.PROBABILITY", SQLTYPES.VARCHAR, 3)]) +", '', '', '', " ; + } + + volumeColumns = " 0 as sum_planning, 0 as sum_forecast, 0 as sum_turnover, " + + sqlHelper.cast("(FORECAST.VOLUME/100*SALESPROJECT.PROBABILITY)", SQLTYPES.INTEGER) + + " as sum_forecast_weighted"; + } + + select += volumeColumns; + + return newSelect(select) + .from("FORECAST") + .join("SALESPROJECT", "OBJECT_TYPE = 'Salesproject' and OBJECT_ROWID = SALESPROJECTID") + .leftJoin("CONTACT", "SALESPROJECT.CONTACT_ID = CONTACT.CONTACTID and PERSON_ID is null") + .leftJoin("ORGANISATION", "CONTACT.ORGANISATION_ID = ORGANISATION.ORGANISATIONID") + .leftJoin("ADDRESS", "CONTACT.ADDRESS_ID = ADDRESS.ADDRESSID") + .leftJoin("CLASSIFICATIONSTORAGE", "CLASSIFICATIONSTORAGE.OBJECT_ROWID = CONTACT.CONTACTID") + .where("FORECAST.KIND", $KeywordRegistry.forecastKind$forecast()) + .and("year(FORECAST.DATE_START) >= " + this.firstYear) + .and("year(FORECAST.DATE_START) <= " + this.lastYear); +} + + +/** + * Returns the turnover query. + * + */ +TurnoverDynamicChart.prototype.getTurnoverFromSql = function () +{ + var sqlHelper = new SqlMaskingUtils(); + + var select = "SALESORDERITEM.SALESORDERITEMID, '', '', '', "; + + if(this.groupedField) + { + select = this.groupMapping[this.groupedField]["forGrouping"][this.idxTurnover] + " as uid, " + + "(" + this.getGroupFieldDisplayValue(this.idxTurnover) + ") as groupField, "; + } + + select += " 0 as sum_planning, 0 as sum_forecast, " + + sqlHelper.cast("((SALESORDERITEM.PRICE * SALESORDERITEM.QUANTITY * (100 - " + sqlHelper.isNull("SALESORDERITEM.DISCOUNT", 0) + + ") / 100) + (SALESORDERITEM.PRICE * SALESORDERITEM.QUANTITY * (100 - " + sqlHelper.isNull("SALESORDERITEM.DISCOUNT", 0) + + ") / 100 * " + sqlHelper.isNull("SALESORDERITEM.VAT", 0) + " / 100))", SQLTYPES.INTEGER) + " as sum_turnover" + + ", 0 as sum_forecast_weighted"; + + return newSelect(select) + .from("SALESORDERITEM") + .join("SALESORDER", "SALESORDER.SALESORDERID = SALESORDERITEM.SALESORDER_ID") + .leftJoin("CONTACT", "SALESORDER.CONTACT_ID = CONTACT.CONTACTID and PERSON_ID is null") + .leftJoin("ORGANISATION", "CONTACT.ORGANISATION_ID = ORGANISATION.ORGANISATIONID") + .leftJoin("ADDRESS", "CONTACT.ADDRESS_ID = ADDRESS.ADDRESSID") + .leftJoin("CLASSIFICATIONSTORAGE", "CLASSIFICATIONSTORAGE.OBJECT_ROWID = CONTACT.CONTACTID") + .where("year(SALESORDER.SALESORDERDATE) >= " + this.firstYear) + .and("year(SALESORDER.SALESORDERDATE) <= " + this.lastYear); +} + + +/** + * Returns the display part for the from sqls. + * + * @param {int} pIndexGroupMapping <p> + * The index for the grouping object of the diffrent kinds<br> + */ +TurnoverDynamicChart.prototype.getGroupFieldDisplayValue = function (pIndexGroupMapping) +{ + var compareField = this.groupMapping[this.groupedField]["forGrouping"][pIndexGroupMapping]; + var subSqlDisplay; + + switch(this.groupMapping[this.groupedField]["fieldName"]) + { + case "YEAR": + subSqlDisplay = compareField; + break; + case "MONTH": + subSqlDisplay = "case when " + compareField + " = 1 then '" + translate.text("January") + "' " + + "when " + compareField + " = 2 then '" + translate.text("February") + "' " + + "when " + compareField + " = 3 then '" + translate.text("March") + "' " + + "when " + compareField + " = 4 then '" + translate.text("April") + "' " + + "when " + compareField + " = 5 then '" + translate.text("May") + "' " + + "when " + compareField + " = 6 then '" + translate.text("June") + "' " + + "when " + compareField + " = 7 then '" + translate.text("July") + "' " + + "when " + compareField + " = 8 then '" + translate.text("August") + "' " + + "when " + compareField + " = 9 then '" + translate.text("September") + "' " + + "when " + compareField + " = 10 then '" + translate.text("October") + "' " + + "when " + compareField + " = 11 then '" + translate.text("November") + "' " + + "when " + compareField + " = 12 then '" + translate.text("December") + "' end"; + break; + case "ORGANISATION": + subSqlDisplay = "ORGANISATION.NAME"; + break; + case "GROUPCODE": + subSqlDisplay = KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.productGroupcode(), compareField); + break; + } + + return subSqlDisplay; +} + + +/** + * Returns the condition for the from sqls. + * + * @param {String} pKind <p> + * <br> Kind of the diffrent categories + */ +TurnoverDynamicChart.prototype.getFilterCond = function (pKind) +{ + var filterCond; + + switch(pKind) + { + case "Planning": + filterCond = JditoFilterUtils.getSqlCondition(this.filter, "FORECAST", null, this.filterMappingPlanning ); + break; + case "Forecast": + filterCond = JditoFilterUtils.getSqlCondition(this.filter, "FORECAST", null, this.filterMappingForecast); + break; + case "Turnover": + filterCond = JditoFilterUtils.getSqlCondition(this.filter, "SALESORDER", null, this.filterMappingTurnover ); + + break; + } + + return filterCond; +} + + +/** + * Returns the finished sql for the from part. <br> + * The sqls of Planning, Forecast and Turnover are put together with a union and the filters are added. + * + */ +TurnoverDynamicChart.prototype.getFromSql = function () +{ + var planningSql= this.getPlanningFromSql(); + var forecastSql = this.getForecastFromSql(); + var forecastWeightedSql = this.getForecastFromSql(true); + var turnoverSql = this.getTurnoverFromSql(); + + if(this.filter != null && this.filter.childs.length > 0) + { + planningSql.and(this.getFilterCond("Planning")); + forecastSql.and(this.getFilterCond("Forecast")); + forecastWeightedSql.and(this.getFilterCond("Forecast")); + turnoverSql.and(this.getFilterCond("Turnover")); + } + + var fromSql = forecastSql.unionAll(turnoverSql).unionAll(planningSql).unionAll(forecastWeightedSql); + return fromSql; +} + + + +/** + * Returns the group mapping Object. <br> + * Structure of the Object: {GroupedFieldName: <br> + * {"forGrouping": [columnPlanning, columnForecast, columnTurnover], <br> + * "fieldName": generalNameOfGroupedFields <br> + * } <br> + * } <br> + */ +TurnoverDynamicChart.getGroupMapping = function () +{ + return { + "TURNOVER_YEAR": {"forGrouping": ["FORECAST.FORECAST_YEAR", "year(FORECAST.DATE_START)", "year(SALESORDER.SALESORDERDATE)"], + "fieldName": "YEAR"}, + "ORGANISATION_ID" : {"forGrouping": ["FORECAST.CONTACT_ID", "SALESPROJECT.CONTACT_ID", "SALESORDER.CONTACT_ID"], + "fieldName": "ORGANISATION"}, + "#EXTENSION.Month_filter.Month_filter#TEXT" : {"forGrouping": ["PLANNING_MONTH.MONTH_NUMBER", "MONTH(FORECAST.DATE_START)", "MONTH(SALESORDER.SALESORDERDATE)"], + "fieldName": "MONTH"}, + "#EXTENSION.Groupcode_filter.Groupcode_filter#TEXT" : {"forGrouping": ["FORECAST.GROUPCODE", "FORECAST.GROUPCODE", "SALESORDERITEM.GROUPCODEID"], + "fieldName": "GROUPCODE"} + }; +} + +/** + * Returns the filter mapping Object. <br> + * Structure of the Object: {Kind: <br> + * {FilteredFieldName: columnName or function} <br> + * } <br> + * @param {String} pKind <p> + * <br> Kind of the diffrent categories + */ +TurnoverDynamicChart.getFilterMapping = function (pKind) +{ + var filterMapping = { + + "Planning": { + "TURNOVER_YEAR" : function (pValue, pOperator) { + return TurnoverDynamicChart.dateCond(pValue, pOperator, "FORECAST.FORECAST_YEAR"); + }, + "#EXTENSION.Month_filter.Month_filter#TEXT" : function (pValue, pOperator) { + return TurnoverDynamicChart.dateCond(pValue, pOperator, "PLANNING_MONTH.MONTH_NUMBER"); + }, + "ORGANISATION_ID" : "FORECAST.CONTACT_ID", + "#EXTENSION.Groupcode_filter.Groupcode_filter#TEXT" : "FORECAST.GROUPCODE", + "#EXTENSION.Salesproject_filter.Salesproject_filter#TEXT" : function (pValue, pOperator) { + + return TurnoverDynamicChart.planningSalesprojectCond(pValue, pOperator); + } + + }, + "Forecast" : { + "TURNOVER_YEAR" : function (pValue, pOperator) { + return TurnoverDynamicChart.dateCond(pValue, pOperator, "YEAR(FORECAST.DATE_START)"); + }, + "#EXTENSION.Month_filter.Month_filter#TEXT" : function (pValue, pOperator) { + return TurnoverDynamicChart.dateCond(pValue, pOperator, "MONTH(FORECAST.DATE_START)"); + }, + "ORGANISATION_ID" :"SALESPROJECT.CONTACT_ID", + "#EXTENSION.Groupcode_filter.Groupcode_filter#TEXT" : "FORECAST.GROUPCODE", + "#EXTENSION.Salesproject_filter.Salesproject_filter#TEXT" : "SALESPROJECT.SALESPROJECTID" + }, + "Turnover" : { + "TURNOVER_YEAR" : function (pValue, pOperator) { + return TurnoverDynamicChart.dateCond(pValue, pOperator, "YEAR(SALESORDER.SALESORDERDATE)"); + }, + "#EXTENSION.Month_filter.Month_filter#TEXT" : function (pValue, pOperator) { + return TurnoverDynamicChart.dateCond(pValue, pOperator, "MONTH(SALESORDER.SALESORDERDATE)"); + }, + "ORGANISATION_ID" : "SALESORDER.CONTACT_ID", + "#EXTENSION.Groupcode_filter.Groupcode_filter#TEXT" : "SALESORDERITEM.GROUPCODEID", + "#EXTENSION.Salesproject_filter.Salesproject_filter#TEXT" : "SALESORDER.OBJECT_ROWID" + } + }; + + filterMapping = TurnoverDynamicChart.addOrganisationFiltersToFilterMapping(filterMapping); + filterMapping = TurnoverDynamicChart.addClassificationGroupFilterToFilterMapping(filterMapping); + filterMapping = TurnoverDynamicChart.addClassificationTypeFilterToFilterMapping(filterMapping); + filterMapping = TurnoverDynamicChart.addAttributeFilterToFilterMapping(filterMapping); + + return filterMapping[pKind]; +} + + +/** + * Adds the organisation filter extensions to the filter object and returns the complete object. <br> + * + * @param {Object} pMapping <p> + * <br> The filter mapping object + */ +TurnoverDynamicChart.addOrganisationFiltersToFilterMapping = function (pMapping) +{ + var orgFilters = [["#EXTENSION.OrgCountry_filter.OrgCountry_filter#TEXT", "ADDRESS.COUNTRY"], + ["#EXTENSION.OrgAddress_filter.OrgAddress_filter#TEXT", "ADDRESS.ADDRESS"], + ["#EXTENSION.OrgDistrict_filter.OrgDistrict_filter#TEXT", "ADDRESS.DISTRICT"], + ["#EXTENSION.OrgState_filter.OrgState_filter#TEXT", "ADDRESS.STATE"], + ["#EXTENSION.OrgZip_filter.OrgZip_filter#TEXT", "ADDRESS.ZIP"], + [ "#EXTENSION.OrgCity_filter.OrgCity_filter#TEXT", "ADDRESS.CITY"], + [ "#EXTENSION.OrgRegion_filter.OrgRegion_filter#TEXT", "ADDRESS.REGION"], + [ "#EXTENSION.OrgType_filter.OrgType_filter#TEXT", "ORGANISATION.KIND"], + [ "#EXTENSION.OrgClassification_filter.OrgClassification_filter#TEXT", "CLASSIFICATIONSTORAGE.CLASSIFICATIONVALUE"], + [ "#EXTENSION.OrgLanguage_filter.OrgLanguage_filter#TEXT", "CONTACT.ISOLANGUAGE"]]; + + orgFilters.forEach(function([filterFieldName, dbFilterColumn]) + { + pMapping.Planning[filterFieldName] = dbFilterColumn; + pMapping.Forecast[filterFieldName] = dbFilterColumn; + pMapping.Turnover[filterFieldName] = dbFilterColumn; + }); + + return pMapping; + +} + + +/** + * Adds the classification group filter extension to the filter object and returns the complete object. <br> + * + * @param {Object} pMapping <p> + * <br> The filter mapping object + */ +TurnoverDynamicChart.addClassificationGroupFilterToFilterMapping = function (pMapping) +{ + + var fields = JSON.parse(ClassificationGroupFilterUtils.makeFilterFields("Organisation")); // gets all possible classification group for filtering + var classificationTable = "CLASSIFICATIONSTORAGE"; + + fields.forEach(function(classificationField) + { + let decodedFilterName = ClassificationGroupFilterNameCoder.decode(classificationField["name"]); //decode the base 64 string to its original form to receive the sql expression of the classification + let sqlCondExpression = decodedFilterName["representingSqlExpression"]; + let filterFieldName = "#EXTENSION.ClassificationGroup_filter." + classificationField.name + "#TEXT"; + + pMapping.Planning[filterFieldName] = function (pValue, pOperator) { + return TurnoverDynamicChart.classificationCond(pValue, pOperator, "FORECAST.CONTACT_ID", sqlCondExpression, classificationTable); + }; + pMapping.Forecast[filterFieldName] = function (pValue, pOperator) { + return TurnoverDynamicChart.classificationCond(pValue, pOperator, "SALESPROJECT.CONTACT_ID", sqlCondExpression, classificationTable); + }; + pMapping.Turnover[filterFieldName] = function (pValue, pOperator) { + return TurnoverDynamicChart.classificationCond(pValue, pOperator, "SALESORDER.CONTACT_ID", sqlCondExpression, classificationTable); + }; + }); + return pMapping; + +} + + +/** + * Adds the classification type filter extensions to the filter object and returns the complete object. <br> + * + * @param {Object} pMapping <p> + * <br> The filter mapping object + */ +TurnoverDynamicChart.addClassificationTypeFilterToFilterMapping = function (pMapping) +{ + + var fields = JSON.parse(ClassificationTypeFilterUtils.getFilterFields("Organisation")); // gets all possible classification types for filtering + var classificationTable = "CLASSIFICATION"; + var compareField = "CLASSIFICATION.VALUE"; + + fields.forEach(function(classificationField) + { + let filterName = classificationField["name"]; + let filterFieldName = "#EXTENSION.ClassificationType_filter." + filterName + "#TEXT"; + + pMapping.Planning[filterFieldName] = function (pValue, pOperator) { + return TurnoverDynamicChart.classificationCond(pValue, pOperator, "FORECAST.CONTACT_ID", compareField, classificationTable); + }; + pMapping.Forecast[filterFieldName] = function (pValue, pOperator) { + return TurnoverDynamicChart.classificationCond(pValue, pOperator, "SALESPROJECT.CONTACT_ID", compareField, classificationTable); + }; + pMapping.Turnover[filterFieldName] = function (pValue, pOperator) { + return TurnoverDynamicChart.classificationCond(pValue, pOperator, "SALESORDER.CONTACT_ID", compareField, classificationTable); + }; + }); + return pMapping; + +} + + +/** + * Adds the attribute filter extensions to the filter object and returns the complete object. <br> + * + * @param {Object} pMapping <p> + * <br> The filter mapping object + */ +TurnoverDynamicChart.addAttributeFilterToFilterMapping = function (pMapping) +{ + var fields = JSON.parse(AttributeFilterExtensionMaker.makeFilterFields("Organisation")); // gets all possible attributes for filtering + + fields.forEach(function(attributeField) + { + let attributeId = JSON.parse(util.decodeBase64String(attributeField.name))["id"]; //decode the base 64 string to its original form to receive the id of the attribute + let type = AttributeUtil.getAttributeType(attributeId); + let valueField = AttributeTypeUtil.getDatabaseField(type); + + pMapping.Planning["#EXTENSION.OrgAttribute_filter." + attributeField.name + "#TEXT"] = function (pValue, pOperator) { + return TurnoverDynamicChart.attributeCond(pValue, pOperator, "FORECAST.CONTACT_ID", attributeId, valueField); + }; + pMapping.Forecast["#EXTENSION.OrgAttribute_filter." + attributeField.name + "#TEXT"] = function (pValue, pOperator) { + return TurnoverDynamicChart.attributeCond(pValue, pOperator, "SALESPROJECT.CONTACT_ID", attributeId, valueField); + }; + pMapping.Turnover["#EXTENSION.OrgAttribute_filter." + attributeField.name + "#TEXT"] = function (pValue, pOperator) { + return TurnoverDynamicChart.attributeCond(pValue, pOperator, "SALESORDER.CONTACT_ID", attributeId, valueField); + }; + }); + + return pMapping; + +} + + +/** + * Returns the cond for Date Columns. + * + * @param {String} pValue <p> + * <br> The value of the chosen filter + * @param {String} pOperator <p> + * <br> The operator of the chosen filter + * @param {String} pColumn <p> + * <br> The column with which the value is compared + */ +TurnoverDynamicChart.dateCond = function (pValue, pOperator, pColumn) { + + var cond = TurnoverDynamicChart.getCondition(pValue, pOperator, pColumn); + + if(Array.isArray(cond)) + { + cond = cond[0]; + cond = cond.replace(new RegExp("#", "g"), pColumn); + cond = cond.replace("?", pValue); + } + + return cond; + +} + +/** + * Returns the cond for classification. + * + * @param {String} pValue <p> + * <br> The value of the chosen filter + * @param {String} pOperator <p> + * <br> The operator of the chosen filter + * @param {String} pContactIdColumn <p> + * <br> The contact id column with which the subselect is compared + * @param {String} pCompareField <p> + * <br> The column name with which the value is compared + * @param {String} pClassificationTable <p> + * <br> The classification table used in the subselect + */ +TurnoverDynamicChart.classificationCond = function (pValue, pOperator, pContactIdColumn, pCompareField, pClassificationTable) { + + var cond = TurnoverDynamicChart.getCondition(pValue, pOperator, pCompareField); + if(Array.isArray(cond)) + { + cond = cond[0]; + cond = cond.replace(new RegExp("#", "g"), " UPPER(" + pCompareField + ")"); + cond = cond.replace("?", " UPPER('" + pValue + "')"); + } + + var resSql = newSelect("CONTACTID") + .from("CONTACT") + .join(pClassificationTable, pClassificationTable + ".OBJECT_ROWID = CONTACT.CONTACTID") + .where(cond); + + var finishedCond = newWhere(pContactIdColumn, resSql, SqlBuilder.IN()); + + return finishedCond; + +} + + +/** + * Returns the cond for Attributes. + * + * @param {String} pValue <p> + * <br> The value of the chosen filter + * @param {String} pOperator <p> + * <br> The operator of the chosen filter + * @param {String} pContactIdColumn <p> + * <br> The contact id column with which the subselect is compared + * @param {String} pAttributeId <p> + * <br> The attribute id of the chosen filter + * @param {String} pValueField <p> + * <br> The column name with which the value is compared + */ +TurnoverDynamicChart.attributeCond = function (pValue, pOperator, pContactIdColumn, pAttributeId, pValueField) { + + let sqlCond = pContactIdColumn; + let subsqlAttributes = newSelect("OBJECT_ROWID") + .from("AB_ATTRIBUTERELATION") + .where("AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID", pAttributeId) + .and("AB_ATTRIBUTERELATION.OBJECT_TYPE", "Organisation"); + + if (pOperator == "ISNULL") + { + sqlCond += " not in (" + subsqlAttributes.toString() + ")"; + } + else if (pOperator == "ISNOTNULL") + { + sqlCond += " in (" + subsqlAttributes.toString() + ")"; + } + else if ( pOperator == "NOT_EQUAL") + { + sqlCond += " not in (" + subsqlAttributes.and("AB_ATTRIBUTERELATION." + pValueField, pValue).toString() + ")"; + } + else if (pOperator == "EQUAL") + { + sqlCond += " in (" + subsqlAttributes.and("AB_ATTRIBUTERELATION." + pValueField, pValue).toString() + ")"; + } + + return sqlCond; + +} + + +/** + * Returns the cond for the planning salesproject filter + * + * @param {String} pValue <p> + * <br> The value of the chosen filter + * @param {String} pOperator <p> + * <br> The operator of the chosen filter + */ +TurnoverDynamicChart.planningSalesprojectCond = function (pValue, pOperator) { + + var contactId = newSelect("CONTACT_ID").from("SALESPROJECT").where("SALESPROJECT.SALESPROJECTID", pValue).cell(); + var compareField = "FORECAST.CONTACT_ID"; + var cond = TurnoverDynamicChart.getCondition(pValue, pOperator, contactId); + if(Array.isArray(cond)) + { + cond = cond[0]; + cond = cond.replace(new RegExp("#", "g"), " UPPER(" + compareField + ")"); + cond = cond.replace("?", " UPPER('" + contactId + "')"); + } + + return cond; + +} + + +/** + * returns [condition, value with wildcards] depending on the operator. + * + * @param {String} pValue <p> + * <br> The value to be compared + * @param {String} pOperator <p> + * <br> The compare operator + * @param {String} pField <p> + * <br> The name of the field to be compared + */ +TurnoverDynamicChart.getCondition = function (pValue, pOperator, pField) +{ + switch (pOperator) + { + case "CONTAINS": + return [SqlBuilder.LIKE(), "%" + pValue + "%"]; + case "CONTAINSNOT": + return [SqlBuilder.NOT_LIKE(), "%" + pValue + "%"]; + case "STARTSWITH": + return [SqlBuilder.LIKE(), pValue + "%"]; + case "ENDSWITH": + return [SqlBuilder.LIKE(), "%" + pValue]; + case "EQUAL": + return [SqlBuilder.EQUAL(), pValue]; + case "NOT_EQUAL": + return [SqlBuilder.NOT_EQUAL(), pValue]; + case "LESS": + return [SqlBuilder.LESS(), pValue]; + case "LESS_OR_EQUAL": + return [SqlBuilder.LESS_OR_EQUAL(), pValue]; + case "GREATER": + return [SqlBuilder.GREATER(), pValue]; + case "GREATER_OR_EQUAL": + return [SqlBuilder.GREATER_OR_EQUAL(), pValue]; + case "ISNULL": + return pField + " is null"; + case "ISNOTNULL": + return pField + " is not null"; + case "TIMEFRAME_EQUAL": + case "TIMEFRAME_COMING": + case "TIMEFRAME_PAST": + var [start, end] = datetime.resolveRelativeDateExpression(pValue); + return newWhere(pField, start, SqlBuilder.GREATER_OR_EQUAL()) + .and(pField, end, SqlBuilder.LESS_OR_EQUAL()); + } +} diff --git a/process/UnitTest_lib/process.js b/process/UnitTest_lib/process.js index 382d37e021567c924734a1350a7a368acd1796d3..210ab48b8f435e633a665feed0a9dd766630d990 100644 --- a/process/UnitTest_lib/process.js +++ b/process/UnitTest_lib/process.js @@ -261,7 +261,7 @@ Tester.prototype.equals = function(pExpect, pCustomDescription) if(Utils.isObject(this.actualValue) || Utils.isObject(this.expectedValue)) { - this.expectedDisplayValue = JSON.stringify(this.actualValue); + this.expectedDisplayValue = JSON.stringify(this.actualValue, _getCircularReplacer()); this._testResult = Utils.isEqual(this.actualValue, this.expectedValue); this._generateAssertDescription({custom: pCustomDescription, operator: "===", name: "Object value"}); } @@ -272,6 +272,24 @@ Tester.prototype.equals = function(pExpect, pCustomDescription) } return this; + + //custom replacer that supports cyclic references + function _getCircularReplacer () + { + var seen = new WeakSet(); + return function (key, value) + { + if (typeof value === "object" && value !== null) + { + if (seen.has(value)) + { + return "{...}"; + } + seen.add(value); + } + return value; + } + } } /** @@ -1202,7 +1220,7 @@ Tester.prototype._generateTestTitle = function(pTest, pDataProviderIndex) var titleValues = []; this.dataProvider[pDataProviderIndex].forEach(function(pElement) { - titleValues.push(pElement === undefined ? "undefined" : JSON.stringify(pElement)); + titleValues.push(pElement === undefined ? "undefined" : JSON.stringify(pElement, _getCircularReplacer())); }); this._log("", this.t.info("\t\u2699 Test: " + pTest.name) + this.t.debug(" (#" + (pDataProviderIndex + 1) + ": " + titleValues.join(" | ") + ")")); } @@ -1210,6 +1228,24 @@ Tester.prototype._generateTestTitle = function(pTest, pDataProviderIndex) { this._log("info", "\t\u2699 Test: " + pTest.name); } + + //custom replacer that supports cyclic references + function _getCircularReplacer () + { + var seen = new WeakSet(); + return function (key, value) + { + if (typeof value === "object" && value !== null) + { + if (seen.has(value)) + { + return "{...}"; + } + seen.add(value); + } + return value; + } + } } /** diff --git a/process/Util_lib/process.js b/process/Util_lib/process.js index 8ea572643943a2724f7a323e207122ff530957de..4ef286fe09d3ed55ed6394c8b950ed650c71c67c 100644 --- a/process/Util_lib/process.js +++ b/process/Util_lib/process.js @@ -100,7 +100,7 @@ Utils.isNotNullOrEmptyString = function (pValue) */ Utils.clone = function (pObject) { - var referenceMap = new Map(); + var referenceMap = new WeakMap(); return _clone(pObject); function _clone (pObject) @@ -173,35 +173,62 @@ Utils.clone = function (pObject) */ Utils.isEqual = function (pFirstObject, pSecondObject) { - var firstType = typeof pFirstObject; - var secondType = typeof pSecondObject; - if (firstType !== secondType) - return false; - if (firstType === "object" && pFirstObject !== null && pSecondObject !== null) //check for null because typeof null is also "object" + var comparedObjects = new WeakMap(); + return _isEqual(pFirstObject, pSecondObject); + + function _isEqual (pFirstObject, pSecondObject) { - var isFirstArray = Array.isArray(pFirstObject); - var isSecondArray = Array.isArray(pSecondObject); - if (isFirstArray !== isSecondArray) //return false if only one object is an array - return false; - if (isFirstArray && pFirstObject.length !== pSecondObject.length) + var firstType = typeof pFirstObject; + var secondType = typeof pSecondObject; + if (firstType !== secondType) + { return false; - - for (let key in pSecondObject) + } + if (firstType === "object" && pFirstObject !== null && pSecondObject !== null) //check for null because typeof null is also "object" { - if (!(key in pFirstObject)) + //All object comparisons are saved in comparedObjects, this makes it possible to detect recursions. + //If two objects have been checked for equality already, it can be safely assumed they are equal, + //because if they weren't, this function would have returned false already + if (comparedObjects.get(pFirstObject) === pSecondObject) + { + return true; + } + comparedObjects.set(pFirstObject, pSecondObject); + + var isFirstArray = Array.isArray(pFirstObject); + var isSecondArray = Array.isArray(pSecondObject); + if (isFirstArray !== isSecondArray) //return false if only one object is an array + { + return false; + } + if (isFirstArray && pFirstObject.length !== pSecondObject.length) + { return false; + } + + for (let key in pSecondObject) + { + if (!(key in pFirstObject)) + { + return false; + } + } + for (let key in pFirstObject) + { + if (!(key in pSecondObject) || !_isEqual(pFirstObject[key], pSecondObject[key])) + { + return false; + } + } + return true; } - for (let key in pFirstObject) + if (firstType === "number" && Number.isNaN(pFirstObject) && Number.isNaN(pSecondObject)) //NaN should be equal to NaN { - if (!(key in pSecondObject) || !Utils.isEqual(pFirstObject[key], pSecondObject[key])) - return false; + return true; } - return true; + + return pFirstObject === pSecondObject; } - if (firstType === "number" && Number.isNaN(pFirstObject) && Number.isNaN(pSecondObject)) //NaN should be equal to NaN - return true; - - return pFirstObject === pSecondObject; } /** diff --git a/process/Utils_test/Utils_test.aod b/process/Utils_test/Utils_test.aod new file mode 100644 index 0000000000000000000000000000000000000000..f877069734b9b8465243129b62e612e9f887887a --- /dev/null +++ b/process/Utils_test/Utils_test.aod @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.2" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.2"> + <name>Utils_test</name> + <title>[TEST] Util_lib</title> + <majorModelMode>DISTRIBUTED</majorModelMode> + <icon>VAADIN:CHECK_CIRCLE</icon> + <process>%aditoprj%/process/Utils_test/process.js</process> + <variants> + <element>EXECUTABLE</element> + </variants> +</process> diff --git a/process/Utils_test/process.js b/process/Utils_test/process.js new file mode 100644 index 0000000000000000000000000000000000000000..3a094ad4dcb4e17784be072b5c6089ac636b2d8a --- /dev/null +++ b/process/Utils_test/process.js @@ -0,0 +1,542 @@ +import("Util_lib"); +import("system.result"); +import("system.vars"); +import("UnitTest_lib"); + +var isEmpty = new TestSuite("Utils.isEmpty", [ + new Test("should test if an object, string or array is empty", + function (pTester, pDataProvider) + { + var expectValue = pDataProvider[0]; + var actualValue = Utils.isEmpty(pDataProvider[1]); + + pTester.expectThat(actualValue).equals(expectValue).assert(); + }, + function dataProvider() + { + return [ + [true, ""], + [true, []], + [true, {}], + [true, new Set()], + [true, new Map()], + [true, function () {}], + [false, "never gonna"], + [false, ["give"]], + [false, {you: "up"}], + [false, new Set(["never gonna"])], + [false, new Map([["let", "you down"]])] + ]; + } + ) +]); + +var isNullOrEmpty = new TestSuite("Utils.isNullOrEmpty", [ + new Test("should test if value is null, undefined or empty", + function (pTester, pDataProvider) + { + var expectValue = pDataProvider[0]; + var actualValue = Utils.isNullOrEmpty(pDataProvider[1]); + + pTester.expectThat(actualValue).equals(expectValue).assert(); + }, + function dataProvider() + { + return [ + [true, null], + [true, undefined], + [true, ""], + [true, []], + [true, {}], + [true, new Set()], + [true, new Map()], + [true, function () {}], + [false, "never gonna"], + [false, ["give"]], + [false, {you: "up"}], + [false, new Set(["never gonna"])], + [false, new Map([["let", "you down"]])] + ]; + } + ) +]); + +var isNullOrEmptyString = new TestSuite("Utils.isNullOrEmptyString", [ + new Test("should test if value is null, undefined or empty string", + function (pTester, pDataProvider) + { + var expectValue = pDataProvider[0]; + var actualValue = Utils.isNullOrEmptyString(pDataProvider[1]); + + pTester.expectThat(actualValue).equals(expectValue).assert(); + }, + function dataProvider() + { + return [ + [true, null], + [true, undefined], + [true, ""], + [false, 0], + [false, 42], + [false, false], + [false, true], + [false, []], + [false, {}], + [false, new Set()], + [false, new Map()], + [false, function () {}], + [false, "never gonna"], + [false, ["give"]], + [false, {you: "up"}], + [false, new Set(["never gonna"])], + [false, new Map([["let", "you down"]])] + ]; + } + ) +]); + +var isNotNullOrEmptyString = new TestSuite("Utils.isNotNullOrEmptyString", [ + new Test("should test if value isn't null, undefined or empty string", + function (pTester, pDataProvider) + { + var expectValue = pDataProvider[0]; + var actualValue = Utils.isNotNullOrEmptyString(pDataProvider[1]); + + pTester.expectThat(actualValue).equals(expectValue).assert(); + }, + function dataProvider() + { + return [ + [false, null], + [false, undefined], + [false, ""], + [true, 0], + [true, 42], + [true, false], + [true, true], + [true, []], + [true, {}], + [true, new Set()], + [true, new Map()], + [true, function () {}], + [true, "never gonna"], + [true, ["give"]], + [true, {you: "up"}], + [true, new Set(["never gonna"])], + [true, new Map([["let", "you down"]])] + ]; + } + ) +]); + +var clone = new TestSuite("Utils.clone", [ + new Test("should test if value is copied correctly", + function (pTester, pDataProvider) + { + var original = pDataProvider[0]; + var copy = Utils.clone(original); + + pTester.expectThat(original).equals(copy).assert(); + }, + function dataProvider() + { + var recursiveObj = {test: "Test"}; + recursiveObj.recursion = recursiveObj; + return [ + [null], + [undefined], + [0], + [42], + [""], + ["yeee"], + [[]], + [{}], + [["one", "two", 3, 4]], + [{one: "two", three: 4}], + [["one", "two", [3, 4, {five: "6"}]]], + [{one: "two", three: [4, {five: "6"}]}], + [new Set(["one", "two", 3, 4])], + [new Map([["one", "two"], [3, 4]])], + [recursiveObj] + ]; + } + ) +]); + +var isEqual = new TestSuite("Utils.isEqual", [ + new Test("should test if object equality is checked correctly", + function (pTester, pDataProvider) + { + var expectValue = pDataProvider[0]; + var actualValue = Utils.isEqual(pDataProvider[1], pDataProvider[2]); + + pTester.expectThat(actualValue).equals(expectValue).assert(); + }, + function dataProvider() + { + var num = 0; + var str = "0"; + var objStr = new String("0"); + var obj_1 = {a: 1, b: 2, c: 3}; + var obj_2 = {x: null, y: "test", z: true}; + var recursiveObj1 = {test: "Test"}; + recursiveObj1.recursion = recursiveObj1; + var recursiveObj2 = {test: "Test"}; + recursiveObj2.recursion = recursiveObj2; + + return [ + [true, num, num], + [true, str, str], + [true, true, true], + [true, objStr, objStr], + [true, obj_1, obj_1], + [true, obj_2, obj_2], + [false, true, false], + [false, obj_1, obj_2], + [false, num, objStr], + [false, num, str], + [false, objStr, str], + [false, null, undefined], + [false, objStr, null], + [false, objStr, undefined], + [false, null, "null"], + [true, recursiveObj1, recursiveObj2] + ]; + } + ) +]); + +var isFunction = new TestSuite("Utils.isFunction", [ + new Test("should test if functions are identified correctly", + function (pTester, pDataProvider) + { + var expectValue = pDataProvider[0]; + var actualValue = Utils.isFunction(pDataProvider[1]); + + pTester.expectThat(actualValue).equals(expectValue).assert(); + }, + function dataProvider() + { + return [ + [true, function () {}], + [true, (function () {}).bind({})], + [false, null], + [false, undefined], + [false, true], + [false, false], + [false, 0], + [false, "str"], + [false, {}], + [false, []], + [false, new Map()], + [false, new Set()] + ]; + } + ) +]); + +var isString = new TestSuite("Utils.isString", [ + new Test("should test if strings are identified correctly", + function (pTester, pDataProvider) + { + var expectValue = pDataProvider[0]; + var actualValue = Utils.isString(pDataProvider[1]); + + pTester.expectThat(actualValue).equals(expectValue).assert(); + }, + function dataProvider() + { + return [ + [false, null], + [false, undefined], + [false, true], + [false, false], + [false, 0], + [true, ""], + [true, "str"], + [false, new String("")], + [false, {}], + [false, []], + [false, function () {}], + [false, new Map()], + [false, new Set()] + ]; + } + ) +]); + +var isNumber = new TestSuite("Utils.isNumber", [ + new Test("should test if numbers are identified correctly", + function (pTester, pDataProvider) + { + var expectValue = pDataProvider[0]; + var actualValue = Utils.isNumber(pDataProvider[1]); + + pTester.expectThat(actualValue).equals(expectValue).assert(); + }, + function dataProvider() + { + return [ + [false, null], + [false, undefined], + [false, true], + [false, false], + [true, 0], + [true, NaN], + [true, Infinity], + [false, "0"], + [false, {}], + [false, []], + [false, function () {}], + [false, new Map()], + [false, new Set()] + ]; + } + ) +]); + +var isNumeric = new TestSuite("Utils.isNumeric", [ + new Test("should test if numbers are identified correctly", + function (pTester, pDataProvider) + { + var expectValue = pDataProvider[0]; + var actualValue = Utils.isNumeric(pDataProvider[1]); + + pTester.expectThat(actualValue).equals(expectValue).assert(); + }, + function dataProvider() + { + return [ + [false, null], + [false, undefined], + [false, true], + [false, false], + [true, 0], + [true, "0"], + [false, "notnumber"], + [false, {}], + [false, []], + [false, function () {}], + [false, new Map()], + [false, new Set()] + ]; + } + ) +]); + +var isInteger = new TestSuite("Utils.isInteger", [ + new Test("should test if integers are identified correctly", + function (pTester, pDataProvider) + { + var expectValue = pDataProvider[0]; + var actualValue = Utils.isInteger(pDataProvider[1]); + + pTester.expectThat(actualValue).equals(expectValue).assert(); + }, + function dataProvider() + { + return [ + [false, null], + [false, undefined], + [false, true], + [false, false], + [true, 0], + [true, "0"], + [true, 1.0], + [true, "1.0"], + [false, 1.2], + [false, "1.2"], + [false, NaN], + [false, Infinity], + [false, "notnumber"], + [false, {}], + [false, []], + [false, function () {}], + [false, new Map()], + [false, new Set()] + ]; + } + ) +]); + +var isFloat = new TestSuite("Utils.isFloat", [ + new Test("should test if floats are identified correctly", + function (pTester, pDataProvider) + { + var expectValue = pDataProvider[0]; + var actualValue = Utils.isFloat(pDataProvider[1]); + + pTester.expectThat(actualValue).equals(expectValue).assert(); + }, + function dataProvider() + { + return [ + [false, null], + [false, undefined], + [false, true], + [false, false], + [false, 0], + [false, "0"], + [false, 1.0], + [false, "1.0"], + [true, 1.2], + [true, "1.2"], + [false, NaN], + [false, Infinity], + [false, "notnumber"], + [false, {}], + [false, []], + [false, function () {}], + [false, new Map()], + [false, new Set()] + ]; + } + ) +]); + +var isObject = new TestSuite("Utils.isObject", [ + new Test("should test if objects are identified correctly", + function (pTester, pDataProvider) + { + var expectValue = pDataProvider[0]; + var actualValue = Utils.isObject(pDataProvider[1]); + + pTester.expectThat(actualValue).equals(expectValue).assert(); + }, + function dataProvider() + { + return [ + [false, null], + [false, undefined], + [false, true], + [false, false], + [false, 0], + [false, "0"], + [false, NaN], + [false, Infinity], + [true, {}], + [true, []], + [false, function () {}], + [true, new Map()], + [true, new Set()] + ]; + } + ) +]); + +var isMap = new TestSuite("Utils.isMap", [ + new Test("should test if maps are identified correctly", + function (pTester, pDataProvider) + { + var expectValue = pDataProvider[0]; + var actualValue = Utils.isMap(pDataProvider[1]); + + pTester.expectThat(actualValue).equals(expectValue).assert(); + }, + function dataProvider() + { + return [ + [false, null], + [false, undefined], + [false, true], + [false, false], + [false, 0], + [false, "0"], + [false, NaN], + [false, Infinity], + [false, {}], + [false, []], + [false, function () {}], + [true, new Map()], + [false, new Set()] + ]; + } + ) +]); + +var isBoolean = new TestSuite("Utils.isBoolean", [ + new Test("should test if booleans are identified correctly", + function (pTester, pDataProvider) + { + var expectValue = pDataProvider[0]; + var actualValue = Utils.isBoolean(pDataProvider[1]); + + pTester.expectThat(actualValue).equals(expectValue).assert(); + }, + function dataProvider() + { + return [ + [false, null], + [false, undefined], + [true, true], + [true, false], + [false, 0], + [false, "0"], + [false, NaN], + [false, Infinity], + [false, {}], + [false, []], + [false, function () {}], + [false, new Map()], + [false, new Set()] + ]; + } + ) +]); + +var toBoolean = new TestSuite("Utils.toBoolean", [ + new Test("should test if boolean-ish values are parsed correctly", + function (pTester, pDataProvider) + { + var expectValue = pDataProvider[0]; + var actualValue = Utils.toBoolean(pDataProvider[1]); + + pTester.expectThat(actualValue).equals(expectValue).assert(); + }, + function dataProvider() + { + return [ + [true, true], + [true, 1], + [true, "1"], + [true, "true"], + [true, {}], + [true, []], + [true, function () {}], + [true, new Map()], + [true, new Set()], + [false, false], + [false, 0], + [false, "0"], + [false, ""], + [false, "false"], + [false, null], + [false, "null"], + [false, undefined], + [false, "undefined"] + ]; + } + ) +]); + +var tester = new Tester("Test Util_lib"); +tester.initCoverage(Utils); +tester.test(isEmpty); +tester.test(isNullOrEmpty); +tester.test(isNullOrEmptyString); +tester.test(clone); +tester.test(isEqual); +tester.test(isFunction); +tester.test(isString); +tester.test(isNumber); +tester.test(isNumeric); +tester.test(isInteger); +tester.test(isFloat); +tester.test(isObject); +tester.test(isMap); +tester.test(isBoolean); +tester.test(toBoolean); + +tester.summary(); + +result.object(tester.getResults()); diff --git a/process/Workflow_lib/process.js b/process/Workflow_lib/process.js index e645f7a4aa67bdb71c03361840943f8e9ebfff2a..52634e53c71a268418f1dd680093c0b5096e6618 100644 --- a/process/Workflow_lib/process.js +++ b/process/Workflow_lib/process.js @@ -236,7 +236,8 @@ WorkflowSignalSender.eventHappened = function (pEvent, pTargetId, pTargetContext */ WorkflowSignalSender.getSignalConfig = function (pContext, pEvent) { - var signals = newSelect("SIGNAL_NAME, TRIGGER_EVENT, OBJECT_CONDITION, OBJECT_TYPE, VARIABLES", db.getCurrentAlias()) + //Data_alias explicitly because this can be called from a system alias context + var signals = newSelect("SIGNAL_NAME, TRIGGER_EVENT, OBJECT_CONDITION, OBJECT_TYPE, VARIABLES", "Data_alias") .from("WORKFLOWSIGNAL") .whereIfSet("WORKFLOWSIGNAL.OBJECT_TYPE", pContext) .andIfSet("WORKFLOWSIGNAL.TRIGGER_EVENT", pEvent) diff --git a/rendererDefinition/numberPlus1000/numberPlus1000.aod b/rendererDefinition/numberPlus1000/numberPlus1000.aod new file mode 100644 index 0000000000000000000000000000000000000000..42ad72cbb27949ddadbc44088be105d02c5329c6 --- /dev/null +++ b/rendererDefinition/numberPlus1000/numberPlus1000.aod @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<rendererDefinition xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.0.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/rendererDefinition/1.0.0"> + <name>numberPlus1000</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <rendererType>NUMBERFIELD</rendererType> + <rendererConfig> + <numberFieldRendererConfig> + <name>rendererConfig</name> + <numberfieldStep v="1000" /> + </numberFieldRendererConfig> + </rendererConfig> +</rendererDefinition> diff --git a/report/Offer_report/reportData.jrxml b/report/Offer_report/reportData.jrxml index 909a49ae0c633c8db4975aad71b03479e196b122..24951a28ca3413c30c5d27918635f83e8e3e6f1e 100644 --- a/report/Offer_report/reportData.jrxml +++ b/report/Offer_report/reportData.jrxml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="report1" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="e7a916c8-3f9a-497d-84bb-3909b15271ea"> - <property name="ireport.zoom" value="1.0"/> - <property name="ireport.x" value="0"/> - <property name="ireport.y" value="0"/> + <property name="ireport.zoom" value="2.1435888100000016"/> + <property name="ireport.x" value="260"/> + <property name="ireport.y" value="395"/> <parameter name="myAddr" class="java.lang.String"/> <parameter name="Pos" class="java.lang.String"/> <parameter name="Articledescription" class="java.lang.String"/> @@ -24,7 +24,7 @@ <parameter name="OfferDeliveryTerm" class="java.lang.String"/> <parameter name="responsible" class="java.lang.String"/> <parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false"> - <defaultValueExpression><![CDATA["C:\\Entwicklung\\0.0\\project\\basic2\\report\\Offer_report\\"]]></defaultValueExpression> + <defaultValueExpression><![CDATA["C:\\entwicklungszweige\\master\\project\\xRM-Basic\\report\\Offer_report\\"]]></defaultValueExpression> </parameter> <parameter name="adito.datasource.subdata" class="java.lang.Object"/> <parameter name="SUMITEMSUM" class="java.lang.Double"/> @@ -37,6 +37,7 @@ <parameter name="TotalWithoutVat" class="java.lang.String"/> <parameter name="TotalWithVat" class="java.lang.String"/> <parameter name="printHeadDiscount" class="java.lang.String"/> + <parameter name="Optional" class="java.lang.String"/> <queryString> <![CDATA[]]> </queryString> @@ -145,7 +146,7 @@ </band> <band height="42"> <staticText> - <reportElement x="358" y="23" width="27" height="15" isRemoveLineWhenBlank="true" uuid="a81f864d-b418-4f1d-9410-2eb7ac8cff60"> + <reportElement x="320" y="23" width="27" height="15" isRemoveLineWhenBlank="true" uuid="a81f864d-b418-4f1d-9410-2eb7ac8cff60"> <printWhenExpression><![CDATA[!$P{printDiscount}.equals("0")]]></printWhenExpression> </reportElement> <textElement textAlignment="Right"> @@ -185,7 +186,7 @@ <textFieldExpression><![CDATA[$P{Unitprice}]]></textFieldExpression> </textField> <textField> - <reportElement x="345" y="11" width="40" height="12" isRemoveLineWhenBlank="true" uuid="91319825-d02b-4a0d-9234-8342b8518c61"> + <reportElement x="307" y="11" width="40" height="12" isRemoveLineWhenBlank="true" uuid="91319825-d02b-4a0d-9234-8342b8518c61"> <printWhenExpression><![CDATA[!$P{printDiscount}.equals("0")]]></printWhenExpression> </reportElement> <textElement textAlignment="Right"> @@ -201,7 +202,7 @@ <textFieldExpression><![CDATA[$P{Pos}]]></textFieldExpression> </textField> <textField> - <reportElement x="279" y="11" width="54" height="12" uuid="3bb98c33-f62c-444f-b706-49d4dd54cf35"/> + <reportElement x="252" y="11" width="54" height="12" uuid="3bb98c33-f62c-444f-b706-49d4dd54cf35"/> <textElement textAlignment="Right"> <font size="8"/> </textElement> @@ -229,7 +230,7 @@ <textFieldExpression><![CDATA[$F{OFFER_CURRENCY}]]></textFieldExpression> </textField> <textField> - <reportElement x="122" y="11" width="156" height="12" uuid="0dbb9e83-463b-45e4-a702-2d1699220383"/> + <reportElement x="122" y="11" width="130" height="12" uuid="0dbb9e83-463b-45e4-a702-2d1699220383"/> <textElement> <font size="8"/> </textElement> @@ -238,6 +239,13 @@ <line> <reportElement x="14" y="6" width="541" height="1" uuid="c19244a8-cbd9-4a8a-b2e4-25e6aa6d730d"/> </line> + <textField> + <reportElement x="349" y="11" width="40" height="12" isRemoveLineWhenBlank="true" uuid="34c76f59-4476-41f7-8326-5bef886cc0da"/> + <textElement textAlignment="Right"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$P{Optional}]]></textFieldExpression> + </textField> </band> </groupHeader> <groupFooter> @@ -429,14 +437,14 @@ <textFieldExpression><![CDATA[$F{PRODUCT_PRODUCTCODE}]]></textFieldExpression> </textField> <textField> - <reportElement x="122" y="0" width="156" height="15" uuid="b0a5ce7d-8c01-41e5-8a59-bae7ec156590"/> + <reportElement x="122" y="0" width="130" height="15" uuid="b0a5ce7d-8c01-41e5-8a59-bae7ec156590"/> <textElement> <font size="8"/> </textElement> <textFieldExpression><![CDATA[$F{OFFERITEM_ITEMNAME}]]></textFieldExpression> </textField> <textField isStretchWithOverflow="true" pattern=""> - <reportElement x="345" y="0" width="40" height="15" isRemoveLineWhenBlank="true" uuid="dab4d8da-3af4-4d4d-b78d-a2e97b17271a"> + <reportElement x="307" y="0" width="40" height="15" isRemoveLineWhenBlank="true" uuid="dab4d8da-3af4-4d4d-b78d-a2e97b17271a"> <printWhenExpression><![CDATA[!$F{OFFERITEM_DISCOUNT}.equals("0,00") && !$F{OFFERITEM_DISCOUNT}.equals("0.00")]]></printWhenExpression> </reportElement> <textElement textAlignment="Right"> @@ -459,7 +467,7 @@ <textFieldExpression><![CDATA[!$F{OFFERITEM_VAT}.equals(null)? $F{OFFERITEM_VAT} : ""]]></textFieldExpression> </textField> <textField pattern="###0;-###0"> - <reportElement x="282" y="0" width="51" height="15" uuid="bd119f1f-b7f2-4df2-a807-2acbbbc19b74"/> + <reportElement x="255" y="0" width="51" height="15" uuid="bd119f1f-b7f2-4df2-a807-2acbbbc19b74"/> <textElement textAlignment="Right"> <font size="8"/> </textElement> @@ -474,11 +482,18 @@ </textElement> <textFieldExpression><![CDATA[$F{ITEMSUM}]]></textFieldExpression> </textField> + <textField isStretchWithOverflow="true" pattern=""> + <reportElement x="349" y="0" width="40" height="15" isRemoveLineWhenBlank="true" uuid="01e982a3-df8d-4445-83be-d6a61c69d2e9"/> + <textElement textAlignment="Right"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$F{OFFERITEM_OPTIONAL}]]></textFieldExpression> + </textField> </band> <band height="15"> <printWhenExpression><![CDATA[!$F{OFFERITEM_ASSIGNEDTO}.equals(null) && !$F{OFFERITEM_ASSIGNEDTO}.equals("")]]></printWhenExpression> <textField> - <reportElement x="122" y="0" width="156" height="15" forecolor="#999999" uuid="ae45c708-344e-4a7d-8756-de306f3ec922"/> + <reportElement x="122" y="0" width="130" height="15" forecolor="#999999" uuid="ae45c708-344e-4a7d-8756-de306f3ec922"/> <textElement> <font size="8"/> </textElement> @@ -492,7 +507,7 @@ <textFieldExpression><![CDATA[$F{OFFERITEM_ITEMPOSITION}]]></textFieldExpression> </textField> <textField pattern="###0;-###0"> - <reportElement x="282" y="0" width="51" height="15" forecolor="#999999" uuid="4337f5ec-5d87-403e-a6fd-d7036ae210b5"/> + <reportElement x="255" y="0" width="51" height="15" forecolor="#999999" uuid="4337f5ec-5d87-403e-a6fd-d7036ae210b5"/> <textElement textAlignment="Right"> <font size="8"/> </textElement> @@ -505,6 +520,13 @@ </textElement> <textFieldExpression><![CDATA[$F{PRODUCT_PRODUCTCODE}]]></textFieldExpression> </textField> + <textField isStretchWithOverflow="true" pattern=""> + <reportElement x="349" y="0" width="40" height="15" isRemoveLineWhenBlank="true" forecolor="#999999" uuid="9658ee4e-0c56-4cf0-9db0-5623edd01075"/> + <textElement textAlignment="Right"> + <font size="8"/> + </textElement> + <textFieldExpression><![CDATA[$F{OFFERITEM_OPTIONAL}]]></textFieldExpression> + </textField> </band> <band height="18"> <textField isStretchWithOverflow="true">