Breaking
No breaking changes.
Compliance
🇧🇭 Bahrain - 🇯🇴 Jordan - 🇴🇲 Oman - 🇦🇪 UAE
🆕 Arabic Translation Updates
We've introduced several updates to the Arabic translations on the CertifiedInvoice thermal and PDF templates. Additionally, we've added a VAT rate breakdown table in the PDF template (United Arab Emirates already included the VAT breakdown table in the certified invoice PDF template).
🇪🇸 Spain
🆕 Local Mode Support in Spain
Local Mode is now supported in Spain, enabling offline functionality. For configuration details, see Enabling Local Mode.
🇵🇱 Poland
✅ Generating JPK Files
We've improved the performance of generating JPK files in EVA for Poland, which should expedite the process and decrease the likelihood of errors.
All countries without an auditing provider or Default
EVA will no longer enforce certain checkout options for countries that do not necessarily require them.
These are countries which don't have an auditing provider set or have it set to Default.
The checkout options in question are the following:
- FiscalID
- FiscalRemark
- Tax registration number (VAT number)
Of course these checkout options can still be set voluntarily.
🇸🇪 Sweden
We are changing the current Document output logic for Sweden specifically, to make it more consistent with the logic we have across all countries.
Receipts and Simplified invoices
- The Document output number will be: OU ID - Document Type Code - Sequential number
- For receipts & simplified invoices this will be: 148-01-1
- For credit receipts & credit simplified invoices this will be: 148-03-1
- The simplified invoice treshold is: 4000SEK
Furthermore:
Only the sequential number is shared with Infrasec, because Infrasec can only handle numeric receipt numbers.
With the new format, the current sequence remains intact (in other words: we will not start over).
For example: if we now have receipt number 56, the next one will be 148-01-57.
The identifier for the invoice chain within the code is based on the OU, so an OU ID and Company ID won’t cause collisions.
Invoices
- The Document output number will be: OU ID - Document Type Code - Sequential number
- For Invoices this will be: 148-02-1
- For credit invoices this will be: 148-04-1
Properties
🆕 Manage Discount Layers More Effectively
You can now manage discount layers more effectively by optionally forcing the deletion of layers with active discounts.
Details
When deleting a layer with an active discount, EVA will return an error, since you can't delete layers with active discounts by default.
You can however override this by setting the new property ArchiveDiscounts to true in the request to the DeleteDiscountLayer
service.
✅ MaxAmountPerOrder
We are making a few changes to the MaxAmountPerOrder property, as introduced in Core 2.0.750.
Details
The MaxAmountPerOrder is now also available in the AvailablePaymentMethods
service. This change makes the property context-aware, practically meaning that EVA remembers what was already paid on that payment method, ensuring the max amount of a cash handler is upheld even when a payment gets split.
Furthermore, we've changed the create
and update
services for the MaxAmountPerOrder of a cash handler to not accept unrounded values, preventing possible edge cases where a rounded payment would trigger the max amount's limit
🆕 DiscountTriggers
Building further on the new service GetActiveDiscounts
introduced in Core 2.0757, which allow for displaying active discounts in a store, we are now also adding the property DiscountTriggers to the GetActiveDiscounts
service.
This change will allow for more trigger types, such as coupons, instead of only returning automatic discounts.
✅ Double Opt-In for Marketing Subscriptions
This update introduces a double opt-in feature for marketing subscriptions, allowing users to confirm their subscription via email or webhook for improved compliance.
Details
- New Property: A new enum property, SubscriptionConfirmation, has been added with the following options:
- none
- webhook
- Service Updates: Users can set the SubscriptionConfirmation property via the following services:
CreateSubscriptionOrganisationUnitSet
GetSubscriptionOrganisationUnitSet
UpdateSubscriptionOrganisationUnitSet
- Deprecated Property: The ConfirmationRequired property is now deprecated and replaced by the email option in SubscriptionConfirmation.
- Webhook Option: A new webhook event, subscription_confirmation, is available for the webhook option. It includes a confirmation token and user ID.
- Email Option: The existing email confirmation process remains unchanged.
- Event Notification: Users will receive an event export notification when a subscription confirmation is sent out, categorized under “Target”: Customer and “EventType”: subscription_changed.
- Subscription Confirmation: Users can confirm a subscription using a token retrieved from the NewsLetterSubscription stencil with the
ConfirmSubscription
function.
✅ PreSaleData
The PreSaleDate property, announced in Core 2.0.760, is now taken into account by the following services:
AddProductToOrder
PushSalesOrder
AddBundleProductToOrder
AddDigitalGiftCardToOrder
Practically this means when a product with a PreSaleDate set to a future date is added to an order, EVA will respond with the following clear error: OrderLineCreator:OrderBeforePreSaleDate
.
Services
🆕 GetFieldValidatorsForEntity
A new service has been introduced that allows users to retrieve validation rules for specific fields in the Price List and Price List Adjustment entities. This enhancement helps ensure data integrity by applying appropriate validation based on user context.
Details
The service, named GetFieldValidatorsForEntity
, accepts an EntityType and returns all configured validators for that entity. It considers the context of the logged-in user to determine applicable validations.
Supported entity types include PriceList and PriceListAdjustment.
Key Features:
- Retrieves multiple validation rules for fields such as BackendID and BackendSystemID.
- Validations include requirements like whether a field is mandatory, specific length constraints, and regex patterns.
Example Usage:
{ "EntityType": 1 } // PriceList
{
"Validators": [
{
"EntityFieldName": "BackendID",
"ValidatorType": 0,
"ValidatorData": { "Required": true }
},
{
"EntityFieldName": "BackendSystemID",
"ValidatorType": 1,
"ValidatorData": { "MaxLength": 15 }
}
]
}
✅ Update to PushCase: Attach Customers by Backend ID
You can now link cases to existing customers using their Backend ID, reducing duplicate entries and ensuring better data synchronization.
Details
The PushCase
API has been updated to allow cases to be associated with existing customers based on their BackendID. If a customer with the specified BackendID exists, the case will be attached to that customer instead of creating a new one. This update helps prevent duplicate customer entries in the system.
- If a customer does not exist with the given BackendID, a new customer will be created when you use
PushCase
. - If a customer does exist, they will be attached to the case without updating their existing information.
- This change applies to both Basic and Standard account types.
{
"Description": "Template request for PushCase.",
"Title": "PushCase Template 002",
"CaseTopic": {
"Name": "Fix Lining",
"BackendID": "PUSHCASETOPIC-001"
},
"Status": "New",
"BackendID": "PUSH-003520932",
"Customer": {
"BackendID": "LE-ACCOUNTTYPE1",
"EmailAddress": "[email protected]",
"Gender": "M",
"Initials": "P",
"FirstName": "Pedro",
"LastName": "Pascal",
"ShippingAddress": {
"Address1": "Lelylaan",
"HouseNumber": "1",
"FirstName": "Pedro",
"LastName": "Pascal",
"ZipCode": "1423DE",
"City": "Almere",
"State": "FL",
"CountryID": "NL"
}
},
"Priority": 2,
"OriginatingOrganizationUnitID": 60
}
✅ Update to PushUser
and PushUser_Async
Requests
This update ensures that when sending PushUser
or PushUser_Async
requests without a Date of Birth (DoB), the existing DoB value on the user profile is not unintentionally removed.
Details
Previously, if a PushUser
or PushUser_Async
request was sent without the DateOfBirth field, it would nullify the existing DoB on the user's profile. With this update, the system now uses a Maybe<>
implementation, allowing you to selectively update user fields. To intentionally clear a field, you must explicitly set its value to null.
Example Usage:
{
"Users": [
{
"BackendID": "325423523",
"Nickname": "LE_PushUser_00051",
"FiscalID": 52573323,
"CompanyID": "C-309521",
"SocialSecurityNumber": "6263099032",
"PhoneNumber": "0629522214",
"Title": "Mr.",
"Salutation": "Sally",
"EmailAddress": "[email protected]",
"Password": "Testing1234",
"Initials": "LE",
"FirstName": "Lars Test",
"LastName": "PushUser",
"Gender": "M"
},
{
"BackendID": "32542352325",
"DateOfBirth": null
}
]
}
In this example, the second user object explicitly sets DateOfBirth to null, which will clear the DoB field in the user's profile. If the DateOfBirth field is omitted, the existing DoB will remain unchanged.
🆕 GetUserLoyaltySubscriptions
The ResubscribeHandling property, added in Core drop 2.0.759 is now also included in GetUserLoyaltySubscriptions
.
Sample response
{
"Status": 2,
"IsBlocked": false,
"UserIdentifier": "PRE-103-SUFFIX",
"IsUnsubscribeAllowed": false,
"CreationTime": "2024-09-26T11:26:00.673Z",
"CreatedBy": {
"ID": 262,
"FirstName": "Pedro",
"LastName": "Pascal",
"FullName": "Pedro Pascal"
},
"LastModifiedBy": {
"ID": 0,
"FullName": ""
},
"Subscription": {
"ID": 201,
"LoyaltyProgramGroupID": 21,
"LoyaltyProgramGroupName": "Tiers",
"LoyaltyProgramID": 99,
"LoyaltyProgramName": "Tier3",
"LoyaltyProgramOptions": 6,
"LoyaltyProgramPointUsageOptions": 5,
"LoyaltyBalance": {
"Points": 0,
"PointRegistrations": [],
"CurrencyID": "EUR",
"CurrencyValue": 0
},
"BackendID": "LOYALTY-6039285023",
"Name": "Tier 3",
"Description": "Spend and earn loyalty points.",
"ConfirmationRequired": false,
"Default": false,
"Hidden": false,
"OriginatingOrganizationUnitID": 53,
"Preferred": false,
"UserIdentifierRequiredForSubscription": false,
"HasCustomFieldIdentifier": false,
"Priority": 0,
"IsExternal": false,
"ResubscribeHandling": 0, <----------------- HERE
"AllowUnsubscribeBy": 1
}
}
🆕 DeleteSerialNumberConfiguration
We added a new service to EVA to delete SerialNumberConfigurations: DeleteSerialNumberConfiguration
It can delete a serial number configuration only if it's not attached to any serial number products.
✅ PushSerialNumbers
We improved the efficiency of our PushSerialNumbers
service, greatly improving its speed and reducing its impact on EVA.
Details
This service, introduced in Core 2.0.753 and used to push multiple serial numbers into EVA, requires the following properties:
- The ProductID is always required
- Either both, or neither of StockLabelID and OrganizationUnitID
We recommend to keep the JSON request size limit to 10 MB, which will result in somewhere between 100.000 and 200.000 serials per call when using solely a SerialNumber and a ProductID.
Important to note
- When a product belongs to a Serial Number Configuration that is configured with a validation regex, serial numbers pushed for that product must match this regex.
- The service skips over errors and attempts to persist as many serial numbers as possible.
- Gathers any error encountered and returns (up to 1.000 of) them, allowing you to fix & retry.
Ignored serial numbers
- Ignores serial numbers that already exist in EVA.
- Ignores duplicates within the same call (but it's undefined which serial number is used).
- Ignores duplicates within multiple simultaneous calls (but it's undefined which serial number is used).
SpecialOpeningHours
We are introducing two new services, both relating to your stores' SpecialOpeningHours.
UploadSpecialOpeningHoursExcel
DownloadSpecialOpeningHoursExcelTemplate
Details
These services facilitate uploading special opening hours in bulk. You can then assign the templates to your OU (sets).
The DownloadSpecialOpeningHoursExcelTemplate
service gives you a template which you can fill in with your new hours, while UploadSpecialOpeningHoursExcel
is used to upload the same Excel file. You can use this functionality to overwrite existing values for special opening hours.
Note that EVA supports two opening hours per open day in general.
For a sample of how this works, please see the below table, which would match one of your Excel files. After uploading, it will result in the following overview in Admin Suite.
Description | Status | Date | From | To | From2 | To2 |
---|---|---|---|---|---|---|
Christmas 1 | Closed | 25/12/2024 | ||||
Christmas 2 | Open | 27/12/2024 | 09:00 | 12:00 | ||
Christmas 3 | Open | 28/12/2024 | 09:00 | 12:00 | 14:00 | 17:30 |
Christmas 4 | Closed | 29/12/2024 | ||||
Christmas 5 | Closed | 30/12/2024 |
Other topics
🆕 EVA-IDs-Mode header: Hybrid
The header EVA-IDs-Mode now accepts an additional value: Hybrid.
By inserting this value, you can mix and match both BackendIDs and EVA IDs, the latter of which requires a prefix.
Details
Example
- A
GetOrder
call can be used with: { "ID": "my-pretty-backend-identifier" } to use a BackendID to match the order - Or { "ID": "eva:123" } to request an order that is matched on the ID with the value 123
Take note that when using this header, the response will also return the ID property as a string, as if the user used the String-IDs as the header value.
✅ Order orchestration for Elevated products
The following change is introduced as part of a bigger development - this feature is not ready for use
The Order orchestration engine now includes support for Elevated products.
Details
With the new functionality, users can ensure that order orchestration calculates the most optimal fulfillment when an elevated product is included in the order.
• Recognition of Elevated Products: The system now identifies elevated products that require specific fulfillment handling.
• Assortment and Allocation Rules: Only products that match the **SoldFromOrganizationUnit** and have an existing supplier relationship can be used. Products must also have proper allocation (practically meaning > 1).
• Product Preference: Priority is given to products with a 'use up' status, selecting those with the closest end date or earliest start date.
• SKU Validation: The App now supports scanning all related SKUs for an order line, with manual additions possible to the **StockProductIds**.
• Task Completion: Upon task completion, shipped **ProductIDs** are updated in the **StockProductIds** array on the order line.
🆕 Digital receipts for anonymous orders
EVA now supports the transmission of digital receipts for orders without a customer attached.
Details
This can be achieved by using the HTTP stencil destination.
All available properties in the template will be sent towards the endpoint, whcih includes the new property: MailTo.
This new property is to be used by a 3rd party for sending the email towards the email address attached to the anonymous order.
Additionally, the template will include a new object: ‘body’: ‘attachments’. This will ensure any attachments are rendered and supplied as a blob to the configured HTTP endpoint.
{
"TemplateName": "ElectronicReceipt",
"OrganizationUnit": "Almere_store",
"Customer": "Jenny Mera", //null for anonymous orders
"InvoiceNumber": "1547",
"AssetsUrl": "https://assets.fg4r.on-eva.io",
"LanguageID": "en",
"CountryID": "NL",
"TimeZone": "Etc/UTC",
"IsTestEnvironment": true,
"IsSentinel": false,
"RunningOnWatchtower": false,
"CurrentOrganizationUnit":
{
"Name": "Almere_store",
"Description": null,
"BackendID": "almerestore",
"EmailAddress": "[email protected]",
"PhoneNumber": "+31 6 12234402",
"HouseNumber": "35",
"Address1": "Fien de la mar straat",
"Address2": null,
"ZipCodeAndCity": "2331HM Almere",
"State": null,
"ZipCode": "2331HM",
"City": "Almere",
"BankAccount": null,
"VatNumber": null,
"RegistrationNumber": null,
"BranchNumber": null,
"Website": null,
"BIC": null,
"OpeningHours":
[],
"CocNumber": null,
"StreetAndHouseNumber": "Fien de la mar straat 35"
}
}
{
"context":
{
"id": "2l0xUtt8SMyf37noLLZE9cKDT",
"ts": "2024-08-22T12:46:53.941Z",
"pipeline_id": null,
"workflow_id": "p_13C56Y",
"deployment_id": "d_5ZskN8R",
"source_type": "TRACE",
"verified": false,
"hops": null,
"test": true,
"replay": false,
"owner_id": "o_API",
"platform_version": "3.50.2",
"workflow_name": "ElectronicReceipt",
"resume": null,
"emitter_id": "hi_a1Om",
"trace_id": "2l0xUtt8SMyfoMkLLZE9cKDT"
},
"event":
{
"body":
{
"BccTo": null,
"CcTo": null,
"Content":
{
"Customer": null,
"InvoiceNumber": "1545",
"OrganizationUnit": "Almere_Store",
"TemplateName": "ElectronicReceipt"
},
"Context":
{
"ApplicationID": 1,
"CountryID": "NL",
"CountrySubdivisionID": null,
"CreationTime": "2024-08-22T12:44:49.844277Z",
"CurrencyID": "EUR",
"LanguageID": "en",
"MessageQueueErrorID": null,
"OrganizationUnitID": 123,
"RetryCount": null,
"TimeZone": "Etc/UTC",
"UserID": 1041,
"UserType": 4097
},
"MailTo": null,
"OrganizationUnitID": 123,
"Subject": null
},
"client_ip": "51.105.219.80",
"headers":
{
"accept-encoding": "gzip, deflate",
"content-length": "480",
"content-type": "application/json; charset=utf-8",
"host": "eso6.m.pipedream.net"
},
"method": "POST",
"path": "/",
"query":
{},
"url": "https://eso6.m.pipedream.net/"
}
}
✅ Support for fully rounded payments
EVA now includes support for paying OpenAmounts that would be fully rounded by doing a Cash payment. These transactions will now result in a single PaymentTransaction of type Rounding.
Furthermore, the AmountGiven can now be set to 0, for situations where the consumer would be "paying" 0,02ct. In case of a larger OpenAmount, a request with amount given 0, will result in no transactions being created.
Fixes
- Fixed an issue where products outside of the assortment could not be called succesfully when
Discounts:PickProductAction:FilterOptionsOnAssortment
was set to false (not the default). - Fixed an edge-case where DiscountIsApplied would be returned as true while it shouldn't.
- Made a fix to
SearchProductPropertyTypes
which was missing paging placeholders, causing it to ignore paging. - We updated the
UploadPriceListManualInputAdjustment
service to give more descriptive errors instead of "Internal Server Error".this will give more guidance when it comes to date validation and product ID limits
- Fixed a mapping issue with the Exempt tax code for Fiskaly in Austria.
Deprecations
🆕 Introduced
These deprecations are now announced for the first time. Usage of these services and/or fields will return the appropriate EVA-Warnings
header.
Deprecated
High
- High ConfirmationRequired is deprecated and will be removed in 2.0.793: This property has been replaced by SubscriptionConfirmation.
- UpdateSubscriptionOrganizationUnitSet.ConfirmationRequired
- High ConfirmationRequired is deprecated and will be removed in 2.0.793: This property has been replaced by SubscriptionConfirmation. Setting this property to true is equivalent to setting SubscriptionConfirmation to Email..
- CreateSubscriptionOrganizationUnitSet.ConfirmationRequired
- High EVA.CRM.Core.Services.OrderInterventionTasks.CompleteOrderInterventionTask is deprecated and will be removed in 2.0.793: No longer supported..
- CompleteOrderInterventionTask
- High EVA.CRM.Core.Services.OrderInterventionTasks.ListOrderInterventionTasks is deprecated and will be removed in 2.0.793: No longer supported..
- ListOrderInterventionTasks
- High EVA.CRM.Core.Services.OrderInterventionTasks.StartOrderInterventionTask is deprecated and will be removed in 2.0.793: No longer supported..
- StartOrderInterventionTask
- High OrganizationUnitSets.ConfirmationRequired is deprecated and will be removed in 2.0.793: This property has been replaced by SubscriptionConfirmation.
- PushLoyaltyProgram.OrganizationUnitSets.ConfirmationRequired
- High SerialNumbers is deprecated and will be removed in 2.0.793: Does no longer match the nature of this call, use
Errors
instead. Will always be empty after version 2.0.793!.- PushSerialNumbersResponse.SerialNumbers
- High SubscriptionOrganizationUnitSets.ConfirmationRequired is deprecated and will be removed in 2.0.793: This property has been replaced by SubscriptionConfirmation.
- GetSubscriptionOrganizationUnitSetsResponse.SubscriptionOrganizationUnitSets.ConfirmationRequired
For more details on the impact categories, please see When are changes communicated?.
Release dates may vary
The exact date for deploying a Core release to production environments may vary. See How we handle Core releases for more details.