Актуальный код

Последняя версия кода

Code.js
/**
 * @OnlyCurrentDoc
 * @author Mikhail Nosaev <m.nosaev@gmail.com>
 * @see {@link https://t.me/nosaev_m Telegram} разработка Google таблиц и GAS скриптов
 * @see {@link https://docs.ozon.ru/api/seller/ Ozon API}
 * Ozon Актуально для версии 306
 */

var service = PropertiesService.getScriptProperties();

const context = {
  service: PropertiesService,
  logRequest: false,
  debug: false,
};

Ozon.context = Object.assign(Ozon.context, {
  ...context,
  storage: Ozon.setStorage({ service: context.service }),
  ...JSON.parse(context.service[Ozon.context.serviceType]().getProperty(Ozon.context.serviceName) || "{}")
});


const Support = Ozon.setSheet("⚙️ Поддержка");
const scriptRows = Ozon.CONFIG.settings.scriptRows;

function onOpen() {
  Ozon.CONFIG.menu.reports();
}

const Seller =
  Ozon.context?.clientId && Ozon.context?.apiKey
    ? Ozon.sellerApi(Ozon.context) : null;

function ozonSetSellerAccess() {
  Ozon.ozonSetSellerAccess();
}

// ####################################################################################################################################
// ЗАКАЗЫ
// ####################################################################################################################################

// начальная дата для выгрузки
const tzoffset = new Date().getTimezoneOffset() * 60000; // смещение в миллисекундах

function fboPostingList() {
  // Список отправлений FBO (заказы)
  // https://docs.ozon.ru/api/seller/#operation/PostingAPI_GetFboPostingList

  const row = scriptRows.fboPostingList;
  const [[dateFrom, dateTo, accumulate, msk, offsetDays]] =
    Support.getRange(`E${row}:I${row}`).getValues();

  Ozon.fboPostingList(Seller, {
    since: dateFrom ? dateFrom.toISOString() : null,
    to: dateTo ? dateTo.toISOString() : null,
    indexesToDelete: [3, 9, 11, 14, 15, 18, 19, 20, 26, 27, 29, 30],
    datesRange: ["C:C"],
    generalRange: ["H:S"],
    numberShortRange: ["L:L"],
    msk,
    offsetDays,
    accumulate, // on ChekBox для накопления
    removeDuplicates: true,
    formulas: [
      `={"Дата UTC+${msk ? "0" : "3"}"; ARRAYFORMULA(IF(INDIRECT("C2:C")="";;
      IF('⚙️ Поддержка'!H7=TRUE;FLOOR(INDIRECT("C2:C"));1*TEXT(INDIRECT("C2:C") + TIME(3;0;0); "DD.MM.YYYY"))))}`
    ],
  });
}

function fbsPostingList() {
  // Список отправлений FBS (заказы)
  // https://docs.ozon.ru/api/seller/#operation/PostingAPI_GetFbsPostingListV3

  const row = scriptRows.fbsPostingList;
  const [[dateFrom, dateTo, accumulate, msk, offsetDays]] =
    Support.getRange(`E${row}:I${row}`).getValues();

  Ozon.fbsPostingList(Seller, {
    since: dateFrom ? dateFrom.toISOString() : null,
    to: dateTo ? dateTo.toISOString() : null,
    indexesToDelete: [
      4, 6, 7, 8, 13, 15, 16, 20, 21, 22, 23, 24, 25, 28, 29, 30, 36, 37,
    ],
    datesRange: ["C:D"],
    generalRange: ["I:U"],
    numberShortRange: ["N:N"],
    msk,
    offsetDays,
    accumulate, // on ChekBox для накопления
    removeDuplicates: true,
    formulas: [
      `={"Дата UTC+${msk ? "0" : "3"}"; ARRAYFORMULA(IF(INDIRECT("C2:C")="";;
      IF('⚙️ Поддержка'!H8=TRUE;FLOOR(INDIRECT("C2:C"));1*TEXT(INDIRECT("C2:C") + TIME(3;0;0); "DD.MM.YYYY"))))}`
    ],
  });
}

