Business Central - POST sales invoice line using REST API - setting multiple dimension values - dynamics-business-central

We use Business Central cloud API to POST sales invoices from other system
After creating the the sales invoice we create sales invoice lines to it
by using
{BC Endpoint}/SalesInvoiceLine API call
but we are able to enter only two shortcut dimensions
eg.
"Shortcut_Dimension_1_Code": "{value_fordim1}",
"Shortcut_Dimension_2_Code": "{value_fordim2}
HOWEVER we need to set 4 dimensions for sales invoice line
We have tried to search MS API documentation for this situation but no luck
So far we haven't found a way to set all 4 dimension values to sales invoice line directly.
Current assumption is that we should somehow add new dimension set entry to BC
(or search suitable combination from Dimension Set Entry table)
and then somehow tie the sales invoice line to that Dimension Set Entry ID. However we do not know what API calls we could use for this.
Any guidance or help appriciated

In API v2.0 both entities salesInvoice and salesInvoiceLine contain a child object dimensionSetLines. If you run a request on the $metadata endpoint, you can find the definition in the API metadata.
<EntityType Name="dimensionSetLine">
<Key>
<PropertyRef Name="id"/>
</Key>
<Property Name="id" Type="Edm.Guid" Nullable="false"/>
<Property Name="code" Type="Edm.String" Nullable="false" MaxLength="20"/>
<Property Name="parentId" Type="Edm.Guid"/>
<Property Name="parentType" Type="Microsoft.NAV.dimensionSetEntryBufferParentType"/>
<Property Name="displayName" Type="Edm.String" MaxLength="30"/>
<Property Name="valueId" Type="Edm.Guid"/>
<Property Name="valueCode" Type="Edm.String"/>
<Property Name="valueDisplayName" Type="Edm.String" MaxLength="50"/>
To view all dimensions on an invoice, send a GET request on
https://<Tenant URL>/api/v2.0/salesInvoices(<Invoice ID (GUID)>)?$expand=dimensionSetLines
To create an invoice with multiple dimension, include the dimensionSetLines object in the salesInvoice entity when sending the POST request.
{
"invoiceDate": "2024-01-22",
"postingDate": "2024-01-22",
"customerNumber": "10000",
"dimensionSetLines": [
{
"code": "SALESCAMPAIGN",
"valueCode": "SUMMER"
},
{
"code": "PROJECT",
"valueCode": "VW"
},
{
"code": "BUSINESSGROUP",
"valueCode": "INTERCOMPANY"
}
]
}

We were able to solve this by using:
POST {BC-endpoint}/SalesInvoiceLine call
and just by entering the additional shortcut dimensions to the body
{
.......
"ShortcutDimCode4": "{value_for_dim4}",
"ShortcutDimCode5": "{value_for_dim5}"
}

Related

The table with name already exist

