=== Kurirko ===
Contributors: expresskurirko
Tags: shipping, woocommerce, courier, serbia, posta
Requires at least: 6.6
Tested up to: 7.1
Requires PHP: 8.1
Stable tag: 0.3.1
License: GPLv3
License URI: https://www.gnu.org/licenses/gpl-3.0.html

Software for your store, not a courier: create shipments, print labels and validate Serbian addresses inside WooCommerce; premium tracks parcels.

== Description ==

**Kurirko is software for online stores — it is not a courier service and does not carry, collect or deliver anything.** It connects your WooCommerce store to **Pošta Srbije / Post Express** using your own contract and credentials. From an order you create a shipment in one click, print the official address label ("adresnica") and the acceptance book ("prijemna knjiga"), and automatically validate the customer's address — without retyping anything into a separate courier portal. The premium build then follows every parcel after handover: tracking, the delivery-status column, automatic completion and the customer e-mails.

The plugin's interface is fully localized to **Serbian (Latin and Cyrillic)**.

**Independent plugin.** Kurirko is an independent WooCommerce extension. It is NOT a courier, NOT a delivery company and NOT a shipping broker, and it is NOT affiliated with, endorsed by, certified by or a product of any courier company — including any company with a similar name. Kurirko is NOT an official product of JP "Pošta Srbije"; "Pošta Srbije" and "Post Express" are trademarks of their respective owners. Kurirko talks to the courier only through your own business contract and API credentials.

= Which couriers are supported? =

Today Kurirko ships with **Pošta Srbije (Post Express)** — fully implemented and tested end-to-end against Pošta's official WSP WebApi, through the standard B2B onboarding flow under the merchant's own contract. Kurirko is not certified, endorsed or approved by Pošta; as part of that onboarding Pošta reviews and approves the address label your store prints. Kurirko is built on a courier-agnostic core and further Serbian couriers are **in preparation**; each one is announced when it has been proven end-to-end, not when work on it starts. When a new courier is added it plugs into the same order workflow you already use.

= Do I need a contract? =

Yes. Kurirko uses **your** contract with Pošta and your access to the WSP WebApi service (credentials are requested from Pošta at b2b@posta.rs). Step 1 of the onboarding guide walks you through it. Until you enter credentials the plugin waits quietly — nothing breaks and no data is sent.

= Premium =

The free build covers the whole sending flow — creating the shipment, address validation, the label and the acceptance book. The premium build adds the volume tools a busy store needs and everything AFTER the parcel is handed over: **auto-send** when an order reaches "processing", the **"Slanje danas"** batch screen that reviews and creates every ready shipment at once (with 4-per-A4 bulk labels or A6 for a thermal printer), **several boxes on one order**, **optional courier services** per shipment, **parcel tracking** with the courier's delivery status in the orders list and **automatic completion** of delivered orders, the **customer e-mails** (tracking number, "your parcel is waiting"), **"Spasilac paketa"** reminders that chase a COD parcel waiting at the post office before it turns into a return, and a **COD ledger** that tracks what the courier still owes you. Details: https://kurirko.com

Documentation and troubleshooting: https://kurirko.com/pomoc

== Features ==

* **Send a shipment from an order** — one click; auto-send on "processing" is available in the premium build.
* **Address label (PDF) and acceptance book** — print-ready, with barcode and full Cyrillic support.
* **Address validation** — recognizes and corrects Serbian addresses (Cyrillic/Latin, ordinal street names, ambiguous settlements) and offers one-click fixes.
* **Cash on delivery (COD)** and declared value — carried on the shipment automatically; optional services the merchant picks (SMS on delivery, return receipt) are available in the premium build.
* **Order status at a glance** — a traffic-light column in the orders list and the outcome of a send appearing in the order box without a manual refresh.
* **Parcel tracking (premium)** — hourly status checks, the courier's delivery status in the orders list, automatic completion of delivered orders, and the customer email with the tracking number.
* **Works with both checkouts** — classic and Cart/Checkout Blocks — and with High-Performance Order Storage (HPOS).
* **Latin and Cyrillic** admin interface (a "Pismo/Script" setting).
* **Diagnostics** — connection test, system report, and a guided test → production onboarding flow.

== Installation ==

