Repository URL to install this package:
|
Version:
0.4.190 ▾
|
lib-py-b2b
/
embargo.py
|
|---|
# from collections import namedtuple
# from datetime import datetime, timezone
# import time
# from dateutil.parser import isoparse, parse
# from dateutil.tz import UTC
#
# from lib_b2b.util import group_by
# from .calendar import next_manufacturing_day
#
# """
# BIAB
# ----
# Now Changed to immediate availability
# ---orders between midnight to 3pm show up at 3pm => orders between 04:00:00Z and 19:00:00Z show up at day+0 19:00:00Z
# ---orders between 3pm and midnight show up at 6am => orders between 19:00:01Z and 23:59:59Z show up at day+1 10:00:00Z
# orders between 00:00:00Z and 04:00:00Z show up at day+0 10:00:00Z
#
#
# Indigo
# ------
# orders after 3pm show on the following day after 12pm => orders between 19:00:00Z and 23:59:59Z show up at day+1 16:00:00Z
# orders between 00:00:01Z and 18:59:59Z show up at day+0 16:00:00Z
#
#
# RDME
# ----
# orders show 1 hour after receipt => show up at day+0, hour+1
# """
#
# # TODO: - Migrate this to be data driven
# # I should be able to define a data format for the rules.
# # For example, x time to y time ship_date = next manufacturing day + 1, release_date = next manufacturing day
# # I should be able to define per customer the valid manufacturing
# # days. For example, Indigo is Tues-Fri excluding holidays.
#
#
# class DisplayFunction:
# def display_at(self, order_date: datetime) -> datetime:
# pass
#
#
# class ManufactureFunction:
# def make_at(self, order_date: datetime, ignore_offset=False) -> datetime:
# pass
#
#
# class GenericDisplayFunction(DisplayFunction):
# def __init__(self, hour: int = None, minute: int = 0, second: int = 0, offset: int = 0):
# self.offset = offset
# self.hour = hour
# self.minute = minute
# self.second = second
#
# def display_at(self, order_date: datetime) -> datetime:
# if not self.hour and not self.minute and not self.second and not self.offset:
# return order_date
# _dt = next_manufacturing_day(ccn='402100', from_date=order_date, offset=self.offset)
# if self.hour:
# # return datetime(_dt.year, _dt.month, _dt.day, self.hour, self.minute, self.second)
# return datetime(_dt.year, _dt.month, _dt.day, self.hour, self.minute, self.second, tzinfo=UTC)
# else:
# return _dt
#
# def __str__(self):
# local_release_time = time.localtime(int(self.hour or 0) * 60 * 60 + int(self.minute) * 60 + int(self.second) * 1)
# if self.offset == 0 and self.hour is None:
# return f"available immediately"
# elif self.offset == 0 and self.hour is not None:
# return f"available same day at {time.strftime('%I:%M %p %Z', local_release_time)}"
# elif self.offset == 1:
# return f"available next day at {time.strftime('%I:%M %p %Z', local_release_time)}"
# else:
# f"available {self.offset} days"
#
#
# class GenericManufactureFunction(ManufactureFunction):
# def __init__(self, offset: int):
# self.offset = offset
#
# def make_at(self, order_date: datetime, ignore_offset=False) -> datetime:
# _offset = 0 if ignore_offset else self.offset
# mfg_date = next_manufacturing_day(ccn='402100', from_date=order_date, offset=_offset)
# return mfg_date
#
# def __str__(self):
# if self.offset == 0:
# return "same day"
# elif self.offset == 1:
# return "next day (M-F)"
# else:
# return f"{self.offset} manufacturing days (M-F)"
#
#
# class IndigoManufactureFunction(ManufactureFunction):
# def __init__(self, offset: int):
# self.offset = offset
#
# def make_at(self, order_date: datetime, ignore_offset=False) -> datetime:
# _offset = 0 if ignore_offset else self.offset
# if order_date.weekday() in range(4, 7) and self.offset < 2:
# _offset += 1
# mfg_date = next_manufacturing_day(ccn='402100', from_date=order_date, offset=_offset)
# return mfg_date
#
# def __str__(self):
# if self.offset == 0:
# return "same day"
# elif self.offset == 1:
# return "next day (M-F)"
# else:
# return f"{self.offset} manufacturing days (M-F)"
#
# class DisplayRule:
# def __init__(self, customer_edi_id, start_time, end_time, display_func: DisplayFunction, mfg_func: ManufactureFunction):
# self.customer_edi_id = customer_edi_id
# self.start_time = start_time
# self.end_time = end_time
# self.display_func = display_func
# self.mfg_func = mfg_func
#
# def __convert_to_seconds(self, value):
# if isinstance(value, datetime):
# return value.hour*60*60 + value.minute*60 + value.second*1
# elif isinstance(value, str):
# dt_arr = value.split(':')
# return int(dt_arr[0]) * 60 * 60 + int(dt_arr[1]) * 60 + int(dt_arr[2]) * 1
# else:
# return None
#
# @property
# def local_start_time(self):
# return time.localtime(self.__convert_to_seconds(self.start_time))
#
# @property
# def local_end_time(self):
# return time.localtime(self.__convert_to_seconds(self.end_time))
#
# def matches(self, customer_edi_id, order_date):
# if customer_edi_id != self.customer_edi_id:
# return False
#
# _order_date = order_date
# if isinstance(order_date, str):
# _order_date = isoparse(order_date)
# # print(_order_date)
# order_tm = self.__convert_to_seconds(_order_date)
# # print(order_tm)
# start_tm = self.__convert_to_seconds(self.start_time)
# # print(start_tm)
# end_tm = self.__convert_to_seconds(self.end_time)
# # print(end_tm)
# return start_tm <= order_tm <= end_tm
#
# def display_at(self, order_date) -> datetime:
# _order_date = order_date
# if isinstance(order_date, str):
# _order_date = isoparse(order_date)
# return self.display_func.display_at(_order_date)
#
# def make_at(self, order_date, ignore_offset=False) -> datetime:
# _order_date = order_date
# if isinstance(order_date, str):
# _order_date = isoparse(order_date)
# return self.mfg_func.make_at(_order_date, ignore_offset)
#
# def __str__(self):
# return f"{self.customer_edi_id} - {self.start_time} - {self.end_time}"
#
# @property
# def description(self):
# return f"{self.customer_edi_id} : " \
# f"{time.strftime('%I:%M %p %Z', self.local_start_time)} - {time.strftime('%I:%M %p %Z', self.local_end_time)} : " \
# f"Embargo: {str(self.display_func)} : " \
# f"Ship: {str(self.mfg_func)} "
#
# __repr__ = __str__
#
#
# biab_rules = [
# DisplayRule('4021001305', '04:00:00', '18:59:59', GenericDisplayFunction(), GenericManufactureFunction(offset=1)),
# DisplayRule('4021001305', '19:00:00', '23:59:59', GenericDisplayFunction(), GenericManufactureFunction(offset=1)),
# DisplayRule('4021001305', '00:00:00', '03:59:59', GenericDisplayFunction(), GenericManufactureFunction(offset=0))
# ]
#
# sleepdog_rules = [
# DisplayRule('402100200186', '05:00:00', '19:59:59', GenericDisplayFunction(), GenericManufactureFunction(offset=1)),
# DisplayRule('402100200186', '19:00:00', '23:59:59', GenericDisplayFunction(), GenericManufactureFunction(offset=1)),
# DisplayRule('402100200186', '00:00:00', '03:59:59', GenericDisplayFunction(), GenericManufactureFunction(offset=0))
# ]
#
# indigo_rules = [
# DisplayRule('402100100554', '19:00:00', '23:59:59', GenericDisplayFunction(hour=16, offset=1), IndigoManufactureFunction(offset=2)),
# DisplayRule('402100100554', '00:00:00', '18:59:59', GenericDisplayFunction(hour=16), IndigoManufactureFunction(offset=1))
# ]
#
# letsgel_rules = [
# DisplayRule('402100200002', '19:00:00', '23:59:59', GenericDisplayFunction(hour=16, offset=1), IndigoManufactureFunction(offset=2)),
# DisplayRule('402100200002', '00:00:00', '18:59:59', GenericDisplayFunction(hour=16), IndigoManufactureFunction(offset=1))
# ]
#
# rdme_rules = [
# DisplayRule('705700100991', '00:00:00', '23:59:59', GenericDisplayFunction(offset=0), GenericManufactureFunction(offset=0))
# ]
#
# all_rules = [y for x in [biab_rules, indigo_rules, rdme_rules, letsgel_rules, sleepdog_rules] for y in x]
#
#
# CalculatedDate = namedtuple('CalculatedDate', 'date rule')
#
#
# def determine_release_date(customer_edi_id, order_date):
# _order_date = order_date
# if isinstance(order_date, str):
# _order_date = parse(order_date)
# else:
# _order_date = order_date
# _order_date = _order_date.astimezone(timezone.utc)
# release_on_holder = {'release_on': _order_date, 'rule_used': None}
# for rule in all_rules:
# if rule.matches(customer_edi_id, _order_date):
# release_on_holder['release_on'] = rule.display_at(_order_date)
# release_on_holder['rule_used'] = str(rule)
# return CalculatedDate(release_on_holder['release_on'], release_on_holder['rule_used'])
#
#
# def determine_make_date(customer_edi_id, order_date, ignore_offset=False):
# _order_date = order_date
# if isinstance(order_date, str):
# _order_date = parse(order_date)
# else:
# _order_date = order_date
# _order_date = _order_date.astimezone(timezone.utc)
# _holder = {'make_on': _order_date, 'rule_used': None}
# for rule in all_rules:
# if rule.matches(customer_edi_id, _order_date):
# make_date = rule.make_at(_order_date, ignore_offset)
# # make_date = make_date.replace(hour=0, minute=0, second=0, microsecond=0, tzinfo=None)
# _holder['make_on'] = make_date
# _holder['rule_used'] = str(rule)
# return CalculatedDate(_holder['make_on'], _holder['rule_used'])
#
#
# def print_rules(customer_edi_id = None):
# customer_rule_idx = group_by(lambda x: x.customer_edi_id, all_rules)
# for customer in customer_rule_idx.keys():
# print(customer)
# print('*' * 40)
# for rule in customer_rule_idx[customer]:
# print(rule)
# print(rule.description)
#
#