// ####################################################################################################################################
// ВОЗВРАТЫ
// ####################################################################################################################################

function fboFbsReturnsList() {
  // Информация о возвратах FBO и FBS
  // https://docs.ozon.ru/api/seller/#operation/returnsList

  const row = scriptRows.fboFbsReturnsList;
  const [[dateFrom, dateTo, return_schema]] =
    Support.getRange(`E${row}:G${row}`).getValues();

  Ozon.fboFbsReturnsList(Seller, {
    logistic_return_date_time_from: dateFrom ? dateFrom.toISOString() : null,
    logistic_return_date_time_to: dateTo ? dateTo.toISOString() : null,
    return_schema,
  });
}

function rfbsReturns() {
  // Список заявок на возврат rFBS
  // https://docs.ozon.ru/api/seller/#operation/RFBSReturnsAPI_ReturnsRfbsListV2
  Ozon.rfbsReturns(Seller, {});
}

function reportReturns() {
  // Отчёт о возвратах (версия 2)
  // https://docs.ozon.ru/api/seller/#operation/ReportAPI_ReportReturnsCreate
  const row = scriptRows.reportReturns;
  const status = Support.getRange(`G${row}`).getValue();
  Ozon.reportReturns(Seller, { status });
}

// ####################################################################################################################################
// ОСТАТКИ
// ####################################################################################################################################

function stocksAll() {
  // Информация о количестве товаров (все)
  // https://docs.ozon.ru/api/seller/#operation/ProductAPI_GetProductInfoStocksV3

  const row = scriptRows.stocksAll;
  const [[exists, accumulate, stockType]] = Support.getRange(`F${row}:H${row}`).getValues();

  Ozon.stocks(Seller, {
    stockType, // склад fbo или fbs, если пусто то все
    accumulate, // on ChekBox для накопления
    aboveZero: true, // остаток > 0
    exists,
  });
}

function analyticsStockOnWarehousesReport() {
  // Отчёт по остаткам и товарам (fbo) (версия 2)
  // https://docs.ozon.ru/api/seller/?utm_source=tg_seller_bot#operation/AnalyticsAPI_AnalyticsGetStockOnWarehousesV2

  const row = scriptRows.analyticsStockOnWarehousesReport;
  const accumulate = Support.getRange(`G${row}`).getValue();

  Ozon.analyticsStockOnWarehousesReport(Seller, {
    accumulate, // on ChekBox для накопления
    clusterNew: true, // добавить столбец кластер
    // formatUpdatedDate: "dd.MM.yyyy", // формат даты обновления
    aboveZero: true, // остатки > 0
  });
}

function analyticsStocks() {
  // Получить аналитику по остаткам
  // https://docs.ozon.ru/api/seller/#operation/AnalyticsAPI_AnalyticsStocks
  Ozon.analyticsStocks(Seller, {});
}

function analyticsTurnoverStocksReport() {
  // Оборачиваемость товара FBO
  // https://docs.ozon.ru/api/seller/#operation/AnalyticsAPI_StocksTurnover
  Ozon.analyticsTurnoverStocksReport(Seller, {});
}

function fboClusterList() {
  // Информация о кластерах и их складах FBO
  // https://docs.ozon.ru/api/seller/#operation/SupplyDraftAPI_DraftClusterList
  Ozon.fboClusterList(Seller);
}

function stocksByWarehouseFbs() {
  // Информация об остатках на складах продавца (FBS и rFBS)
  Ozon.stocksByWarehouseFbs(Seller);
}

function reportWarehouseStock() {
  // Отчёт об остатках на FBS-складе
  // https://docs.ozon.ru/api/seller/#operation/ReportAPI_CreateStockByWarehouseReport
  Ozon.reportWarehouseStock(Seller);
}