1. Install the plugin from your WordPress admin (Plugins → Add New → search for "Kurirko") or upload the ZIP.
2. Activate it — an active WooCommerce (9.0+) is required.
3. Open **Kurirko → Settings** and enter your WSP credentials — if you do not have them yet, step 1 of the onboarding guide walks you through requesting them — plus your sender details and the bank account used for cash on delivery.
4. In **WooCommerce → Settings → Shipping**, add the "Kurirko (Pošta Srbije)" method to your Serbia zone.
5. On the Diagnostics page click **Test connection**, then create a test shipment on the TEST environment; once Pošta approves it, switch the environment to "Production".

== Frequently Asked Questions ==

= Do I need a contract with Pošta? =

Yes. Kurirko uses YOUR contract and WSP WebApi credentials. If you do not have them yet, contact Pošta (b2b@posta.rs); until then the plugin runs in a safe waiting mode.

= Does Kurirko charge for shipments? =

No. Shipments are billed under your own contract with Pošta. Kurirko does not process any shipping payments and is not a payment intermediary.

= Does it work with the block-based checkout? =

Yes — with both the classic and the Cart/Checkout Blocks checkout, and with HPOS order storage.

= Does it support parcel lockers (paketomati)? =

Not yet. Pošta's WebApi does carry parcel-locker delivery, but Kurirko does not yet offer your customer a way to choose a locker at checkout, so nothing is sent that way. It is on the list.

= In which language is the plugin? =

The admin interface is in Serbian and can be switched between Latin and Cyrillic script. This readme is in English per WordPress.org convention.

= What is free and what is premium? =

The plugin's settings screen shows this same comparison, drawn from the one list the features are registered in — so what you read here is what the build actually ships.

Free — the whole sending flow:

* Sending a shipment from an order, in one click — the outcome appears on the screen by itself.
* Checking and correcting the customer's address.
* The cash-on-delivery amount filled in from the order's payment method.
* The courier's own address directory, the parcel contents and the weight.
* Cancelling a shipment (storno).
* The address label (PDF) for a single order.
* The acceptance book, for one order or for several picked in the orders list.
* Diagnostics and the copyable support report.

Premium adds — the volume tools and everything after handover:

* The "Slanje danas" batch screen — review every ready order, then send them all at once.
* Auto-send when an order reaches "processing".
* Several boxes on one order, each with its own label and tracking number.
* Optional courier services per shipment (SMS on delivery, return receipt).
* Bulk label printing, four per A4 sheet.
* The A6 label format for thermal printers.
* Parcel tracking — hourly status checks and a manual refresh on the order.
* The courier's delivery status in the orders-list column.
* Automatic completion of an order the courier reports as delivered.
* "Spasilac paketa" reminders for a parcel waiting uncollected at the post office.
* The e-mail that gives the customer the tracking number.
* The "your parcel is waiting" e-mail to the customer.
* The COD ledger — payouts by dispatch day, with CSV export.
* Support response within one business day.
* Further couriers as they arrive (in preparation).

See https://kurirko.com

= Does the shipping price at checkout come from the courier? =

No. The "Kurirko" shipping method is a flat rate you set yourself in WooCommerce → Settings → Shipping (cost, and an optional free-over threshold). The postage the courier actually charges is fetched when the shipment is created and printed in the acceptance book — it is separate from what the customer paid.

= The courier does not recognise a customer's address. What now? =

Open the order and use the Kurirko box. It offers ranked corrections you apply with one click, and a picker that completes the settlement and the street out of the courier's own directory — an address chosen there travels with the courier's codes instead of free text. The house number stays as the customer entered it. Then send again; the address is re-validated on submission, so a flagged order is never a dead end.

= My shipments stay in the queue and never go out. =

Kurirko sends in the background, so this is almost always WordPress scheduled tasks (WP-Cron) not running on the site — a low-traffic site is the usual case. Kurirko notices and shows an admin notice with a "process now" button that drains the queue immediately. The permanent fix is a real system cron, which any host can enable. You can check the queue on the Diagnostics page.

= What customer data is sent, and where? =

The recipient's name, address and phone number go ONLY to Pošta's API, under YOUR own contract — that is what a courier needs to deliver the parcel. Nothing goes anywhere else: the plugin author receives no customer data, no order data and no store data. See the "External services" section below for the full list.

== Screenshots ==

1. Orders list — the Kurirko status column with a traffic-light indicator and the tracking number (tracking is premium).
2. The Kurirko box on an order — send, print label, track and cancel a shipment in one place (tracking is premium).
3. Send Today — review every ready order and create all shipments in one click (premium).
4. Address label (PDF) — vertical Code128 barcode and the Post Express B2B panel.
5. Diagnostics — the status grid, the connection test and a copyable support report.
6. Settings — the guided onboarding steps (contract to production) and the connected couriers.