I'm trying to solve this issue
when doing
php bin/console doctrine:schema:update --dump-sql
I am getting
In SchemaException.php line 108:
The table with name 'chris_test_sonata.page__block' already exists.
Obviously, the table isn't existing in my database. To be sure it was not something cache related I even made the operation with a new database I just created, the result is the same.
When I search for page__block occurences in my project I only find this mapping
/**
* #ORM\Entity
* #ORM\Table(name="page__block")
* #ORM\HasLifecycleCallbacks
*/
class SonataPageBlock extends BaseBlock
So there should not be other mapping for this table.
I also have a block.orm.xml
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xsi="http://www.w3.org/2001/XMLSchema-instance" schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<!--
This file has been generated by the EasyExtends bundle ( https://sonata-project.org/easy-extends )
References :
xsd : https://github.com/doctrine/doctrine2/blob/master/doctrine-mapping.xsd
xml mapping : http://www.doctrine-project.org/projects/orm/2.0/docs/reference/xml-mapping/en
association mapping : http://www.doctrine-project.org/projects/orm/2.0/docs/reference/association-mapping/en
-->
<entity
name="App\Application\Sonata\PageBundle\Entity\Block"
table="page__block"
repository-class="Doctrine\ORM\EntityRepository">
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
</entity>
</doctrine-mapping>
There is some other occurences but all in dev.log
And I also have this in a cache file from symfony dev/pools
<?php
namespace Symfony\Component\VarExporter\Internal;
return $getExpiry ? PHP_INT_MAX : Hydrator::hydrate(
$o = [
clone (($p = &Registry::$prototypes)['Doctrine\\ORM\\Mapping\\Entity'] ?? Registry::p('Doctrine\\ORM\\Mapping\\Entity')),
clone ($p['Doctrine\\ORM\\Mapping\\Table'] ?? Registry::p('Doctrine\\ORM\\Mapping\\Table')),
clone ($p['Doctrine\\ORM\\Mapping\\HasLifecycleCallbacks'] ?? Registry::p('Doctrine\\ORM\\Mapping\\HasLifecycleCallbacks')),
],
null,
[
'stdClass' => [
'name' => [
1 => 'page__block',
],
],
],
[
$o[0],
$o[1],
$o[2],
],
[]
);
I have no idea what is wrong with it and why the mapping is'nt working.
The problem is that you have Block entity with table page__block and you created a new entity SonataPageBlock with same table name. If you change table name of SonataPageBlock everything be fine, but it will be 2 different tables in database.
If you are looking way for extending base entity you can read about Table Inheritance.
For anyone who finds this on a search, receiving this error means that the table name already exists within an annotation.
#ORM\Table(name="page__block")
I had this problem with ManyToMany relationship. I was declaring the associative table twice ( one time in each entity )
In my case with Sylius there was an entity class that extends an entity from a plugin.
I did fix it by adding a class model in config/packages/_sylius.yaml :
sylius_taxonomy:
resources:
taxon:
classes:
model: App\Entity\Taxonomy\Taxon

Rules for a group in openerp 7

I have inherited project task module and created a group 'Inspector'.
I need to create a rule, when a inspector logged in, see tasks that assigned to him only. I created a rule is given below:
<record model="ir.rule" id="project_inspector_project_tasks_rule">
<field name="name">Inspector Project Tasks</field>
<field model="ir.model" name="model_id" ref="model_project_task"/>
<field name="domain_force">[('user_id','=','user.id')]</field>
</record>
but it doesn't work. Please help me.
In domain has following syntax:
[('field_name', 'operator', 'field_value')]
In your case, field_value will be integer. You given value as a string.
Try with this code:
<record model="ir.rule" id="project_inspector_project_tasks_rule">
<field name="name">Inspector Project Tasks</field>
<field name="model_id" ref="project.model_project_task"/>
<field name="domain_force">[('user_id', '=', user.id)]</field>
</record>

Alfresco search page, sorting by custom property not indexed error

I got an error within Alfresco search page, when I try to sort by my custom property:
environment:
Alfresco 5.0.1
Postgres
Solr4
tomcat 7
Error:
2015-05-12 12:54:34,864 ERROR [solr.core.SolrCore] [http-bio-8443-exec-7] org.apache.solr.common.SolrException: sort param could not be parsed as a query, and is not a field that exists in the index: #{http://global.oup.com/dam/model/1.0}supplierName
at org.apache.solr.search.QueryParsing.parseSortSpec(QueryParsing.java:358)
at org.alfresco.solr.query.AbstractQParser.getSort(AbstractQParser.java:569)
at org.apache.solr.handler.component.QueryComponent.prepare(QueryComponent.java:175)
at org.apache.solr.handler.component.AlfrescoSearchHandler.handleRequestBody(AlfrescoSearchHandler.java:233)
at org.apache.solr.handler.RequestHandlerBase.handleRequest(RequestHandlerBase.java:135)
at org.apache.solr.core.SolrCore.execute(SolrCore.java:1962)
at org.apache.solr.servlet.SolrDispatchFilter.execute(SolrDispatchFilter.java:777)
at org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:418)
at org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:207)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:613)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1074)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:744)
Caused by: org.apache.solr.search.SyntaxError: Expected identifier at pos 0 str='#{http://global.oup.com/dam/model/1.0}supplierName desc'
at org.apache.solr.search.QueryParsing$StrParser.getId(QueryParsing.java:770)
at org.apache.solr.search.QueryParsing$StrParser.getId(QueryParsing.java:749)
at org.apache.solr.search.FunctionQParser.parseValueSource(FunctionQParser.java:345)
at org.apache.solr.search.FunctionQParser.parse(FunctionQParser.java:68)
at org.apache.solr.search.QParser.getQuery(QParser.java:141)
at org.apache.solr.search.QueryParsing.parseSortSpec(QueryParsing.java:286)
... 25 more
My custom field is configured as following into the content model file:
<types>
<type name="oup:asset">
<title>Asset</title>
<parent>ipp:asset</parent>
<property name='oup:supplierName'>
<title>Supplier Name</title>
<description>Name of the supplier (note there is also a supplier
specified on asset rights)
</description>
<type>d:mltext</type>
<mandatory enforced='false'>true</mandatory>
<multiple>true</multiple>
<index enabled="true">
<atomic>true</atomic>
<stored>false</stored>
<tokenised>both</tokenised>
</index>
</property>
</type>
</types>
As far as I know, the index configuration should be fine, I tried also putting atomic to false with no luck.
The above configuration was working fine using Alfresco 4.1.1 and Solr 1, but now, the porting to Alfresco 5 and Solr 4 does not work.
I tried the js code from the javascript console in the Alfresco Admin page using the search service and the sorting works fine for cm:name but not for oup:supplierName, following the code:
var orderedNodes = search.luceneSearch("#cm\\:name:\"my-file\"", "#oup:supplierName", false);
logger.log("retrieved " + orderedNodes.length + " nodes\n");
Any Idea ?
I found the problem, it's a Solr4 bug/behavior, when it tries to perform the sorting of multiple properties like the Alfresco multivalued properties -
I found this piece of code in the Solr web app:
private void addSortSearchFields( PropertyDefinition propertyDefinition , IndexedField indexedField)
{
// Can only order on single valued fields
DataTypeDefinition dataTypeDefinition = propertyDefinition.getDataType();
if(dataTypeDefinition.getName().equals(DataTypeDefinition.TEXT))
{
if(propertyDefinition.isMultiValued() == false)
{
if ((propertyDefinition.getIndexTokenisationMode() == IndexTokenisationMode.FALSE)
|| (propertyDefinition.getIndexTokenisationMode() == IndexTokenisationMode.BOTH))
{
indexedField.addField(getFieldForText(false, false, true, propertyDefinition), false, true);
}
else if (isIdentifierTextProperty(propertyDefinition.getName()))
{
indexedField.addField(getFieldForText(false, false, false, propertyDefinition), false, false);
}
else
{
indexedField.addField(getFieldForText(false, true, false, propertyDefinition), false, false);
}
}
}
if(dataTypeDefinition.getName().equals(DataTypeDefinition.MLTEXT))
{
if(propertyDefinition.isMultiValued() == false)
{
if ((propertyDefinition.getIndexTokenisationMode() == IndexTokenisationMode.FALSE)
|| (propertyDefinition.getIndexTokenisationMode() == IndexTokenisationMode.BOTH))
{
indexedField.addField(getFieldForText(false, false, true, propertyDefinition), false, true);
}
else
{
indexedField.addField(getFieldForText(false, true, false, propertyDefinition), false, false);
}
}
}
}
So, it does the sorting only if propertyDefinition.isMultiValued() == false and then it throws the exception later in the code because it is not able to map the QName.
Is that right?
Is there a way to skip it without coding?
If not, I think the only way to fix it is to override the Spring bean in some way to use our custom function, any suggestion to do so without doing the deploy of Solr too?
Or possibly a Spring AOP, but to be honest I don't like this idea.
Any possible solution?
I found a work-around:
create a new property in the content model, just text. This one is a string representation of the multivalued field, indexed as well;
create a behavior with the two policies: onUpdatePolicy and onCreatePolicy that makes the string representation of the multivalued field;
create a patch (Spring bean) that set up the value for the new field for all the old content;
The field is hidden for all the UI and is not possible to be set up by a user.
It is indexed to get the faceted search working in alfresco 5 and sorting as well.
The described solution is the best I found, hope it helps. Any suggestion is welcome.
Change d:mltext to d:text only.If you don't require multilingual support.Some time d:mltext creates problem.
May be below will help you.
Atomic="true"
If this is true, the property is indexed in the transaction if not the property is indexed in the background.
Indexing of content that requires transformation before being indexed (e.g. PDFs) will only obey Atomic=true if the transformation takes less time than the value specified for lucene.maxAtomicTransformationTime.
lucene.maxAtomicTransformationTime=20
Transformations of content that are likely to take longer than this time (in millis) will be done in the background. To force atomic content indexing, increase this value.
You must know that
SOLR does not perform in-transaction indexing.