function wherehouses() {
  // Список складов FBS
  Ozon.wherehouses(Seller);
}

function warehousesAvailable() {
  // Загруженность складов Ozon
  // https://docs.ozon.ru/api/seller/#operation/SupplierAPI_SupplierAvailableWarehouses
  Ozon.warehousesAvailable(Seller);
}

// ####################################################################################################################################
// ЦЕНЫ
// ####################################################################################################################################

function prices() {
  // Получить информацию о цене товара
  // https://docs.ozon.ru/api/seller/#operation/ProductAPI_GetProductInfoPricesV4

  const row = scriptRows.prices;
  const accumulate = Support.getRange(`G${row}`).getValue();

  Ozon.prices(Seller, {
    // raw: false, // если используем formulas
    accumulate, // on ChekBox для накопления
  });
}

function pricesFull() {
  // Получить информацию о цене товара (все)
  // https://docs.ozon.ru/api/seller/#operation/ProductAPI_GetProductInfoPricesV4
  Ozon.pricesFull(Seller, {});
}

// ####################################################################################################################################
// ТОВАРЫ
// ####################################################################################################################################

function reportProducts() {
  // Отчёт по товарам
  // https://docs.ozon.ru/api/seller/#operation/ReportAPI_CreateCompanyProductsReport
  Ozon.reportProducts(Seller, {});
  productsPhoto();
}

function productsPhoto() {
  // Фото товаров
  // https://docs.ozon.ru/api/seller/#operation/ProductAPI_GetProductInfoV2
  Ozon.productsPhoto(Seller, {});
}

function reportDiscounted() {
  // Отчёт об уценённых товарах
  // https://docs.ozon.ru/api/seller/#operation/ReportAPI_CreateDiscountedReport
  Ozon.reportDiscounted(Seller);
}

// ####################################################################################################################################
// ОТЧЁТЫ
// ####################################################################################################################################

function reportPostingsFbo() {
  // Отчёт об отправлениях
  // https://docs.ozon.ru/api/seller/#operation/ReportAPI_CreateCompanyPostingsReport

  const row = scriptRows.reportPostingsFbo;
  const accumulate = Support.getRange(`G${row}`).getValue();

  Ozon.reportPostings(Seller, {
    accumulate, // on ChekBox для накопления
    delivery_schema: "fbo",
    // minusDays: 90,
    // status_alias: ["delivered"],
  });
}

function reportPostingsFbs() {
  // Отчёт об отправлениях
  // https://docs.ozon.ru/api/seller/#operation/ReportAPI_CreateCompanyPostingsReport

  const row = scriptRows.reportPostingsFbs;
  const accumulate = Support.getRange(`G${row}`).getValue();

  Ozon.reportPostings(Seller, {
    accumulate, // on ChekBox для накопления
    delivery_schema: "fbs",
    // minusDays: 90,
    // status_alias: ["delivered"],
  });
}

function reportCashFlowStatement() {
  // Финансовый отчёт
  // https://docs.ozon.ru/api/seller/#operation/FinanceAPI_FinanceCashFlowStatementList

  const row = scriptRows.reportCashFlowStatement;
  const dateFrom = Support.getRange(`E${row}`).getValue();
  const from = dateFrom
    ? new Date(dateFrom - tzoffset).toISOString()
    : new Date(new Date(2023, 0, 1, 0, 0, 0) - tzoffset).toISOString();

  Ozon.reportCashFlowStatement(Seller, { from });
}

function reportCashFlowStatementWithDetails() {
  // Финансовый отчёт (расшифровка)
  // https://docs.ozon.ru/api/seller/#operation/FinanceAPI_FinanceCashFlowStatementList

  const row = scriptRows.reportCashFlowStatementWithDetails;
  const dateFrom = Support.getRange(`E${row}`).getValue();
  const from = dateFrom
    ? new Date(dateFrom - tzoffset).toISOString()
    : new Date(new Date(2023, 0, 1, 0, 0, 0) - tzoffset).toISOString();

  Ozon.reportCashFlowStatement(Seller, { from, with_details: true });
}