== External services ==

This plugin connects to external services. What each one does, when, and what data it sends is described below.

The plugin makes NO automatic call to any server of ours. It talks to your courier's API with the credentials you entered yourself, and to nothing else: there is no phone-home, no analytics, no version ping, no service-health check and no telemetry of any kind. The only other outbound calls are ones you trigger by clicking, and Freemius' licensing, which is opt-in.

**1. Pošta Srbije — WSP WebApi (courier service)**

The core function of the plugin. Kurirko contacts Pošta's WSP WebApi to create shipments, calculate postage, validate addresses and check tracking status. This happens only for orders you act on (manually, or via auto-send that you enable).

* Endpoint (production): https://api.posta.rs/transakcija
* Endpoint (test): http://212.62.32.201/WspWebApi/transakcija
* Note: Pošta's TEST server has no TLS (http), so test credentials travel unencrypted — use only disposable test accounts in test mode. The production endpoint is always https with certificate verification.
* When data is sent: on address validation (order create/edit), when a shipment is sent, and during periodic status checks (premium tracking).
* What data is sent: the shipment data required for delivery — recipient name, address (city, street, number, postcode), phone and e-mail, weight, declared value and COD amount, the parcel contents, plus the sender details from your settings and your API credentials.
* Terms / privacy policy: https://www.posta.rs/ (contact: b2b@posta.rs)

**2. Kurirko support (kurirko.com)**

On the **Kurirko → Diagnostics** page there is a "Copy report and report a problem" button that — and only when you click it — opens the support page in a new tab. There is no automatic call to this service; nothing is sent on page load.

* Address: https://kurirko.com/podrska
* When data is sent: never automatically — only when you click that button.
* What data is sent: only version numbers for support context — plugin, WordPress, WooCommerce and PHP versions — passed as URL parameters (ver, wp, wc, php, src), plus an optional `kur` parameter: an internal support reference code (order number + short hash); it contains no customer personal data. No personal data, customer data or order data is sent.
* Terms / privacy policy: https://kurirko.com/

**3. Freemius (licensing and updates)**

The plugin bundles the Freemius SDK, which powers licensing, the optional premium upgrade and update services. Freemius operates in WordPress.org-compliant mode: no usage data is sent unless you explicitly opt in on the one-time activation screen (you can click "Skip"). Freemius may contact its API to manage the opt-in, licenses and premium upgrade information.

* Service: Freemius, Inc. — https://freemius.com/
* Endpoint: https://api.freemius.com/
* When data is sent: when you interact with the activation opt-in, manage a license, or view upgrade/account screens. Anonymous usage data is sent ONLY after you explicitly opt in.
* What data is sent (only if you opt in): site URL, admin e-mail, and technical environment data (WordPress, PHP and plugin versions, active plugins/theme). No customer or order data is sent.
* Terms of Service: https://freemius.com/terms/
* Privacy policy: https://freemius.com/privacy/

== Third-party code ==

Kurirko bundles the following third-party components. Each keeps its own license and copyright notices in the shipped files.

