god help me

This commit is contained in:
zman 2025-04-19 22:54:07 -04:00
parent 6178fdd15d
commit 34eac3d954
2864 changed files with 318 additions and 3207 deletions

View File

@ -0,0 +1,86 @@
"""idk lol
Revision ID: 28cfdbde1796
Revises: d4d3f43ce86a
Create Date: 2025-04-19 16:17:07.109451
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision: str = '28cfdbde1796'
down_revision: Union[str, None] = 'd4d3f43ce86a'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index('ix_cost_basis_id', table_name='cost_basis')
op.drop_table('cost_basis')
op.drop_index('ix_cards_id', table_name='cards')
op.drop_index('ix_cards_name', table_name='cards')
op.drop_index('ix_cards_set_name', table_name='cards')
op.drop_index('ix_cards_tcgplayer_sku', table_name='cards')
op.drop_table('cards')
# ### end Alembic commands ###
def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('cards',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('name', sa.VARCHAR(), autoincrement=False, nullable=True),
sa.Column('rarity', sa.VARCHAR(), autoincrement=False, nullable=True),
sa.Column('set_name', sa.VARCHAR(), autoincrement=False, nullable=True),
sa.Column('price', sa.DOUBLE_PRECISION(precision=53), autoincrement=False, nullable=True),
sa.Column('quantity', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('tcgplayer_sku', sa.VARCHAR(), autoincrement=False, nullable=True),
sa.Column('product_line', sa.VARCHAR(), autoincrement=False, nullable=True),
sa.Column('product_name', sa.VARCHAR(), autoincrement=False, nullable=True),
sa.Column('title', sa.VARCHAR(), autoincrement=False, nullable=True),
sa.Column('number', sa.VARCHAR(), autoincrement=False, nullable=True),
sa.Column('condition', sa.VARCHAR(), autoincrement=False, nullable=True),
sa.Column('tcg_market_price', sa.DOUBLE_PRECISION(precision=53), autoincrement=False, nullable=True),
sa.Column('tcg_direct_low', sa.DOUBLE_PRECISION(precision=53), autoincrement=False, nullable=True),
sa.Column('tcg_low_price_with_shipping', sa.DOUBLE_PRECISION(precision=53), autoincrement=False, nullable=True),
sa.Column('tcg_low_price', sa.DOUBLE_PRECISION(precision=53), autoincrement=False, nullable=True),
sa.Column('total_quantity', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('add_to_quantity', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('tcg_marketplace_price', sa.DOUBLE_PRECISION(precision=53), autoincrement=False, nullable=True),
sa.Column('photo_url', sa.VARCHAR(), autoincrement=False, nullable=True),
sa.Column('created_at', postgresql.TIMESTAMP(timezone=True), server_default=sa.text('now()'), autoincrement=False, nullable=True),
sa.Column('updated_at', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=True),
sa.PrimaryKeyConstraint('id', name='cards_pkey')
)
op.create_index('ix_cards_tcgplayer_sku', 'cards', ['tcgplayer_sku'], unique=True)
op.create_index('ix_cards_set_name', 'cards', ['set_name'], unique=False)
op.create_index('ix_cards_name', 'cards', ['name'], unique=False)
op.create_index('ix_cards_id', 'cards', ['id'], unique=False)
op.create_table('cost_basis',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('transaction_item_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('sealed_case_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('sealed_box_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('open_box_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('open_card_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('quantity', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('unit_cost', sa.DOUBLE_PRECISION(precision=53), autoincrement=False, nullable=False),
sa.Column('created_at', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=True),
sa.Column('updated_at', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=True),
sa.Column('deleted_at', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(['open_box_id'], ['open_boxes.id'], name='cost_basis_open_box_id_fkey'),
sa.ForeignKeyConstraint(['open_card_id'], ['open_cards.id'], name='cost_basis_open_card_id_fkey'),
sa.ForeignKeyConstraint(['sealed_box_id'], ['sealed_boxes.id'], name='cost_basis_sealed_box_id_fkey'),
sa.ForeignKeyConstraint(['sealed_case_id'], ['sealed_cases.id'], name='cost_basis_sealed_case_id_fkey'),
sa.ForeignKeyConstraint(['transaction_item_id'], ['transaction_items.id'], name='cost_basis_transaction_item_id_fkey'),
sa.PrimaryKeyConstraint('id', name='cost_basis_pkey')
)
op.create_index('ix_cost_basis_id', 'cost_basis', ['id'], unique=False)
# ### end Alembic commands ###

94
app.log
View File

@ -1,28 +1,66 @@
2025-04-19 13:56:40,410 - INFO - app.main - Application starting up...
2025-04-19 13:56:40,492 - INFO - app.main - Database initialized successfully
2025-04-19 13:56:40,492 - INFO - app.services.service_manager - Service OrderManagementService registered
2025-04-19 13:56:40,492 - INFO - app.services.service_manager - Service TCGPlayerInventoryService registered
2025-04-19 13:56:40,492 - INFO - app.services.service_manager - Service LabelPrinterService registered
2025-04-19 13:56:40,492 - INFO - app.services.service_manager - Service RegularPrinterService registered
2025-04-19 13:56:40,495 - INFO - app.services.service_manager - Service AddressLabelService registered
2025-04-19 13:56:40,497 - INFO - app.services.service_manager - Service PullSheetService registered
2025-04-19 13:56:40,497 - INFO - app.services.service_manager - Service SetLabelService registered
2025-04-19 13:56:40,497 - INFO - app.services.service_manager - Service DataInitializationService registered
2025-04-19 13:56:40,498 - INFO - app.services.service_manager - Service SchedulerService registered
2025-04-19 13:56:40,498 - INFO - app.services.service_manager - Service FileService registered
2025-04-19 13:56:40,498 - INFO - app.services.service_manager - Service TCGCSVService registered
2025-04-19 13:56:40,498 - INFO - app.services.service_manager - Service MTGJSONService registered
2025-04-19 13:56:40,499 - INFO - app.services.service_manager - All services initialized successfully
2025-04-19 13:56:40,499 - INFO - app.services.data_initialization - Starting data initialization process
2025-04-19 13:56:40,499 - INFO - app.services.data_initialization - Data initialization completed
2025-04-19 13:56:40,499 - INFO - app.main - Data initialization results: {}
2025-04-19 13:56:40,499 - INFO - apscheduler.scheduler - Adding job tentatively -- it will be properly scheduled when the scheduler starts
2025-04-19 13:56:40,499 - INFO - app.services.scheduler.base_scheduler - Scheduled task update_open_orders_hourly to run every 3600 seconds
2025-04-19 13:56:40,499 - INFO - apscheduler.scheduler - Adding job tentatively -- it will be properly scheduled when the scheduler starts
2025-04-19 13:56:40,499 - INFO - app.services.scheduler.base_scheduler - Scheduled task update_all_orders_daily to run every 86400 seconds
2025-04-19 13:56:40,499 - INFO - apscheduler.scheduler - Added job "SchedulerService.start_scheduled_tasks.<locals>.<lambda>" to job store "default"
2025-04-19 13:56:40,500 - INFO - apscheduler.scheduler - Added job "SchedulerService.start_scheduled_tasks.<locals>.<lambda>" to job store "default"
2025-04-19 13:56:40,500 - INFO - apscheduler.scheduler - Scheduler started
2025-04-19 13:56:40,500 - INFO - app.services.scheduler.base_scheduler - Scheduler started
2025-04-19 13:56:40,500 - INFO - app.services.scheduler.scheduler_service - All scheduled tasks started
2025-04-19 13:56:40,500 - INFO - app.main - Scheduler started successfully
2025-04-19 21:40:53,869 - INFO - app.main - Application starting up...
2025-04-19 21:40:53,914 - INFO - app.main - Database initialized successfully
2025-04-19 21:40:53,914 - INFO - app.services.service_manager - Service OrderManagementService registered
2025-04-19 21:40:53,914 - INFO - app.services.service_manager - Service TCGPlayerInventoryService registered
2025-04-19 21:40:53,915 - INFO - app.services.service_manager - Service LabelPrinterService registered
2025-04-19 21:40:53,915 - INFO - app.services.service_manager - Service RegularPrinterService registered
2025-04-19 21:40:53,918 - INFO - app.services.service_manager - Service AddressLabelService registered
2025-04-19 21:40:53,920 - INFO - app.services.service_manager - Service PullSheetService registered
2025-04-19 21:40:53,920 - INFO - app.services.service_manager - Service SetLabelService registered
2025-04-19 21:40:53,920 - INFO - app.services.service_manager - Service DataInitializationService registered
2025-04-19 21:40:53,920 - DEBUG - tzlocal - /etc/localtime found
2025-04-19 21:40:53,921 - DEBUG - tzlocal - 1 found:
{'/etc/localtime is a symlink to': 'US/Michigan'}
2025-04-19 21:40:53,921 - INFO - app.services.service_manager - Service SchedulerService registered
2025-04-19 21:40:53,921 - INFO - app.services.service_manager - Service FileService registered
2025-04-19 21:40:53,921 - INFO - app.services.service_manager - Service TCGCSVService registered
2025-04-19 21:40:53,921 - INFO - app.services.service_manager - Service MTGJSONService registered
2025-04-19 21:40:53,921 - INFO - app.services.service_manager - All services initialized successfully
2025-04-19 21:40:53,921 - INFO - app.services.data_initialization - Starting data initialization process
2025-04-19 21:40:53,921 - INFO - app.services.data_initialization - Initializing MTGJSON data...
2025-04-19 21:40:53,921 - INFO - app.services.data_initialization - Starting MTGJSON initialization
2025-04-19 21:40:53,947 - DEBUG - app.services.external_api.mtgjson.mtgjson_service - Loaded SKUs from cache: app/data/cache/mtgjson/skus/TcgplayerSkus.json
2025-04-19 22:38:54,248 - INFO - app.services.data_initialization - Data initialization completed
2025-04-19 22:38:54,249 - INFO - app.main - Data initialization results: {'mtgjson': {'identifiers_processed': 0, 'skus_processed': 4764017}}
2025-04-19 22:38:54,249 - INFO - apscheduler.scheduler - Adding job tentatively -- it will be properly scheduled when the scheduler starts
2025-04-19 22:38:54,249 - INFO - app.services.scheduler.base_scheduler - Scheduled task update_open_orders_hourly to run every 3600 seconds
2025-04-19 22:38:54,249 - INFO - apscheduler.scheduler - Adding job tentatively -- it will be properly scheduled when the scheduler starts
2025-04-19 22:38:54,249 - INFO - app.services.scheduler.base_scheduler - Scheduled task update_all_orders_daily to run every 86400 seconds
2025-04-19 22:38:54,250 - INFO - apscheduler.scheduler - Added job "SchedulerService.start_scheduled_tasks.<locals>.<lambda>" to job store "default"
2025-04-19 22:38:54,250 - INFO - apscheduler.scheduler - Added job "SchedulerService.start_scheduled_tasks.<locals>.<lambda>" to job store "default"
2025-04-19 22:38:54,250 - INFO - apscheduler.scheduler - Scheduler started
2025-04-19 22:38:54,250 - INFO - app.services.scheduler.base_scheduler - Scheduler started
2025-04-19 22:38:54,250 - INFO - app.services.scheduler.scheduler_service - All scheduled tasks started
2025-04-19 22:38:54,250 - INFO - app.main - Scheduler started successfully
2025-04-19 22:38:54,251 - DEBUG - apscheduler.scheduler - Looking for jobs to run
2025-04-19 22:38:54,251 - DEBUG - apscheduler.scheduler - Next wakeup is due at 2025-04-19 23:38:54.249141-04:00 (in 3599.997778 seconds)
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service MTGJSONService cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service mtgjson cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service TCGCSVService cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service tcgcsv cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service FileService cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service file cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.scheduler.base_scheduler - Scheduler stopped
2025-04-19 22:53:56,053 - INFO - app.services.scheduler.scheduler_service - Scheduler services closed
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service SchedulerService cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.scheduler.scheduler_service - Scheduler services closed
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service scheduler cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service DataInitializationService cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service data_initialization cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service SetLabelService cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service set_label cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service PullSheetService cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service pull_sheet cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service AddressLabelService cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service address_label cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service RegularPrinterService cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service regular_printer cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service LabelPrinterService cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service label_printer cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service TCGPlayerInventoryService cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service tcgplayer_inventory cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service OrderManagementService cleaned up
2025-04-19 22:53:56,053 - INFO - app.services.service_manager - Service order_management cleaned up
2025-04-19 22:53:56,054 - INFO - app.services.service_manager - All services cleaned up successfully
2025-04-19 22:53:56,054 - INFO - app.main - All services cleaned up successfully
2025-04-19 22:53:56,054 - INFO - apscheduler.scheduler - Scheduler has been shut down

View File

@ -30,7 +30,7 @@ file_handler.setFormatter(formatter)
# Configure root logger
root_logger = logging.getLogger()
root_logger.setLevel(logging.INFO)
root_logger.setLevel(logging.DEBUG)
root_logger.addHandler(console_handler)
root_logger.addHandler(file_handler)
@ -58,7 +58,7 @@ async def lifespan(app: FastAPI):
db = SessionLocal()
try:
data_init_service = service_manager.get_service('data_initialization')
data_init = await data_init_service.initialize_data(db, game_ids=[1, 3], use_cache=False, init_categories=False, init_products=False, init_groups=False, init_archived_prices=False, init_mtgjson=False, archived_prices_start_date="2024-03-05", archived_prices_end_date="2025-04-17")
data_init = await data_init_service.initialize_data(db, game_ids=[1, 3], use_cache=True, init_categories=False, init_products=False, init_groups=False, init_archived_prices=False, init_mtgjson=True, archived_prices_start_date="2024-03-05", archived_prices_end_date="2025-04-17")
logger.info(f"Data initialization results: {data_init}")
# Start the scheduler

View File

@ -6,8 +6,7 @@ from app.models.inventory_management import (
OpenEvent,
Vendor,
Customer,
Transaction,
CostBasis
Transaction
)
from app.models.mtgjson_card import MTGJSONCard
from app.models.mtgjson_sku import MTGJSONSKU
@ -34,7 +33,6 @@ __all__ = [
'Vendor',
'Customer',
'Transaction',
'CostBasis',
'MTGJSONCard',
'MTGJSONSKU',
'Product',

View File

@ -1,8 +1,4 @@
from pydantic import BaseModel, ConfigDict
from typing import List, Optional
from datetime import datetime
from sqlalchemy import Column, Integer, String, DateTime, JSON
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from app.db.database import Base

View File

@ -1,4 +1,4 @@
from sqlalchemy import Column, Integer, String, Float, DateTime, ForeignKey, Table
from sqlalchemy import Column, Integer, String, Float, DateTime, ForeignKey
from sqlalchemy.orm import relationship
from app.db.database import Base
@ -32,7 +32,7 @@ class SealedCase(PhysicalItem):
}
# Relationships
boxes = relationship("SealedBox", back_populates="case")
boxes = relationship("SealedBox", back_populates="case", foreign_keys="[SealedBox.case_id]")
open_event = relationship("OpenEvent", uselist=False, back_populates="sealed_case")
class SealedBox(PhysicalItem):
@ -46,7 +46,7 @@ class SealedBox(PhysicalItem):
}
# Relationships
case = relationship("SealedCase", back_populates="boxes")
case = relationship("SealedCase", back_populates="boxes", foreign_keys=[case_id])
open_event = relationship("OpenEvent", uselist=False, back_populates="sealed_box")
class OpenBox(PhysicalItem):
@ -62,8 +62,8 @@ class OpenBox(PhysicalItem):
# Relationships
open_event = relationship("OpenEvent", back_populates="resulting_boxes")
sealed_box = relationship("SealedBox")
cards = relationship("OpenCard", back_populates="box")
sealed_box = relationship("SealedBox", foreign_keys=[sealed_box_id])
cards = relationship("OpenCard", back_populates="box", foreign_keys="[OpenCard.box_id]")
class OpenCard(PhysicalItem):
__tablename__ = "open_cards"
@ -78,7 +78,7 @@ class OpenCard(PhysicalItem):
# Relationships
open_event = relationship("OpenEvent", back_populates="resulting_cards")
box = relationship("OpenBox", back_populates="cards")
box = relationship("OpenBox", back_populates="cards", foreign_keys=[box_id])
class InventoryItem(Base):
__tablename__ = "inventory_items"
@ -93,8 +93,8 @@ class InventoryItem(Base):
# Relationships
physical_item = relationship("PhysicalItem", back_populates="inventory_item")
parent = relationship("InventoryItem", remote_side=[id])
children = relationship("InventoryItem")
parent = relationship("InventoryItem", remote_side=[id], back_populates="children")
children = relationship("InventoryItem", back_populates="parent", overlaps="parent")
class TransactionItem(Base):
__tablename__ = "transaction_items"
@ -160,26 +160,4 @@ class Transaction(Base):
deleted_at = Column(DateTime(timezone=True), nullable=True)
# Relationships
transaction_items = relationship("TransactionItem", back_populates="transaction")
class CostBasis(Base):
__tablename__ = "cost_basis"
id = Column(Integer, primary_key=True, index=True)
transaction_item_id = Column(Integer, ForeignKey("transaction_items.id"))
sealed_case_id = Column(Integer, ForeignKey("sealed_cases.id"), nullable=True)
sealed_box_id = Column(Integer, ForeignKey("sealed_boxes.id"), nullable=True)
open_box_id = Column(Integer, ForeignKey("open_boxes.id"), nullable=True)
open_card_id = Column(Integer, ForeignKey("open_cards.id"), nullable=True)
quantity = Column(Integer, nullable=False, default=1)
unit_cost = Column(Float, nullable=False)
created_at = Column(DateTime(timezone=True))
updated_at = Column(DateTime(timezone=True))
deleted_at = Column(DateTime(timezone=True), nullable=True)
# Relationships
transaction_item = relationship("TransactionItem")
sealed_case = relationship("SealedCase")
sealed_box = relationship("SealedBox")
open_box = relationship("OpenBox")
open_card = relationship("OpenCard")
transaction_items = relationship("TransactionItem", back_populates="transaction")

View File

@ -1,17 +1,13 @@
from fastapi import APIRouter, HTTPException, Depends, Query, UploadFile, File
from fastapi import APIRouter, HTTPException, Depends, UploadFile, File
from typing import List
from datetime import datetime
from enum import Enum
from app.schemas.tcgplayer import TCGPlayerAPIOrderSummary, TCGPlayerAPIOrder
from app.schemas.generate import GenerateAddressLabelsRequest, GeneratePackingSlipsRequest, GeneratePullSheetsRequest, GenerateResponse, GenerateReturnLabelsRequest
from app.schemas.file import FileUpload
from app.services.service_manager import ServiceManager
from app.services.file_service import FileService
from sqlalchemy.orm import Session
from app.db.database import get_db
import os
import tempfile
import logging
from datetime import datetime
logger = logging.getLogger(__name__)
@ -223,3 +219,24 @@ async def print_pirate_ship_label(
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to print Pirate Ship label: {str(e)}")
@router.post("/process-manabox-csv")
async def process_manabox_csv(
file: UploadFile = File(...),
db: Session = Depends(get_db)
) -> GenerateResponse:
try:
# ensure csv
if file.content_type != "text/csv":
raise HTTPException(status_code=400, detail="File must be a CSV")
# read file
content = await file.read()
# save file
file_service = service_manager.get_service('file')
stored_file = await file_service.save_file(db, content, f'manabox_upload_{datetime.now().strftime("%Y%m%d_%H%M%S")}.csv', "manabox_csvs", "csv")
# process csv
manabox_service = service_manager.get_service('manabox')
success = await manabox_service.process_manabox_csv(db, stored_file)
return {"success": success, "message": "Manabox CSV processed successfully"}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to process Manabox CSV: {str(e)}")

View File

@ -1,7 +1,7 @@
import os
import json
from datetime import datetime, timedelta
from typing import Optional, List, Dict, Any, Union, Generator, Callable
from typing import Optional, List, Dict, Any, Union, Generator, Callable, AsyncGenerator
from sqlalchemy.orm import Session
from app.models.tcgplayer_group import TCGPlayerGroup
from app.models.tcgplayer_product import TCGPlayerProduct
@ -462,111 +462,37 @@ class DataInitializationService(BaseService):
identifiers_count = 0
skus_count = 0
# Process identifiers
if use_cache:
cached_file = await self.file_service.get_file_by_filename(db, "mtgjson_identifiers.json")
if cached_file and os.path.exists(cached_file.path):
logger.info("MTGJSON identifiers initialized from cache")
identifiers_count = await self._process_streamed_data(
db,
self._stream_json_file(cached_file.path),
"mtgjson_identifiers.json",
"mtgjson",
self.sync_mtgjson_identifiers
)
else:
logger.info("Downloading MTGJSON identifiers from API")
identifiers_count = await self._process_streamed_data(
db,
await mtgjson_service.get_identifiers(db),
"mtgjson_identifiers.json",
"mtgjson",
self.sync_mtgjson_identifiers
)
else:
logger.info("Downloading MTGJSON identifiers from API")
identifiers_count = await self._process_streamed_data(
db,
await mtgjson_service.get_identifiers(db),
"mtgjson_identifiers.json",
"mtgjson",
self.sync_mtgjson_identifiers
)
# Get identifiers data
identifiers_data = await mtgjson_service.get_identifiers(db, use_cache)
if identifiers_data and "data" in identifiers_data:
identifiers_count = await self.sync_mtgjson_identifiers(db, list(identifiers_data["data"].values()))
# Process SKUs
if use_cache:
cached_file = await self.file_service.get_file_by_filename(db, "mtgjson_skus.json")
if cached_file and os.path.exists(cached_file.path):
logger.info("MTGJSON SKUs initialized from cache")
skus_count = await self._process_streamed_data(
db,
self._stream_json_file(cached_file.path),
"mtgjson_skus.json",
"mtgjson",
self.sync_mtgjson_skus
)
else:
logger.info("Downloading MTGJSON SKUs from API")
skus_count = await self._process_streamed_data(
db,
await mtgjson_service.get_skus(db),
"mtgjson_skus.json",
"mtgjson",
self.sync_mtgjson_skus
)
else:
logger.info("Downloading MTGJSON SKUs from API")
skus_count = await self._process_streamed_data(
db,
await mtgjson_service.get_skus(db),
"mtgjson_skus.json",
"mtgjson",
self.sync_mtgjson_skus
)
# Get SKUs data
skus_data = await mtgjson_service.get_skus(db, use_cache)
if skus_data and "data" in skus_data:
skus_count = await self.sync_mtgjson_skus(db, list(skus_data["data"].values()))
return {
"identifiers_processed": identifiers_count,
"skus_processed": skus_count
}
async def _process_streamed_data(
self,
db: Session,
data_stream: Generator[Dict[str, Any], None, None],
filename: str,
subdir: str,
sync_func: Callable
) -> int:
"""Process streamed data and sync to database"""
count = 0
items = []
batch_size = 1000
for item in data_stream:
if item["type"] == "meta":
# Handle meta data separately
continue
count += 1
items.append(item["data"])
# Process in batches
if len(items) >= batch_size:
await sync_func(db, items)
items = []
# Process any remaining items
if items:
await sync_func(db, items)
return count
async def sync_mtgjson_identifiers(self, db: Session, identifiers_data: dict):
async def sync_mtgjson_identifiers(self, db: Session, identifiers_data: List[dict]) -> int:
"""Sync MTGJSON identifiers data to the database"""
from app.models.mtgjson_card import MTGJSONCard
count = 0
with transaction(db):
for card_id, card_data in identifiers_data.items():
for card_data in identifiers_data:
if not isinstance(card_data, dict):
logger.debug(f"Skipping non-dict item: {card_data}")
continue
card_id = card_data.get("uuid")
if not card_id:
logger.debug(f"Skipping item without UUID: {card_data}")
continue
existing_card = db.query(MTGJSONCard).filter(MTGJSONCard.card_id == card_id).first()
if existing_card:
# Update existing card
@ -636,53 +562,47 @@ class DataInitializationService(BaseService):
tnt_id=card_data.get("identifiers", {}).get("tntId")
)
db.add(new_card)
count += 1
async def sync_mtgjson_skus(self, db: Session, skus_data: dict):
return count
async def sync_mtgjson_skus(self, db: Session, skus_data: List[List[dict]]) -> int:
"""Sync MTGJSON SKUs data to the database"""
from app.models.mtgjson_sku import MTGJSONSKU
count = 0
with transaction(db):
for card_uuid, sku_list in skus_data.items():
for sku in sku_list:
# Handle case where sku is a string (skuId)
if isinstance(sku, str):
sku_id = sku
existing_sku = db.query(MTGJSONSKU).filter(MTGJSONSKU.sku_id == sku_id).first()
if existing_sku:
# Update existing SKU
existing_sku.card_id = card_uuid
else:
new_sku = MTGJSONSKU(
sku_id=sku_id,
card_id=card_uuid
)
db.add(new_sku)
# Handle case where sku is a dictionary
for product_data in skus_data:
for sku_data in product_data:
sku_id = sku_data.get("skuId")
if not sku_id:
logger.debug(f"Skipping item without SKU ID: {sku_data}")
continue
existing_sku = db.query(MTGJSONSKU).filter(MTGJSONSKU.sku_id == str(sku_id)).first()
if existing_sku:
# Update existing SKU
for key, value in {
"product_id": sku_data.get("productId"),
"condition": sku_data.get("condition"),
"finish": sku_data.get("finish"),
"language": sku_data.get("language"),
"printing": sku_data.get("printing"),
}.items():
setattr(existing_sku, key, value)
else:
sku_id = str(sku.get("skuId"))
existing_sku = db.query(MTGJSONSKU).filter(MTGJSONSKU.sku_id == sku_id).first()
if existing_sku:
# Update existing SKU
for key, value in {
"product_id": str(sku.get("productId")),
"condition": sku.get("condition"),
"finish": sku.get("finish"),
"language": sku.get("language"),
"printing": sku.get("printing"),
"card_id": card_uuid
}.items():
setattr(existing_sku, key, value)
else:
new_sku = MTGJSONSKU(
sku_id=sku_id,
product_id=str(sku.get("productId")),
condition=sku.get("condition"),
finish=sku.get("finish"),
language=sku.get("language"),
printing=sku.get("printing"),
card_id=card_uuid
)
db.add(new_sku)
new_sku = MTGJSONSKU(
sku_id=sku_id,
product_id=sku_data.get("productId"),
condition=sku_data.get("condition"),
finish=sku_data.get("finish"),
language=sku_data.get("language"),
printing=sku_data.get("printing"),
)
db.add(new_sku)
count += 1
return count
async def initialize_data(
self,

View File

@ -2,7 +2,8 @@ import os
import json
import zipfile
import time
from typing import Dict, Any, Optional, Generator
import shutil
from typing import Dict, Any, Optional
from sqlalchemy.orm import Session
from app.services.external_api.base_external_service import BaseExternalService
from app.schemas.file import FileInDB
@ -11,32 +12,10 @@ import logging
logger = logging.getLogger(__name__)
class MTGJSONService(BaseExternalService):
def __init__(self, cache_dir: str = "app/data/cache/mtgjson"):
def __init__(self):
super().__init__(base_url="https://mtgjson.com/api/v5/")
# Ensure the cache directory exists
os.makedirs(cache_dir, exist_ok=True)
self.cache_dir = cache_dir
self.identifiers_dir = os.path.join(cache_dir, "identifiers")
self.skus_dir = os.path.join(cache_dir, "skus")
# Ensure subdirectories exist
os.makedirs(self.identifiers_dir, exist_ok=True)
os.makedirs(self.skus_dir, exist_ok=True)
def _format_progress(self, current: int, total: int, start_time: float) -> str:
"""Format a progress message with percentage and timing information"""
elapsed = time.time() - start_time
if total > 0:
percent = (current / total) * 100
items_per_second = current / elapsed if elapsed > 0 else 0
eta = (total - current) / items_per_second if items_per_second > 0 else 0
return f"[{current}/{total} ({percent:.1f}%)] {items_per_second:.1f} items/sec, ETA: {eta:.1f}s"
return f"[{current} items] {current/elapsed:.1f} items/sec"
def _print_progress(self, message: str, end: str = "\n") -> None:
"""Print progress message with flush"""
print(message, end=end, flush=True)
async def _download_file(self, db: Session, url: str, filename: str, subdir: str) -> FileInDB:
async def _download_and_unzip_file(self, db: Session, url: str, filename: str, subdir: str) -> FileInDB:
"""Download a file from the given URL and save it using FileService"""
print(f"Downloading {url}...")
start_time = time.time()
@ -49,7 +28,7 @@ class MTGJSONService(BaseExternalService):
)
# Save the file using the file service
return await self.file_service.save_file(
file_record = await self.file_service.save_file(
db=db,
file_data=file_data,
filename=filename,
@ -57,18 +36,24 @@ class MTGJSONService(BaseExternalService):
file_type="application/zip",
content_type="application/zip"
)
# Unzip the file
await self._unzip_file(file_record, subdir, db)
return file_record
async def _unzip_file(self, file_record: FileInDB, subdir: str, db: Session) -> str:
async def _unzip_file(self, file_record: FileInDB, subdir: str, db: Session) -> FileInDB:
"""Unzip a file to the specified subdirectory and return the path to the extracted JSON file"""
try:
# Use the appropriate subdirectory based on the type
extract_path = self.identifiers_dir if subdir == "identifiers" else self.skus_dir
os.makedirs(extract_path, exist_ok=True)
file_service = self.get_service('file')
cache_dir = file_service.base_cache_dir
temp_dir = os.path.join(cache_dir,'mtgjson', subdir, 'temp')
os.makedirs(temp_dir, exist_ok=True)
with zipfile.ZipFile(file_record.path, 'r') as zip_ref:
json_filename = zip_ref.namelist()[0]
zip_ref.extractall(extract_path)
json_path = os.path.join(extract_path, json_filename)
zip_ref.extractall(temp_dir)
json_path = os.path.join(temp_dir, json_filename)
# Create a file record for the extracted JSON file
with open(json_path, 'r') as f:
@ -82,127 +67,57 @@ class MTGJSONService(BaseExternalService):
content_type="application/json"
)
return str(json_file_record.path)
# remove the temp directory
shutil.rmtree(temp_dir)
return json_file_record
except Exception as e:
logger.error(f"Error unzipping file: {e}")
raise
def _stream_json_file(self, file_path: str) -> Generator[Dict[str, Any], None, None]:
"""Stream a JSON file and yield items one at a time using a streaming parser"""
logger.info(f"Starting to stream JSON file: {file_path}")
try:
with open(file_path, 'r') as f:
# First, we need to find the start of the data section
data_started = False
current_key = None
current_value = []
brace_count = 0
for line in f:
line = line.strip()
if not line:
continue
if not data_started:
if '"data":' in line:
data_started = True
# Skip the opening brace of the data object
line = line[line.find('"data":') + 7:].strip()
if line.startswith('{'):
line = line[1:].strip()
else:
# Yield meta data if found
if '"meta":' in line:
meta_start = line.find('"meta":') + 7
meta_end = line.rfind('}')
if meta_end > meta_start:
meta_json = line[meta_start:meta_end + 1]
try:
meta_data = json.loads(meta_json)
yield {"type": "meta", "data": meta_data}
except json.JSONDecodeError as e:
logger.warning(f"Failed to parse meta data: {e}")
continue
# Process the data section
if data_started:
if not current_key:
# Look for a new key
if '"' in line:
key_start = line.find('"') + 1
key_end = line.find('"', key_start)
if key_end > key_start:
current_key = line[key_start:key_end]
# Get the rest of the line after the key
line = line[key_end + 1:].strip()
if ':' in line:
line = line[line.find(':') + 1:].strip()
if current_key:
# Accumulate the value
current_value.append(line)
brace_count += line.count('{') - line.count('}')
if brace_count == 0 and line.endswith(','):
# We have a complete value
value_str = ''.join(current_value).rstrip(',')
try:
value = json.loads(value_str)
yield {"type": "item", "data": {current_key: value}}
except json.JSONDecodeError as e:
logger.warning(f"Failed to parse value for key {current_key}: {e}")
current_key = None
current_value = []
except Exception as e:
logger.error(f"Error streaming JSON file: {e}")
raise
async def get_identifiers(self, db: Session) -> Generator[Dict[str, Any], None, None]:
async def get_identifiers(self, db: Session, use_cache: bool = True) -> Dict[str, Any]:
"""Download and get MTGJSON identifiers data"""
# Check if we have a cached version
cached_file = await self.file_service.get_file_by_filename(db, "AllIdentifiers.json")
if cached_file:
# Ensure the file exists at the path
if os.path.exists(cached_file.path):
return self._stream_json_file(cached_file.path)
# Download and process the file
file_record = await self._download_file(
db=db,
url="https://mtgjson.com/api/v5/AllIdentifiers.json.zip",
filename="AllIdentifiers.json.zip",
subdir="identifiers"
)
# Unzip and process the file
json_path = await self._unzip_file(file_record, "identifiers", db)
# Return a generator that streams the JSON file
return self._stream_json_file(json_path)
if cached_file and os.path.exists(cached_file.path) and use_cache:
with open(cached_file.path, 'r') as f:
logger.debug(f"Loaded identifiers from cache: {cached_file.path}")
return json.load(f)
else:
# Download and process the file
logger.debug(f"Downloading identifiers from MTGJSON")
file_record = await self._download_and_unzip_file(
db=db,
url="https://mtgjson.com/api/v5/AllIdentifiers.json.zip",
filename="AllIdentifiers.json.zip",
subdir="identifiers"
)
async def get_skus(self, db: Session) -> Generator[Dict[str, Any], None, None]:
with open(file_record.path, 'r') as f:
logger.debug(f"Loaded identifiers from MTGJSON: {file_record.path}")
return json.load(f)
async def get_skus(self, db: Session, use_cache: bool = True) -> Dict[str, Any]:
"""Download and get MTGJSON SKUs data"""
# Check if we have a cached version
cached_file = await self.file_service.get_file_by_filename(db, "TcgplayerSkus.json")
if cached_file:
# Ensure the file exists at the path
if os.path.exists(cached_file.path):
return self._stream_json_file(cached_file.path)
# Download and process the file
file_record = await self._download_file(
db=db,
url="https://mtgjson.com/api/v5/TcgplayerSkus.json.zip",
filename="TcgplayerSkus.json.zip",
subdir="skus"
)
# Unzip and process the file
json_path = await self._unzip_file(file_record, "skus", db)
# Return a generator that streams the JSON file
return self._stream_json_file(json_path)
if cached_file and os.path.exists(cached_file.path) and use_cache:
with open(cached_file.path, 'r') as f:
logger.debug(f"Loaded SKUs from cache: {cached_file.path}")
return json.load(f)
else:
# Download and process the file
logger.debug(f"Downloading SKUs from MTGJSON")
file_record = await self._download_and_unzip_file(
db=db,
url="https://mtgjson.com/api/v5/TcgplayerSkus.json.zip",
filename="TcgplayerSkus.json.zip",
subdir="skus"
)
with open(file_record.path, 'r') as f:
logger.debug(f"Loaded SKUs from MTGJSON: {file_record.path}")
return json.load(f)
async def clear_cache(self, db: Session) -> None:
"""Clear all cached data"""

View File

@ -153,7 +153,8 @@ class FileService:
async def get_file_by_filename(self, db: Session, filename: str) -> Optional[FileInDB]:
"""Get a file record from the database by filename"""
file_record = db.query(File).filter(File.name == filename).first()
# get most recent file by filename
file_record = db.query(File).filter(File.name == filename).order_by(File.created_at.desc()).first()
if file_record:
return FileInDB.model_validate(file_record)
return None

View File

@ -0,0 +1,15 @@
from app.services.base_service import BaseService
from sqlalchemy.orm import Session
from app.schemas.file import FileInDB
from typing import Dict, Any
import csv
class ManaboxService(BaseService):
def __init__(self):
super().__init__(None)
async def process_manabox_csv(self, db: Session, csv_file: FileInDB) -> bool:
return True
# Name,Set code,Set name,Collector number,Foil,Rarity,Quantity,ManaBox ID,Scryfall ID,Purchase price,Misprint,Altered,Condition,Language,Purchase price currency

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"success": true, "errors": [], "results": [{"productId": 38444, "lowPrice": 154.95, "midPrice": 223.55, "highPrice": 275.98, "marketPrice": 218.59, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 38445, "lowPrice": 349.49, "midPrice": 374.75, "highPrice": 400.0, "marketPrice": 385.0, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 38446, "lowPrice": 97.71, "midPrice": 120.99, "highPrice": 255.61, "marketPrice": 258.98, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 38447, "lowPrice": 80.0, "midPrice": 109.99, "highPrice": 214.45, "marketPrice": 99.92, "directLowPrice": 94.98, "subTypeName": "Foil"}, {"productId": 57653, "lowPrice": 71.99, "midPrice": 75.99, "highPrice": 100.0, "marketPrice": 69.44, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 67401, "lowPrice": 28.01, "midPrice": 78.72, "highPrice": 119.99, "marketPrice": 33.73, "directLowPrice": 114.99, "subTypeName": "Foil"}, {"productId": 71898, "lowPrice": 167.25, "midPrice": 183.34, "highPrice": 223.35, "marketPrice": 167.25, "directLowPrice": 168.28, "subTypeName": "Foil"}, {"productId": 78237, "lowPrice": 36.0, "midPrice": 89.24, "highPrice": 159.91, "marketPrice": 47.42, "directLowPrice": 59.99, "subTypeName": "Foil"}, {"productId": 95046, "lowPrice": 43.0, "midPrice": 62.92, "highPrice": 97.57, "marketPrice": 64.98, "directLowPrice": 44.0, "subTypeName": "Foil"}, {"productId": 110267, "lowPrice": 23.75, "midPrice": 31.21, "highPrice": 48.4, "marketPrice": 27.89, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 125324, "lowPrice": 18.0, "midPrice": 25.99, "highPrice": 53.45, "marketPrice": 25.86, "directLowPrice": 28.58, "subTypeName": "Foil"}, {"productId": 154792, "lowPrice": 16.73, "midPrice": 25.43, "highPrice": 49.0, "marketPrice": 17.47, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 181788, "lowPrice": 23.57, "midPrice": 27.83, "highPrice": 51.0, "marketPrice": 23.83, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 205180, "lowPrice": 16.99, "midPrice": 29.99, "highPrice": 70.2, "marketPrice": 18.3, "directLowPrice": 70.58, "subTypeName": "Foil"}, {"productId": 228752, "lowPrice": 24.99, "midPrice": 29.98, "highPrice": 224.99, "marketPrice": 29.43, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 257182, "lowPrice": 30.6, "midPrice": 75.0, "highPrice": 141.0, "marketPrice": 30.6, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 455848, "lowPrice": 15.0, "midPrice": 27.98, "highPrice": 134.0, "marketPrice": 20.73, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 527738, "lowPrice": 14.69, "midPrice": 19.31, "highPrice": 80.0, "marketPrice": 16.28, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 600517, "lowPrice": 47.97, "midPrice": 61.22, "highPrice": 75.0, "marketPrice": 61.22, "directLowPrice": null, "subTypeName": "Foil"}]}

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"success": true, "errors": [], "results": [{"productId": 21705, "lowPrice": 0.18, "midPrice": 0.57, "highPrice": 29.99, "marketPrice": 0.56, "directLowPrice": 0.43, "subTypeName": "Foil"}, {"productId": 37765, "lowPrice": 0.1, "midPrice": 0.25, "highPrice": 1.6, "marketPrice": 0.14, "directLowPrice": 0.18, "subTypeName": "Normal"}, {"productId": 37767, "lowPrice": 0.18, "midPrice": 0.41, "highPrice": 4.99, "marketPrice": 0.25, "directLowPrice": 0.6, "subTypeName": "Normal"}, {"productId": 37772, "lowPrice": 0.14, "midPrice": 0.39, "highPrice": 4.99, "marketPrice": 0.15, "directLowPrice": 0.17, "subTypeName": "Normal"}, {"productId": 37773, "lowPrice": 0.05, "midPrice": 0.24, "highPrice": 3.99, "marketPrice": 0.12, "directLowPrice": 0.07, "subTypeName": "Normal"}, {"productId": 37778, "lowPrice": 0.09, "midPrice": 0.25, "highPrice": 3.13, "marketPrice": 0.22, "directLowPrice": 0.18, "subTypeName": "Normal"}, {"productId": 37780, "lowPrice": 0.04, "midPrice": 0.37, "highPrice": 4.99, "marketPrice": 0.13, "directLowPrice": 0.19, "subTypeName": "Normal"}, {"productId": 37784, "lowPrice": 0.15, "midPrice": 0.3, "highPrice": 4.99, "marketPrice": 0.22, "directLowPrice": 0.2, "subTypeName": "Normal"}, {"productId": 37785, "lowPrice": 0.15, "midPrice": 0.37, "highPrice": 3.99, "marketPrice": 0.19, "directLowPrice": 0.09, "subTypeName": "Normal"}, {"productId": 37788, "lowPrice": 0.14, "midPrice": 0.3, "highPrice": 3.0, "marketPrice": 0.31, "directLowPrice": 0.2, "subTypeName": "Normal"}, {"productId": 37789, "lowPrice": 0.15, "midPrice": 0.35, "highPrice": 4.99, "marketPrice": 0.31, "directLowPrice": 0.15, "subTypeName": "Normal"}, {"productId": 37790, "lowPrice": 0.14, "midPrice": 0.39, "highPrice": 3.99, "marketPrice": 0.22, "directLowPrice": 0.14, "subTypeName": "Normal"}, {"productId": 37793, "lowPrice": 0.05, "midPrice": 0.25, "highPrice": 3.99, "marketPrice": 0.08, "directLowPrice": 0.08, "subTypeName": "Normal"}, {"productId": 37799, "lowPrice": 0.1, "midPrice": 0.25, "highPrice": 3.0, "marketPrice": 0.2, "directLowPrice": 0.19, "subTypeName": "Normal"}, {"productId": 37802, "lowPrice": 0.1, "midPrice": 0.25, "highPrice": 5.0, "marketPrice": 0.17, "directLowPrice": 0.1, "subTypeName": "Normal"}, {"productId": 37809, "lowPrice": 0.1, "midPrice": 0.25, "highPrice": 1.67, "marketPrice": 0.19, "directLowPrice": 0.07, "subTypeName": "Normal"}, {"productId": 37810, "lowPrice": 0.09, "midPrice": 0.35, "highPrice": 5.25, "marketPrice": 0.28, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 37812, "lowPrice": 0.18, "midPrice": 0.51, "highPrice": 4.99, "marketPrice": 0.83, "directLowPrice": 0.18, "subTypeName": "Normal"}, {"productId": 37813, "lowPrice": 0.15, "midPrice": 0.25, "highPrice": 2.99, "marketPrice": 0.22, "directLowPrice": 0.14, "subTypeName": "Normal"}, {"productId": 37814, "lowPrice": 0.14, "midPrice": 0.28, "highPrice": 1.76, "marketPrice": 0.18, "directLowPrice": null, "subTypeName": "Normal"}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"success": true, "errors": [], "results": [{"productId": 70757, "lowPrice": 0.8, "midPrice": 2.48, "highPrice": 54.0, "marketPrice": 2.61, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 70758, "lowPrice": 1.14, "midPrice": 1.74, "highPrice": 12.88, "marketPrice": 1.37, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 70759, "lowPrice": 0.75, "midPrice": 2.05, "highPrice": 8.99, "marketPrice": 2.51, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 70760, "lowPrice": 0.79, "midPrice": 1.61, "highPrice": 6.0, "marketPrice": 1.17, "directLowPrice": 1.6, "subTypeName": "Foil"}, {"productId": 70761, "lowPrice": 8.0, "midPrice": 11.12, "highPrice": 49.95, "marketPrice": 11.01, "directLowPrice": 11.96, "subTypeName": "Foil"}, {"productId": 70762, "lowPrice": 0.66, "midPrice": 1.34, "highPrice": 3.99, "marketPrice": 1.22, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 70763, "lowPrice": 4.1, "midPrice": 6.0, "highPrice": 19.99, "marketPrice": 5.09, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 70764, "lowPrice": 15.53, "midPrice": 19.96, "highPrice": 159.99, "marketPrice": 19.05, "directLowPrice": 21.69, "subTypeName": "Foil"}, {"productId": 70765, "lowPrice": 100.0, "midPrice": 119.99, "highPrice": 400.0, "marketPrice": 85.88, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 70782, "lowPrice": 7.26, "midPrice": 13.24, "highPrice": 20.57, "marketPrice": 13.16, "directLowPrice": 17.05, "subTypeName": "Foil"}, {"productId": 70783, "lowPrice": 4.0, "midPrice": 6.15, "highPrice": 11.84, "marketPrice": 5.69, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 70784, "lowPrice": 3.86, "midPrice": 5.41, "highPrice": 19.55, "marketPrice": 4.66, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 70785, "lowPrice": 1.25, "midPrice": 1.9, "highPrice": 7.4, "marketPrice": 1.6, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 70786, "lowPrice": 3.0, "midPrice": 4.4, "highPrice": 10.0, "marketPrice": 3.42, "directLowPrice": 4.39, "subTypeName": "Foil"}, {"productId": 70787, "lowPrice": 9.25, "midPrice": 11.47, "highPrice": 49.88, "marketPrice": 11.19, "directLowPrice": 19.37, "subTypeName": "Foil"}, {"productId": 70789, "lowPrice": 0.5, "midPrice": 1.04, "highPrice": 16.99, "marketPrice": 0.8, "directLowPrice": 1.07, "subTypeName": "Foil"}, {"productId": 70790, "lowPrice": 0.39, "midPrice": 0.99, "highPrice": 16.45, "marketPrice": 0.68, "directLowPrice": 0.6, "subTypeName": "Foil"}, {"productId": 70791, "lowPrice": 0.23, "midPrice": 0.59, "highPrice": 3.99, "marketPrice": 0.45, "directLowPrice": 0.49, "subTypeName": "Foil"}, {"productId": 70792, "lowPrice": 1.5, "midPrice": 2.49, "highPrice": 9.99, "marketPrice": 2.26, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 70793, "lowPrice": 49.0, "midPrice": 59.02, "highPrice": 200.0, "marketPrice": 59.02, "directLowPrice": 51.49, "subTypeName": "Foil"}, {"productId": 70794, "lowPrice": 1.8, "midPrice": 3.91, "highPrice": 88.0, "marketPrice": 3.69, "directLowPrice": 2.94, "subTypeName": "Foil"}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"success": true, "errors": [], "results": [{"productId": 21603, "lowPrice": 11.0, "midPrice": 16.55, "highPrice": 97.99, "marketPrice": 17.1, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21604, "lowPrice": 4.95, "midPrice": 10.97, "highPrice": 14.97, "marketPrice": 6.99, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21605, "lowPrice": 10.0, "midPrice": 13.95, "highPrice": 79.45, "marketPrice": 14.97, "directLowPrice": 5.01, "subTypeName": "Normal"}, {"productId": 21606, "lowPrice": 18.95, "midPrice": 21.88, "highPrice": 86.37, "marketPrice": 17.0, "directLowPrice": 43.94, "subTypeName": "Normal"}, {"productId": 21607, "lowPrice": 0.38, "midPrice": 2.46, "highPrice": 5.7, "marketPrice": 1.5, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21608, "lowPrice": 1.55, "midPrice": 2.47, "highPrice": 4.95, "marketPrice": 2.0, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21609, "lowPrice": 98.95, "midPrice": 103.94, "highPrice": 108.93, "marketPrice": 57.85, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21610, "lowPrice": 4.73, "midPrice": 7.87, "highPrice": 11.0, "marketPrice": 7.61, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21611, "lowPrice": 9.0, "midPrice": 16.58, "highPrice": 22.17, "marketPrice": 14.16, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21612, "lowPrice": 5.99, "midPrice": 6.91, "highPrice": 15.74, "marketPrice": 6.29, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21613, "lowPrice": 9.55, "midPrice": 14.61, "highPrice": 18.95, "marketPrice": 13.98, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21614, "lowPrice": 1.7, "midPrice": 2.5, "highPrice": 4.95, "marketPrice": 1.4, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21615, "lowPrice": 3.86, "midPrice": 5.5, "highPrice": 8.0, "marketPrice": 6.07, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21616, "lowPrice": 8.84, "midPrice": 19.97, "highPrice": 24.95, "marketPrice": 8.5, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21617, "lowPrice": 6.92, "midPrice": 8.0, "highPrice": 13.99, "marketPrice": 7.23, "directLowPrice": 5.23, "subTypeName": "Normal"}, {"productId": 21618, "lowPrice": 25.0, "midPrice": 29.91, "highPrice": 50.0, "marketPrice": 27.0, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21619, "lowPrice": 8.0, "midPrice": 11.41, "highPrice": 18.61, "marketPrice": 9.89, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21620, "lowPrice": 15.0, "midPrice": 18.95, "highPrice": 20.59, "marketPrice": 8.76, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21621, "lowPrice": 18.5, "midPrice": 22.49, "highPrice": 49.95, "marketPrice": 25.0, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21622, "lowPrice": 7.99, "midPrice": 16.72, "highPrice": 19.95, "marketPrice": 11.91, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21623, "lowPrice": 12.0, "midPrice": 15.0, "highPrice": 16.99, "marketPrice": 15.95, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21624, "lowPrice": 0.59, "midPrice": 1.87, "highPrice": 9.95, "marketPrice": 2.5, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21625, "lowPrice": 49.95, "midPrice": 71.67, "highPrice": 99.95, "marketPrice": 66.45, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21626, "lowPrice": 3.99, "midPrice": 4.87, "highPrice": 8.12, "marketPrice": 5.5, "directLowPrice": 3.0, "subTypeName": "Normal"}, {"productId": 21627, "lowPrice": 6.77, "midPrice": 9.03, "highPrice": 24.99, "marketPrice": 5.16, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21628, "lowPrice": 1.1, "midPrice": 2.25, "highPrice": 4.23, "marketPrice": 1.5, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21629, "lowPrice": 5.0, "midPrice": 5.22, "highPrice": 13.97, "marketPrice": 5.0, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21630, "lowPrice": 16.8, "midPrice": 27.54, "highPrice": 45.0, "marketPrice": 15.95, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21631, "lowPrice": 114.95, "midPrice": 150.0, "highPrice": 154.97, "marketPrice": 42.5, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21632, "lowPrice": 16.99, "midPrice": 55.98, "highPrice": 150.0, "marketPrice": 14.79, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 21633, "lowPrice": 10.99, "midPrice": 13.84, "highPrice": 23.95, "marketPrice": 15.49, "directLowPrice": 19.88, "subTypeName": "Normal"}, {"productId": 21634, "lowPrice": 49.97, "midPrice": 74.36, "highPrice": 98.75, "marketPrice": 49.97, "directLowPrice": null, "subTypeName": "Normal"}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"success": true, "errors": [], "results": [{"productId": 82198, "lowPrice": 79.26, "midPrice": 94.13, "highPrice": 249.99, "marketPrice": 89.08, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 82732, "lowPrice": 0.74, "midPrice": 1.03, "highPrice": 3.01, "marketPrice": 0.98, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 82733, "lowPrice": 13.4, "midPrice": 18.14, "highPrice": 38.5, "marketPrice": 14.09, "directLowPrice": 35.1, "subTypeName": "Normal"}, {"productId": 82734, "lowPrice": 0.99, "midPrice": 1.62, "highPrice": 9.9, "marketPrice": 1.36, "directLowPrice": 1.58, "subTypeName": "Normal"}, {"productId": 82735, "lowPrice": 0.46, "midPrice": 0.85, "highPrice": 4.91, "marketPrice": 0.69, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 82736, "lowPrice": 0.54, "midPrice": 0.82, "highPrice": 3.88, "marketPrice": 0.83, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 82737, "lowPrice": 0.99, "midPrice": 2.25, "highPrice": 19.99, "marketPrice": 2.15, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 82738, "lowPrice": 0.15, "midPrice": 0.5, "highPrice": 2.0, "marketPrice": 0.39, "directLowPrice": 0.25, "subTypeName": "Normal"}, {"productId": 82739, "lowPrice": 1.5, "midPrice": 2.96, "highPrice": 8.87, "marketPrice": 2.32, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 82740, "lowPrice": 0.15, "midPrice": 0.47, "highPrice": 2.99, "marketPrice": 0.34, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 82741, "lowPrice": 0.45, "midPrice": 0.9, "highPrice": 8.53, "marketPrice": 0.56, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 82742, "lowPrice": 0.25, "midPrice": 0.75, "highPrice": 27.99, "marketPrice": 0.5, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 82743, "lowPrice": 0.09, "midPrice": 0.33, "highPrice": 1.99, "marketPrice": 0.21, "directLowPrice": 0.25, "subTypeName": "Normal"}, {"productId": 82744, "lowPrice": 0.18, "midPrice": 0.48, "highPrice": 1.83, "marketPrice": 0.45, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 82745, "lowPrice": 0.77, "midPrice": 1.25, "highPrice": 18.99, "marketPrice": 0.95, "directLowPrice": 1.71, "subTypeName": "Normal"}, {"productId": 82746, "lowPrice": 0.03, "midPrice": 0.25, "highPrice": 1.5, "marketPrice": 0.11, "directLowPrice": 0.1, "subTypeName": "Normal"}, {"productId": 82747, "lowPrice": 0.2, "midPrice": 0.38, "highPrice": 1.99, "marketPrice": 0.26, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 82748, "lowPrice": 0.22, "midPrice": 0.39, "highPrice": 1.52, "marketPrice": 0.29, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 82749, "lowPrice": 20.14, "midPrice": 27.69, "highPrice": 79.99, "marketPrice": 22.14, "directLowPrice": 25.63, "subTypeName": "Normal"}, {"productId": 82750, "lowPrice": 0.06, "midPrice": 0.3, "highPrice": 2.99, "marketPrice": 0.07, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 82751, "lowPrice": 4.97, "midPrice": 7.93, "highPrice": 17.38, "marketPrice": 7.63, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 82752, "lowPrice": 0.12, "midPrice": 0.4, "highPrice": 2.99, "marketPrice": 0.16, "directLowPrice": 0.15, "subTypeName": "Normal"}, {"productId": 82753, "lowPrice": 2.09, "midPrice": 3.5, "highPrice": 11.99, "marketPrice": 2.76, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 82754, "lowPrice": 0.05, "midPrice": 0.26, "highPrice": 1.5, "marketPrice": 0.17, "directLowPrice": 0.14, "subTypeName": "Normal"}, {"productId": 82755, "lowPrice": 0.25, "midPrice": 0.75, "highPrice": 3.59, "marketPrice": 0.58, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 82756, "lowPrice": 0.9, "midPrice": 1.75, "highPrice": 11.97, "marketPrice": 1.36, "directLowPrice": 1.5, "subTypeName": "Normal"}, {"productId": 82757, "lowPrice": 3.97, "midPrice": 6.25, "highPrice": 13.5, "marketPrice": 3.97, "directLowPrice": 7.99, "subTypeName": "Normal"}, {"productId": 83374, "lowPrice": 8.96, "midPrice": 13.5, "highPrice": 19.99, "marketPrice": 11.77, "directLowPrice": 19.97, "subTypeName": "Normal"}, {"productId": 83376, "lowPrice": 0.19, "midPrice": 0.5, "highPrice": 5.0, "marketPrice": 0.7, "directLowPrice": 0.49, "subTypeName": "Normal"}, {"productId": 83377, "lowPrice": 0.05, "midPrice": 0.25, "highPrice": 1.5, "marketPrice": 0.17, "directLowPrice": 0.5, "subTypeName": "Normal"}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"success": true, "errors": [], "results": []}

View File

@ -1 +0,0 @@
{"success": true, "errors": [], "results": [{"productId": 91636, "lowPrice": 29.85, "midPrice": 45.99, "highPrice": 495.95, "marketPrice": 30.89, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 91637, "lowPrice": 14.19, "midPrice": 14.94, "highPrice": 34.8, "marketPrice": 14.73, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 91638, "lowPrice": 3.29, "midPrice": 4.86, "highPrice": 16.78, "marketPrice": 4.65, "directLowPrice": 4.0, "subTypeName": "Foil"}, {"productId": 91639, "lowPrice": 3.67, "midPrice": 5.55, "highPrice": 15.99, "marketPrice": 5.57, "directLowPrice": 5.99, "subTypeName": "Foil"}, {"productId": 91640, "lowPrice": 2.92, "midPrice": 4.0, "highPrice": 19.99, "marketPrice": 3.4, "directLowPrice": 3.99, "subTypeName": "Foil"}, {"productId": 91641, "lowPrice": 2.04, "midPrice": 3.0, "highPrice": 9.99, "marketPrice": 2.47, "directLowPrice": 2.64, "subTypeName": "Foil"}, {"productId": 92296, "lowPrice": 0.4, "midPrice": 0.94, "highPrice": 4.78, "marketPrice": 0.53, "directLowPrice": 0.69, "subTypeName": "Foil"}, {"productId": 92297, "lowPrice": 0.82, "midPrice": 1.43, "highPrice": 29.98, "marketPrice": 1.19, "directLowPrice": 1.29, "subTypeName": "Foil"}, {"productId": 92298, "lowPrice": 1.63, "midPrice": 4.48, "highPrice": 15.0, "marketPrice": 5.31, "directLowPrice": 3.29, "subTypeName": "Foil"}, {"productId": 92299, "lowPrice": 0.63, "midPrice": 1.0, "highPrice": 3.99, "marketPrice": 0.83, "directLowPrice": 0.96, "subTypeName": "Foil"}, {"productId": 92300, "lowPrice": 0.72, "midPrice": 2.06, "highPrice": 19.99, "marketPrice": 2.5, "directLowPrice": 2.5, "subTypeName": "Foil"}, {"productId": 92301, "lowPrice": 0.96, "midPrice": 1.65, "highPrice": 19.99, "marketPrice": 1.16, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 92302, "lowPrice": 2.85, "midPrice": 4.29, "highPrice": 39.99, "marketPrice": 4.29, "directLowPrice": 3.99, "subTypeName": "Foil"}, {"productId": 92303, "lowPrice": 2.49, "midPrice": 3.61, "highPrice": 16.99, "marketPrice": 2.86, "directLowPrice": 3.08, "subTypeName": "Foil"}, {"productId": 92304, "lowPrice": 0.25, "midPrice": 0.93, "highPrice": 19.99, "marketPrice": 0.74, "directLowPrice": 1.53, "subTypeName": "Foil"}, {"productId": 92305, "lowPrice": 0.38, "midPrice": 0.81, "highPrice": 6.85, "marketPrice": 0.63, "directLowPrice": null, "subTypeName": "Foil"}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"success": true, "errors": [], "results": [{"productId": 95578, "lowPrice": 40.0, "midPrice": 48.63, "highPrice": 150.0, "marketPrice": 40.66, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95579, "lowPrice": 23.58, "midPrice": 31.72, "highPrice": 55.21, "marketPrice": 31.84, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95580, "lowPrice": 0.69, "midPrice": 1.38, "highPrice": 6.0, "marketPrice": 1.06, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95581, "lowPrice": 1.0, "midPrice": 2.79, "highPrice": 6.95, "marketPrice": 1.91, "directLowPrice": 2.35, "subTypeName": "Normal"}, {"productId": 95582, "lowPrice": 7.59, "midPrice": 12.19, "highPrice": 24.66, "marketPrice": 10.49, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95583, "lowPrice": 0.25, "midPrice": 1.16, "highPrice": 4.0, "marketPrice": 0.84, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95584, "lowPrice": 0.45, "midPrice": 1.5, "highPrice": 6.31, "marketPrice": 0.8, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95585, "lowPrice": 0.8, "midPrice": 1.55, "highPrice": 4.79, "marketPrice": 0.85, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95586, "lowPrice": 0.1, "midPrice": 0.44, "highPrice": 1.5, "marketPrice": 0.23, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95587, "lowPrice": 0.15, "midPrice": 0.5, "highPrice": 1.5, "marketPrice": 0.49, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95588, "lowPrice": 0.25, "midPrice": 0.54, "highPrice": 2.43, "marketPrice": 0.3, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95589, "lowPrice": 0.25, "midPrice": 0.75, "highPrice": 4.25, "marketPrice": 0.82, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95590, "lowPrice": 0.1, "midPrice": 0.37, "highPrice": 11.5, "marketPrice": 0.25, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95591, "lowPrice": 0.18, "midPrice": 0.39, "highPrice": 2.0, "marketPrice": 0.19, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95592, "lowPrice": 0.14, "midPrice": 0.49, "highPrice": 1.77, "marketPrice": 0.22, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95593, "lowPrice": 0.15, "midPrice": 0.4, "highPrice": 7.0, "marketPrice": 0.23, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95594, "lowPrice": 0.07, "midPrice": 0.39, "highPrice": 3.0, "marketPrice": 0.22, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95595, "lowPrice": 0.2, "midPrice": 0.48, "highPrice": 2.0, "marketPrice": 0.22, "directLowPrice": 0.25, "subTypeName": "Normal"}, {"productId": 95596, "lowPrice": 1.18, "midPrice": 2.62, "highPrice": 10.49, "marketPrice": 2.36, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95597, "lowPrice": 1.93, "midPrice": 2.96, "highPrice": 6.0, "marketPrice": 2.96, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95598, "lowPrice": 0.19, "midPrice": 0.44, "highPrice": 2.91, "marketPrice": 0.21, "directLowPrice": 0.42, "subTypeName": "Normal"}, {"productId": 95599, "lowPrice": 0.15, "midPrice": 0.5, "highPrice": 2.0, "marketPrice": 0.23, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95600, "lowPrice": 0.24, "midPrice": 0.89, "highPrice": 3.0, "marketPrice": 0.65, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95601, "lowPrice": 0.14, "midPrice": 0.5, "highPrice": 2.91, "marketPrice": 0.2, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 95602, "lowPrice": 0.14, "midPrice": 0.5, "highPrice": 2.5, "marketPrice": 0.21, "directLowPrice": 0.35, "subTypeName": "Normal"}, {"productId": 95603, "lowPrice": 0.15, "midPrice": 0.49, "highPrice": 3.0, "marketPrice": 0.43, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 99943, "lowPrice": 14.32, "midPrice": 20.0, "highPrice": 39.99, "marketPrice": 13.81, "directLowPrice": null, "subTypeName": "Normal"}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"success": true, "errors": [], "results": [{"productId": 96436, "lowPrice": 0.41, "midPrice": 0.93, "highPrice": 20.0, "marketPrice": 0.84, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 96437, "lowPrice": 0.39, "midPrice": 0.62, "highPrice": 5.0, "marketPrice": 0.57, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 96438, "lowPrice": 0.1, "midPrice": 0.33, "highPrice": 3.0, "marketPrice": 0.34, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 96439, "lowPrice": 0.05, "midPrice": 0.26, "highPrice": 5.0, "marketPrice": 0.26, "directLowPrice": null, "subTypeName": "Normal"}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"success": true, "errors": [], "results": [{"productId": 100611, "lowPrice": 4.33, "midPrice": 6.37, "highPrice": 123.0, "marketPrice": 4.76, "directLowPrice": 6.4, "subTypeName": "Foil"}, {"productId": 100612, "lowPrice": 3.0, "midPrice": 4.17, "highPrice": 15.99, "marketPrice": 3.88, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 100667, "lowPrice": 119.99, "midPrice": 142.49, "highPrice": 999.95, "marketPrice": 124.0, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 101468, "lowPrice": 35.0, "midPrice": 41.65, "highPrice": 75.68, "marketPrice": 43.6, "directLowPrice": 37.15, "subTypeName": "Foil"}, {"productId": 101469, "lowPrice": 5.0, "midPrice": 7.25, "highPrice": 19.99, "marketPrice": 7.0, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 102777, "lowPrice": 0.51, "midPrice": 1.73, "highPrice": 20.03, "marketPrice": 1.7, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 102778, "lowPrice": 7.51, "midPrice": 10.11, "highPrice": 22.72, "marketPrice": 9.96, "directLowPrice": 14.28, "subTypeName": "Foil"}, {"productId": 102779, "lowPrice": 2.54, "midPrice": 3.43, "highPrice": 8.25, "marketPrice": 2.94, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 102780, "lowPrice": 1.99, "midPrice": 3.42, "highPrice": 14.99, "marketPrice": 3.28, "directLowPrice": 2.0, "subTypeName": "Foil"}, {"productId": 102781, "lowPrice": 1.03, "midPrice": 2.0, "highPrice": 8.0, "marketPrice": 1.75, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 102782, "lowPrice": 0.7, "midPrice": 1.07, "highPrice": 3.41, "marketPrice": 0.99, "directLowPrice": 1.02, "subTypeName": "Foil"}, {"productId": 102783, "lowPrice": 0.26, "midPrice": 0.99, "highPrice": 5.0, "marketPrice": 0.82, "directLowPrice": null, "subTypeName": "Foil"}, {"productId": 102784, "lowPrice": 0.21, "midPrice": 0.82, "highPrice": 2.59, "marketPrice": 0.66, "directLowPrice": 0.44, "subTypeName": "Foil"}, {"productId": 102785, "lowPrice": 6.02, "midPrice": 7.52, "highPrice": 19.0, "marketPrice": 7.17, "directLowPrice": 9.99, "subTypeName": "Foil"}, {"productId": 102786, "lowPrice": 0.74, "midPrice": 2.74, "highPrice": 49.99, "marketPrice": 2.61, "directLowPrice": 2.48, "subTypeName": "Foil"}, {"productId": 102787, "lowPrice": 0.98, "midPrice": 2.49, "highPrice": 12.01, "marketPrice": 2.58, "directLowPrice": null, "subTypeName": "Foil"}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"success": true, "errors": [], "results": []}

View File

@ -1 +0,0 @@
{"success": true, "errors": [], "results": []}

View File

@ -1 +0,0 @@
{"success": true, "errors": [], "results": []}

View File

@ -1 +0,0 @@
{"success": true, "errors": [], "results": []}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"success": true, "errors": [], "results": [{"productId": 116780, "lowPrice": 0.25, "midPrice": 0.5, "highPrice": 6.99, "marketPrice": 0.29, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 116781, "lowPrice": 0.01, "midPrice": 0.19, "highPrice": 1.32, "marketPrice": 0.07, "directLowPrice": 0.03, "subTypeName": "Normal"}, {"productId": 116782, "lowPrice": 0.01, "midPrice": 0.15, "highPrice": 5.0, "marketPrice": 0.02, "directLowPrice": 0.02, "subTypeName": "Normal"}, {"productId": 116783, "lowPrice": 0.01, "midPrice": 0.2, "highPrice": 16.0, "marketPrice": 0.04, "directLowPrice": 0.14, "subTypeName": "Normal"}, {"productId": 116784, "lowPrice": 0.01, "midPrice": 0.19, "highPrice": 1.32, "marketPrice": 0.04, "directLowPrice": 0.1, "subTypeName": "Normal"}, {"productId": 116785, "lowPrice": 0.01, "midPrice": 0.2, "highPrice": 1.32, "marketPrice": 0.08, "directLowPrice": 0.1, "subTypeName": "Normal"}, {"productId": 116786, "lowPrice": 0.01, "midPrice": 0.2, "highPrice": 1.32, "marketPrice": 0.04, "directLowPrice": 0.25, "subTypeName": "Normal"}, {"productId": 116787, "lowPrice": 0.01, "midPrice": 0.18, "highPrice": 5.0, "marketPrice": 0.13, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 116788, "lowPrice": 0.04, "midPrice": 0.25, "highPrice": 4.99, "marketPrice": 0.13, "directLowPrice": 0.13, "subTypeName": "Normal"}, {"productId": 116789, "lowPrice": 0.01, "midPrice": 0.15, "highPrice": 2.0, "marketPrice": 0.03, "directLowPrice": 0.16, "subTypeName": "Normal"}, {"productId": 116790, "lowPrice": 0.01, "midPrice": 0.2, "highPrice": 1.35, "marketPrice": 0.1, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 116791, "lowPrice": 0.03, "midPrice": 0.2, "highPrice": 1.53, "marketPrice": 0.12, "directLowPrice": 0.1, "subTypeName": "Normal"}, {"productId": 116792, "lowPrice": 0.02, "midPrice": 0.25, "highPrice": 5.06, "marketPrice": 0.12, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 116793, "lowPrice": 0.98, "midPrice": 1.2, "highPrice": 4.99, "marketPrice": 1.03, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 116794, "lowPrice": 0.01, "midPrice": 0.25, "highPrice": 4.99, "marketPrice": 0.16, "directLowPrice": null, "subTypeName": "Normal"}, {"productId": 116795, "lowPrice": 0.01, "midPrice": 0.15, "highPrice": 5.0, "marketPrice": 0.02, "directLowPrice": 0.06, "subTypeName": "Normal"}]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More