Struts2 : use of roles

I'm working on a small Java EE application using Struts 2, which i have 2 different users with different roles (Admin & Member).
//Member
class Member extends User {
//...
}
//Admin
class Admin extends User {
//...
}
I have to distinguish between "member" and "admin" roles in order to stop member from using some Actions, or show some extract options to admin. so I found that i should use RolesInterceptor.
So i added it to my Action in my struts.xml.
<action name="dashboard" class="com.examples.DashboardAction">
<interceptor-ref name="completeStack"/>
<interceptor-ref name="roles">
<param name="allowedRoles">admin</param>
<param name="disallowedRoles">member</param>
</interceptor-ref>
<result name="success">dashboard.jsp</result>
</action>
My question is how to declare to struts that Admin and Member classes have the following roles "admin" & "member".
Edit: i found some articles recommend the use of PrincipalProxy and PrincipalAware interfaces that allows indirect access to HttpServletRequest, but i don't know how to combine all this.
Thank you.

http code for partual success / error

I have a service that takes a list of items to handle.
Each of the items is handeled one at the time in the backend, when all items is done the service returns a document containing the original list of items but with a success or failure status on each line.
example:
PUT - body:
[
{"item" : 1},
{"item" : 2},
{"item" : 3}
]
reponse - body:
[
{"item" : 1, "state" : "OK"},
{"item" : 2, "state" : "OK"},
{"item" : 3, "state" : "FAILED"}
]
The question is now:
which return code should I use if one of the items has failed?
I cannot seem to find any correct matching http status code for this, it is a failure, but then again its not, but allmost;) ?
From the HTTP point of view, it's a success - I'd return 200 - the request was successfully received and processed.
It's then up to the app to check if it's all OK.
However, to make life easier I might add an error field into the response?
A better idea would be to use a 207 multi-status response, but to send the data in a POST.
This happens a lot with things that upload/update a lot of items. In the multistatus response, you can correspond each action and a specific response, like so:
<response>
<item id="1">
<status>200 OK</status>
</item>
<item id="2">
<status>403 Forbidden</status>
</item>
</response>

Resources