* **Freemius WordPress SDK 2.13.4** (`vendor/freemius/wordpress-sdk`) — licensing, updates and the optional premium upgrade. License: GNU GPL v3.0 only (`vendor/freemius/wordpress-sdk/LICENSE.txt`). Copyright (c) Freemius, Inc. — https://freemius.com/ — Its bundled PHP API client (`vendor/freemius/wordpress-sdk/includes/sdk/`) carries its own GNU GPL v2 notice (`includes/sdk/LICENSE.txt`).
* **Composer autoloader** (`vendor/autoload.php`, `vendor/composer/`) — class autoloading, generated by Composer. License: MIT (`vendor/composer/LICENSE`). Copyright (c) Nils Adermann, Jordi Boggiano — https://getcomposer.org/
* **tFPDF and TTFontFile** (`src/Pdf/Tfpdf.php`, `src/Pdf/TtFontFile.php`) — PDF generation for the address label and the acceptance book. License: GNU LGPL. Copyright (c) Ian Back, Tycho Veltmeijer; TTFontFile is based on the ReportLab Open Source PDF library. The files are namespaced into `Kurirko\Pdf` and modified as documented at the top of each file; the original license headers are retained.
* **DejaVu Sans / DejaVu Sans Bold** (`fonts/unifont/`) — Cyrillic text rendering in the PDFs. License: Bitstream Vera Fonts Copyright (Bitstream, Inc.; Arev additions (c) Tavmjong Bah; DejaVu changes are in the public domain). The full license text ships with the fonts in `fonts/unifont/DejaVu_LICENSE.txt`.
* **jQuery postMessage v0.5** (`vendor/freemius/wordpress-sdk/assets/js/nojquery.ba-postmessage.js`) — cross-frame messaging used by the Freemius checkout. Copyright (c) 2009 "Cowboy" Ben Alman, dual licensed MIT and GPL; non-jQuery fork by Jeff Lee. The notice is at the top of the file.
* **Freemius Pricing app** (`vendor/freemius/wordpress-sdk/assets/js/pricing/freemius-pricing.js`) — the React pricing screen inside the SDK. License: MIT. The bundle embeds React 17.0.2 and ReactDOM 17.0.2 (MIT, copyright (c) Facebook, Inc. and its affiliates), scheduler 0.20.2 (MIT), object-assign (MIT, Sindre Sorhus), is-buffer (MIT, Feross Aboukhadijeh) and Font Awesome Free 5.15.4 (icons CC BY 4.0, fonts SIL OFL 1.1, code MIT — https://fontawesome.com/license/free). All of these notices ship next to the bundle in `vendor/freemius/wordpress-sdk/assets/js/pricing/freemius-pricing.js.LICENSE.txt`.

= Where the bundled minified files come from =

Three shipped JavaScript files are compiled or minified. None of them is our code; each is maintained in a public repository, and this is where its source and build tooling live.

* `vendor/freemius/wordpress-sdk/assets/js/pricing/freemius-pricing.js` — a webpack build of the Freemius Pricing app. Source and build tools: https://github.com/Freemius/pricing-page (MIT). Its README states the app is shipped as part of the Freemius WordPress SDK from SDK version 2.9.0 onward, and it is built with `npm install` then `npm run build`, which writes the bundle into `dist/`; that output is what the SDK carries under `assets/js/pricing/`. The accompanying `freemius-pricing.js.LICENSE.txt` lists every library webpack inlined into it.
* `vendor/freemius/wordpress-sdk/assets/js/jquery.form.js` — a small helper that builds a hidden form for a redirect POST. It is maintained, in this exact form, in the Freemius WordPress SDK repository at the same path: https://github.com/Freemius/wordpress-sdk (GPL-3.0-only), tag `2.13.4`. There is no separate build step; the SDK repository is the file's development location.
* `vendor/freemius/wordpress-sdk/assets/js/postmessage.js` — the `FS.PostMessage` wrapper around `nojquery.ba-postmessage.js`. Same development location: https://github.com/Freemius/wordpress-sdk, tag `2.13.4`, path `assets/js/postmessage.js`. The unminified companion it wraps ships beside it as `nojquery.ba-postmessage.js`.

The SDK is bundled through Composer (`composer.json` in the plugin root pins `freemius/wordpress-sdk`), so the exact commit that produced the shipped copy is recorded in `vendor/composer/installed.json`.

= License of the combined work =

Our own code — the plugin's source, apart from the bundled third-party components listed above — is licensed under the **GNU GPL, version 2 or later** (https://www.gnu.org/licenses/gpl-2.0.html). That is what the `license` field of `composer.json` declares, and it is what makes the combination below possible.

What you install is that code together with the bundled Freemius SDK, which is GPL-3.0-**only**. GPLv2-or-later code combined with GPLv3-only code is distributable under version 3, so the plugin as distributed — the combined work in this ZIP — is licensed under the **GNU GPL version 3** and cannot be offered as "version 3 or later". That is what `License: GPLv3` at the top of this readme and `License: GPL-3.0` in the `kurirko.php` header both declare (the same license, two spellings), and a copy of the GPL v3 ships with the plugin as `license.txt`. Taken on its own, our code stays GPL-2.0-or-later.

== Changelog ==

= 0.3.1 =
* Fixed: a cancelled shipment can be sent again — the new send gets a fresh number and a fresh label instead of waiting in the queue forever.
* Fixed: an order whose background job got stuck no longer hides its actions; it reports the state and offers a way out.
* Fixed: hourly tracking no longer refreshes a shipment you cancelled — a storno stays a storno on the order screen.
* Fixed: the address check no longer blames the wrong field when the courier rejects a recipient detail.
* New: the order now distinguishes "cancelled in the store" from "confirmed by the courier", and asks for your confirmation where the courier offers no cancel API.
* New: auto-send (premium) never re-sends an order after a storno on its own; a second parcel is always a human decision.
* Improved: the licensing screens now speak Serbian.

= 0.3.0 =
* **New packaging** — the free build keeps the whole sending flow (create, validate, print, cancel, diagnostics); everything after the parcel is handed over is now part of the premium tier: parcel tracking, the delivery-status column, automatic order completion, "Spasilac paketa" and the customer e-mails.
* **Review before you send** — the batch screen now opens a review step first: correct an address, a phone number or the cash-on-delivery amount row by row, watch each shipment's outcome as it lands, and retry only the rows that failed (premium).
* **The outcome finds you** — the Kurirko box on an order shows how a send ended by itself; no more reloading the page to find out.
* **Optional courier services per shipment** — SMS on delivery and return receipt, set per courier as always on, offered in the review step, or off; charged on the first box only (premium).
* **Several boxes on one order** — each box gets its own label and its own tracking number, cash on delivery and declared value ride on the first, and a cancellation cancels the whole order (premium).
* **A6 labels for thermal printers** — the same address label with a page to itself instead of a quarter of a sheet (premium).
* **Book of COD payouts** — what the courier owes you, grouped by dispatch day, marked paid a day at a time, with an export to CSV (premium).
* New: a default shipment contents setting, used when an order's own items cannot name themselves.
* New: a free/premium comparison on the settings screen, built from the same list the features are registered in — it can name nothing the build does not ship.
* Improved: every Kurirko order note now opens with one symbol for its kind of event, so a long order history can be scanned instead of read.
* Improved: Kurirko's own buttons wear WordPress' icons instead of typographic stand-ins.
* Improved: the shipment-status feed both screens poll answers for the whole set in one query instead of three per order — a batch of 200 costs 17 queries, not 603.
* Improved: the rescue counter adds up the postage a rescued parcel saved, not the whole cash-on-delivery amount it carried.

= 0.2.0 =
* **Address picker** — when the courier does not recognise an address, pick the settlement and the street from the courier's own directory. The choice travels as the courier's codes, so two places with the same name resolve to the one you actually picked.
* **"I already have a tracking number"** — record a parcel you handed over at the counter. Tracking starts and the customer is notified; no label is printed, because the courier already has one.
* **What this courier supports** — each courier's card now lists what it can and cannot do, and says what an absence means for you in plain words.
* Wording — the plugin and the customer's email now say "broj pošiljke" everywhere instead of one courier's own term for it.
* Fix: a cancelled parcel could still chase the customer with a "collect your parcel" reminder, and the reminder guard it left behind silenced the next shipment's reminder.
* Fix: a tracking number typed in by hand kept blocking the address label of a LATER, real shipment on the same order.
* Fix: the shipment email to the customer could name the wrong courier and link the wrong tracking page.
* Fix: a company buying as a company was reduced to its contact person on the label; the company name and tax number now travel where the courier accepts them.
* Fix: sending or refreshing tracking could block the screen for up to twenty seconds when the courier went quiet. Waiting now happens only in background jobs.
* Under the hood: the core no longer knows which courier it is talking to. That is what lets further couriers be added without touching how your orders work.

= 0.1.1 =
* Onboarding: five-step guide with collapsible panel, real error messages from the courier, payment-gateway checkboxes, field validation hints.

= 0.1.0 =
* Initial release: send a shipment, address label and acceptance book (PDF), tracking, address validation, diagnostics, Latin/Cyrillic interface. Pošta Srbije (Post Express) courier; HPOS and Cart/Checkout Blocks compatible.

== Upgrade Notice ==

= 0.3.1 =
Re-send after a storno now works (fresh number and label), stuck orders offer a way out, cancelled shipments stay cancelled in tracking, and auto-send never re-sends after a storno on its own.

= 0.3.0 =
Adds batch sending with a preflight review, multi-box orders, optional services, an A6 label format and a COD ledger. Tracking, the delivery status column, auto-completion and customer emails are now part of the premium tier.

= 0.2.0 =
Fixes a cancelled parcel that could still chase your customer with a reminder, and a hand-typed tracking number that blocked a later shipment's label. Adds an address picker that reads the courier's own directory.

= 0.1.1 =
First public release.
