Merged in feature/IO-3515-bill-ocr-feedback (pull request #3142)
Feature/IO-3515 bill ocr feedback Approved-by: Dave Richer
This commit is contained in:
@@ -2696,6 +2696,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>oem_partno</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>quantity</name>
|
<name>quantity</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -3684,6 +3705,48 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>feedback_placeholder</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>feedback_prompt</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>generic_failure</name>
|
<name>generic_failure</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -3831,6 +3894,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>submit_feedback</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
@@ -8641,6 +8725,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>manual-line</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>partsqueue</name>
|
<name>partsqueue</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -17816,6 +17921,468 @@
|
|||||||
<folder_node>
|
<folder_node>
|
||||||
<name>labels</name>
|
<name>labels</name>
|
||||||
<children>
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>banner_message</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>banner_status_connected</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>banner_status_disconnected</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>clear_logs</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>collapse_all</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>color_json</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>copied</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>copy</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>copy_request</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>copy_response</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>details</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>expand_all</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>hide_details</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>log_level</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>plain_json</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>provider_cdk</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>provider_dms</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>provider_fortellis</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>provider_pbs</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>provider_reynolds</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>reconnect</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>reconnected_export_service</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>refreshallocations</name>
|
<name>refreshallocations</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -17837,6 +18404,153 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>request_xml</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>response_xml</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>rr_validation_message</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>rr_validation_notice_description</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>rr_validation_notice_title</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>transport_ws</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>transport_wss</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
</children>
|
</children>
|
||||||
@@ -20590,6 +21304,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>done</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>download</name>
|
<name>download</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -23009,6 +23744,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>validationerror</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>view</name>
|
<name>view</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -23423,6 +24179,27 @@
|
|||||||
<folder_node>
|
<folder_node>
|
||||||
<name>validation</name>
|
<name>validation</name>
|
||||||
<children>
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>array</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>dateRangeExceeded</name>
|
<name>dateRangeExceeded</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -57452,6 +58229,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>work_in_progress_labour_summary</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>work_in_progress_payables</name>
|
<name>work_in_progress_payables</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -57473,6 +58271,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>work_in_progress_payables_summary</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
</children>
|
</children>
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
import { DislikeOutlined, LikeOutlined } from "@ant-design/icons";
|
||||||
|
import { Button, Form, Input, Radio, Space } from "antd";
|
||||||
|
import axios from "axios";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
function BillAiFeedback({ billForm, rawAIData }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const [submitting, setSubmitting] = useState(false);
|
||||||
|
const notification = useNotification();
|
||||||
|
|
||||||
|
//Need to sanitize becuase we pass as form data to include the attachment.
|
||||||
|
const sanitizeBillFormValues = (value) => {
|
||||||
|
const seen = new WeakSet();
|
||||||
|
return JSON.stringify(
|
||||||
|
value,
|
||||||
|
(key, v) => {
|
||||||
|
if (key === "originFileObj") return undefined;
|
||||||
|
if (key === "thumbUrl") return undefined;
|
||||||
|
if (key === "preview") return undefined;
|
||||||
|
if (typeof v === "function") return undefined;
|
||||||
|
if (v && typeof v === "object") {
|
||||||
|
if (seen.has(v)) return "[Circular]";
|
||||||
|
seen.add(v);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
},
|
||||||
|
0
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAttachmentFromBillFormUpload = () => {
|
||||||
|
const uploads = billForm?.getFieldValue?.("upload") || [];
|
||||||
|
const files = uploads.map((u) => u?.originFileObj).filter(Boolean);
|
||||||
|
|
||||||
|
return (
|
||||||
|
files.find((f) => f?.type === "application/pdf") ||
|
||||||
|
files.find((f) => isString(f?.name) && f.name.toLowerCase().endsWith(".pdf")) ||
|
||||||
|
files[0] ||
|
||||||
|
null
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const submitFeedback = async ({ rating, comments }) => {
|
||||||
|
setSubmitting(true);
|
||||||
|
try {
|
||||||
|
const billFormValues = billForm.getFieldsValue(true);
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("rating", rating);
|
||||||
|
formData.append("comments", comments || "");
|
||||||
|
formData.append("billFormValues", sanitizeBillFormValues(billFormValues));
|
||||||
|
formData.append("rawAIData", sanitizeBillFormValues(rawAIData));
|
||||||
|
|
||||||
|
const attachmentFile = getAttachmentFromBillFormUpload();
|
||||||
|
if (attachmentFile) {
|
||||||
|
formData.append("billPdf", attachmentFile, attachmentFile.name || "bill.pdf");
|
||||||
|
}
|
||||||
|
|
||||||
|
await axios.post("/ai/bill-feedback", formData);
|
||||||
|
|
||||||
|
notification.success({
|
||||||
|
title: "Thanks — feedback submitted"
|
||||||
|
});
|
||||||
|
form.resetFields();
|
||||||
|
} catch (error) {
|
||||||
|
notification.error({
|
||||||
|
title: "Failed to submit feedback",
|
||||||
|
description: error?.response?.data?.message || error?.message
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setSubmitting(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const isString = (v) => typeof v === "string";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form form={form} onFinish={submitFeedback} requiredMark={false}>
|
||||||
|
<Space wrap align="top" size="small">
|
||||||
|
<Form.Item name="rating" label={t("bills.labels.ai.feedback_prompt")} rules={[{ required: true }]}>
|
||||||
|
<Radio.Group optionType="button" buttonStyle="solid">
|
||||||
|
<Radio.Button value="up">
|
||||||
|
<LikeOutlined />
|
||||||
|
</Radio.Button>
|
||||||
|
<Radio.Button value="down">
|
||||||
|
<DislikeOutlined />
|
||||||
|
</Radio.Button>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Space wrap size="small" orientation="vertical">
|
||||||
|
<Form.Item name="comments">
|
||||||
|
<Input.TextArea
|
||||||
|
rows={3}
|
||||||
|
style={{ minWidth: "400px" }}
|
||||||
|
placeholder={t("bills.labels.ai.feedback_placeholder")}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Button onClick={() => form.submit()} loading={submitting} disabled={submitting}>
|
||||||
|
{t("bills.labels.ai.submit_feedback")}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</Space>
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export default BillAiFeedback;
|
||||||
@@ -23,7 +23,8 @@ function BillEnterAiScan({
|
|||||||
fileInputRef,
|
fileInputRef,
|
||||||
scanLoading,
|
scanLoading,
|
||||||
setScanLoading,
|
setScanLoading,
|
||||||
setIsAiScan
|
setIsAiScan,
|
||||||
|
setRawAIData
|
||||||
}) {
|
}) {
|
||||||
const notification = useNotification();
|
const notification = useNotification();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -57,6 +58,7 @@ function BillEnterAiScan({
|
|||||||
}
|
}
|
||||||
setScanLoading(false);
|
setScanLoading(false);
|
||||||
|
|
||||||
|
setRawAIData(data.data);
|
||||||
// Update form with the extracted data
|
// Update form with the extracted data
|
||||||
if (data?.data?.billForm) {
|
if (data?.data?.billForm) {
|
||||||
form.setFieldsValue(data.data.billForm);
|
form.setFieldsValue(data.data.billForm);
|
||||||
@@ -147,6 +149,7 @@ function BillEnterAiScan({
|
|||||||
setScanLoading(false);
|
setScanLoading(false);
|
||||||
|
|
||||||
form.setFieldsValue(data.data.billForm);
|
form.setFieldsValue(data.data.billForm);
|
||||||
|
setRawAIData(data.data);
|
||||||
await form.validateFields(["billlines"], { recursive: true });
|
await form.validateFields(["billlines"], { recursive: true });
|
||||||
|
|
||||||
notification.success({
|
notification.success({
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useApolloClient, useMutation } from "@apollo/client/react";
|
import { useApolloClient, useMutation } from "@apollo/client/react";
|
||||||
import { useTreatmentsWithConfig } from "@splitsoftware/splitio-react";
|
import { useTreatmentsWithConfig } from "@splitsoftware/splitio-react";
|
||||||
import { Button, Checkbox, Form, Modal, Space } from "antd";
|
import { Button, Checkbox, Divider, Form, Modal, Space } from "antd";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { useEffect, useMemo, useRef, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -28,6 +28,7 @@ import { CalculateBillTotal } from "../bill-form/bill-form.totals.utility";
|
|||||||
import { handleUpload as handleLocalUpload } from "../documents-local-upload/documents-local-upload.utility";
|
import { handleUpload as handleLocalUpload } from "../documents-local-upload/documents-local-upload.utility";
|
||||||
import { handleUpload as handleUploadToImageProxy } from "../documents-upload-imgproxy/documents-upload-imgproxy.utility";
|
import { handleUpload as handleUploadToImageProxy } from "../documents-upload-imgproxy/documents-upload-imgproxy.utility";
|
||||||
import { handleUpload } from "../documents-upload/documents-upload.utility";
|
import { handleUpload } from "../documents-upload/documents-upload.utility";
|
||||||
|
import BillAiFeedback from "../bill-ai-feedback/bill-ai-feedback.component.jsx";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
billEnterModal: selectBillEnterModal,
|
billEnterModal: selectBillEnterModal,
|
||||||
@@ -53,6 +54,7 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
|
|||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [scanLoading, setScanLoading] = useState(false);
|
const [scanLoading, setScanLoading] = useState(false);
|
||||||
const [isAiScan, setIsAiScan] = useState(false);
|
const [isAiScan, setIsAiScan] = useState(false);
|
||||||
|
const [rawAIData, setRawAIData] = useState(null);
|
||||||
const client = useApolloClient();
|
const client = useApolloClient();
|
||||||
const [generateLabel, setGenerateLabel] = useLocalStorage("enter_bill_generate_label", false);
|
const [generateLabel, setGenerateLabel] = useLocalStorage("enter_bill_generate_label", false);
|
||||||
const notification = useNotification();
|
const notification = useNotification();
|
||||||
@@ -387,6 +389,7 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
|
|||||||
billlines: []
|
billlines: []
|
||||||
});
|
});
|
||||||
setIsAiScan(false);
|
setIsAiScan(false);
|
||||||
|
setRawAIData(null);
|
||||||
// form.resetFields();
|
// form.resetFields();
|
||||||
} else {
|
} else {
|
||||||
toggleModalVisible();
|
toggleModalVisible();
|
||||||
@@ -404,6 +407,7 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
|
|||||||
}
|
}
|
||||||
setScanLoading(false);
|
setScanLoading(false);
|
||||||
setIsAiScan(false);
|
setIsAiScan(false);
|
||||||
|
setRawAIData(null);
|
||||||
toggleModalVisible();
|
toggleModalVisible();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -429,6 +433,7 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
|
|||||||
}
|
}
|
||||||
setScanLoading(false);
|
setScanLoading(false);
|
||||||
setIsAiScan(false);
|
setIsAiScan(false);
|
||||||
|
setRawAIData(null);
|
||||||
}
|
}
|
||||||
}, [billEnterModal.open, form, formValues]);
|
}, [billEnterModal.open, form, formValues]);
|
||||||
|
|
||||||
@@ -456,6 +461,7 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
|
|||||||
scanLoading={scanLoading}
|
scanLoading={scanLoading}
|
||||||
setScanLoading={setScanLoading}
|
setScanLoading={setScanLoading}
|
||||||
setIsAiScan={setIsAiScan}
|
setIsAiScan={setIsAiScan}
|
||||||
|
setRawAIData={setRawAIData}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Space>
|
</Space>
|
||||||
@@ -471,26 +477,34 @@ function BillEnterModalContainer({ billEnterModal, toggleModalVisible, bodyshop,
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
}}
|
}}
|
||||||
footer={
|
footer={
|
||||||
<Space>
|
<Space orientation="vertical">
|
||||||
<Checkbox checked={generateLabel} onChange={(e) => setGenerateLabel(e.target.checked)}>
|
{isAiScan && (
|
||||||
{t("bills.labels.generatepartslabel")}
|
<>
|
||||||
</Checkbox>
|
<BillAiFeedback billForm={form} rawAIData={rawAIData} />
|
||||||
<Button onClick={handleCancel}>{t("general.actions.cancel")}</Button>
|
<Divider orientation="horizontal" />
|
||||||
<Button loading={loading} onClick={() => form.submit()} id="save-bill-enter-modal">
|
</>
|
||||||
{t("general.actions.save")}
|
|
||||||
</Button>
|
|
||||||
{billEnterModal.context && billEnterModal.context.id ? null : (
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
loading={loading}
|
|
||||||
onClick={() => {
|
|
||||||
setEnterAgain(true);
|
|
||||||
}}
|
|
||||||
id="save-and-new-bill-enter-modal"
|
|
||||||
>
|
|
||||||
{t("general.actions.saveandnew")}
|
|
||||||
</Button>
|
|
||||||
)}
|
)}
|
||||||
|
<Space wrap align="top">
|
||||||
|
<Checkbox checked={generateLabel} onChange={(e) => setGenerateLabel(e.target.checked)}>
|
||||||
|
{t("bills.labels.generatepartslabel")}
|
||||||
|
</Checkbox>
|
||||||
|
<Button onClick={handleCancel}>{t("general.actions.cancel")}</Button>
|
||||||
|
<Button loading={loading} onClick={() => form.submit()} id="save-bill-enter-modal">
|
||||||
|
{t("general.actions.save")}
|
||||||
|
</Button>
|
||||||
|
{billEnterModal.context && billEnterModal.context.id ? null : (
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
loading={loading}
|
||||||
|
onClick={() => {
|
||||||
|
setEnterAgain(true);
|
||||||
|
}}
|
||||||
|
id="save-and-new-bill-enter-modal"
|
||||||
|
>
|
||||||
|
{t("general.actions.saveandnew")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Space>
|
||||||
</Space>
|
</Space>
|
||||||
}
|
}
|
||||||
destroyOnHidden
|
destroyOnHidden
|
||||||
|
|||||||
@@ -231,13 +231,16 @@
|
|||||||
"overall": "Overall"
|
"overall": "Overall"
|
||||||
},
|
},
|
||||||
"disclaimer_title": "AI Scan Beta Disclaimer",
|
"disclaimer_title": "AI Scan Beta Disclaimer",
|
||||||
|
"feedback_placeholder": "Tell us what worked, what didn't, and what could be better.",
|
||||||
|
"feedback_prompt": "Was this AI scan helpful?",
|
||||||
"generic_failure": "Failed to process invoice.",
|
"generic_failure": "Failed to process invoice.",
|
||||||
"multipage": "The is a multi-page document. Processing will take a few moments.",
|
"multipage": "The is a multi-page document. Processing will take a few moments.",
|
||||||
"processing": "Analyzing Bill",
|
"processing": "Analyzing Bill",
|
||||||
"scan": "AI Bill Scanner",
|
"scan": "AI Bill Scanner",
|
||||||
"scancomplete": "AI Scan Complete",
|
"scancomplete": "AI Scan Complete",
|
||||||
"scanfailed": "AI Scan Failed",
|
"scanfailed": "AI Scan Failed",
|
||||||
"scanstarted": "AI Scan Started"
|
"scanstarted": "AI Scan Started",
|
||||||
|
"submit_feedback": "Submit Feedback"
|
||||||
},
|
},
|
||||||
"bill_lines": "Bill Lines",
|
"bill_lines": "Bill Lines",
|
||||||
"bill_total": "Bill Total Amount",
|
"bill_total": "Bill Total Amount",
|
||||||
@@ -1076,36 +1079,36 @@
|
|||||||
"earlyrorequired.message": "This job requires an early Repair Order to be created before posting to Reynolds. Please use the admin panel to create the early RO first."
|
"earlyrorequired.message": "This job requires an early Repair Order to be created before posting to Reynolds. Please use the admin panel to create the early RO first."
|
||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"refreshallocations": "Refresh to see DMS Allocations.",
|
"banner_message": "Posting to {{provider}} | {{transport}} | {{status}}",
|
||||||
"provider_reynolds": "Reynolds",
|
|
||||||
"provider_fortellis": "Fortellis",
|
|
||||||
"provider_cdk": "CDK",
|
|
||||||
"provider_pbs": "PBS",
|
|
||||||
"provider_dms": "DMS",
|
|
||||||
"transport_wss": "(WSS)",
|
|
||||||
"transport_ws": "(WS)",
|
|
||||||
"banner_status_connected": "Connected",
|
"banner_status_connected": "Connected",
|
||||||
"banner_status_disconnected": "Disconnected",
|
"banner_status_disconnected": "Disconnected",
|
||||||
"banner_message": "Posting to {{provider}} | {{transport}} | {{status}}",
|
|
||||||
"reconnected_export_service": "Reconnected to {{provider}} Export Service",
|
|
||||||
"rr_validation_message": "Repair Order created in Reynolds. Complete validation in Reynolds, then click Finished/Close to finalize.",
|
|
||||||
"rr_validation_notice_title": "Reynolds RO created",
|
|
||||||
"rr_validation_notice_description": "Complete validation in Reynolds, then click Finished/Close to finalize and mark this export complete.",
|
|
||||||
"color_json": "Color JSON",
|
|
||||||
"plain_json": "Plain JSON",
|
|
||||||
"collapse_all": "Collapse All",
|
|
||||||
"expand_all": "Expand All",
|
|
||||||
"log_level": "Log Level",
|
|
||||||
"clear_logs": "Clear Logs",
|
"clear_logs": "Clear Logs",
|
||||||
"reconnect": "Reconnect",
|
"collapse_all": "Collapse All",
|
||||||
"details": "Details",
|
"color_json": "Color JSON",
|
||||||
"hide_details": "Hide details",
|
|
||||||
"copy": "Copy",
|
|
||||||
"copied": "Copied",
|
"copied": "Copied",
|
||||||
|
"copy": "Copy",
|
||||||
"copy_request": "Copy Request",
|
"copy_request": "Copy Request",
|
||||||
"copy_response": "Copy Response",
|
"copy_response": "Copy Response",
|
||||||
|
"details": "Details",
|
||||||
|
"expand_all": "Expand All",
|
||||||
|
"hide_details": "Hide details",
|
||||||
|
"log_level": "Log Level",
|
||||||
|
"plain_json": "Plain JSON",
|
||||||
|
"provider_cdk": "CDK",
|
||||||
|
"provider_dms": "DMS",
|
||||||
|
"provider_fortellis": "Fortellis",
|
||||||
|
"provider_pbs": "PBS",
|
||||||
|
"provider_reynolds": "Reynolds",
|
||||||
|
"reconnect": "Reconnect",
|
||||||
|
"reconnected_export_service": "Reconnected to {{provider}} Export Service",
|
||||||
|
"refreshallocations": "Refresh to see DMS Allocations.",
|
||||||
"request_xml": "Request XML",
|
"request_xml": "Request XML",
|
||||||
"response_xml": "Response XML"
|
"response_xml": "Response XML",
|
||||||
|
"rr_validation_message": "Repair Order created in Reynolds. Complete validation in Reynolds, then click Finished/Close to finalize.",
|
||||||
|
"rr_validation_notice_description": "Complete validation in Reynolds, then click Finished/Close to finalize and mark this export complete.",
|
||||||
|
"rr_validation_notice_title": "Reynolds RO created",
|
||||||
|
"transport_ws": "(WS)",
|
||||||
|
"transport_wss": "(WSS)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"documents": {
|
"documents": {
|
||||||
|
|||||||
@@ -231,13 +231,16 @@
|
|||||||
"overall": ""
|
"overall": ""
|
||||||
},
|
},
|
||||||
"disclaimer_title": "",
|
"disclaimer_title": "",
|
||||||
|
"feedback_placeholder": "",
|
||||||
|
"feedback_prompt": "",
|
||||||
"generic_failure": "",
|
"generic_failure": "",
|
||||||
"multipage": "",
|
"multipage": "",
|
||||||
"processing": "",
|
"processing": "",
|
||||||
"scan": "",
|
"scan": "",
|
||||||
"scancomplete": "",
|
"scancomplete": "",
|
||||||
"scanfailed": "",
|
"scanfailed": "",
|
||||||
"scanstarted": ""
|
"scanstarted": "",
|
||||||
|
"submit_feedback": ""
|
||||||
},
|
},
|
||||||
"bill_lines": "",
|
"bill_lines": "",
|
||||||
"bill_total": "",
|
"bill_total": "",
|
||||||
@@ -1076,36 +1079,36 @@
|
|||||||
"earlyrorequired.message": ""
|
"earlyrorequired.message": ""
|
||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"refreshallocations": "",
|
"banner_message": "",
|
||||||
"provider_reynolds": "",
|
|
||||||
"provider_fortellis": "",
|
|
||||||
"provider_cdk": "",
|
|
||||||
"provider_pbs": "",
|
|
||||||
"provider_dms": "",
|
|
||||||
"transport_wss": "",
|
|
||||||
"transport_ws": "",
|
|
||||||
"banner_status_connected": "",
|
"banner_status_connected": "",
|
||||||
"banner_status_disconnected": "",
|
"banner_status_disconnected": "",
|
||||||
"banner_message": "",
|
|
||||||
"reconnected_export_service": "",
|
|
||||||
"rr_validation_message": "",
|
|
||||||
"rr_validation_notice_title": "",
|
|
||||||
"rr_validation_notice_description": "",
|
|
||||||
"color_json": "",
|
|
||||||
"plain_json": "",
|
|
||||||
"collapse_all": "",
|
|
||||||
"expand_all": "",
|
|
||||||
"log_level": "",
|
|
||||||
"clear_logs": "",
|
"clear_logs": "",
|
||||||
"reconnect": "",
|
"collapse_all": "",
|
||||||
"details": "",
|
"color_json": "",
|
||||||
"hide_details": "",
|
|
||||||
"copy": "",
|
|
||||||
"copied": "",
|
"copied": "",
|
||||||
|
"copy": "",
|
||||||
"copy_request": "",
|
"copy_request": "",
|
||||||
"copy_response": "",
|
"copy_response": "",
|
||||||
|
"details": "",
|
||||||
|
"expand_all": "",
|
||||||
|
"hide_details": "",
|
||||||
|
"log_level": "",
|
||||||
|
"plain_json": "",
|
||||||
|
"provider_cdk": "",
|
||||||
|
"provider_dms": "",
|
||||||
|
"provider_fortellis": "",
|
||||||
|
"provider_pbs": "",
|
||||||
|
"provider_reynolds": "",
|
||||||
|
"reconnect": "",
|
||||||
|
"reconnected_export_service": "",
|
||||||
|
"refreshallocations": "",
|
||||||
"request_xml": "",
|
"request_xml": "",
|
||||||
"response_xml": ""
|
"response_xml": "",
|
||||||
|
"rr_validation_message": "",
|
||||||
|
"rr_validation_notice_description": "",
|
||||||
|
"rr_validation_notice_title": "",
|
||||||
|
"transport_ws": "",
|
||||||
|
"transport_wss": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"documents": {
|
"documents": {
|
||||||
|
|||||||
@@ -231,13 +231,16 @@
|
|||||||
"overall": ""
|
"overall": ""
|
||||||
},
|
},
|
||||||
"disclaimer_title": "",
|
"disclaimer_title": "",
|
||||||
|
"feedback_placeholder": "",
|
||||||
|
"feedback_prompt": "",
|
||||||
"generic_failure": "",
|
"generic_failure": "",
|
||||||
"multipage": "",
|
"multipage": "",
|
||||||
"processing": "",
|
"processing": "",
|
||||||
"scan": "",
|
"scan": "",
|
||||||
"scancomplete": "",
|
"scancomplete": "",
|
||||||
"scanfailed": "",
|
"scanfailed": "",
|
||||||
"scanstarted": ""
|
"scanstarted": "",
|
||||||
|
"submit_feedback": ""
|
||||||
},
|
},
|
||||||
"bill_lines": "",
|
"bill_lines": "",
|
||||||
"bill_total": "",
|
"bill_total": "",
|
||||||
@@ -1076,36 +1079,36 @@
|
|||||||
"earlyrorequired.message": ""
|
"earlyrorequired.message": ""
|
||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"refreshallocations": "",
|
"banner_message": "",
|
||||||
"provider_reynolds": "",
|
|
||||||
"provider_fortellis": "",
|
|
||||||
"provider_cdk": "",
|
|
||||||
"provider_pbs": "",
|
|
||||||
"provider_dms": "",
|
|
||||||
"transport_wss": "",
|
|
||||||
"transport_ws": "",
|
|
||||||
"banner_status_connected": "",
|
"banner_status_connected": "",
|
||||||
"banner_status_disconnected": "",
|
"banner_status_disconnected": "",
|
||||||
"banner_message": "",
|
|
||||||
"reconnected_export_service": "",
|
|
||||||
"rr_validation_message": "",
|
|
||||||
"rr_validation_notice_title": "",
|
|
||||||
"rr_validation_notice_description": "",
|
|
||||||
"color_json": "",
|
|
||||||
"plain_json": "",
|
|
||||||
"collapse_all": "",
|
|
||||||
"expand_all": "",
|
|
||||||
"log_level": "",
|
|
||||||
"clear_logs": "",
|
"clear_logs": "",
|
||||||
"reconnect": "",
|
"collapse_all": "",
|
||||||
"details": "",
|
"color_json": "",
|
||||||
"hide_details": "",
|
|
||||||
"copy": "",
|
|
||||||
"copied": "",
|
"copied": "",
|
||||||
|
"copy": "",
|
||||||
"copy_request": "",
|
"copy_request": "",
|
||||||
"copy_response": "",
|
"copy_response": "",
|
||||||
|
"details": "",
|
||||||
|
"expand_all": "",
|
||||||
|
"hide_details": "",
|
||||||
|
"log_level": "",
|
||||||
|
"plain_json": "",
|
||||||
|
"provider_cdk": "",
|
||||||
|
"provider_dms": "",
|
||||||
|
"provider_fortellis": "",
|
||||||
|
"provider_pbs": "",
|
||||||
|
"provider_reynolds": "",
|
||||||
|
"reconnect": "",
|
||||||
|
"reconnected_export_service": "",
|
||||||
|
"refreshallocations": "",
|
||||||
"request_xml": "",
|
"request_xml": "",
|
||||||
"response_xml": ""
|
"response_xml": "",
|
||||||
|
"rr_validation_message": "",
|
||||||
|
"rr_validation_notice_description": "",
|
||||||
|
"rr_validation_notice_title": "",
|
||||||
|
"transport_ws": "",
|
||||||
|
"transport_wss": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"documents": {
|
"documents": {
|
||||||
|
|||||||
0
localstack/init/10-bootstrap.sh
Normal file → Executable file
0
localstack/init/10-bootstrap.sh
Normal file → Executable file
72
server/ai/bill-ai-feedback.js
Normal file
72
server/ai/bill-ai-feedback.js
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
const { isString } = require("lodash");
|
||||||
|
const { sendServerEmail } = require("../email/sendemail");
|
||||||
|
const logger = require("../utils/logger");
|
||||||
|
const { raw } = require("express");
|
||||||
|
|
||||||
|
const SUPPORT_EMAIL = "patrick@imexsystems.ca";
|
||||||
|
|
||||||
|
const safeJsonParse = (maybeJson) => {
|
||||||
|
if (!isString(maybeJson)) return null;
|
||||||
|
try {
|
||||||
|
return JSON.parse(maybeJson);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const handleBillAiFeedback = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const rating = req.body?.rating;
|
||||||
|
const comments = isString(req.body?.comments) ? req.body?.comments?.trim() : "";
|
||||||
|
|
||||||
|
const billFormValues = safeJsonParse(req.body?.billFormValues);
|
||||||
|
const rawAIData = safeJsonParse(req.body?.rawAIData);
|
||||||
|
|
||||||
|
const jobid = billFormValues?.jobid || billFormValues?.jobId || "unknown";
|
||||||
|
const subject = `Bill AI Feedback (${rating === "up" ? "+" : "-"}) jobid=${jobid}`;
|
||||||
|
|
||||||
|
const text = [
|
||||||
|
`User: ${req?.user?.email || "unknown"}`,
|
||||||
|
`Rating: ${rating}`,
|
||||||
|
comments ? `Comments: ${comments}` : "Comments: (none)",
|
||||||
|
"",
|
||||||
|
"Form Values (User):",
|
||||||
|
JSON.stringify(billFormValues, null, 4),
|
||||||
|
"",
|
||||||
|
"Raw AI Data:",
|
||||||
|
JSON.stringify(rawAIData, null, 4)
|
||||||
|
]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
const attachments = [];
|
||||||
|
if (req.file?.buffer) {
|
||||||
|
attachments.push({
|
||||||
|
filename: req.file.originalname || `bill-${jobid}.pdf`,
|
||||||
|
content: req.file.buffer,
|
||||||
|
contentType: req.file.mimetype || "application/pdf"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await sendServerEmail({
|
||||||
|
to: [SUPPORT_EMAIL],
|
||||||
|
subject,
|
||||||
|
type: "text",
|
||||||
|
text,
|
||||||
|
attachments
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.json({ success: true });
|
||||||
|
} catch (error) {
|
||||||
|
logger.log("bill-ai-feedback-error", "ERROR", req?.user?.email, null, {
|
||||||
|
message: error?.message,
|
||||||
|
stack: error?.stack
|
||||||
|
});
|
||||||
|
return res.status(500).json({ message: "Failed to submit feedback" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
handleBillAiFeedback
|
||||||
|
};
|
||||||
@@ -212,7 +212,8 @@ async function processSinglePageDocument(pdfBuffer) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...processedData,
|
...processedData,
|
||||||
originalTextractResponse: result
|
//Removed as this is a large object that provides minimal value to send to client.
|
||||||
|
// originalTextractResponse: result
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,7 +393,8 @@ async function handleTextractNotification(message) {
|
|||||||
status: 'COMPLETED',
|
status: 'COMPLETED',
|
||||||
data: {
|
data: {
|
||||||
...processedData,
|
...processedData,
|
||||||
originalTextractResponse: originalResponse
|
//Removed as this is a large object that provides minimal value to send to client.
|
||||||
|
// originalTextractResponse: originalResponse
|
||||||
},
|
},
|
||||||
completedAt: new Date().toISOString()
|
completedAt: new Date().toISOString()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const logEmail = async (req, email) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const sendServerEmail = async ({ subject, text, to = [] }) => {
|
const sendServerEmail = async ({ subject, text, to = [], attachments }) => {
|
||||||
if (process.env.NODE_ENV === undefined) return;
|
if (process.env.NODE_ENV === undefined) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -57,6 +57,7 @@ const sendServerEmail = async ({ subject, text, to = [] }) => {
|
|||||||
to: ["support@imexsystems.ca", ...to],
|
to: ["support@imexsystems.ca", ...to],
|
||||||
subject: subject,
|
subject: subject,
|
||||||
text: text,
|
text: text,
|
||||||
|
attachments: attachments,
|
||||||
ses: {
|
ses: {
|
||||||
// optional extra arguments for SendRawEmail
|
// optional extra arguments for SendRawEmail
|
||||||
Tags: [
|
Tags: [
|
||||||
|
|||||||
@@ -4,9 +4,14 @@ const multer = require("multer");
|
|||||||
const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware");
|
const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware");
|
||||||
const withUserGraphQLClientMiddleware = require("../middleware/withUserGraphQLClientMiddleware");
|
const withUserGraphQLClientMiddleware = require("../middleware/withUserGraphQLClientMiddleware");
|
||||||
const { handleBillOcr, handleBillOcrStatus } = require("../ai/bill-ocr/bill-ocr");
|
const { handleBillOcr, handleBillOcrStatus } = require("../ai/bill-ocr/bill-ocr");
|
||||||
|
const { handleBillAiFeedback } = require("../ai/bill-ai-feedback");
|
||||||
|
|
||||||
// Configure multer for form data parsing
|
// Configure multer for form data parsing (memory storage)
|
||||||
const upload = multer();
|
const upload = multer({
|
||||||
|
limits: {
|
||||||
|
fileSize: 5 * 1024 * 1024 // 5MB
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
router.use(validateFirebaseIdTokenMiddleware);
|
router.use(validateFirebaseIdTokenMiddleware);
|
||||||
router.use(withUserGraphQLClientMiddleware);
|
router.use(withUserGraphQLClientMiddleware);
|
||||||
@@ -14,4 +19,6 @@ router.use(withUserGraphQLClientMiddleware);
|
|||||||
router.post("/bill-ocr", upload.single('billScan'), handleBillOcr);
|
router.post("/bill-ocr", upload.single('billScan'), handleBillOcr);
|
||||||
router.get("/bill-ocr/status/:textractJobId", handleBillOcrStatus);
|
router.get("/bill-ocr/status/:textractJobId", handleBillOcrStatus);
|
||||||
|
|
||||||
|
router.post("/bill-feedback", upload.single("billPdf"), handleBillAiFeedback);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
Reference in New Issue
Block a user