Extras catalogue
PraisovedSync
Latest release 2 months ago (September 10, 2026).
praisovedsync
About
# PraisovedSync
**Client for the Praisoved service — keeps miniShop3 prices, stock and product
attributes in step with an external price-list catalogue.**
---
## What it is
PraisovedSync is the site-side client for [praisoved.com](https://praisoved.com/),
a service that collects supplier price lists, merges them into one catalogue and
works out what each product should cost.
The shop keeps its catalogue where it belongs — in miniShop3. This package is the
half that lives on the site: it hands the shop catalogue over to the service, and
brings the resulting prices back. Nothing else about the shop changes.
The package is useless on its own — an account on the service is required.
## How the exchange works
**The site always starts the conversation.** The service never calls in. There is
no webhook, no open endpoint, no public entry point of any kind; the front end of
the site gains nothing that can be reached from outside.
Two directions, both initiated by the site:
| Direction | What happens |
|---|---|
| **In** | The site downloads an NDJSON exchange file from its personal link and applies prices, stock and attributes to matching products. |
| **Out** | The site builds a CSV of its own catalogue and posts it to the service, so the service knows what the shop actually sells. |
Products are matched by **resource id first, article number as a checksum**. The
id is an address the service learned from the shop's own export; the article is
there to catch the case where the catalogue changed underneath and the id now
points at a different product. When the two disagree, the product is left alone
and counted separately. For rows that carry no id — a catalogue uploaded to the
service by hand, for instance — the article number, MPN or barcode column is used
instead, and duplicate values are skipped rather than guessed at.
## What it writes
Only what the exchange file is allowed to bring:
- **Price**, when it differs by more than half a kopeck.
- **Old price** — and only together with a price change, so the shop never shows a
discount that does not exist.
- **Stock**.
- **Extra fields** of the product (miniShop3 extra fields).
- **Options** (product attributes), converted to the option's own type: numbers,
yes/no, dates, values from a fixed list. Multi-value options are written as a set.
- **Weight** and **country of origin** — the only two base columns that are ever
written back.
- **Unpublish**, and only if the exchange file explicitly asks for that policy for
products the service's catalogue no longer contains.
Writing goes through **miniShop3's own product Update processor**, not straight
into the tables, so plugins from other components still fire on
`OnBeforeDocFormSave` / `OnDocFormSave`. Options are written through miniShop3's
own option service. Resource locks are cleared before and after every run.
## What it never touches
- **Never creates products.** Never deletes them.
- **Never writes** the title, long title, menu title, description, images, article
number, alias, category or vendor.
- **Never creates** options, extra fields, categories or vendors that the site does
not already have.
- **Never touches** orders, customers, discounts, warehouses.
- Products in the recycle bin are ignored; products with a duplicated match value
are left alone entirely.
## What it sends out
A CSV of the shop catalogue: site product id, article, title, category, vendor,
country, price, old price, stock, weight, product URL, up to five image URLs —
plus a column for every active extra field and every option that at least one
product uses. Alongside the file go two dictionaries: the unit of measurement for
each column, and the allowed values of multi-value options.
Boolean options travel as words rather than as 1 and 0. Multi-value options are
sorted, so the same catalogue always produces the same file.
## Safety
The exchange is meant to be dull and reversible-by-hand, not clever:
- **Preview mode is on out of the box.** The component reports what it would change
and writes nothing until that switch is turned off. The "Synchronise" button
refuses to bypass it and says which setting is in the way.
- **Two passes over the file.** The first pass works out the plan and records it;
only then are the limits checked and the second pass writes.
- **A truncated download changes nothing.** The exchange file ends with an explicit
end marker; without it the whole run is refused. A half-downloaded file is
otherwise perfectly valid NDJSON, just shorter — and would have looked like "every
product is out of stock".
- **A price-change threshold** stops the run when the file would move prices further
than allowed. The threshold is set on the service side, next to the catalogue it
describes.
- **The link must be https.** The certificate is verified. Verification can be
switched off for local development, and the admin page says so in red for as long
as it stays off.
- One product failing to save does not abort the run — its id and the reason land
in the run's notes.
There is **no one-click rollback**. The journal keeps the previous value next to the
new one for every field it changed, so a mistake can be undone by hand, but nothing
in the component will undo it for you.
## Admin page
A single page under the MODX manager, built on UIkit and htmx rather than ExtJS:
- **Exchange** — a status block that says what is missing (no link, no miniShop3,
preview mode still on, cron disabled), buttons for *Preview*, *Synchronise* and
*Send catalogue*, and the run journal with a per-run "what changed" table showing
old value beside new.
- **How it works** — the manual, in place: what the component does, how to set it
up, where the limits are, and a ready-to-paste cron line with the real path to
this installation.
Three permissions are supplied: `praisovedsync_view`, `praisovedsync_save`,
`praisovedsync_remove`, with a policy and policy template to match.
## Scheduled runs
A CLI script, run from the system cron:
```
0 * * * * /usr/bin/php /path/to/site/core/components/praisovedsync/cron/sync.php --quiet
```
It refuses to run outside CLI and takes a file lock, so two overlapping cron runs
cannot fight over the same catalogue. After a successful price run it also sends the
catalogue up, if enough hours have passed since the last one.
`--targets` prints a diagnostic list: every name under which this site will accept a
value, with its type, and the image thumbnail sizes available.
## Requirements
- **MODX Revolution 3.0** or newer.
- **miniShop3.**
- **PHP 8.2** or newer.
- **MySQL / MariaDB.**
- An account on [praisoved.com](https://praisoved.com/) — the package has nothing to
talk to without one.
## Setup
1. Install the package.
2. Paste the personal exchange link from the service into
`praisovedsync.feed_url`.
3. Point `praisovedsync.column_sku` at the column holding your article numbers
(`article` by default), and check the result with *Preview*.
4. When the preview looks right, turn `praisovedsync.dry_run` off, turn
`praisovedsync.enabled` on and add the cron line.
Twenty system settings in four groups cover the rest: which columns identify a
product, which title field to export, whether to send attributes and options,
thumbnail size, network timeout, journal depth, and which user the product updates
run as.
At a glance
MODX 3 compatibility unknown. Based on our testing and community reports where available.
- Developer MisterWooster
- Latest release September 10, 2026 (2 months ago)
- First seen in SiteDash September 10, 2026 (2 months ago)
- License GPLv2
- MODX support 3.1 – 100.0
| Changelog | |||
|---|---|---|---|
| MODX.com |
3.0.43-pl |
September 10, 2026
2 months ago |
— |
| MODX.com |
3.0.36-pl |
August 20, 2026
2 months ago |
— |
|
No matching releases. |
|||