function financeTransactionListLoadGrupped() {
  // Список транзакций
  // https://docs.ozon.ru/api/seller/#operation/FinanceAPI_FinanceTransactionListV3

  const row = scriptRows.financeTransactionListLoadGrupped;
  const [[dateOffsetFrom, dateOffsetTo, accumulate, full, operations]] = Support.getRange(`E${row}:I${row}`).getValues();

  Ozon.financeTransactionListLoadGrupped(Seller, {
    dateOffsetFrom,
    dateOffsetTo,
    accumulate, // on ChekBox для накопления
    full,
    operations,
  });
}

function financeRealizations() {
  // Отчёт о реализации товаров
  // https://docs.ozon.ru/api/seller/#operation/FinanceAPI_GetRealizationReport

  const row = scriptRows.financeRealizations;
  const [[dateFrom, _, accumulate]] = Support.getRange(`E${row}:G${row}`).getValues();

  Ozon.financeRealizations(Seller, {
    dateFrom,
    accumulate, // on ChekBox для накопления
  });
}

function financeRealizationsPostings() {
  // Позаказный отчёт о реализации товаров
  // https://docs.ozon.ru/api/seller/#operation/FinanceAPI_GetRealizationReportV1

  const row = scriptRows.financeRealizations;
  const [[dateFrom, _, accumulate]] = Support.getRange(`E${row}:G${row}`).getValues();

  Ozon.financeRealizationsPostings(Seller, {
    dateFrom,
    accumulate, // on ChekBox для накопления
  });
}

function analyticsDataReport() {
  // Данные аналитики
  // https://docs.ozon.ru/api/seller/#operation/AnalyticsAPI_AnalyticsGetData

  const row = scriptRows.analyticsDataReport;
  let [[accumulate, premium, sales, offsetDays]] = Support.getRange(`E${row}:H${row}`).getValues();

  const sheet = Ozon.setSheet("Данные аналитики");

  // ##############################
  const timeZone = "Europe/Moscow";
  const dateFormat = "yyyy-MM-dd";
  let date_from, date_to;

  // первичная выгрузка
  if (!accumulate && offsetDays > 0) {
    date_from = Utilities.formatDate(
      new Date(new Date().setDate(new Date().getDate() - offsetDays)),
      timeZone,
      dateFormat
    );

    sheet.clearContents();
  }

  date_to = Utilities.formatDate(
    new Date(new Date().setDate(new Date().getDate() - 1)),
    timeZone,
    dateFormat
  );
  // ##############################

  const options = {
    date_from,
    date_to,
    sales: false, // true, если запрос по продажам
    emptyCols: false, // true, удалить пустые столбцы
    sleep: 25000,
  };

  options.key = "day";

  if (premium) {
    options.premium = true;

    if (sales) {
      options.sales = true;
      options.dimension = ["category1", "sku", "day"];
      options.metrics = [
        "ordered_units",
        "revenue",
        "returns",
        "cancellations",
      ];

      options.header = [
        "Категория",
        "Ozon SKU id",
        "Название",
        "Дата",
        "Заказано товаров",
        "Заказано на сумму",
        "Возвращено товаров",
        "Отменено товаров",
        "",
      ];
      options.filters = [
        { key: "ordered_units", op: "GTE", value: "1" },
        { key: "revenue", op: "GTE", value: "0" },
        { key: "returns", op: "GTE", value: "0" },
        { key: "cancellations", op: "GTE", value: "0" },
      ];
    } else {
      options.filters = [{ key: "hits_view", op: "GT", value: "0" }];
    }
  } else {
    options.filters = [{ key: "ordered_units", op: "GTE", value: "1" }];
    options.dimension = ["sku", "day"];
    options.metrics = ["ordered_units", "revenue"];
    options.header = [
      "Ozon SKU id",
      "Название",
      "Дата",
      "Заказано товаров",
      "Заказано на сумму",
    ];
  }

  Ozon.analyticsDataReport(Seller, options);

  if (premium && !sales) {
    sheet.getRange("T:T").setNumberFormat("@");
    sheet.getRange("T1")
      .setFormula(`={"Артикул продавца";ArrayFormula(IF(INDIRECT("C2:C")="";;
        IFNA(IFNA(VLOOKUP(INDIRECT("C2:C");{'Отчёт по товарам'!\$C:\$C\\'Отчёт по товарам'!\$A:\$A};2;0);
        VLOOKUP(INDIRECT("C2:C");{'Отчёт по товарам'!\$D:\$D\\'Отчёт по товарам'!\$A:\$A};2;0));"!!! Удаленный товар")))}`);
  } else if (sales) {
    sheet.getRange("I:I").setNumberFormat("@");
    sheet.getRange("I1")
      .setFormula(`={"Артикул";ArrayFormula(IF(INDIRECT("B2:B")="";;
        IFNA(IFNA(VLOOKUP(INDIRECT("B2:B");{'Отчёт по товарам'!\$C:\$C\\'Отчёт по товарам'!\$A:\$A};2;0);
        VLOOKUP(INDIRECT("B2:B");{'Отчёт по товарам'!\$D:\$D\\'Отчёт по товарам'!\$A:\$A};2;0));"!!! Удаленный товар")))}`);
  } else {
    sheet.getRange("F:F").setNumberFormat("@");
    sheet.getRange("F1")
      .setFormula(`={"Артикул";ArrayFormula(IF(INDIRECT("A2:A")="";;
        IFNA(IFNA(VLOOKUP(INDIRECT("A2:A");{'Отчёт по товарам'!\$C:\$C\\'Отчёт по товарам'!\$A:\$A};2;0);
        VLOOKUP(INDIRECT("A2:A");{'Отчёт по товарам'!\$D:\$D\\'Отчёт по товарам'!\$A:\$A};2;0));"!!! Удаленный товар")))}`);
  }

  SpreadsheetApp.flush();
}

