Visma.NET Connector - ItemUpdate
This function synchronizes item data from Visma.NET to App4Sales. It retrieves item information, VAT details, unit of measure data, sales categories, and item attachments (images) from Visma.NET. The retrieved data is then transformed and mapped to App4Sales internal item structures, including item codes, descriptions, prices, VAT percentages, units, EAN codes, item classes, item categories, purchase package sizes, and stock amounts. Finally, it updates the App4Sales database with the processed item data, including item pictures.
Data Source Configuration
Item data is pulled from the Visma.NET API using the following endpoints and parameters:
VAT Information: Fetched from
/v1/vat.Inventory (Items): Fetched from
/v1/inventory. Supports pagination with a page size of 500. Each item can be filtered by its status (InactiveorNoSalesare skipped).Unit of Measure: Fetched from
/v1/unitofmeasure. Supports pagination with a page size of 500.Sales Categories: Fetched from
/v1/salescategory.Sales Category Inventory: Fetched from
/v1/salescategory/{categoryId}/item, where{categoryId}is the ID of a sales category.Inventory Attachments (Images): Fetched from
/v1/attachment/{attachmentId}, where{attachmentId}is the ID of an attachment associated with an item. Returns raw byte data.Warehouses: Fetched from
/v1/warehouse. Supports pagination with a page size of 500. Only active warehouses are considered.Sales Order Types: Fetched from
/v1/salesordertype. Supports pagination with a page size of 500. Only active sales order types are processed.
Authentication is handled via OAuth2 (Visma Connect) or an older username/password flow, depending on connector settings.
Data Mapping Table: Item
App4Sales Field | Source Field (API/Excel/DB) | Logic/Notes |
|
| Directly mapped from the Visma.NET inventory number. |
|
| Mapped from the Visma.NET inventory ID, converted to string. |
|
| Directly mapped from the Visma.NET item description. |
|
| Directly mapped from the Visma.NET default price. |
| Hardcoded | Hardcoded to 'E'. |
|
| Derived from |
|
| Directly mapped from the Visma.NET sales unit. |
|
| Extracted from |
|
| If |
|
|
|
|
| Derived from |
|
| First, determined from |
|
| If |
Data Mapping Table: Item Pictures
App4Sales Field | Source Field (API/Excel/DB) | Logic/Notes |
|
| A SHA1 hash is generated from the raw bytes of the attachment. |
|
| Raw bytes of the attachment. Only stored if the hash is new (not existing in App4Sales). |
| Hardcoded | Hardcoded to 'ERP'. |
|
| A SHA1 hash is generated from the raw bytes of the attachment. |
|
| Determined by the order of attachments, sorted by name, starting from 1. |
|
| Links the picture to the item using the item's inventory number. |
Special Logic & Filters
Item Filtering: Items with
VismaNetInventoryStatusas 'Inactive' or 'NoSales' are skipped.Order Type Synchronization: The connector attempts to add Visma.NET sales order types to App4Sales. If a 'SO' (SalesOrder) type exists in Visma.NET, it's mapped to the App4Sales 'Order' type. Other active Visma.NET sales order types are added as new order types in App4Sales if they don't already exist, with
SendToBackofficeset to true andOnRelationCardset to false. This occurs at the beginning of theItemUpdateprocess.Warehouse Synchronization: Active warehouses from Visma.NET are retrieved and updated in App4Sales. This happens at the end of the
ItemUpdateprocess.Image Synchronization:
Images are synchronized only if
ConnectorSettings.DontSyncErpAttachmentsis false ANDPimSettings.UseImagesOnlyFromPIMis false.Attachments are retrieved as raw bytes. A hash is generated for each attachment.
If an attachment's hash already exists in App4Sales, only a link to the existing image is created. Otherwise, the raw image bytes are stored along with the link.
Attachments are sorted by name for consistent sequencing.
Stock Synchronization:
If
ConnectorSettings.SyncDetailedStockInformationis true, a separate API call is made to retrieve detailed stock information for each item.If
ConnectorSettings.SyncDetailedStockInformationis false, stock is aggregated fromVismaNetInventory.WarehouseDetails.
Domain Specifics (Expanded)
Price Logic
The base sales price for an item is directly sourced from VismaNetInventory.DefaultPrice. VAT percentage is dynamically determined based on the connector settings (DefaultVatCodeForItems) and the item's VAT code. The system hardcodes 'E' for VatIncluded. No tier/volume pricing rules, quantity breaks, or customer-specific price lists are explicitly handled in this update function.
Image Handling
Item images are sourced directly from item attachments within Visma.NET. The system retrieves all attachments associated with an inventory item. Each attachment is treated as an image, and its raw bytes are fetched from the /v1/attachment/{attachmentId} endpoint. The attachments are sorted alphabetically by name before processing. A SHA1 hash is generated from the image's raw bytes, which is used to prevent duplicate storage in App4Sales if the exact image (based on its hash) already exists. Images are linked to items using their ItemCode.
Stock & Availability
Stock information is updated in App4Sales based on configuration. If detailed stock synchronization is enabled (ConnectorSettings.SyncDetailedStockInformation is true), a live API call is made for each item to retrieve comprehensive stock values, including AvailableForShipment, which populates LastAvailableStock in App4Sales. Otherwise, LastAvailableStock is calculated by summing the AvailableForShipment values from each of the item's warehouse details (VismaNetInventory.WarehouseDetails). If a ConnectorSettings.Warehouse is specified, stock is only considered from those designated warehouses.
Matrix & Attributes
Item classes are derived from Visma.NET's posting classes, item classes, and sales categories. Posting classes and item classes from Visma.NET are mapped to generic 'Filter' and 'Item class' categories in App4Sales, respectively. Sales categories from Visma.NET are also mapped to item classes in App4Sales, using their names as values and their parent category names (or a default 'Sales category' label) as descriptions.
Item categories in App4Sales are populated from VismaNetInventory.Attributes. The exact mapping depends on the ConnectorSettings.OnlyUseAttributeDescriptionForItemCategories setting. No explicit matrix item (parent/child variant) handling or linking logic is present within this specific ItemUpdate function.
Related Settings & Prerequisites
DefaultVatCodeForItems: Used to determine the VAT percentage for items by matching against Visma.NET VAT zones.CustomItemFieldForTheItemStatus: Specifies a custom field in Visma.NET inventory attributes or unknown elements to use for setting the item status in App4Sales.UnitFieldForPackageSize: Determines whether the sales, purchase, or base unit of measure should be used to calculatePurchasePackageSize.PurchasePackageSizeAttribute: An optional setting that, if configured, overrides the calculatedPurchasePackageSizewith a value from a specific inventory attribute.DontSyncErpAttachments: If true, item attachments (images) from Visma.NET will not be synchronized.PimSettings.UseImagesOnlyFromPIM: If true, item attachments (images) from Visma.NET will not be synchronized, as images are expected to be managed by a Product Information Management (PIM) system.SyncDetailedStockInformation: If true, detailed stock information for each item is retrieved via a live API call; otherwise, it's aggregated from warehouse details.Warehouse: A comma- or semicolon-separated list of warehouses. If specified, stock calculations will only consider these warehouses.
Known Limitations
The ItemUpdate function does not explicitly handle matrix item (parent/child variant) relationships, such as linking parent items to their variants or synchronizing variant-specific data. All items are processed individually based on their VismaNetInventory entry.
Price logic is limited to the default sales price. Advanced pricing features like tier pricing, volume discounts, or customer-specific price lists are not implemented within this update mechanism.
The system assumes that the /v1/inventory endpoint, when called without specific item IDs, returns a list of all inventory items. The RouteInfoProvider's current definition for VismaNetInventory (v1/inventory/{0}) primarily suggests fetching a single item by ID, which could lead to unexpected behavior if this assumption is incorrect.