generated from the-collab-lab/smart-shopping-list
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #45 from the-collab-lab/nk-estimate-next-purchase-…
…date [ISSUE 11] Nk estimate next purchase date
- Loading branch information
Showing
13 changed files
with
204 additions
and
56 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,116 @@ | ||
const ONE_DAY_IN_MILLISECONDS = 86400000; | ||
import { calculateEstimate } from '@the-collab-lab/shopping-list-utils'; | ||
|
||
export const ONE_DAY_IN_MILLISECONDS = 86400000; | ||
|
||
/** | ||
* Get a new JavaScript Date that is `offset` days in the future. | ||
* @example | ||
* // Returns a Date 3 days in the future | ||
* getFutureDate(3) | ||
* @param {number} offset | ||
* addDaysFromToday(3) | ||
* @param {number} daysOffset | ||
*/ | ||
export function addDaysFromToday(daysOffset) { | ||
return new Date(Date.now() + daysOffset * ONE_DAY_IN_MILLISECONDS); | ||
} | ||
|
||
/** | ||
* Calculates the estimated date for the next purchase based on current date, purchase history, | ||
* and total purchases. | ||
* @param {Date} currentDate - The current date to calculate against. | ||
* @param {Object} item - The item object containing purchase data. | ||
* @param {Date} item.dateCreated - The date the item was created. | ||
* @param {Date} item.dateNextPurchased - The previously estimated next purchase date. | ||
* @param {Date|null} item.dateLastPurchased - The last date the item was actually purchased, or null if not purchased yet. | ||
* @param {number} item.totalPurchases - The total number of purchases made for the item. | ||
* @returns {Date} - The estimated date of the next purchase. | ||
* @throws {Error} - Throws an error if the next purchase date cannot be calculated. | ||
*/ | ||
export const calculateDateNextPurchased = (currentDate, item) => { | ||
try { | ||
// get purchase intervals and get new estimation for next purchase date | ||
const purchaseIntervals = calculatePurchaseIntervals( | ||
currentDate, | ||
item.dateCreated, | ||
item.dateNextPurchased, | ||
item.dateLastPurchased, | ||
); | ||
const estimatedNextPurchaseDate = getNextPurchaseEstimate( | ||
purchaseIntervals, | ||
item.totalPurchases + 1, | ||
); | ||
|
||
return estimatedNextPurchaseDate; | ||
} catch (error) { | ||
throw new Error(`Failed getting next purchase date: ${error}`); | ||
} | ||
}; | ||
|
||
/** | ||
* Calculate the number of days between two dates. | ||
* @param {Date} earlierDate The starting date. | ||
* @param {Date} laterDate The ending date. | ||
* @returns {number} The number of days between the two dates. | ||
*/ | ||
function getDaysBetweenDates(earlierDate, laterDate) { | ||
return Math.floor( | ||
(laterDate.getTime() - earlierDate.getTime()) / ONE_DAY_IN_MILLISECONDS, | ||
); | ||
} | ||
|
||
/** | ||
* Calculate the purchase intervals between current, next, and last purchase dates. | ||
* @param {Date} currentDate The current date. | ||
* @param {Date} dateNextPurchased The previously estimated next purchase date. | ||
* @param {Date|null} dateLastPurchased The date the item was last purchased (can be null). | ||
* @returns {Object} An object containing the last estimated interval and days since last purchase. | ||
*/ | ||
function calculatePurchaseIntervals( | ||
currentDate, | ||
dateCreated, | ||
dateNextPurchased, | ||
dateLastPurchased, | ||
) { | ||
const lastPurchaseDate = dateLastPurchased?.toDate(); | ||
|
||
const lastEstimatedIntervalStartDate = | ||
lastPurchaseDate ?? dateCreated.toDate(); | ||
|
||
const lastEstimatedInterval = getDaysBetweenDates( | ||
lastEstimatedIntervalStartDate, | ||
dateNextPurchased.toDate(), | ||
); | ||
|
||
const daysSinceLastPurchase = | ||
lastPurchaseDate === undefined | ||
? 0 | ||
: getDaysBetweenDates(lastPurchaseDate, currentDate); | ||
|
||
return { lastEstimatedInterval, daysSinceLastPurchase }; | ||
} | ||
|
||
/** | ||
* Calculate the next purchase estimate based on purchase intervals and total purchases. | ||
* @param {Object} purchaseIntervals The intervals between the previous and current purchases. | ||
* @param {number} purchaseIntervals.lastEstimatedInterval The previously estimated number of days between purchases. | ||
* @param {number} purchaseIntervals.daysSinceLastPurchase The number of days since the last purchase. | ||
* @param {number} totalPurchases The total number of purchases made. | ||
* @returns {Date} The estimated next purchase date. | ||
* @throws {Error} If an error occurs during the next purchase estimation process. | ||
*/ | ||
export function getFutureDate(offset) { | ||
return new Date(Date.now() + offset * ONE_DAY_IN_MILLISECONDS); | ||
function getNextPurchaseEstimate(purchaseIntervals, totalPurchases) { | ||
const { lastEstimatedInterval, daysSinceLastPurchase } = purchaseIntervals; | ||
|
||
try { | ||
const estimatedDaysUntilPurchase = calculateEstimate( | ||
lastEstimatedInterval, | ||
daysSinceLastPurchase, | ||
totalPurchases, | ||
); | ||
|
||
const nextPurchaseEstimate = addDaysFromToday(estimatedDaysUntilPurchase); | ||
|
||
return nextPurchaseEstimate; | ||
} catch (error) { | ||
throw new Error(`Failed updaing date next purchased: ${error}`); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.