// ####################################################################################################################################
// АКЦИИ
// ####################################################################################################################################

function actionsList() {
  // Список акций
  // https://docs.ozon.ru/api/seller/#operation/Promos
  Ozon.actionsList(Seller);
}

function actionsCandidates() {
  // Список доступных для акции товаров
  // https://docs.ozon.ru/api/seller/#operation/PromosCandidates
  Ozon.actionsCandidates(Seller);
}

function actionsProducts() {
  // Список товаров в акциях
  // https://docs.ozon.ru/api/seller/#operation/PromosProducts
  Ozon.actionsProducts(Seller);
}

// ####################################################################################################################################
// РЕКЛАМА
// ####################################################################################################################################

const utilsPerformance = Ozon.utilsPerformance;

function ozonSetPerformanceAccess() {
  Ozon.ozonSetPerformanceAccess();
}

// const Performance =
//   Ozon.context?.client_id && Ozon.context?.client_secret ?
//     Ozon.performanceApi(Ozon.context) : null;

function pfCampaigns() {
  // Список кампаний
  // https://docs.ozon.ru/api/performance/#operation/ListCampaigns

  const Performance = Ozon.performanceApi(Ozon.context);

  const row = scriptRows.pfCampaigns;
  const type = Support.getRange(`E${row}`).getValue() || null;

  Ozon.pfCampaigns(Performance, {
    advObjectType: utilsPerformance.CampaignObjectTypeReverse[type],
  });
}

function pfLimitsList() {
  // Лимиты ставок для инструментов продвижения
  // https://docs.ozon.ru/api/performance/#operation/GetLimitsList

  const Performance = Ozon.performanceApi(Ozon.context);

  Ozon.pfLimitsList(Performance, {
  });
}

