diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index acbc529d12de..999e05ece942 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -6,6 +6,7 @@ - [Internal] Improve WebView experience by using Authenticated WebView for more scenarios [https://github.com/woocommerce/woocommerce-android/pull/14826] - [Internal] Update In-Person Payments setup flow to use Authenticated WebView [https://github.com/woocommerce/woocommerce-android/pull/14827] - [*] Improved the Filters button colors on the Orders and Products screens [https://github.com/woocommerce/woocommerce-android/pull/14832] +- [*] Fixed an issue with inconsistent data on the Customers screen [https://github.com/woocommerce/woocommerce-android/pull/14839] - [*] Fixed an issue when images for the card reader flows were not shown on tablets [https://github.com/woocommerce/woocommerce-android/pull/14849] - [*] Fixed an issue where the count of the filters applied to the orders was not updated correctly [https://github.com/woocommerce/woocommerce-android/pull/14844] diff --git a/libs/fluxc-plugin/schemas/org.wordpress.android.fluxc.persistence.WCAndroidDatabase/72.json b/libs/fluxc-plugin/schemas/org.wordpress.android.fluxc.persistence.WCAndroidDatabase/72.json new file mode 100644 index 000000000000..66d6767303e8 --- /dev/null +++ b/libs/fluxc-plugin/schemas/org.wordpress.android.fluxc.persistence.WCAndroidDatabase/72.json @@ -0,0 +1,4317 @@ +{ + "formatVersion": 1, + "database": { + "version": 72, + "identityHash": "e94f8b70f90756ca710f86422b5924d6", + "entities": [ + { + "tableName": "AddonEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`addonLocalId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `globalGroupLocalId` INTEGER, `productRemoteId` INTEGER, `localSiteId` INTEGER, `type` TEXT NOT NULL, `display` TEXT, `name` TEXT NOT NULL, `titleFormat` TEXT NOT NULL, `description` TEXT, `required` INTEGER NOT NULL, `position` INTEGER NOT NULL, `restrictions` TEXT, `priceType` TEXT, `price` TEXT, `min` INTEGER, `max` INTEGER, FOREIGN KEY(`globalGroupLocalId`) REFERENCES `GlobalAddonGroupEntity`(`globalGroupLocalId`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "addonLocalId", + "columnName": "addonLocalId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "globalGroupLocalId", + "columnName": "globalGroupLocalId", + "affinity": "INTEGER" + }, + { + "fieldPath": "productRemoteId", + "columnName": "productRemoteId", + "affinity": "INTEGER" + }, + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER" + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "display", + "columnName": "display", + "affinity": "TEXT" + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "titleFormat", + "columnName": "titleFormat", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT" + }, + { + "fieldPath": "required", + "columnName": "required", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "position", + "columnName": "position", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "restrictions", + "columnName": "restrictions", + "affinity": "TEXT" + }, + { + "fieldPath": "priceType", + "columnName": "priceType", + "affinity": "TEXT" + }, + { + "fieldPath": "price", + "columnName": "price", + "affinity": "TEXT" + }, + { + "fieldPath": "min", + "columnName": "min", + "affinity": "INTEGER" + }, + { + "fieldPath": "max", + "columnName": "max", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "addonLocalId" + ] + }, + "indices": [ + { + "name": "index_AddonEntity_globalGroupLocalId", + "unique": false, + "columnNames": [ + "globalGroupLocalId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_AddonEntity_globalGroupLocalId` ON `${TABLE_NAME}` (`globalGroupLocalId`)" + } + ], + "foreignKeys": [ + { + "table": "GlobalAddonGroupEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "globalGroupLocalId" + ], + "referencedColumns": [ + "globalGroupLocalId" + ] + } + ] + }, + { + "tableName": "AddonOptionEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`addonOptionLocalId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `addonLocalId` INTEGER NOT NULL, `priceType` TEXT NOT NULL, `label` TEXT, `price` TEXT, `image` TEXT, FOREIGN KEY(`addonLocalId`) REFERENCES `AddonEntity`(`addonLocalId`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "addonOptionLocalId", + "columnName": "addonOptionLocalId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "addonLocalId", + "columnName": "addonLocalId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "priceType", + "columnName": "priceType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "label", + "columnName": "label", + "affinity": "TEXT" + }, + { + "fieldPath": "price", + "columnName": "price", + "affinity": "TEXT" + }, + { + "fieldPath": "image", + "columnName": "image", + "affinity": "TEXT" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "addonOptionLocalId" + ] + }, + "indices": [ + { + "name": "index_AddonOptionEntity_addonLocalId", + "unique": false, + "columnNames": [ + "addonLocalId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_AddonOptionEntity_addonLocalId` ON `${TABLE_NAME}` (`addonLocalId`)" + } + ], + "foreignKeys": [ + { + "table": "AddonEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "addonLocalId" + ], + "referencedColumns": [ + "addonLocalId" + ] + } + ] + }, + { + "tableName": "Coupons", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `localSiteId` INTEGER NOT NULL, `code` TEXT, `amount` TEXT, `dateCreated` TEXT, `dateCreatedGmt` TEXT, `dateModified` TEXT, `dateModifiedGmt` TEXT, `discountType` TEXT, `description` TEXT, `dateExpires` TEXT, `dateExpiresGmt` TEXT, `usageCount` INTEGER, `isForIndividualUse` INTEGER, `usageLimit` INTEGER, `usageLimitPerUser` INTEGER, `limitUsageToXItems` INTEGER, `isShippingFree` INTEGER, `areSaleItemsExcluded` INTEGER, `minimumAmount` TEXT, `maximumAmount` TEXT, `includedProductIds` TEXT, `excludedProductIds` TEXT, `includedCategoryIds` TEXT, `excludedCategoryIds` TEXT, PRIMARY KEY(`id`, `localSiteId`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "code", + "columnName": "code", + "affinity": "TEXT" + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "TEXT" + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "TEXT" + }, + { + "fieldPath": "dateCreatedGmt", + "columnName": "dateCreatedGmt", + "affinity": "TEXT" + }, + { + "fieldPath": "dateModified", + "columnName": "dateModified", + "affinity": "TEXT" + }, + { + "fieldPath": "dateModifiedGmt", + "columnName": "dateModifiedGmt", + "affinity": "TEXT" + }, + { + "fieldPath": "discountType", + "columnName": "discountType", + "affinity": "TEXT" + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT" + }, + { + "fieldPath": "dateExpires", + "columnName": "dateExpires", + "affinity": "TEXT" + }, + { + "fieldPath": "dateExpiresGmt", + "columnName": "dateExpiresGmt", + "affinity": "TEXT" + }, + { + "fieldPath": "usageCount", + "columnName": "usageCount", + "affinity": "INTEGER" + }, + { + "fieldPath": "isForIndividualUse", + "columnName": "isForIndividualUse", + "affinity": "INTEGER" + }, + { + "fieldPath": "usageLimit", + "columnName": "usageLimit", + "affinity": "INTEGER" + }, + { + "fieldPath": "usageLimitPerUser", + "columnName": "usageLimitPerUser", + "affinity": "INTEGER" + }, + { + "fieldPath": "limitUsageToXItems", + "columnName": "limitUsageToXItems", + "affinity": "INTEGER" + }, + { + "fieldPath": "isShippingFree", + "columnName": "isShippingFree", + "affinity": "INTEGER" + }, + { + "fieldPath": "areSaleItemsExcluded", + "columnName": "areSaleItemsExcluded", + "affinity": "INTEGER" + }, + { + "fieldPath": "minimumAmount", + "columnName": "minimumAmount", + "affinity": "TEXT" + }, + { + "fieldPath": "maximumAmount", + "columnName": "maximumAmount", + "affinity": "TEXT" + }, + { + "fieldPath": "includedProductIds", + "columnName": "includedProductIds", + "affinity": "TEXT" + }, + { + "fieldPath": "excludedProductIds", + "columnName": "excludedProductIds", + "affinity": "TEXT" + }, + { + "fieldPath": "includedCategoryIds", + "columnName": "includedCategoryIds", + "affinity": "TEXT" + }, + { + "fieldPath": "excludedCategoryIds", + "columnName": "excludedCategoryIds", + "affinity": "TEXT" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id", + "localSiteId" + ] + } + }, + { + "tableName": "CouponEmails", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`couponId` INTEGER NOT NULL, `localSiteId` INTEGER NOT NULL, `email` TEXT NOT NULL, PRIMARY KEY(`couponId`, `localSiteId`, `email`), FOREIGN KEY(`couponId`, `localSiteId`) REFERENCES `Coupons`(`id`, `localSiteId`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "couponId", + "columnName": "couponId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "email", + "columnName": "email", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "couponId", + "localSiteId", + "email" + ] + }, + "foreignKeys": [ + { + "table": "Coupons", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "couponId", + "localSiteId" + ], + "referencedColumns": [ + "id", + "localSiteId" + ] + } + ] + }, + { + "tableName": "GlobalAddonGroupEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`globalGroupLocalId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `restrictedCategoriesIds` TEXT NOT NULL, `localSiteId` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "globalGroupLocalId", + "columnName": "globalGroupLocalId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "restrictedCategoriesIds", + "columnName": "restrictedCategoriesIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "globalGroupLocalId" + ] + } + }, + { + "tableName": "OrderNotes", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `noteId` INTEGER NOT NULL, `orderId` INTEGER NOT NULL, `dateCreated` TEXT, `note` TEXT, `author` TEXT, `isSystemNote` INTEGER NOT NULL, `isCustomerNote` INTEGER NOT NULL, PRIMARY KEY(`localSiteId`, `noteId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "noteId", + "columnName": "noteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "orderId", + "columnName": "orderId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "TEXT" + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT" + }, + { + "fieldPath": "author", + "columnName": "author", + "affinity": "TEXT" + }, + { + "fieldPath": "isSystemNote", + "columnName": "isSystemNote", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isCustomerNote", + "columnName": "isCustomerNote", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "noteId" + ] + } + }, + { + "tableName": "OrderEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `orderId` INTEGER NOT NULL, `number` TEXT NOT NULL, `status` TEXT NOT NULL, `currency` TEXT NOT NULL, `orderKey` TEXT NOT NULL, `dateCreated` TEXT NOT NULL, `dateModified` TEXT NOT NULL, `total` TEXT NOT NULL, `totalTax` TEXT NOT NULL, `shippingTotal` TEXT NOT NULL, `paymentMethod` TEXT NOT NULL, `paymentMethodTitle` TEXT NOT NULL, `datePaid` TEXT NOT NULL, `pricesIncludeTax` INTEGER NOT NULL, `customerNote` TEXT NOT NULL, `discountTotal` TEXT NOT NULL, `discountCodes` TEXT NOT NULL, `refundTotal` TEXT NOT NULL, `customerId` INTEGER NOT NULL DEFAULT 0, `billingFirstName` TEXT NOT NULL, `billingLastName` TEXT NOT NULL, `billingCompany` TEXT NOT NULL, `billingAddress1` TEXT NOT NULL, `billingAddress2` TEXT NOT NULL, `billingCity` TEXT NOT NULL, `billingState` TEXT NOT NULL, `billingPostcode` TEXT NOT NULL, `billingCountry` TEXT NOT NULL, `billingEmail` TEXT NOT NULL, `billingPhone` TEXT NOT NULL, `shippingFirstName` TEXT NOT NULL, `shippingLastName` TEXT NOT NULL, `shippingCompany` TEXT NOT NULL, `shippingAddress1` TEXT NOT NULL, `shippingAddress2` TEXT NOT NULL, `shippingCity` TEXT NOT NULL, `shippingState` TEXT NOT NULL, `shippingPostcode` TEXT NOT NULL, `shippingCountry` TEXT NOT NULL, `shippingPhone` TEXT NOT NULL, `lineItems` TEXT NOT NULL, `shippingLines` TEXT NOT NULL, `feeLines` TEXT NOT NULL, `taxLines` TEXT NOT NULL, `couponLines` TEXT NOT NULL DEFAULT '', `metaData` TEXT NOT NULL, `paymentUrl` TEXT NOT NULL DEFAULT '', `isEditable` INTEGER NOT NULL DEFAULT 1, `needsPayment` INTEGER, `needsProcessing` INTEGER, `giftCardCode` TEXT NOT NULL DEFAULT '', `giftCardAmount` TEXT NOT NULL DEFAULT '', `shippingTax` TEXT NOT NULL DEFAULT '', `createdVia` TEXT NOT NULL DEFAULT '', PRIMARY KEY(`localSiteId`, `orderId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "orderId", + "columnName": "orderId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "currency", + "columnName": "currency", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "orderKey", + "columnName": "orderKey", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateModified", + "columnName": "dateModified", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "total", + "columnName": "total", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "totalTax", + "columnName": "totalTax", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingTotal", + "columnName": "shippingTotal", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "paymentMethod", + "columnName": "paymentMethod", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "paymentMethodTitle", + "columnName": "paymentMethodTitle", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "datePaid", + "columnName": "datePaid", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pricesIncludeTax", + "columnName": "pricesIncludeTax", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "customerNote", + "columnName": "customerNote", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "discountTotal", + "columnName": "discountTotal", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "discountCodes", + "columnName": "discountCodes", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "refundTotal", + "columnName": "refundTotal", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "customerId", + "columnName": "customerId", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "billingFirstName", + "columnName": "billingFirstName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingLastName", + "columnName": "billingLastName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingCompany", + "columnName": "billingCompany", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingAddress1", + "columnName": "billingAddress1", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingAddress2", + "columnName": "billingAddress2", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingCity", + "columnName": "billingCity", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingState", + "columnName": "billingState", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingPostcode", + "columnName": "billingPostcode", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingCountry", + "columnName": "billingCountry", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingEmail", + "columnName": "billingEmail", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingPhone", + "columnName": "billingPhone", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingFirstName", + "columnName": "shippingFirstName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingLastName", + "columnName": "shippingLastName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingCompany", + "columnName": "shippingCompany", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingAddress1", + "columnName": "shippingAddress1", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingAddress2", + "columnName": "shippingAddress2", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingCity", + "columnName": "shippingCity", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingState", + "columnName": "shippingState", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingPostcode", + "columnName": "shippingPostcode", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingCountry", + "columnName": "shippingCountry", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingPhone", + "columnName": "shippingPhone", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lineItems", + "columnName": "lineItems", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingLines", + "columnName": "shippingLines", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "feeLines", + "columnName": "feeLines", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "taxLines", + "columnName": "taxLines", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "couponLines", + "columnName": "couponLines", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "metaData", + "columnName": "metaData", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "paymentUrl", + "columnName": "paymentUrl", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "isEditable", + "columnName": "isEditable", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "needsPayment", + "columnName": "needsPayment", + "affinity": "INTEGER" + }, + { + "fieldPath": "needsProcessing", + "columnName": "needsProcessing", + "affinity": "INTEGER" + }, + { + "fieldPath": "giftCardCode", + "columnName": "giftCardCode", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "giftCardAmount", + "columnName": "giftCardAmount", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "shippingTax", + "columnName": "shippingTax", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "createdVia", + "columnName": "createdVia", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "orderId" + ] + }, + "indices": [ + { + "name": "index_OrderEntity_localSiteId_orderId", + "unique": false, + "columnNames": [ + "localSiteId", + "orderId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_OrderEntity_localSiteId_orderId` ON `${TABLE_NAME}` (`localSiteId`, `orderId`)" + } + ] + }, + { + "tableName": "RefundEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`siteId` INTEGER NOT NULL, `orderId` INTEGER NOT NULL, `refundId` INTEGER NOT NULL, `data` TEXT NOT NULL, PRIMARY KEY(`siteId`, `orderId`, `refundId`))", + "fields": [ + { + "fieldPath": "siteId", + "columnName": "siteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "orderId", + "columnName": "orderId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "refundId", + "columnName": "refundId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "data", + "columnName": "data", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "siteId", + "orderId", + "refundId" + ] + } + }, + { + "tableName": "MetaData", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `id` INTEGER NOT NULL, `parentItemId` INTEGER NOT NULL, `key` TEXT NOT NULL, `value` TEXT NOT NULL, `type` TEXT NOT NULL DEFAULT 'ORDER', PRIMARY KEY(`localSiteId`, `parentItemId`, `id`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "parentItemId", + "columnName": "parentItemId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "key", + "columnName": "key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "'ORDER'" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "parentItemId", + "id" + ] + } + }, + { + "tableName": "InboxNotes", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `remoteId` INTEGER NOT NULL, `localSiteId` INTEGER NOT NULL, `name` TEXT NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `dateCreated` TEXT NOT NULL, `status` TEXT NOT NULL, `source` TEXT, `type` TEXT, `dateReminder` TEXT)", + "fields": [ + { + "fieldPath": "localId", + "columnName": "localId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteId", + "columnName": "remoteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "source", + "columnName": "source", + "affinity": "TEXT" + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT" + }, + { + "fieldPath": "dateReminder", + "columnName": "dateReminder", + "affinity": "TEXT" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "localId" + ] + }, + "indices": [ + { + "name": "index_InboxNotes_remoteId_localSiteId", + "unique": true, + "columnNames": [ + "remoteId", + "localSiteId" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_InboxNotes_remoteId_localSiteId` ON `${TABLE_NAME}` (`remoteId`, `localSiteId`)" + } + ] + }, + { + "tableName": "InboxNoteActions", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`remoteId` INTEGER NOT NULL, `inboxNoteLocalId` INTEGER NOT NULL, `localSiteId` INTEGER NOT NULL, `name` TEXT NOT NULL, `label` TEXT NOT NULL, `url` TEXT NOT NULL, `query` TEXT, `status` TEXT, `primary` INTEGER NOT NULL, `actionedText` TEXT, PRIMARY KEY(`remoteId`, `inboxNoteLocalId`), FOREIGN KEY(`inboxNoteLocalId`) REFERENCES `InboxNotes`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "remoteId", + "columnName": "remoteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "inboxNoteLocalId", + "columnName": "inboxNoteLocalId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "label", + "columnName": "label", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "query", + "columnName": "query", + "affinity": "TEXT" + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT" + }, + { + "fieldPath": "primary", + "columnName": "primary", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "actionedText", + "columnName": "actionedText", + "affinity": "TEXT" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "remoteId", + "inboxNoteLocalId" + ] + }, + "indices": [ + { + "name": "index_InboxNoteActions_inboxNoteLocalId", + "unique": false, + "columnNames": [ + "inboxNoteLocalId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_InboxNoteActions_inboxNoteLocalId` ON `${TABLE_NAME}` (`inboxNoteLocalId`)" + } + ], + "foreignKeys": [ + { + "table": "InboxNotes", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "inboxNoteLocalId" + ], + "referencedColumns": [ + "localId" + ] + } + ] + }, + { + "tableName": "TopPerformerProducts", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `datePeriod` TEXT NOT NULL, `productId` INTEGER NOT NULL, `name` TEXT NOT NULL, `imageUrl` TEXT, `quantity` INTEGER NOT NULL, `currency` TEXT NOT NULL, `total` REAL NOT NULL, `millisSinceLastUpdated` INTEGER NOT NULL, PRIMARY KEY(`datePeriod`, `productId`, `localSiteId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "datePeriod", + "columnName": "datePeriod", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "productId", + "columnName": "productId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "imageUrl", + "columnName": "imageUrl", + "affinity": "TEXT" + }, + { + "fieldPath": "quantity", + "columnName": "quantity", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "currency", + "columnName": "currency", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "total", + "columnName": "total", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "millisSinceLastUpdated", + "columnName": "millisSinceLastUpdated", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "datePeriod", + "productId", + "localSiteId" + ] + } + }, + { + "tableName": "TaxBasedOnSetting", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `selectedOption` TEXT NOT NULL, PRIMARY KEY(`localSiteId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "selectedOption", + "columnName": "selectedOption", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId" + ] + } + }, + { + "tableName": "TaxRate", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `localSiteId` INTEGER NOT NULL, `country` TEXT, `state` TEXT, `postcode` TEXT, `city` TEXT, `rate` TEXT, `name` TEXT, `taxClass` TEXT, PRIMARY KEY(`id`, `localSiteId`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "country", + "columnName": "country", + "affinity": "TEXT" + }, + { + "fieldPath": "state", + "columnName": "state", + "affinity": "TEXT" + }, + { + "fieldPath": "postcode", + "columnName": "postcode", + "affinity": "TEXT" + }, + { + "fieldPath": "city", + "columnName": "city", + "affinity": "TEXT" + }, + { + "fieldPath": "rate", + "columnName": "rate", + "affinity": "TEXT" + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT" + }, + { + "fieldPath": "taxClass", + "columnName": "taxClass", + "affinity": "TEXT" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id", + "localSiteId" + ] + } + }, + { + "tableName": "WooPaymentsDepositsOverview", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `depositsEnabled` INTEGER, `depositsBlocked` INTEGER, `defaultCurrency` TEXT, `delayDays` INTEGER, `weeklyAnchor` TEXT, `monthlyAnchor` INTEGER, `interval` TEXT, PRIMARY KEY(`localSiteId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "account.depositsEnabled", + "columnName": "depositsEnabled", + "affinity": "INTEGER" + }, + { + "fieldPath": "account.depositsBlocked", + "columnName": "depositsBlocked", + "affinity": "INTEGER" + }, + { + "fieldPath": "account.defaultCurrency", + "columnName": "defaultCurrency", + "affinity": "TEXT" + }, + { + "fieldPath": "account.depositsSchedule.delayDays", + "columnName": "delayDays", + "affinity": "INTEGER" + }, + { + "fieldPath": "account.depositsSchedule.weeklyAnchor", + "columnName": "weeklyAnchor", + "affinity": "TEXT" + }, + { + "fieldPath": "account.depositsSchedule.monthlyAnchor", + "columnName": "monthlyAnchor", + "affinity": "INTEGER" + }, + { + "fieldPath": "account.depositsSchedule.interval", + "columnName": "interval", + "affinity": "TEXT" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId" + ] + } + }, + { + "tableName": "WooPaymentsDeposits", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `localSiteId` INTEGER NOT NULL, `depositId` TEXT, `date` INTEGER, `type` TEXT, `amount` INTEGER, `status` TEXT, `bankAccount` TEXT, `currency` TEXT, `automatic` INTEGER, `fee` INTEGER, `feePercentage` REAL, `created` INTEGER, `depositType` TEXT NOT NULL, FOREIGN KEY(`localSiteId`) REFERENCES `WooPaymentsDepositsOverview`(`localSiteId`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "depositId", + "columnName": "depositId", + "affinity": "TEXT" + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER" + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT" + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "INTEGER" + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT" + }, + { + "fieldPath": "bankAccount", + "columnName": "bankAccount", + "affinity": "TEXT" + }, + { + "fieldPath": "currency", + "columnName": "currency", + "affinity": "TEXT" + }, + { + "fieldPath": "automatic", + "columnName": "automatic", + "affinity": "INTEGER" + }, + { + "fieldPath": "fee", + "columnName": "fee", + "affinity": "INTEGER" + }, + { + "fieldPath": "feePercentage", + "columnName": "feePercentage", + "affinity": "REAL" + }, + { + "fieldPath": "created", + "columnName": "created", + "affinity": "INTEGER" + }, + { + "fieldPath": "depositType", + "columnName": "depositType", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "foreignKeys": [ + { + "table": "WooPaymentsDepositsOverview", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "localSiteId" + ], + "referencedColumns": [ + "localSiteId" + ] + } + ] + }, + { + "tableName": "WooPaymentsManualDeposits", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `localSiteId` INTEGER NOT NULL, `currency` TEXT, `date` INTEGER, FOREIGN KEY(`localSiteId`) REFERENCES `WooPaymentsDepositsOverview`(`localSiteId`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "currency", + "columnName": "currency", + "affinity": "TEXT" + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "foreignKeys": [ + { + "table": "WooPaymentsDepositsOverview", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "localSiteId" + ], + "referencedColumns": [ + "localSiteId" + ] + } + ] + }, + { + "tableName": "WooPaymentsBalance", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `localSiteId` INTEGER NOT NULL, `amount` INTEGER, `currency` TEXT, `fee` INTEGER, `feePercentage` REAL, `net` INTEGER, `balanceType` TEXT NOT NULL, `card` INTEGER, FOREIGN KEY(`localSiteId`) REFERENCES `WooPaymentsDepositsOverview`(`localSiteId`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "INTEGER" + }, + { + "fieldPath": "currency", + "columnName": "currency", + "affinity": "TEXT" + }, + { + "fieldPath": "fee", + "columnName": "fee", + "affinity": "INTEGER" + }, + { + "fieldPath": "feePercentage", + "columnName": "feePercentage", + "affinity": "REAL" + }, + { + "fieldPath": "net", + "columnName": "net", + "affinity": "INTEGER" + }, + { + "fieldPath": "balanceType", + "columnName": "balanceType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sourceTypes.card", + "columnName": "card", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "foreignKeys": [ + { + "table": "WooPaymentsDepositsOverview", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "localSiteId" + ], + "referencedColumns": [ + "localSiteId" + ] + } + ] + }, + { + "tableName": "VisitorSummaryStatsEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `date` TEXT NOT NULL, `granularity` TEXT NOT NULL, `views` INTEGER NOT NULL, `visitors` INTEGER NOT NULL, PRIMARY KEY(`localSiteId`, `date`, `granularity`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "granularity", + "columnName": "granularity", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "views", + "columnName": "views", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "visitors", + "columnName": "visitors", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "date", + "granularity" + ] + } + }, + { + "tableName": "ShippingMethod", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `localSiteId` INTEGER NOT NULL, `title` TEXT NOT NULL, PRIMARY KEY(`localSiteId`, `id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "id" + ] + } + }, + { + "tableName": "CustomerFromAnalytics", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `id` INTEGER NOT NULL, `userId` INTEGER NOT NULL, `avgOrderValue` REAL NOT NULL, `city` TEXT NOT NULL, `country` TEXT NOT NULL, `dateLastActive` TEXT NOT NULL, `dateLastActiveGmt` TEXT NOT NULL, `dateLastOrder` TEXT NOT NULL, `dateRegistered` TEXT NOT NULL, `dateRegisteredGmt` TEXT NOT NULL, `email` TEXT NOT NULL, `name` TEXT NOT NULL, `ordersCount` INTEGER NOT NULL, `postcode` TEXT NOT NULL, `state` TEXT NOT NULL, `totalSpend` REAL NOT NULL, `username` TEXT NOT NULL, PRIMARY KEY(`localSiteId`, `id`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "userId", + "columnName": "userId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "avgOrderValue", + "columnName": "avgOrderValue", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "city", + "columnName": "city", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "country", + "columnName": "country", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateLastActive", + "columnName": "dateLastActive", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateLastActiveGmt", + "columnName": "dateLastActiveGmt", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateLastOrder", + "columnName": "dateLastOrder", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateRegistered", + "columnName": "dateRegistered", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateRegisteredGmt", + "columnName": "dateRegisteredGmt", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "email", + "columnName": "email", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "ordersCount", + "columnName": "ordersCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "postcode", + "columnName": "postcode", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "state", + "columnName": "state", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "totalSpend", + "columnName": "totalSpend", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "username", + "columnName": "username", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "id" + ] + } + }, + { + "tableName": "ProductEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `remoteId` INTEGER NOT NULL, `name` TEXT NOT NULL, `slug` TEXT NOT NULL, `permalink` TEXT NOT NULL, `dateCreated` TEXT NOT NULL, `dateModified` TEXT NOT NULL, `type` TEXT NOT NULL, `status` TEXT NOT NULL, `featured` INTEGER NOT NULL, `catalogVisibility` TEXT NOT NULL, `description` TEXT NOT NULL, `shortDescription` TEXT NOT NULL, `sku` TEXT NOT NULL, `globalUniqueId` TEXT NOT NULL, `price` TEXT NOT NULL, `regularPrice` TEXT NOT NULL, `salePrice` TEXT NOT NULL, `onSale` INTEGER NOT NULL, `totalSales` INTEGER NOT NULL, `purchasable` INTEGER NOT NULL, `dateOnSaleFrom` TEXT NOT NULL, `dateOnSaleTo` TEXT NOT NULL, `dateOnSaleFromGmt` TEXT NOT NULL, `dateOnSaleToGmt` TEXT NOT NULL, `virtual` INTEGER NOT NULL, `downloadable` INTEGER NOT NULL, `downloadLimit` INTEGER NOT NULL, `downloadExpiry` INTEGER NOT NULL, `soldIndividually` INTEGER NOT NULL, `externalUrl` TEXT NOT NULL, `buttonText` TEXT NOT NULL, `taxStatus` TEXT NOT NULL, `taxClass` TEXT NOT NULL, `manageStock` INTEGER NOT NULL, `stockQuantity` REAL NOT NULL, `stockStatus` TEXT NOT NULL, `backorders` TEXT NOT NULL, `backordersAllowed` INTEGER NOT NULL, `backordered` INTEGER NOT NULL, `shippingRequired` INTEGER NOT NULL, `shippingTaxable` INTEGER NOT NULL, `shippingClass` TEXT NOT NULL, `shippingClassId` INTEGER NOT NULL, `reviewsAllowed` INTEGER NOT NULL, `averageRating` TEXT NOT NULL, `ratingCount` INTEGER NOT NULL, `parentId` INTEGER NOT NULL, `purchaseNote` TEXT NOT NULL, `menuOrder` INTEGER NOT NULL, `categories` TEXT NOT NULL, `tags` TEXT NOT NULL, `images` TEXT NOT NULL, `attributes` TEXT NOT NULL, `variations` TEXT NOT NULL, `downloads` TEXT NOT NULL, `relatedIds` TEXT NOT NULL, `crossSellIds` TEXT NOT NULL, `upsellIds` TEXT NOT NULL, `groupedProductIds` TEXT NOT NULL, `weight` TEXT NOT NULL, `length` TEXT NOT NULL, `width` TEXT NOT NULL, `height` TEXT NOT NULL, `bundledItems` TEXT NOT NULL, `compositeComponents` TEXT NOT NULL, `specialStockStatus` TEXT NOT NULL, `bundleMinSize` REAL, `bundleMaxSize` REAL, `minAllowedQuantity` INTEGER NOT NULL, `maxAllowedQuantity` INTEGER NOT NULL, `groupOfQuantity` INTEGER NOT NULL, `combineVariationQuantities` INTEGER NOT NULL, `password` TEXT, `isSampleProduct` INTEGER NOT NULL, PRIMARY KEY(`localSiteId`, `remoteId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteId", + "columnName": "remoteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "slug", + "columnName": "slug", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "permalink", + "columnName": "permalink", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateModified", + "columnName": "dateModified", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "featured", + "columnName": "featured", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "catalogVisibility", + "columnName": "catalogVisibility", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shortDescription", + "columnName": "shortDescription", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sku", + "columnName": "sku", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "globalUniqueId", + "columnName": "globalUniqueId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "price", + "columnName": "price", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "regularPrice", + "columnName": "regularPrice", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "salePrice", + "columnName": "salePrice", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "onSale", + "columnName": "onSale", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "totalSales", + "columnName": "totalSales", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "purchasable", + "columnName": "purchasable", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateOnSaleFrom", + "columnName": "dateOnSaleFrom", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateOnSaleTo", + "columnName": "dateOnSaleTo", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateOnSaleFromGmt", + "columnName": "dateOnSaleFromGmt", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateOnSaleToGmt", + "columnName": "dateOnSaleToGmt", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "virtual", + "columnName": "virtual", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "downloadable", + "columnName": "downloadable", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "downloadLimit", + "columnName": "downloadLimit", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "downloadExpiry", + "columnName": "downloadExpiry", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "soldIndividually", + "columnName": "soldIndividually", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "externalUrl", + "columnName": "externalUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "buttonText", + "columnName": "buttonText", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "taxStatus", + "columnName": "taxStatus", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "taxClass", + "columnName": "taxClass", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "manageStock", + "columnName": "manageStock", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "stockQuantity", + "columnName": "stockQuantity", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "stockStatus", + "columnName": "stockStatus", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "backorders", + "columnName": "backorders", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "backordersAllowed", + "columnName": "backordersAllowed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "backordered", + "columnName": "backordered", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "shippingRequired", + "columnName": "shippingRequired", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "shippingTaxable", + "columnName": "shippingTaxable", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "shippingClass", + "columnName": "shippingClass", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingClassId", + "columnName": "shippingClassId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "reviewsAllowed", + "columnName": "reviewsAllowed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "averageRating", + "columnName": "averageRating", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "ratingCount", + "columnName": "ratingCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "parentId", + "columnName": "parentId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "purchaseNote", + "columnName": "purchaseNote", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "menuOrder", + "columnName": "menuOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "categories", + "columnName": "categories", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "tags", + "columnName": "tags", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "images", + "columnName": "images", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "attributes", + "columnName": "attributes", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "variations", + "columnName": "variations", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "downloads", + "columnName": "downloads", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "relatedIds", + "columnName": "relatedIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "crossSellIds", + "columnName": "crossSellIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "upsellIds", + "columnName": "upsellIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupedProductIds", + "columnName": "groupedProductIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "weight", + "columnName": "weight", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "length", + "columnName": "length", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "width", + "columnName": "width", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "height", + "columnName": "height", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bundledItems", + "columnName": "bundledItems", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "compositeComponents", + "columnName": "compositeComponents", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "specialStockStatus", + "columnName": "specialStockStatus", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bundleMinSize", + "columnName": "bundleMinSize", + "affinity": "REAL" + }, + { + "fieldPath": "bundleMaxSize", + "columnName": "bundleMaxSize", + "affinity": "REAL" + }, + { + "fieldPath": "minAllowedQuantity", + "columnName": "minAllowedQuantity", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "maxAllowedQuantity", + "columnName": "maxAllowedQuantity", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "groupOfQuantity", + "columnName": "groupOfQuantity", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "combineVariationQuantities", + "columnName": "combineVariationQuantities", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "password", + "columnName": "password", + "affinity": "TEXT" + }, + { + "fieldPath": "isSampleProduct", + "columnName": "isSampleProduct", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "remoteId" + ] + } + }, + { + "tableName": "PosProductEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `remoteId` INTEGER NOT NULL, `name` TEXT NOT NULL, `sku` TEXT NOT NULL, `globalUniqueId` TEXT NOT NULL, `type` TEXT NOT NULL, `price` TEXT NOT NULL, `downloadable` INTEGER NOT NULL, `images` TEXT NOT NULL, `attributes` TEXT NOT NULL, `parentId` INTEGER, `status` TEXT NOT NULL, `regularPrice` TEXT NOT NULL, `salePrice` TEXT NOT NULL, `onSale` INTEGER NOT NULL, `description` TEXT NOT NULL, `shortDescription` TEXT NOT NULL, `manageStock` INTEGER NOT NULL, `stockQuantity` REAL, `stockStatus` TEXT NOT NULL, `backordersAllowed` INTEGER NOT NULL, `backordered` INTEGER NOT NULL, `categories` TEXT NOT NULL, `tags` TEXT NOT NULL, `dateModified` TEXT NOT NULL, `variations` TEXT NOT NULL, PRIMARY KEY(`localSiteId`, `remoteId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteId", + "columnName": "remoteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sku", + "columnName": "sku", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "globalUniqueId", + "columnName": "globalUniqueId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "price", + "columnName": "price", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "downloadable", + "columnName": "downloadable", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "images", + "columnName": "images", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "attributes", + "columnName": "attributes", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "parentId", + "columnName": "parentId", + "affinity": "INTEGER" + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "regularPrice", + "columnName": "regularPrice", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "salePrice", + "columnName": "salePrice", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "onSale", + "columnName": "onSale", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shortDescription", + "columnName": "shortDescription", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "manageStock", + "columnName": "manageStock", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "stockQuantity", + "columnName": "stockQuantity", + "affinity": "REAL" + }, + { + "fieldPath": "stockStatus", + "columnName": "stockStatus", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "backordersAllowed", + "columnName": "backordersAllowed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "backordered", + "columnName": "backordered", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "categories", + "columnName": "categories", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "tags", + "columnName": "tags", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateModified", + "columnName": "dateModified", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "variations", + "columnName": "variations", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "remoteId" + ] + } + }, + { + "tableName": "PosVariationEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `remoteProductId` INTEGER NOT NULL, `remoteVariationId` INTEGER NOT NULL, `dateModified` TEXT NOT NULL, `sku` TEXT NOT NULL, `globalUniqueId` TEXT NOT NULL, `variationName` TEXT NOT NULL, `price` TEXT NOT NULL, `regularPrice` TEXT NOT NULL, `salePrice` TEXT NOT NULL, `description` TEXT NOT NULL, `stockQuantity` REAL NOT NULL, `stockStatus` TEXT NOT NULL, `manageStock` INTEGER NOT NULL, `backordered` INTEGER NOT NULL, `attributesJson` TEXT NOT NULL, `imageUrl` TEXT NOT NULL, `status` TEXT NOT NULL, `lastUpdated` TEXT NOT NULL, `downloadable` INTEGER NOT NULL, PRIMARY KEY(`localSiteId`, `remoteProductId`, `remoteVariationId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteProductId", + "columnName": "remoteProductId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteVariationId", + "columnName": "remoteVariationId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateModified", + "columnName": "dateModified", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sku", + "columnName": "sku", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "globalUniqueId", + "columnName": "globalUniqueId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "variationName", + "columnName": "variationName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "price", + "columnName": "price", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "regularPrice", + "columnName": "regularPrice", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "salePrice", + "columnName": "salePrice", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "stockQuantity", + "columnName": "stockQuantity", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "stockStatus", + "columnName": "stockStatus", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "manageStock", + "columnName": "manageStock", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "backordered", + "columnName": "backordered", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "attributesJson", + "columnName": "attributesJson", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "imageUrl", + "columnName": "imageUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastUpdated", + "columnName": "lastUpdated", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "downloadable", + "columnName": "downloadable", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "remoteProductId", + "remoteVariationId" + ] + } + }, + { + "tableName": "ProductCategoryEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `remoteCategoryId` INTEGER NOT NULL, `name` TEXT NOT NULL, `slug` TEXT NOT NULL, `parent` INTEGER NOT NULL, PRIMARY KEY(`localSiteId`, `remoteCategoryId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteCategoryId", + "columnName": "remoteCategoryId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "slug", + "columnName": "slug", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "parent", + "columnName": "parent", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "remoteCategoryId" + ] + } + }, + { + "tableName": "ProductVariationEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `remoteProductId` INTEGER NOT NULL, `remoteVariationId` INTEGER NOT NULL, `dateCreated` TEXT NOT NULL, `dateModified` TEXT NOT NULL, `description` TEXT NOT NULL, `permalink` TEXT NOT NULL, `sku` TEXT NOT NULL, `globalUniqueId` TEXT NOT NULL, `status` TEXT NOT NULL, `price` TEXT NOT NULL, `regularPrice` TEXT NOT NULL, `salePrice` TEXT NOT NULL, `dateOnSaleFrom` TEXT NOT NULL, `dateOnSaleTo` TEXT NOT NULL, `dateOnSaleFromGmt` TEXT NOT NULL, `dateOnSaleToGmt` TEXT NOT NULL, `taxStatus` TEXT NOT NULL, `taxClass` TEXT NOT NULL, `onSale` INTEGER NOT NULL, `purchasable` INTEGER NOT NULL, `virtual` INTEGER NOT NULL, `downloadable` INTEGER NOT NULL, `downloadLimit` INTEGER NOT NULL, `downloadExpiry` INTEGER NOT NULL, `downloads` TEXT NOT NULL, `backorders` TEXT NOT NULL, `backordersAllowed` INTEGER NOT NULL, `backordered` INTEGER NOT NULL, `shippingClass` TEXT NOT NULL, `shippingClassId` INTEGER NOT NULL, `manageStock` INTEGER NOT NULL, `stockQuantity` REAL NOT NULL, `stockStatus` TEXT NOT NULL, `image` TEXT NOT NULL, `weight` TEXT NOT NULL, `length` TEXT NOT NULL, `width` TEXT NOT NULL, `height` TEXT NOT NULL, `minAllowedQuantity` INTEGER NOT NULL, `maxAllowedQuantity` INTEGER NOT NULL, `groupOfQuantity` INTEGER NOT NULL, `overrideProductQuantities` INTEGER NOT NULL, `menuOrder` INTEGER NOT NULL, `attributes` TEXT NOT NULL, `metadata` TEXT, PRIMARY KEY(`localSiteId`, `remoteProductId`, `remoteVariationId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteProductId", + "columnName": "remoteProductId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteVariationId", + "columnName": "remoteVariationId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateModified", + "columnName": "dateModified", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "permalink", + "columnName": "permalink", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sku", + "columnName": "sku", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "globalUniqueId", + "columnName": "globalUniqueId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "price", + "columnName": "price", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "regularPrice", + "columnName": "regularPrice", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "salePrice", + "columnName": "salePrice", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateOnSaleFrom", + "columnName": "dateOnSaleFrom", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateOnSaleTo", + "columnName": "dateOnSaleTo", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateOnSaleFromGmt", + "columnName": "dateOnSaleFromGmt", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateOnSaleToGmt", + "columnName": "dateOnSaleToGmt", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "taxStatus", + "columnName": "taxStatus", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "taxClass", + "columnName": "taxClass", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "onSale", + "columnName": "onSale", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "purchasable", + "columnName": "purchasable", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "virtual", + "columnName": "virtual", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "downloadable", + "columnName": "downloadable", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "downloadLimit", + "columnName": "downloadLimit", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "downloadExpiry", + "columnName": "downloadExpiry", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "downloads", + "columnName": "downloads", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "backorders", + "columnName": "backorders", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "backordersAllowed", + "columnName": "backordersAllowed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "backordered", + "columnName": "backordered", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "shippingClass", + "columnName": "shippingClass", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingClassId", + "columnName": "shippingClassId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "manageStock", + "columnName": "manageStock", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "stockQuantity", + "columnName": "stockQuantity", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "stockStatus", + "columnName": "stockStatus", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "image", + "columnName": "image", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "weight", + "columnName": "weight", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "length", + "columnName": "length", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "width", + "columnName": "width", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "height", + "columnName": "height", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "minAllowedQuantity", + "columnName": "minAllowedQuantity", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "maxAllowedQuantity", + "columnName": "maxAllowedQuantity", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "groupOfQuantity", + "columnName": "groupOfQuantity", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "overrideProductQuantities", + "columnName": "overrideProductQuantities", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "menuOrder", + "columnName": "menuOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "attributes", + "columnName": "attributes", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "metadata", + "columnName": "metadata", + "affinity": "TEXT" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "remoteProductId", + "remoteVariationId" + ] + } + }, + { + "tableName": "ProductTagEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `remoteTagId` INTEGER NOT NULL, `name` TEXT NOT NULL, `slug` TEXT NOT NULL, `description` TEXT NOT NULL, `count` INTEGER NOT NULL, PRIMARY KEY(`localSiteId`, `remoteTagId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteTagId", + "columnName": "remoteTagId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "slug", + "columnName": "slug", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "count", + "columnName": "count", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "remoteTagId" + ] + } + }, + { + "tableName": "ProductShippingClassEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `remoteShippingClassId` INTEGER NOT NULL, `name` TEXT NOT NULL, `slug` TEXT NOT NULL, `description` TEXT NOT NULL, PRIMARY KEY(`localSiteId`, `remoteShippingClassId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteShippingClassId", + "columnName": "remoteShippingClassId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "slug", + "columnName": "slug", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "remoteShippingClassId" + ] + } + }, + { + "tableName": "ProductReviewEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `remoteProductReviewId` INTEGER NOT NULL, `remoteProductId` INTEGER NOT NULL, `dateCreated` TEXT NOT NULL, `status` TEXT NOT NULL, `reviewerName` TEXT NOT NULL, `reviewerEmail` TEXT NOT NULL, `review` TEXT NOT NULL, `rating` INTEGER NOT NULL, `verified` INTEGER NOT NULL, `reviewerAvatarsJson` TEXT NOT NULL, PRIMARY KEY(`localSiteId`, `remoteProductReviewId`, `remoteProductId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteProductReviewId", + "columnName": "remoteProductReviewId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteProductId", + "columnName": "remoteProductId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "reviewerName", + "columnName": "reviewerName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "reviewerEmail", + "columnName": "reviewerEmail", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "review", + "columnName": "review", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "rating", + "columnName": "rating", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "verified", + "columnName": "verified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "reviewerAvatarsJson", + "columnName": "reviewerAvatarsJson", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "remoteProductReviewId", + "remoteProductId" + ] + } + }, + { + "tableName": "ProductSettingsEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `weightUnit` TEXT NOT NULL, `dimensionUnit` TEXT NOT NULL, PRIMARY KEY(`localSiteId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "weightUnit", + "columnName": "weightUnit", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dimensionUnit", + "columnName": "dimensionUnit", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId" + ] + } + }, + { + "tableName": "CustomerEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`stableId` TEXT NOT NULL, `localSiteId` INTEGER NOT NULL, `remoteCustomerId` INTEGER NOT NULL, `avatarUrl` TEXT NOT NULL, `dateCreated` TEXT NOT NULL, `dateCreatedGmt` TEXT NOT NULL, `dateModified` TEXT NOT NULL, `dateModifiedGmt` TEXT NOT NULL, `email` TEXT NOT NULL, `firstName` TEXT NOT NULL, `isPayingCustomer` INTEGER NOT NULL, `lastName` TEXT NOT NULL, `role` TEXT NOT NULL, `username` TEXT NOT NULL, `billingAddress1` TEXT NOT NULL, `billingAddress2` TEXT NOT NULL, `billingCity` TEXT NOT NULL, `billingCompany` TEXT NOT NULL, `billingCountry` TEXT NOT NULL, `billingEmail` TEXT NOT NULL, `billingFirstName` TEXT NOT NULL, `billingLastName` TEXT NOT NULL, `billingPhone` TEXT NOT NULL, `billingPostcode` TEXT NOT NULL, `billingState` TEXT NOT NULL, `shippingAddress1` TEXT NOT NULL, `shippingAddress2` TEXT NOT NULL, `shippingCity` TEXT NOT NULL, `shippingCompany` TEXT NOT NULL, `shippingCountry` TEXT NOT NULL, `shippingFirstName` TEXT NOT NULL, `shippingLastName` TEXT NOT NULL, `shippingPostcode` TEXT NOT NULL, `shippingState` TEXT NOT NULL, `analyticsCustomerId` INTEGER, PRIMARY KEY(`localSiteId`, `stableId`))", + "fields": [ + { + "fieldPath": "stableId", + "columnName": "stableId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteCustomerId", + "columnName": "remoteCustomerId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "avatarUrl", + "columnName": "avatarUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateCreatedGmt", + "columnName": "dateCreatedGmt", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateModified", + "columnName": "dateModified", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateModifiedGmt", + "columnName": "dateModifiedGmt", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "email", + "columnName": "email", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "firstName", + "columnName": "firstName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isPayingCustomer", + "columnName": "isPayingCustomer", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastName", + "columnName": "lastName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "role", + "columnName": "role", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "username", + "columnName": "username", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingAddress1", + "columnName": "billingAddress1", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingAddress2", + "columnName": "billingAddress2", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingCity", + "columnName": "billingCity", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingCompany", + "columnName": "billingCompany", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingCountry", + "columnName": "billingCountry", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingEmail", + "columnName": "billingEmail", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingFirstName", + "columnName": "billingFirstName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingLastName", + "columnName": "billingLastName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingPhone", + "columnName": "billingPhone", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingPostcode", + "columnName": "billingPostcode", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "billingState", + "columnName": "billingState", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingAddress1", + "columnName": "shippingAddress1", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingAddress2", + "columnName": "shippingAddress2", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingCity", + "columnName": "shippingCity", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingCompany", + "columnName": "shippingCompany", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingCountry", + "columnName": "shippingCountry", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingFirstName", + "columnName": "shippingFirstName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingLastName", + "columnName": "shippingLastName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingPostcode", + "columnName": "shippingPostcode", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "shippingState", + "columnName": "shippingState", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "analyticsCustomerId", + "columnName": "analyticsCustomerId", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "stableId" + ] + } + }, + { + "tableName": "LocationEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`parentCode` TEXT NOT NULL, `code` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`parentCode`, `code`))", + "fields": [ + { + "fieldPath": "parentCode", + "columnName": "parentCode", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "code", + "columnName": "code", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "parentCode", + "code" + ] + } + }, + { + "tableName": "OrderShipmentProviderEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `country` TEXT NOT NULL, `carrierName` TEXT NOT NULL, `carrierLink` TEXT NOT NULL, PRIMARY KEY(`localSiteId`, `carrierName`, `country`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "country", + "columnName": "country", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "carrierName", + "columnName": "carrierName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "carrierLink", + "columnName": "carrierLink", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "carrierName", + "country" + ] + } + }, + { + "tableName": "UserEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `remoteUserId` INTEGER NOT NULL, `firstName` TEXT NOT NULL, `lastName` TEXT NOT NULL, `username` TEXT NOT NULL, `email` TEXT NOT NULL, `roles` TEXT NOT NULL, PRIMARY KEY(`localSiteId`, `remoteUserId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteUserId", + "columnName": "remoteUserId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "firstName", + "columnName": "firstName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastName", + "columnName": "lastName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "username", + "columnName": "username", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "email", + "columnName": "email", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "roles", + "columnName": "roles", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "remoteUserId" + ] + } + }, + { + "tableName": "TaxClassEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `name` TEXT NOT NULL, `slug` TEXT NOT NULL, PRIMARY KEY(`localSiteId`, `slug`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "slug", + "columnName": "slug", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "slug" + ] + } + }, + { + "tableName": "SettingsEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `currencyCode` TEXT NOT NULL, `currencyPosition` TEXT NOT NULL, `currencyThousandSeparator` TEXT NOT NULL, `currencyDecimalSeparator` TEXT NOT NULL, `currencyDecimalNumber` INTEGER NOT NULL, `countryCode` TEXT NOT NULL, `stateCode` TEXT NOT NULL, `address` TEXT NOT NULL, `address2` TEXT NOT NULL, `city` TEXT NOT NULL, `postalCode` TEXT NOT NULL, `couponsEnabled` INTEGER NOT NULL, PRIMARY KEY(`localSiteId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "currencyCode", + "columnName": "currencyCode", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "currencyPosition", + "columnName": "currencyPosition", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "currencyThousandSeparator", + "columnName": "currencyThousandSeparator", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "currencyDecimalSeparator", + "columnName": "currencyDecimalSeparator", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "currencyDecimalNumber", + "columnName": "currencyDecimalNumber", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "countryCode", + "columnName": "countryCode", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "stateCode", + "columnName": "stateCode", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "address", + "columnName": "address", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "address2", + "columnName": "address2", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "city", + "columnName": "city", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "postalCode", + "columnName": "postalCode", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "couponsEnabled", + "columnName": "couponsEnabled", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId" + ] + } + }, + { + "tableName": "OrderSummaryEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`siteId` INTEGER NOT NULL, `orderId` INTEGER NOT NULL, `dateCreated` TEXT NOT NULL, PRIMARY KEY(`siteId`, `orderId`))", + "fields": [ + { + "fieldPath": "siteId", + "columnName": "siteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "orderId", + "columnName": "orderId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "siteId", + "orderId" + ] + } + }, + { + "tableName": "OrderStatusEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`siteId` INTEGER NOT NULL, `statusKey` TEXT NOT NULL, `label` TEXT NOT NULL, `statusCount` INTEGER NOT NULL, `position` INTEGER NOT NULL, PRIMARY KEY(`siteId`, `statusKey`))", + "fields": [ + { + "fieldPath": "siteId", + "columnName": "siteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "statusKey", + "columnName": "statusKey", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "label", + "columnName": "label", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "statusCount", + "columnName": "statusCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "position", + "columnName": "position", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "siteId", + "statusKey" + ] + } + }, + { + "tableName": "WooShippingLabelEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `orderId` INTEGER NOT NULL, `labelId` INTEGER NOT NULL, `tracking` TEXT NOT NULL, `refundableAmount` TEXT NOT NULL, `status` TEXT NOT NULL, `created` TEXT, `carrierId` TEXT NOT NULL, `serviceName` TEXT NOT NULL, `commercialInvoiceUrl` TEXT, `isCommercialInvoiceSubmittedElectronically` INTEGER NOT NULL, `packageName` TEXT NOT NULL, `isLetter` INTEGER NOT NULL, `productNames` TEXT NOT NULL, `productIds` TEXT, `shipmentId` TEXT, `receiptItemId` INTEGER NOT NULL, `createdDate` TEXT, `mainReceiptId` INTEGER NOT NULL, `rate` TEXT NOT NULL, `currency` TEXT NOT NULL, `expiryDate` INTEGER NOT NULL, `usedDate` INTEGER, `refund` TEXT, `hazmatCategory` TEXT, `originAddress` TEXT, `destinationAddress` TEXT, PRIMARY KEY(`localSiteId`, `orderId`, `labelId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "orderId", + "columnName": "orderId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "labelId", + "columnName": "labelId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "tracking", + "columnName": "tracking", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "refundableAmount", + "columnName": "refundableAmount", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "created", + "columnName": "created", + "affinity": "TEXT" + }, + { + "fieldPath": "carrierId", + "columnName": "carrierId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "serviceName", + "columnName": "serviceName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "commercialInvoiceUrl", + "columnName": "commercialInvoiceUrl", + "affinity": "TEXT" + }, + { + "fieldPath": "isCommercialInvoiceSubmittedElectronically", + "columnName": "isCommercialInvoiceSubmittedElectronically", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isLetter", + "columnName": "isLetter", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "productNames", + "columnName": "productNames", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "productIds", + "columnName": "productIds", + "affinity": "TEXT" + }, + { + "fieldPath": "shipmentId", + "columnName": "shipmentId", + "affinity": "TEXT" + }, + { + "fieldPath": "receiptItemId", + "columnName": "receiptItemId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdDate", + "columnName": "createdDate", + "affinity": "TEXT" + }, + { + "fieldPath": "mainReceiptId", + "columnName": "mainReceiptId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "rate", + "columnName": "rate", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "currency", + "columnName": "currency", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "expiryDate", + "columnName": "expiryDate", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "usedDate", + "columnName": "usedDate", + "affinity": "INTEGER" + }, + { + "fieldPath": "refund", + "columnName": "refund", + "affinity": "TEXT" + }, + { + "fieldPath": "hazmatCategory", + "columnName": "hazmatCategory", + "affinity": "TEXT" + }, + { + "fieldPath": "originAddress", + "columnName": "originAddress", + "affinity": "TEXT" + }, + { + "fieldPath": "destinationAddress", + "columnName": "destinationAddress", + "affinity": "TEXT" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "orderId", + "labelId" + ] + } + }, + { + "tableName": "WooShippingShipmentEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `orderId` INTEGER NOT NULL, `shipmentId` TEXT NOT NULL, `items` TEXT NOT NULL, PRIMARY KEY(`localSiteId`, `orderId`, `shipmentId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "orderId", + "columnName": "orderId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "shipmentId", + "columnName": "shipmentId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "items", + "columnName": "items", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "orderId", + "shipmentId" + ] + } + }, + { + "tableName": "WooShippingPackagesEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `storeOptions` TEXT NOT NULL, `savedPackages` TEXT NOT NULL, `carrierPackageGroups` TEXT NOT NULL, PRIMARY KEY(`localSiteId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "storeOptions", + "columnName": "storeOptions", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "savedPackages", + "columnName": "savedPackages", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "carrierPackageGroups", + "columnName": "carrierPackageGroups", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId" + ] + } + }, + { + "tableName": "GlobalAttributeEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`siteId` INTEGER NOT NULL, `remoteId` INTEGER NOT NULL, `name` TEXT NOT NULL, `slug` TEXT NOT NULL, `type` TEXT NOT NULL, `orderBy` TEXT NOT NULL, `hasArchives` INTEGER NOT NULL, PRIMARY KEY(`siteId`, `remoteId`))", + "fields": [ + { + "fieldPath": "siteId", + "columnName": "siteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "remoteId", + "columnName": "remoteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "slug", + "columnName": "slug", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "orderBy", + "columnName": "orderBy", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "hasArchives", + "columnName": "hasArchives", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "siteId", + "remoteId" + ] + } + }, + { + "tableName": "GatewayEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`siteId` INTEGER NOT NULL, `gatewayId` TEXT NOT NULL, `data` TEXT NOT NULL, PRIMARY KEY(`siteId`, `gatewayId`))", + "fields": [ + { + "fieldPath": "siteId", + "columnName": "siteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "gatewayId", + "columnName": "gatewayId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "data", + "columnName": "data", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "siteId", + "gatewayId" + ] + } + }, + { + "tableName": "NewVisitorStatsEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `granularity` TEXT NOT NULL, `date` TEXT NOT NULL, `startDate` TEXT NOT NULL, `endDate` TEXT NOT NULL, `quantity` TEXT NOT NULL, `fields` TEXT NOT NULL, `data` TEXT NOT NULL, PRIMARY KEY(`localSiteId`, `granularity`, `date`, `quantity`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "granularity", + "columnName": "granularity", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "startDate", + "columnName": "startDate", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "endDate", + "columnName": "endDate", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "quantity", + "columnName": "quantity", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "fields", + "columnName": "fields", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "data", + "columnName": "data", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "granularity", + "date", + "quantity" + ] + } + }, + { + "tableName": "Bookings", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `localSiteId` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `allDay` INTEGER NOT NULL, `status` TEXT NOT NULL, `cost` TEXT NOT NULL, `currency` TEXT NOT NULL, `customerId` INTEGER NOT NULL, `productId` INTEGER NOT NULL, `resourceId` INTEGER NOT NULL, `dateCreated` INTEGER NOT NULL, `dateModified` INTEGER NOT NULL, `googleCalendarEventId` TEXT NOT NULL, `orderId` INTEGER NOT NULL, `orderItemId` INTEGER NOT NULL, `parentId` INTEGER NOT NULL, `personCounts` TEXT, `localTimezone` TEXT NOT NULL, `attendanceStatus` TEXT NOT NULL DEFAULT '', `note` TEXT NOT NULL DEFAULT '', `order_status` TEXT, `order_product_name` TEXT, `order_customer_billingFirstName` TEXT, `order_customer_billingLastName` TEXT, `order_customer_billingCompany` TEXT, `order_customer_billingAddress1` TEXT, `order_customer_billingAddress2` TEXT, `order_customer_billingCity` TEXT, `order_customer_billingState` TEXT, `order_customer_billingPostcode` TEXT, `order_customer_billingCountry` TEXT, `order_customer_billingEmail` TEXT, `order_customer_billingPhone` TEXT, `order_payment_paymentMethodId` TEXT, `order_payment_paymentMethodTitle` TEXT, `order_payment_subtotal` TEXT, `order_payment_subtotalTax` TEXT, `order_payment_total` TEXT, `order_payment_totalTax` TEXT, PRIMARY KEY(`id`, `localSiteId`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "start", + "columnName": "start", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "end", + "columnName": "end", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "allDay", + "columnName": "allDay", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "cost", + "columnName": "cost", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "currency", + "columnName": "currency", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "customerId", + "columnName": "customerId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "productId", + "columnName": "productId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "resourceId", + "columnName": "resourceId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateCreated", + "columnName": "dateCreated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateModified", + "columnName": "dateModified", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "googleCalendarEventId", + "columnName": "googleCalendarEventId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "orderId", + "columnName": "orderId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "orderItemId", + "columnName": "orderItemId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "parentId", + "columnName": "parentId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "personCounts", + "columnName": "personCounts", + "affinity": "TEXT" + }, + { + "fieldPath": "localTimezone", + "columnName": "localTimezone", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "attendanceStatus", + "columnName": "attendanceStatus", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "order.status", + "columnName": "order_status", + "affinity": "TEXT" + }, + { + "fieldPath": "order.productInfo.name", + "columnName": "order_product_name", + "affinity": "TEXT" + }, + { + "fieldPath": "order.customerInfo.billingFirstName", + "columnName": "order_customer_billingFirstName", + "affinity": "TEXT" + }, + { + "fieldPath": "order.customerInfo.billingLastName", + "columnName": "order_customer_billingLastName", + "affinity": "TEXT" + }, + { + "fieldPath": "order.customerInfo.billingCompany", + "columnName": "order_customer_billingCompany", + "affinity": "TEXT" + }, + { + "fieldPath": "order.customerInfo.billingAddress1", + "columnName": "order_customer_billingAddress1", + "affinity": "TEXT" + }, + { + "fieldPath": "order.customerInfo.billingAddress2", + "columnName": "order_customer_billingAddress2", + "affinity": "TEXT" + }, + { + "fieldPath": "order.customerInfo.billingCity", + "columnName": "order_customer_billingCity", + "affinity": "TEXT" + }, + { + "fieldPath": "order.customerInfo.billingState", + "columnName": "order_customer_billingState", + "affinity": "TEXT" + }, + { + "fieldPath": "order.customerInfo.billingPostcode", + "columnName": "order_customer_billingPostcode", + "affinity": "TEXT" + }, + { + "fieldPath": "order.customerInfo.billingCountry", + "columnName": "order_customer_billingCountry", + "affinity": "TEXT" + }, + { + "fieldPath": "order.customerInfo.billingEmail", + "columnName": "order_customer_billingEmail", + "affinity": "TEXT" + }, + { + "fieldPath": "order.customerInfo.billingPhone", + "columnName": "order_customer_billingPhone", + "affinity": "TEXT" + }, + { + "fieldPath": "order.paymentInfo.paymentMethodId", + "columnName": "order_payment_paymentMethodId", + "affinity": "TEXT" + }, + { + "fieldPath": "order.paymentInfo.paymentMethodTitle", + "columnName": "order_payment_paymentMethodTitle", + "affinity": "TEXT" + }, + { + "fieldPath": "order.paymentInfo.subtotal", + "columnName": "order_payment_subtotal", + "affinity": "TEXT" + }, + { + "fieldPath": "order.paymentInfo.subtotalTax", + "columnName": "order_payment_subtotalTax", + "affinity": "TEXT" + }, + { + "fieldPath": "order.paymentInfo.total", + "columnName": "order_payment_total", + "affinity": "TEXT" + }, + { + "fieldPath": "order.paymentInfo.totalTax", + "columnName": "order_payment_totalTax", + "affinity": "TEXT" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id", + "localSiteId" + ] + } + }, + { + "tableName": "BookingResources", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `localSiteId` INTEGER NOT NULL, `name` TEXT NOT NULL, `qty` INTEGER NOT NULL, `role` TEXT, `email` TEXT, `phoneNumber` TEXT, `imageId` INTEGER NOT NULL, `imageUrl` TEXT, `description` TEXT, PRIMARY KEY(`id`, `localSiteId`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "qty", + "columnName": "qty", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "role", + "columnName": "role", + "affinity": "TEXT" + }, + { + "fieldPath": "email", + "columnName": "email", + "affinity": "TEXT" + }, + { + "fieldPath": "phoneNumber", + "columnName": "phoneNumber", + "affinity": "TEXT" + }, + { + "fieldPath": "imageId", + "columnName": "imageId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "imageUrl", + "columnName": "imageUrl", + "affinity": "TEXT" + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id", + "localSiteId" + ] + } + }, + { + "tableName": "RevenueStatsEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localSiteId` INTEGER NOT NULL, `interval` TEXT NOT NULL, `startDate` TEXT NOT NULL, `endDate` TEXT NOT NULL, `data` TEXT NOT NULL, `total` TEXT NOT NULL, `rangeId` TEXT NOT NULL, PRIMARY KEY(`localSiteId`, `rangeId`))", + "fields": [ + { + "fieldPath": "localSiteId", + "columnName": "localSiteId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "interval", + "columnName": "interval", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "startDate", + "columnName": "startDate", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "endDate", + "columnName": "endDate", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "data", + "columnName": "data", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "total", + "columnName": "total", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "rangeId", + "columnName": "rangeId", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "localSiteId", + "rangeId" + ] + } + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'e94f8b70f90756ca710f86422b5924d6')" + ] + } +} \ No newline at end of file diff --git a/libs/fluxc-plugin/src/androidTest/java/org/wordpress/android/fluxc/persistence/MigrationTests.kt b/libs/fluxc-plugin/src/androidTest/java/org/wordpress/android/fluxc/persistence/MigrationTests.kt index 52cdc653a989..974c1355c2de 100644 --- a/libs/fluxc-plugin/src/androidTest/java/org/wordpress/android/fluxc/persistence/MigrationTests.kt +++ b/libs/fluxc-plugin/src/androidTest/java/org/wordpress/android/fluxc/persistence/MigrationTests.kt @@ -22,6 +22,7 @@ import org.wordpress.android.fluxc.persistence.migrations.MIGRATION_3_4 import org.wordpress.android.fluxc.persistence.migrations.MIGRATION_4_5 import org.wordpress.android.fluxc.persistence.migrations.MIGRATION_5_6 import org.wordpress.android.fluxc.persistence.migrations.MIGRATION_6_7 +import org.wordpress.android.fluxc.persistence.migrations.MIGRATION_71_72 import org.wordpress.android.fluxc.persistence.migrations.MIGRATION_7_8 import org.wordpress.android.fluxc.persistence.migrations.MIGRATION_8_9 import org.wordpress.android.fluxc.persistence.migrations.MIGRATION_9_10 @@ -184,7 +185,7 @@ class MigrationTests { 2, "/$", 11.0, - 1666727639491 + 1666727639491 ) """.trimIndent() ) @@ -331,6 +332,139 @@ class MigrationTests { } } + @Suppress("LongMethod") + @Test + fun testMigration71to72_deduplicates_and_builds_stableId() { + // 1) Create a v71 database and seed legacy rows, including duplicates + helper.createDatabase(TEST_DB, 71).apply { + // Insert two duplicate registered customers (same siteId + remoteCustomerId), differing only by id and username + execSQL( + """ + INSERT INTO CustomerEntity ( + id, localSiteId, remoteCustomerId, avatarUrl, dateCreated, dateCreatedGmt, dateModified, dateModifiedGmt, + email, firstName, isPayingCustomer, lastName, role, username, + billingAddress1, billingAddress2, billingCity, billingCompany, billingCountry, billingEmail, billingFirstName, + billingLastName, billingPhone, billingPostcode, billingState, + shippingAddress1, shippingAddress2, shippingCity, shippingCompany, shippingCountry, shippingFirstName, + shippingLastName, shippingPostcode, shippingState, analyticsCustomerId + ) VALUES ( + 100, 10, 123, '', '', '', '', '', + 'a@example.com', 'A', 0, 'B', '', 'user_low', + '', '', '', '', '', '', '', + '', '', '', '', + '', '', '', '', '', '', + '', '', '', NULL + ) + """.trimIndent() + ) + execSQL( + """ + INSERT INTO CustomerEntity ( + id, localSiteId, remoteCustomerId, avatarUrl, dateCreated, dateCreatedGmt, dateModified, dateModifiedGmt, + email, firstName, isPayingCustomer, lastName, role, username, + billingAddress1, billingAddress2, billingCity, billingCompany, billingCountry, billingEmail, billingFirstName, + billingLastName, billingPhone, billingPostcode, billingState, + shippingAddress1, shippingAddress2, shippingCity, shippingCompany, shippingCountry, shippingFirstName, + shippingLastName, shippingPostcode, shippingState, analyticsCustomerId + ) VALUES ( + 200, 10, 123, '', '', '', '', '', + 'a2@example.com', 'A2', 1, 'B2', '', 'user_high', + '', '', '', '', '', '', '', + '', '', '', '', + '', '', '', '', '', '', + '', '', '', NULL + ) + """.trimIndent() + ) + + // Insert one analytics/guest row (remoteCustomerId = 0, analyticsCustomerId > 0) + execSQL( + """ + INSERT INTO CustomerEntity ( + id, localSiteId, remoteCustomerId, avatarUrl, dateCreated, dateCreatedGmt, dateModified, dateModifiedGmt, + email, firstName, isPayingCustomer, lastName, role, username, + billingAddress1, billingAddress2, billingCity, billingCompany, billingCountry, billingEmail, billingFirstName, + billingLastName, billingPhone, billingPostcode, billingState, + shippingAddress1, shippingAddress2, shippingCity, shippingCompany, shippingCountry, shippingFirstName, + shippingLastName, shippingPostcode, shippingState, analyticsCustomerId + ) VALUES ( + 300, 10, 0, '', '', '', '', '', + 'guest@example.com', 'G', 0, 'U', '', 'guest', + '', '', '', '', '', '', '', + '', '', '', '', + '', '', '', '', '', '', + '', '', '', 555 + ) + """.trimIndent() + ) + + // Insert invalid row (remoteCustomerId = 0, analyticsCustomerId = NULL) + execSQL( + """ + INSERT INTO CustomerEntity ( + id, localSiteId, remoteCustomerId, avatarUrl, dateCreated, dateCreatedGmt, dateModified, dateModifiedGmt, + email, firstName, isPayingCustomer, lastName, role, username, + billingAddress1, billingAddress2, billingCity, billingCompany, billingCountry, billingEmail, billingFirstName, + billingLastName, billingPhone, billingPostcode, billingState, + shippingAddress1, shippingAddress2, shippingCity, shippingCompany, shippingCountry, shippingFirstName, + shippingLastName, shippingPostcode, shippingState, analyticsCustomerId + ) VALUES ( + 400, 10, 0, '', '', '', '', '', + 'a2@example.com', 'A2', 1, 'B2', '', 'user_high', + '', '', '', '', '', '', '', + '', '', '', '', + '', '', '', '', '', '', + '', '', '', NULL + ) + """.trimIndent() + ) + }.close() + + // 2) Run the migration and validate + val migratedDb = helper.runMigrationsAndValidate(TEST_DB, 72, true, MIGRATION_71_72) + + // 3) Query results and assert deduplication and stableId correctness + migratedDb.query( + """ + SELECT stableId, localSiteId, remoteCustomerId, analyticsCustomerId, username + FROM CustomerEntity + ORDER BY stableId + """.trimIndent() + ).use { cursor -> + assertThat(cursor.count).isEqualTo(2) + + // Move to first row (analytics guest): stableId should be site:10|analytics:555 + cursor.moveToFirst() + val stableId1 = cursor.getString(0) + val siteId1 = cursor.getInt(1) + val remoteId1 = cursor.getLong(2) + val analyticsId1 = if (!cursor.isNull(3)) cursor.getLong(3) else null + val username1 = cursor.getString(4) + assertThat(stableId1).isEqualTo("analytics:555") + assertThat(siteId1).isEqualTo(10) + assertThat(remoteId1).isEqualTo(0) + assertThat(analyticsId1).isEqualTo(555) + assertThat(username1).isEqualTo("guest") + + // Move to second row (registered user deduped): stableId should be site:10|wp:123 and username from higher id row + cursor.moveToNext() + val stableId2 = cursor.getString(0) + val siteId2 = cursor.getInt(1) + val remoteId2 = cursor.getLong(2) + val analyticsId2 = if (!cursor.isNull(3)) cursor.getLong(3) else null + val username2 = cursor.getString(4) + assertThat(stableId2).isEqualTo("wp:123") + assertThat(siteId2).isEqualTo(10) + assertThat(remoteId2).isEqualTo(123) + assertThat(analyticsId2).isNull() + // We kept the row with MAX(id)=200, so its username should be 'user_high' + assertThat(username2).isEqualTo("user_high") + + // Verify the invalid row was filtered out + assertThat(cursor.moveToNext()).isFalse + } + } + companion object { private const val TEST_DB = "migration-test" } diff --git a/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/model/customer/WCCustomerModel.kt b/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/model/customer/WCCustomerModel.kt index 19b48eeb92c5..a99abbf6245c 100644 --- a/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/model/customer/WCCustomerModel.kt +++ b/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/model/customer/WCCustomerModel.kt @@ -1,25 +1,26 @@ package org.wordpress.android.fluxc.model.customer import androidx.room.Entity -import androidx.room.PrimaryKey import org.wordpress.android.fluxc.model.LocalOrRemoteId.LocalId import org.wordpress.android.fluxc.model.LocalOrRemoteId.RemoteId /** * Single Woo customer - see https://woocommerce.github.io/woocommerce-rest-api-docs/#customer-properties */ -@Entity(tableName = "CustomerEntity",) -data class WCCustomerModel( +@ConsistentCopyVisibility +@Entity( + tableName = "CustomerEntity", + primaryKeys = ["localSiteId", "stableId"] +) +data class WCCustomerModel internal constructor( /** - * Synthetic primary key used to uniquely identify a customer. - * - * Some customers, such as guest customers from the Analytics API (represented by - * [org.wordpress.android.fluxc.persistence.entity.CustomerFromAnalyticsEntity]), have `remoteCustomerId = 0`, - * which means they cannot be uniquely identified by (remote id x local site id) pair. + * Deterministic primary key used to uniquely identify a customer across refreshes. * - * To ensure uniqueness across both registered and guest customers, this synthetic ID is used. + * Format examples: + * - "wp:" for registered users (remote > 0) + * - "analytics:" for analytics guests */ - @PrimaryKey(autoGenerate = true) val id: Int = 0, + val stableId: String = "", val localSiteId: LocalId = LocalId(0), val remoteCustomerId: RemoteId = RemoteId(0), val avatarUrl: String = "", @@ -54,4 +55,104 @@ data class WCCustomerModel( val shippingPostcode: String = "", val shippingState: String = "", val analyticsCustomerId: Long? = 0 -) +) { + /** + * A secondary constructor used to easily create a WCCustomerModel with stableId generated. + */ + constructor( + localSiteId: LocalId = LocalId(0), + remoteCustomerId: RemoteId = RemoteId(0), + avatarUrl: String = "", + dateCreated: String = "", + dateCreatedGmt: String = "", + dateModified: String = "", + dateModifiedGmt: String = "", + email: String = "", + firstName: String = "", + isPayingCustomer: Boolean = false, + lastName: String = "", + role: String = "", + username: String = "", + billingAddress1: String = "", + billingAddress2: String = "", + billingCity: String = "", + billingCompany: String = "", + billingCountry: String = "", + billingEmail: String = "", + billingFirstName: String = "", + billingLastName: String = "", + billingPhone: String = "", + billingPostcode: String = "", + billingState: String = "", + shippingAddress1: String = "", + shippingAddress2: String = "", + shippingCity: String = "", + shippingCompany: String = "", + shippingCountry: String = "", + shippingFirstName: String = "", + shippingLastName: String = "", + shippingPostcode: String = "", + shippingState: String = "", + analyticsCustomerId: Long? = 0, + ) : this( + stableId = buildStableId(remoteCustomerId.value, analyticsCustomerId), + localSiteId = localSiteId, + remoteCustomerId = remoteCustomerId, + avatarUrl = avatarUrl, + dateCreated = dateCreated, + dateCreatedGmt = dateCreatedGmt, + dateModified = dateModified, + dateModifiedGmt = dateModifiedGmt, + email = email, + firstName = firstName, + isPayingCustomer = isPayingCustomer, + lastName = lastName, + role = role, + username = username, + billingAddress1 = billingAddress1, + billingAddress2 = billingAddress2, + billingCity = billingCity, + billingCompany = billingCompany, + billingCountry = billingCountry, + billingEmail = billingEmail, + billingFirstName = billingFirstName, + billingLastName = billingLastName, + billingPhone = billingPhone, + billingPostcode = billingPostcode, + billingState = billingState, + shippingAddress1 = shippingAddress1, + shippingAddress2 = shippingAddress2, + shippingCity = shippingCity, + shippingCompany = shippingCompany, + shippingCountry = shippingCountry, + shippingFirstName = shippingFirstName, + shippingLastName = shippingLastName, + shippingPostcode = shippingPostcode, + shippingState = shippingState, + analyticsCustomerId = analyticsCustomerId, + ) + + companion object { + /** + * Builds deterministic primary key used to uniquely identify a customer across refreshes. + * + * Format examples: + * - "wp:" for registered users (remote > 0) + * - "analytics:" for analytics guests + * + * @param siteId local site id + * @param remoteId remote customer id + * @param analyticsId analytics customer id + * @return stable id + */ + private fun buildStableId(remoteId: Long?, analyticsId: Long?): String { + val rid = remoteId ?: 0L + return if (rid > 0L) { + "wp:$rid" + } else { + val aid = analyticsId ?: 0L + if (aid > 0L) "analytics:$aid" else "" + } + } + } +} diff --git a/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/persistence/WCAndroidDatabase.kt b/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/persistence/WCAndroidDatabase.kt index 9e465d6db057..47f5b18a6c74 100644 --- a/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/persistence/WCAndroidDatabase.kt +++ b/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/persistence/WCAndroidDatabase.kt @@ -122,11 +122,12 @@ import org.wordpress.android.fluxc.persistence.migrations.MIGRATION_4_5 import org.wordpress.android.fluxc.persistence.migrations.MIGRATION_5_6 import org.wordpress.android.fluxc.persistence.migrations.MIGRATION_62_63 import org.wordpress.android.fluxc.persistence.migrations.MIGRATION_6_7 +import org.wordpress.android.fluxc.persistence.migrations.MIGRATION_71_72 import org.wordpress.android.fluxc.persistence.migrations.MIGRATION_7_8 import org.wordpress.android.fluxc.persistence.migrations.MIGRATION_8_9 import org.wordpress.android.fluxc.persistence.migrations.MIGRATION_9_10 -const val WC_DATABASE_VERSION = 71 +const val WC_DATABASE_VERSION = 72 @Database( version = WC_DATABASE_VERSION, @@ -315,6 +316,7 @@ abstract class WCAndroidDatabase : RoomDatabase(), TransactionExecutor { .addMigrations(MIGRATION_30_31) .addMigrations(MIGRATION_31_32) .addMigrations(MIGRATION_62_63) + .addMigrations(MIGRATION_71_72) .build() } diff --git a/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/persistence/migrations/Migrations.kt b/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/persistence/migrations/Migrations.kt index 2cd5544b9418..e0e69c543300 100644 --- a/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/persistence/migrations/Migrations.kt +++ b/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/persistence/migrations/Migrations.kt @@ -664,6 +664,7 @@ internal val MIGRATION_21_22 = Migration(21, 22) { database -> database.execSQL("CREATE INDEX IF NOT EXISTS `index_AddonEntity_globalGroupLocalId` ON `AddonEntity` (`globalGroupLocalId`)") database.execSQL("CREATE INDEX IF NOT EXISTS `index_InboxNoteActions_inboxNoteLocalId` ON `InboxNoteActions` (`inboxNoteLocalId`)") } + internal class AutoMigration23to24 : AutoMigrationSpec /** @@ -1084,3 +1085,166 @@ internal val MIGRATION_62_63 = object : Migration(62, 63) { db.execSQL("ALTER TABLE PosProductEntity ADD COLUMN variations TEXT NOT NULL DEFAULT ''") } } + +@Suppress("LongMethod") +internal val MIGRATION_71_72 = object : Migration(71, 72) { + override fun migrate(db: SupportSQLiteDatabase) { + // 1) Create new table with the new schema (stableId TEXT PRIMARY KEY) + db.execSQL( + """ + CREATE TABLE IF NOT EXISTS `CustomerEntity_new` ( + `stableId` TEXT NOT NULL, + `localSiteId` INTEGER NOT NULL, + `remoteCustomerId` INTEGER NOT NULL, + `avatarUrl` TEXT NOT NULL, + `dateCreated` TEXT NOT NULL, + `dateCreatedGmt` TEXT NOT NULL, + `dateModified` TEXT NOT NULL, + `dateModifiedGmt` TEXT NOT NULL, + `email` TEXT NOT NULL, + `firstName` TEXT NOT NULL, + `isPayingCustomer` INTEGER NOT NULL, + `lastName` TEXT NOT NULL, + `role` TEXT NOT NULL, + `username` TEXT NOT NULL, + `billingAddress1` TEXT NOT NULL, + `billingAddress2` TEXT NOT NULL, + `billingCity` TEXT NOT NULL, + `billingCompany` TEXT NOT NULL, + `billingCountry` TEXT NOT NULL, + `billingEmail` TEXT NOT NULL, + `billingFirstName` TEXT NOT NULL, + `billingLastName` TEXT NOT NULL, + `billingPhone` TEXT NOT NULL, + `billingPostcode` TEXT NOT NULL, + `billingState` TEXT NOT NULL, + `shippingAddress1` TEXT NOT NULL, + `shippingAddress2` TEXT NOT NULL, + `shippingCity` TEXT NOT NULL, + `shippingCompany` TEXT NOT NULL, + `shippingCountry` TEXT NOT NULL, + `shippingFirstName` TEXT NOT NULL, + `shippingLastName` TEXT NOT NULL, + `shippingPostcode` TEXT NOT NULL, + `shippingState` TEXT NOT NULL, + `analyticsCustomerId` INTEGER, + PRIMARY KEY(`localSiteId`, `stableId`) + ) + """.trimIndent() + ) + + // 2) Build a temporary deduplication table to collapse duplicates that map to the same stableId + db.execSQL( + """ + CREATE TEMP TABLE IF NOT EXISTS `tmpCustomerDedup` ( + `stableId` TEXT NOT NULL PRIMARY KEY, + `keepId` INTEGER NOT NULL + ) + """.trimIndent() + ) + // Populate the dedup table: compute stableId for each old row and keep the row with the highest id per stableId + db.execSQL( + """ + INSERT OR REPLACE INTO `tmpCustomerDedup` (stableId, keepId) + SELECT stableId, MAX(id) AS keepId FROM ( + SELECT `id`, + CASE + WHEN `remoteCustomerId` > 0 THEN 'wp:' || `remoteCustomerId` + WHEN `analyticsCustomerId` IS NOT NULL AND `analyticsCustomerId` > 0 THEN 'analytics:' || `analyticsCustomerId` + END AS `stableId` + FROM `CustomerEntity` + WHERE `remoteCustomerId` > 0 OR (`analyticsCustomerId` IS NOT NULL AND `analyticsCustomerId` > 0) + ) + GROUP BY stableId + """.trimIndent() + ) + + // 3) Backfill by copying only the deduplicated rows from the old table, joining on keepId + db.execSQL( + """ + INSERT INTO `CustomerEntity_new` ( + `stableId`, + `localSiteId`, + `remoteCustomerId`, + `avatarUrl`, + `dateCreated`, + `dateCreatedGmt`, + `dateModified`, + `dateModifiedGmt`, + `email`, + `firstName`, + `isPayingCustomer`, + `lastName`, + `role`, + `username`, + `billingAddress1`, + `billingAddress2`, + `billingCity`, + `billingCompany`, + `billingCountry`, + `billingEmail`, + `billingFirstName`, + `billingLastName`, + `billingPhone`, + `billingPostcode`, + `billingState`, + `shippingAddress1`, + `shippingAddress2`, + `shippingCity`, + `shippingCompany`, + `shippingCountry`, + `shippingFirstName`, + `shippingLastName`, + `shippingPostcode`, + `shippingState`, + `analyticsCustomerId` + ) + SELECT + d.`stableId`, + c.`localSiteId`, + c.`remoteCustomerId`, + c.`avatarUrl`, + c.`dateCreated`, + c.`dateCreatedGmt`, + c.`dateModified`, + c.`dateModifiedGmt`, + c.`email`, + c.`firstName`, + c.`isPayingCustomer`, + c.`lastName`, + c.`role`, + c.`username`, + c.`billingAddress1`, + c.`billingAddress2`, + c.`billingCity`, + c.`billingCompany`, + c.`billingCountry`, + c.`billingEmail`, + c.`billingFirstName`, + c.`billingLastName`, + c.`billingPhone`, + c.`billingPostcode`, + c.`billingState`, + c.`shippingAddress1`, + c.`shippingAddress2`, + c.`shippingCity`, + c.`shippingCompany`, + c.`shippingCountry`, + c.`shippingFirstName`, + c.`shippingLastName`, + c.`shippingPostcode`, + c.`shippingState`, + c.`analyticsCustomerId` + FROM `CustomerEntity` c + INNER JOIN `tmpCustomerDedup` d ON c.`id` = d.`keepId` + """.trimIndent() + ) + + // 4) Clean up temporary dedup table + db.execSQL("DROP TABLE IF EXISTS `tmpCustomerDedup`") + + // 5) Replace old table with new one + db.execSQL("DROP TABLE `CustomerEntity`") + db.execSQL("ALTER TABLE `CustomerEntity_new` RENAME TO `CustomerEntity`") + } +} diff --git a/libs/fluxc-plugin/src/test/java/org/wordpress/android/fluxc/persistence/dao/CustomerDaoTest.kt b/libs/fluxc-plugin/src/test/java/org/wordpress/android/fluxc/persistence/dao/CustomerDaoTest.kt index 95584e8db72d..2e972f7c8979 100644 --- a/libs/fluxc-plugin/src/test/java/org/wordpress/android/fluxc/persistence/dao/CustomerDaoTest.kt +++ b/libs/fluxc-plugin/src/test/java/org/wordpress/android/fluxc/persistence/dao/CustomerDaoTest.kt @@ -63,7 +63,6 @@ class CustomerDaoTest { val storedCustomer = sut.getCustomerByRemoteId(LocalId(site.id), RemoteId(remoteCustomerId)) assertThat(storedCustomer) .usingRecursiveComparison() - .ignoringFields("id") .isEqualTo(expectedCustomer) } @@ -116,7 +115,6 @@ class CustomerDaoTest { val storedCustomers = sut.getCustomersForSite(LocalId(site.id)) assertThat(storedCustomers) .usingRecursiveComparison() - .ignoringFields("id") .isEqualTo(listOf(customerTwo)) } @@ -145,7 +143,6 @@ class CustomerDaoTest { val storedCustomers = sut.getCustomersForSite(LocalId(customerOne.localSiteId.value)) assertThat(storedCustomers) .usingRecursiveComparison() - .ignoringFields("id") .isEqualTo(listOf(customerOne)) } }