=== Mosley Digital for WooCommerce ===
Contributors: mosleydigital
Tags: woocommerce, mobile app, orders, products, sales
Requires at least: 6.4
Tested up to: 7.1
Requires PHP: 8.1
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Connects your WooCommerce store to the Mosley Digital mobile app: sales, orders, products, low stock and new order notifications.

== Description ==

Mosley Digital for WooCommerce is the companion plugin of the Mosley Digital mobile app. Install it on your store and the app can show you, on your phone:

* **Home**: net sales, number of orders and average order value for today, yesterday, the last 7 days, the last 30 days or this month, each compared with the previous period.
* **Orders to fulfil**: how many orders are processing, on hold or pending payment.
* **Low stock**: the products that are out of stock or below the low stock threshold of the store.
* **Orders**: the list of orders, with search and a filter by status, and the detail of each order: items, totals, payment and shipping method, the customer's contact details and addresses, and the order notes.
* **Products**: the list of products, with search by name or SKU and filters for published products, drafts, low stock and out of stock, and the detail of each product: picture, status, type, SKU, categories, price, stock and, in a variable product, its variations.

From the app you can also change the status of an order and add a note to it, private or for the customer. WooCommerce sends its usual emails for those changes, exactly as it does from the WordPress dashboard.

You can also change the price and the stock of a product or of one of its variations, and publish a product or send it back to draft. A quantity is only saved if it is still the one the app was showing, so a sale that comes in while you are editing is never overwritten. A sale price set from the app starts at once and has no end date. Saving a quantity from the app does not send the low stock and out of stock emails of WooCommerce: those are only sent when an order reduces the stock.

You can create a product from the app too: take or choose up to 8 photos, write its name and its price, and publish it or save it as a draft. It is a simple product, in the default category of the store and with the tax and shipping settings WooCommerce gives any new product; whatever else it needs —categories, attributes, variations— you add later in the WordPress dashboard. Its photos are saved in the media library of your store.

If you turn them on in the app, your phone also gets a notification when a new order comes in, even with the app closed: "New order", with the order number and its total. Tapping it opens that order. See "External services" below for what leaves the store to deliver it.

The plugin does nothing on its own: it needs the Mosley Digital app, which is a separate product for iPhone and Android. The links to get it are at https://mosley.digital/woo.

= How it works =

The plugin adds fifteen REST API routes to the store, under `/wp-json/ai-product-studio/v1/app/`. The app calls them directly, over HTTPS, signed in as a WordPress user of the store with an application password. Only users who can manage WooCommerce can use them, and reading or changing orders also requires the capability to edit shop orders. Reading products also requires the capability to edit products; changing one requires being able to edit that product, and publishing it or sending it back to draft, the capability to publish products. Creating a product and uploading its photos also requires the capability to upload files.

It also adds one read-only page, WooCommerce > Mosley Digital, with the steps to connect the app, two checks of what the app needs from the store and what the new order notifications send to an external service.

= Privacy =

The app talks to your store directly: what you see in the app goes from your store to your phone. The plugin has no tracking and loads no remote scripts, fonts or images, and it does not contact any server of Mosley Digital.

It makes one kind of external request, and only if someone has turned on new order notifications in the app for this store: the notification itself, sent to the Expo push notification service. The section "External services" says exactly what is sent. While no phone has notifications turned on, the plugin makes no external request at all.