function pfExpense() {
  // Статистика по расходу кампаний
  // https://docs.ozon.ru/api/performance/#operation/GetCampaignExpense

  const Performance = Ozon.performanceApi(Ozon.context);

  const row = scriptRows.pfExpense;
  const [[dateFrom, dateTo]] = Support.getRange(`E${row}:F${row}`).getValues();

  Ozon.pfExpense(Performance, {
    dateFrom,
    dateTo,
  });
}

function pfDaily() {
  // Дневная статистика по кампаниям
  // https://docs.ozon.ru/api/performance/#operation/GetCampaignDailyStats

  const Performance = Ozon.performanceApi(Ozon.context);

  const row = scriptRows.pfDaily;
  const [[dateFrom, dateTo]] = Support.getRange(`E${row}:F${row}`).getValues();

  Ozon.pfDaily(Performance, {
    dateFrom,
    dateTo,
  });
}

function pfSkuProduct() {
  // РК По товарным (Трафареты)
  // https://docs.ozon.ru/api/performance/#operation/ProductCampaignList

  const Performance = Ozon.performanceApi(Ozon.context);

  const row = scriptRows.pfSkuProduct;
  const [[dateFrom, dateTo]] = Support.getRange(`E${row}:F${row}`).getValues();

  Ozon.pfSkuProduct(Performance, {
    dateFrom,
    dateTo,
  });
}

function pfSearchPromoOrders() {
  // РК По заказам (Поисковая промо)
  // https://docs.ozon.ru/api/performance/#operation/SearchPromoOrdersReportSubmitRequest

  const Performance = Ozon.performanceApi(Ozon.context);

  Ozon.pfSearchPromoOrders(Performance);
}

function pfSearchPromoProducts() {
  // РК По товарам (Поисковая промо)
  // https://docs.ozon.ru/api/performance/#operation/SearchPromoProductsReportSubmitRequest

  const Performance = Ozon.performanceApi(Ozon.context);

  Ozon.pfSearchPromoProducts(Performance);
}

function pfStatSku() {
  // РК Статистика (Трафареты)
  // https://docs.ozon.ru/api/performance/#operation/SubmitRequest

  const Performance = Ozon.performanceApi(Ozon.context);

  const row = scriptRows.pfStatSku;
  const [[dateFrom, dateTo]] = Support.getRange(`E${row}:F${row}`).getValues();

  const runSkuInfo = Ozon.pfStat(Performance, {
    dateFrom,
    dateTo,
    advType: "Трафареты",
    updatedAtRange: `H${row}`,
  });

  Ozon.pfStatSkuRun(Performance, {
    runSkuInfo,
  });
}

function pfStatSkuRun() {
  // РК Статистика (Трафареты) долгая загрузка
  // https://docs.ozon.ru/api/performance/#operation/SubmitRequest

  const Performance = Ozon.performanceApi(Ozon.context);

  Ozon.pfStatSkuRun(Performance, {});
}

function pfStatSearchPromo() {
  // РК Статистика (Поисковая промо)
  // https://docs.ozon.ru/api/performance/#operation/SubmitRequest

  const Performance = Ozon.performanceApi(Ozon.context);

  const row = scriptRows.pfStatSearchPromo;
  const [[dateFrom, dateTo]] = Support.getRange(`E${row}:F${row}`).getValues();

  Ozon.pfStat(Performance, {
    dateFrom,
    dateTo,
    advType: "Поисковая промо",
    updatedAtRange: `H${row}`,
  });
}

function pfStatBrendSelf() {
  // РК Статистика (Брендовая полка)
  // https://docs.ozon.ru/api/performance/#operation/SubmitRequest

  const Performance = Ozon.performanceApi(Ozon.context);

  const row = scriptRows.pfStatBrendSelf;
  const [[dateFrom, dateTo]] = Support.getRange(`E${row}:F${row}`).getValues();

  Ozon.pfStat(Performance, {
    dateFrom,
    dateTo,
    advType: "Брендовая полка",
    updatedAtRange: `H${row}`,
  });
}

Last updated