Reworked how the flea market categories are calculated, instead of trying to be smart and add/remove in a cache as offers are created, calculate the categories when needed
Categories: Are now much more accurate take into account when player is below flea unlock level Any with a (1) and no offers have been fixed Take into account when offers are barters + barters are filtered out Skip items with a type of `node` during flea assort generation
This commit is contained in:
parent
56366068e0
commit
7f995de5d1
@ -95,7 +95,11 @@ export class RagfairController
|
|||||||
const pmcProfile = this.profileHelper.getPmcProfile(sessionID);
|
const pmcProfile = this.profileHelper.getPmcProfile(sessionID);
|
||||||
|
|
||||||
result.offers = this.getOffersForSearchType(searchRequest, itemsToAdd, traderAssorts, pmcProfile);
|
result.offers = this.getOffersForSearchType(searchRequest, itemsToAdd, traderAssorts, pmcProfile);
|
||||||
result.categories = this.getSpecificCategories(searchRequest, result.offers);
|
|
||||||
|
if (searchRequest.updateOfferCount)
|
||||||
|
{
|
||||||
|
result.categories = this.getSpecificCategories(pmcProfile, searchRequest, result.offers);
|
||||||
|
}
|
||||||
|
|
||||||
// Client requested "required search"
|
// Client requested "required search"
|
||||||
if (searchRequest.neededSearchId)
|
if (searchRequest.neededSearchId)
|
||||||
@ -131,10 +135,8 @@ export class RagfairController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set categories count (needed for categories to show when choosing 'Linked search')
|
|
||||||
this.ragfairHelper.countCategories(result);
|
|
||||||
|
|
||||||
result.offersCount = result.offers.length;
|
result.offersCount = result.offers.length;
|
||||||
|
|
||||||
// Handle paging before returning results only if searching for general items, not preset items
|
// Handle paging before returning results only if searching for general items, not preset items
|
||||||
if (searchRequest.buildCount === 0)
|
if (searchRequest.buildCount === 0)
|
||||||
{
|
{
|
||||||
@ -176,21 +178,28 @@ export class RagfairController
|
|||||||
* @param offers ragfair offers to get categories for
|
* @param offers ragfair offers to get categories for
|
||||||
* @returns record with tpls + counts
|
* @returns record with tpls + counts
|
||||||
*/
|
*/
|
||||||
protected getSpecificCategories(searchRequest: ISearchRequestData, offers: IRagfairOffer[]): Record<string, number>
|
protected getSpecificCategories(pmcProfile: IPmcData, searchRequest: ISearchRequestData, offers: IRagfairOffer[]): Record<string, number>
|
||||||
{
|
{
|
||||||
// Linked/required search categories
|
// Linked/required search categories
|
||||||
|
const playerHasFleaUnlocked = pmcProfile.Info.Level > this.databaseServer.getTables().globals.config.RagFair.minUserLevel;
|
||||||
|
let offerPool = [];
|
||||||
if (this.isLinkedSearch(searchRequest) || this.isRequiredSearch(searchRequest))
|
if (this.isLinkedSearch(searchRequest) || this.isRequiredSearch(searchRequest))
|
||||||
{
|
{
|
||||||
return this.ragfairServer.getBespokeCategories(offers);
|
offerPool = offers;
|
||||||
}
|
}
|
||||||
|
else if ((searchRequest.linkedSearchId === "" && searchRequest.neededSearchId === ""))
|
||||||
// Get all categories
|
|
||||||
if ((searchRequest.linkedSearchId === "" && searchRequest.neededSearchId === ""))
|
|
||||||
{
|
{
|
||||||
return this.ragfairServer.getAllCategories();
|
// Get all categories
|
||||||
|
offerPool = this.ragfairOfferService.getOffers();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.logger.error("Unable to get categories from search criteria, see log for request data");
|
||||||
|
this.logger.debug(JSON.stringify(searchRequest));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return this.ragfairServer.getAllActiveCategories(playerHasFleaUnlocked, searchRequest, offerPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,6 +79,11 @@ export class RagfairAssortGenerator
|
|||||||
const seasonalItemTplBlacklist = this.seasonalEventService.getAllSeasonalEventItems();
|
const seasonalItemTplBlacklist = this.seasonalEventService.getAllSeasonalEventItems();
|
||||||
for (const item of items)
|
for (const item of items)
|
||||||
{
|
{
|
||||||
|
if (item._type === "Node")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.itemHelper.isValidItem(item._id, ragfairItemInvalidBaseTypes))
|
if (!this.itemHelper.isValidItem(item._id, ragfairItemInvalidBaseTypes))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -21,7 +21,6 @@ import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
|||||||
import { SaveServer } from "@spt-aki/servers/SaveServer";
|
import { SaveServer } from "@spt-aki/servers/SaveServer";
|
||||||
import { FenceService } from "@spt-aki/services/FenceService";
|
import { FenceService } from "@spt-aki/services/FenceService";
|
||||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||||
import { RagfairCategoriesService } from "@spt-aki/services/RagfairCategoriesService";
|
|
||||||
import { RagfairOfferService } from "@spt-aki/services/RagfairOfferService";
|
import { RagfairOfferService } from "@spt-aki/services/RagfairOfferService";
|
||||||
import { RagfairPriceService } from "@spt-aki/services/RagfairPriceService";
|
import { RagfairPriceService } from "@spt-aki/services/RagfairPriceService";
|
||||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||||
@ -51,7 +50,6 @@ export class RagfairOfferGenerator
|
|||||||
@inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService,
|
@inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService,
|
||||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||||
@inject("PaymentHelper") protected paymentHelper: PaymentHelper,
|
@inject("PaymentHelper") protected paymentHelper: PaymentHelper,
|
||||||
@inject("RagfairCategoriesService") protected ragfairCategoriesService: RagfairCategoriesService,
|
|
||||||
@inject("FenceService") protected fenceService: FenceService,
|
@inject("FenceService") protected fenceService: FenceService,
|
||||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||||
@ -431,8 +429,6 @@ export class RagfairOfferGenerator
|
|||||||
1,
|
1,
|
||||||
isPreset || isPackOffer,
|
isPreset || isPackOffer,
|
||||||
); // sellAsOnePiece
|
); // sellAsOnePiece
|
||||||
|
|
||||||
this.ragfairCategoriesService.incrementCategory(offer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -510,8 +506,6 @@ export class RagfairOfferGenerator
|
|||||||
|
|
||||||
const offer = this.createFleaOffer(traderID, time, items, barterSchemeItems, loyalLevel, false);
|
const offer = this.createFleaOffer(traderID, time, items, barterSchemeItems, loyalLevel, false);
|
||||||
|
|
||||||
this.ragfairCategoriesService.incrementCategory(offer);
|
|
||||||
|
|
||||||
// Refresh complete, reset flag to false
|
// Refresh complete, reset flag to false
|
||||||
trader.base.refreshTraderRagfairOffers = false;
|
trader.base.refreshTraderRagfairOffers = false;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { inject, injectable } from "tsyringe";
|
import { inject, injectable } from "tsyringe";
|
||||||
|
|
||||||
|
import { Category } from "@spt-aki/models/eft/common/tables/IHandbookBase";
|
||||||
import { Money } from "@spt-aki/models/enums/Money";
|
import { Money } from "@spt-aki/models/enums/Money";
|
||||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||||
@ -164,4 +165,9 @@ export class HandbookHelper
|
|||||||
const price = this.getTemplatePrice(currencyTypeTo);
|
const price = this.getTemplatePrice(currencyTypeTo);
|
||||||
return price ? Math.round(roubleCurrencyCount / price) : 0;
|
return price ? Math.round(roubleCurrencyCount / price) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getCategoryById(handbookId: string): Category
|
||||||
|
{
|
||||||
|
return this.databaseServer.getTables().templates.handbook.Categories.find(x => x.Id === handbookId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,31 +147,6 @@ export class RagfairHelper
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Because of presets, categories are not always 1 */
|
|
||||||
public countCategories(result: IGetOffersResult): void
|
|
||||||
{
|
|
||||||
const categories = {};
|
|
||||||
|
|
||||||
for (const offer of result.offers)
|
|
||||||
{
|
|
||||||
// only the first item can have presets
|
|
||||||
const item = offer.items[0];
|
|
||||||
categories[item._tpl] = categories[item._tpl] || 0;
|
|
||||||
categories[item._tpl]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// not in search mode, add back non-weapon items
|
|
||||||
for (const category in result.categories)
|
|
||||||
{
|
|
||||||
if (!categories[category])
|
|
||||||
{
|
|
||||||
categories[category] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.categories = categories;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges Root Items
|
* Merges Root Items
|
||||||
* Ragfair allows abnormally large stacks.
|
* Ragfair allows abnormally large stacks.
|
||||||
|
@ -58,6 +58,7 @@ export class TraderAssortHelper
|
|||||||
* Filter out assorts not unlocked due to level OR quest completion
|
* Filter out assorts not unlocked due to level OR quest completion
|
||||||
* @param sessionId session id
|
* @param sessionId session id
|
||||||
* @param traderId traders id
|
* @param traderId traders id
|
||||||
|
* @param flea Should assorts player hasn't unlocked be returned - default false
|
||||||
* @returns a traders' assorts
|
* @returns a traders' assorts
|
||||||
*/
|
*/
|
||||||
public getAssort(sessionId: string, traderId: string, flea = false): ITraderAssort
|
public getAssort(sessionId: string, traderId: string, flea = false): ITraderAssort
|
||||||
|
@ -154,7 +154,7 @@ export interface Blacklist
|
|||||||
enableBsgList: boolean;
|
enableBsgList: boolean;
|
||||||
/** Should quest items be blacklisted from flea */
|
/** Should quest items be blacklisted from flea */
|
||||||
enableQuestList: boolean;
|
enableQuestList: boolean;
|
||||||
/** Should trader items that are blacklisted by bsg */
|
/** Should trader items that are blacklisted by bsg be listed on flea */
|
||||||
traderItems: boolean;
|
traderItems: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { RagfairOfferGenerator } from "@spt-aki/generators/RagfairOfferGenerator
|
|||||||
import { TraderAssortHelper } from "@spt-aki/helpers/TraderAssortHelper";
|
import { TraderAssortHelper } from "@spt-aki/helpers/TraderAssortHelper";
|
||||||
import { TraderHelper } from "@spt-aki/helpers/TraderHelper";
|
import { TraderHelper } from "@spt-aki/helpers/TraderHelper";
|
||||||
import { IRagfairOffer } from "@spt-aki/models/eft/ragfair/IRagfairOffer";
|
import { IRagfairOffer } from "@spt-aki/models/eft/ragfair/IRagfairOffer";
|
||||||
|
import { ISearchRequestData } from "@spt-aki/models/eft/ragfair/ISearchRequestData";
|
||||||
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
||||||
import { Traders } from "@spt-aki/models/enums/Traders";
|
import { Traders } from "@spt-aki/models/enums/Traders";
|
||||||
import { IRagfairConfig } from "@spt-aki/models/spt/config/IRagfairConfig";
|
import { IRagfairConfig } from "@spt-aki/models/spt/config/IRagfairConfig";
|
||||||
@ -82,14 +83,9 @@ export class RagfairServer
|
|||||||
return Object.keys(this.ragfairConfig.traders).filter((x) => this.ragfairConfig.traders[x]);
|
return Object.keys(this.ragfairConfig.traders).filter((x) => this.ragfairConfig.traders[x]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getAllCategories(): Record<string, number>
|
public getAllActiveCategories(fleaUnlocked: boolean, searchRequestData: ISearchRequestData, offers: IRagfairOffer[]): Record<string, number>
|
||||||
{
|
{
|
||||||
return this.ragfairCategoriesService.getAllCategories();
|
return this.ragfairCategoriesService.getCategoriesFromOffers(offers, searchRequestData, fleaUnlocked);
|
||||||
}
|
|
||||||
|
|
||||||
public getBespokeCategories(offers: IRagfairOffer[]): Record<string, number>
|
|
||||||
{
|
|
||||||
return this.ragfairCategoriesService.getBespokeCategories(offers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,96 +1,71 @@
|
|||||||
import { inject, injectable } from "tsyringe";
|
import { inject, injectable } from "tsyringe";
|
||||||
|
|
||||||
|
import { PaymentHelper } from "@spt-aki/helpers/PaymentHelper";
|
||||||
import { IRagfairOffer } from "@spt-aki/models/eft/ragfair/IRagfairOffer";
|
import { IRagfairOffer } from "@spt-aki/models/eft/ragfair/IRagfairOffer";
|
||||||
|
import { ISearchRequestData, OfferOwnerType } from "@spt-aki/models/eft/ragfair/ISearchRequestData";
|
||||||
|
import { MemberCategory } from "@spt-aki/models/enums/MemberCategory";
|
||||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class RagfairCategoriesService
|
export class RagfairCategoriesService
|
||||||
{
|
{
|
||||||
protected categories: Record<string, number> = {};
|
constructor(
|
||||||
|
@inject("WinstonLogger") protected logger: ILogger,
|
||||||
constructor(@inject("WinstonLogger") protected logger: ILogger)
|
@inject("PaymentHelper") protected paymentHelper: PaymentHelper,
|
||||||
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all flea categories and their count of offers
|
* Get a dictionary of each item the play can see in their flea menu, filtered by what is available for them to buy
|
||||||
* @returns item categories and count
|
* @param offers All offers in flea
|
||||||
|
* @param searchRequestData Search criteria requested
|
||||||
|
* @param fleaUnlocked Can player see full flea yet (level 15 by default)
|
||||||
|
* @returns KVP of item tpls + count of offers
|
||||||
*/
|
*/
|
||||||
public getAllCategories(): Record<string, number>
|
public getCategoriesFromOffers(offers: IRagfairOffer[], searchRequestData: ISearchRequestData, fleaUnlocked: boolean): Record<string, number>
|
||||||
{
|
{
|
||||||
return this.categories;
|
const validOffersForPlayerToSee = {};
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* With the supplied items, get custom categories
|
|
||||||
* @returns a custom list of categories
|
|
||||||
*/
|
|
||||||
public getBespokeCategories(offers: IRagfairOffer[]): Record<string, number>
|
|
||||||
{
|
|
||||||
return this.processOffersIntoCategories(offers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take an array of ragfair offers and create a dictionary of items with thier corrisponding offer count
|
|
||||||
* @param offers ragfair offers
|
|
||||||
* @returns categories and count
|
|
||||||
*/
|
|
||||||
protected processOffersIntoCategories(offers: IRagfairOffer[]): Record<string, number>
|
|
||||||
{
|
|
||||||
const result = {};
|
|
||||||
for (const offer of offers)
|
for (const offer of offers)
|
||||||
{
|
{
|
||||||
this.addOrIncrementCategory(offer, result);
|
const isTraderOffer = offer.user.memberType === MemberCategory.TRADER;
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
// Not level 15 and offer is from player, skip
|
||||||
}
|
if (!fleaUnlocked && !isTraderOffer)
|
||||||
|
|
||||||
/**
|
|
||||||
* Increment or decrement a category array
|
|
||||||
* @param offer Offer to process
|
|
||||||
* @param categories Categories to update
|
|
||||||
* @param increment (Optional) Should item be incremented or decremented
|
|
||||||
*/
|
|
||||||
protected addOrIncrementCategory(offer: IRagfairOffer, categories: Record<string, number>, increment = true): void
|
|
||||||
{
|
|
||||||
const itemId = offer.items[0]._tpl;
|
|
||||||
if (increment)
|
|
||||||
{
|
|
||||||
categories[itemId] = categories[itemId] ? categories[itemId] + 1 : 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No category, no work to do
|
|
||||||
if (categories[itemId])
|
|
||||||
{
|
{
|
||||||
categories[itemId]--;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove category entirely as its 0 or less
|
// Remove items not for money when `removeBartering` is enabled
|
||||||
if (categories[itemId] < 1)
|
if (searchRequestData.removeBartering && (offer.requirements.length > 1 || !this.paymentHelper.isMoneyTpl(offer.requirements[0]._tpl)))
|
||||||
{
|
{
|
||||||
delete categories[itemId];
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove when filter set to players only + offer is from trader
|
||||||
|
if (searchRequestData.offerOwnerType === OfferOwnerType.PLAYEROWNERTYPE && isTraderOffer)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove when filter set to traders only + offer is not from trader
|
||||||
|
if (searchRequestData.offerOwnerType === OfferOwnerType.TRADEROWNERTYPE && !isTraderOffer)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemTpl = offer.items[0]._tpl
|
||||||
|
|
||||||
|
if (!validOffersForPlayerToSee[itemTpl])
|
||||||
|
{
|
||||||
|
validOffersForPlayerToSee[itemTpl] = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
validOffersForPlayerToSee[itemTpl]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return validOffersForPlayerToSee;
|
||||||
* Increase category count by 1
|
|
||||||
* @param offer
|
|
||||||
*/
|
|
||||||
public incrementCategory(offer: IRagfairOffer): void
|
|
||||||
{
|
|
||||||
this.addOrIncrementCategory(offer, this.categories);
|
|
||||||
this.categories[offer.items[0]._tpl]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reduce category count by 1
|
|
||||||
* @param offer
|
|
||||||
*/
|
|
||||||
public decrementCategory(offer: IRagfairOffer): void
|
|
||||||
{
|
|
||||||
this.addOrIncrementCategory(offer, this.categories, false);
|
|
||||||
this.categories[offer.items[0]._tpl]--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
|||||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||||
import { SaveServer } from "@spt-aki/servers/SaveServer";
|
import { SaveServer } from "@spt-aki/servers/SaveServer";
|
||||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||||
import { RagfairCategoriesService } from "@spt-aki/services/RagfairCategoriesService";
|
|
||||||
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
||||||
import { RagfairOfferHolder } from "@spt-aki/utils/RagfairOfferHolder";
|
import { RagfairOfferHolder } from "@spt-aki/utils/RagfairOfferHolder";
|
||||||
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
|
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
|
||||||
@ -33,7 +32,6 @@ export class RagfairOfferService
|
|||||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||||
@inject("SaveServer") protected saveServer: SaveServer,
|
@inject("SaveServer") protected saveServer: SaveServer,
|
||||||
@inject("RagfairServerHelper") protected ragfairServerHelper: RagfairServerHelper,
|
@inject("RagfairServerHelper") protected ragfairServerHelper: RagfairServerHelper,
|
||||||
@inject("RagfairCategoriesService") protected ragfairCategoriesService: RagfairCategoriesService,
|
|
||||||
@inject("ProfileHelper") protected profileHelper: ProfileHelper,
|
@inject("ProfileHelper") protected profileHelper: ProfileHelper,
|
||||||
@inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder,
|
@inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder,
|
||||||
@inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil,
|
@inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil,
|
||||||
@ -222,9 +220,6 @@ export class RagfairOfferService
|
|||||||
this.returnPlayerOffer(staleOffer);
|
this.returnPlayerOffer(staleOffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reduce category count by 1 as offer is now stale and about to be removed
|
|
||||||
this.ragfairCategoriesService.decrementCategory(staleOffer);
|
|
||||||
|
|
||||||
// Remove expired existing offer from global offers
|
// Remove expired existing offer from global offers
|
||||||
this.removeOfferById(staleOffer._id);
|
this.removeOfferById(staleOffer._id);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user