It has no settings and creates no database tables. It stores a cache of the sales totals of the Home screen, kept for 60 seconds as transients, and, for each user who turns notifications on, the push token of their phone (in the user's metadata), with its platform, the date it was registered, the address of the store it was registered on and the last error it gave. One option keeps the ids of the users who have a phone registered. For about fifteen minutes after a notification is sent it also keeps, in one option, the ids the Expo service gave to it, to ask whether it was delivered. An order that has sent its notification is marked with one piece of order metadata. Uninstalling the plugin deletes all of it except that mark: "What is removed when I uninstall it?", below, has the details.

The photos of a product you create from the app go from your phone to the media library of your store, and nowhere else. They are accepted only if they are real JPEG, PNG or WebP images, of 10 MB and 25 megapixels at most (or less, if that is what your server accepts or has memory to open), and they are saved under a file name generated by the plugin. Each photo is uploaded as soon as you choose it, before the product exists, so it is marked as pending with one piece of metadata of the attachment (the user, the date and, once you save the form, the form). When the product is created, its photos stop being pending and are attached to it.

A photo that has been pending for more than a day —the form was closed without saving— is deleted, with its file, by a scheduled task of WordPress. The task runs once a day and looks at 50 photos each time; while it has photos left to look at, it runs again a minute later, so the deletion comes some time after that day is over, not at the exact minute. It does not delete a photo the site uses: that one stops being pending and is left alone for good. A photo counts as used when it is attached to a post; when it is the featured image of any post, page, product or variation; when it is in the gallery of a product; when it is the image of a product category or of another term; when it is the site icon, the logo of the theme or the placeholder image of WooCommerce; and when its file is linked in the content or the excerpt of any post, page or product, whatever its status, named in a `[gallery]` shortcode, or linked in a widget or in a setting of the theme. It does not count as used when only the data of another plugin refers to it —a custom field that stores its id or its address, or a page builder that keeps its content outside the content of the post—: such a photo is deleted like any other pending one, unless a developer protects it with the filter `apsw_app_pending_upload_in_use`.

A product created from the app also keeps one piece of metadata with the identifier of the form it came from, so that sending the same form twice does not create two products. If the request that creates a product is cut short by the server before the product is complete and the form is not sent again, the same task leaves that product as a draft.

The phones of a user are part of the personal data tools of WordPress (Tools > Export Personal Data and Tools > Erase Personal Data). The export lists each phone by a hashed id, with its platform and the date it was registered, and never the push token; the eraser removes the phones of that user from the store.

= Languages =

The plugin is written in English and includes a Spanish translation. The texts the app reads from the store (labels and messages) follow the language of the site; the page in the dashboard follows the language of each user. A store in any Spanish locale uses the included translation, unless WordPress has a language pack for that locale.

== Installation ==

1. Make sure WooCommerce is installed and active.
2. Install and activate this plugin from the Plugins screen of WordPress.
3. Open WooCommerce > Mosley Digital. The page shows the address of the store and checks that the store is served over HTTPS and that application passwords are available.
4. Install the Mosley Digital app on your phone, from the App Store or Google Play (the links are at https://mosley.digital/woo), type the address of the store and approve the access with your WordPress user.

== Frequently Asked Questions ==

= What does the store need for the app to connect? =

Two things. The store must be served over HTTPS, and WordPress application passwords must be available: the app signs in with one. WordPress turns application passwords off on sites without HTTPS, and some security plugins turn them off too. The page WooCommerce > Mosley Digital tells you whether both are in place.

= Does it send my data anywhere? =

What the app shows goes from your store to your phone, directly. The one exception is the new order notification, and only if you turn notifications on in the app: to reach your phone it has to go through the Expo push notification service and through Apple or Google. It carries the order number, the order total and the name of the store, and no customer data. See "External services".

= How do I turn the new order notifications on or off? =

In the app, in the screen of your store. Each user decides for their own phone. Turning them off, or disconnecting the store in the app, removes the phone from the store.

= Which orders send a notification? =

An order that comes in: one that reaches Processing, On hold or Completed from Pending payment, Failed, Cancelled or a draft (or from a status added by another plugin), or that is created directly in one of those three statuses. Orders that only have downloadable products go straight to Completed when they are paid, and they notify too.

An order that is created with a date of more than 24 hours ago is not a new order and does not notify: orders brought in by an import, or an order entered by hand in the dashboard with an earlier date. An order that already existed notifies whatever its date: one that was pending payment and is paid a week later is a sale of today.

Each order notifies once. What counts is the status the order comes from: a change from Processing, On hold, Completed or Refunded, or a restore from the trash, does not notify, whether or not the order had notified before. So an order that was already in Processing before anyone turned notifications on stays quiet when it moves to Completed; if it first goes back to Pending payment, Failed, Cancelled or a status added by another plugin, its next arrival at Processing, On hold or Completed notifies, if it had not notified yet. An order that is pending payment does not notify until it is paid. If the order is cancelled, refunded, fails or is moved to the trash before its notification has left, the notification is not sent.

The notification is sent by a background task (Action Scheduler, which WooCommerce includes), so it does not slow down the checkout; it usually arrives within a minute.

= Who gets the notification? =

The phones of every user who turned notifications on in the app and can edit orders in the store, except the phones of the person who made the change: if you create an order or mark one as paid yourself, in the dashboard or in the app, your own phones stay quiet and everybody else is notified. An order placed by a customer notifies everybody.

A user who can no longer edit orders stops getting notifications, and their phones are removed from the store the next time a notification is about to be sent. A copy of the store on another address, such as a staging site, does not notify the phones that were registered on the original store. The same happens if the store starts answering on an address different from the one the phones were registered under: the plugin then says so in the WooCommerce log (WooCommerce > Status > Logs, source "mosley-digital"), and opening the app connected to the current address registers the phone again.

= Does it need Jetpack or a WordPress.com account? =

No. It needs WooCommerce and nothing else.

= Who can use the app? =

Any user of the store who can manage WooCommerce, such as an administrator or a shop manager. Each user approves the app with their own WordPress account and can revoke its application password at any time from their profile.

= Does it work with High-Performance Order Storage (HPOS)? =

Yes. Orders are read and written only through the WooCommerce functions.

= I also use Mosley Digital IA for WooCommerce. Do I need this one? =

No. Mosley Digital IA for WooCommerce, the other WooCommerce plugin by Mosley Digital, already includes these same routes. If both are active, this one steps aside and does nothing.

= What is removed when I uninstall it? =

The cached sales totals, the push tokens of the phones that had notifications turned on, the ids of the notifications whose delivery was still to be checked and the notifications waiting to be sent. The mark that says an order already sent its notification stays with the order. The application passwords created for the app belong to each user and stay until that user revokes them.

The scheduled task that deletes the pending photos, and the marks of the photos that were still pending, are removed too; deactivating the plugin already removes the task. No photo is deleted when you uninstall: the ones of your products are yours, and the ones that were still pending stay in the media library, where you can delete them. The products you created from the app stay as they are, each with the piece of metadata that holds the identifier of the form it came from (`_apsw_app_client_id`): it is not removed.

Two details. The notifications waiting to be sent are background tasks of Action Scheduler, which is part of WooCommerce: if WooCommerce is not active when you delete the plugin, they cannot be cancelled. They stay in its queue, and when WooCommerce runs them without the plugin nothing is sent: Action Scheduler marks them as failed. And if another copy of this plugin is still active on the site, the phones are kept, because that copy uses them.

== External services ==

This plugin connects to one external service, the Expo push notification service, to deliver the new order notifications to the phones that asked for them.

* **What the service is and what it is used for.** Expo push notifications is a service of 650 Industries, Inc. It receives a notification and hands it to Apple (for an iPhone) or to Google (for an Android phone), which deliver it to the phone. The plugin sends its requests to `https://exp.host/--/api/v2/push/send` and, about fifteen minutes later, to `https://exp.host/--/api/v2/push/getReceipts` to learn whether the notification was delivered.
* **What is sent.** The push token of each phone that has notifications turned on (an identifier the app gets from Expo), the text of the notification (the title "New order", the order number, the order total and the name of the store) and, so that the app can open the order when you tap the notification, the address of the store and the id of the order. The address is the Site Address (URL) of Settings > General as it is saved, without a slash at the end and without the language folder that a multilingual plugin may add to it. To ask for the receipts, the plugin sends the ids Expo gave to those notifications. No name, email, address or any other data of the customer is sent, and no credentials of the store.
* **When it is sent.** Only if at least one user has turned on new order notifications in the app for this store, and then each time an order comes in: when it reaches Processing, On hold or Completed from a status in which it was not yet a firm order (see "Which orders send a notification?"). The phones of the person who made the change are left out. If nobody has turned notifications on, the plugin never contacts the service.
* **Terms and privacy.** Expo terms of service: https://expo.dev/terms. Expo privacy policy: https://expo.dev/privacy.

== Changelog ==

= 1.0.0 =

* First public release.
* Home: net sales, number of orders and average order value for a period, the orders to fulfil and the products with low stock.
* Orders: the list and the detail of each order, changing its status and adding a note to it.
* Products: the list and the detail of each product, with its variations; changing its price and its stock and publishing it or sending it back to draft; and creating a simple product with up to 8 photos, which are saved in the media library of the store.
* New order notifications on the phones that turn them on in the app. They are delivered through an external service, the Expo push notification service, and only while a phone has them turned on: see "External services".
* Fifteen REST API routes for the app, for users who can manage WooCommerce. No settings and no database tables.
* English is the base language of the plugin, and a Spanish translation is included.
