Exemple #1
0
    def add(self, product):
        """
        :param product: The order that will be added to the machine
        :return: Adds the order to the work center to be scheduled
        """
        product.scheduled = True  # Sets the order as scheduled
        self.products[product.id] = product  # Adds the order to the work center
        changeDuration(product, self.availability)  # Changes the duration of making the order based on the availability of the work center
        add_time = getMouldChangeTime(product.moulds)
        total_time = new_time(self.remainder.year, self.remainder.month, self.remainder.day + (product.time.day - 1), self.remainder.hour + product.time.hour, self.remainder.minute + product.time.minute + add_time, self.remainder.second + product.time.second)

        add_time = 0
        if len(product.combined) > 1:  # There are orders combined
            comb_orders = []
            old_insert = product.insert
            product.combined = order_combined_orders(product, addcolor(product.id), old_insert, comb_orders)

            for p in product.combined:  # For each combined product add the duration and insert change time
                if len(old_insert) == len(p.insert):
                    bo = True
                    for ins in old_insert:
                        if not ins in p.insert:
                            bo = False
                    if not bo:  # There is an insert change
                        add_time += getInsertChangeTime(p.moulds)
                        old_insert = p.insert
                elif len(old_insert) != len(p.insert):  # There is an insert change
                    add_time += getInsertChangeTime(p.moulds)
                    old_insert = p.insert
        self.remainder = new_time(total_time.year, total_time.month, total_time.day, total_time.hour, total_time.minute + add_time, total_time.second)
Exemple #2
0
    def first(self, product):
        """
        :param product: The order to schedule on the work center
        :return: The order is scheduled as the first order on the work center
        """
        begin = self.m_date  # The date that the planning starts
        end = new_time(self.m_date.year, self.m_date.month + (product.duration.month - 1), self.m_date.day + (product.duration.day - 1), self.m_date.hour + product.duration.hour, self.m_date.minute + product.duration.minute, self.m_date.second + product.duration.second)
        self.schedule.append([product, begin, end])  # Adds the information for the schedule
        self.old_insert = product.insert  # Changes the last insert used
        self.old_mould = product.moulds  # Changes the last mould used

        if len(product.combined) > 0:  # Schedule orders with the same mould (combined)
            comb_orders = []
            old_insert = product.insert
            product.combined = order_combined_orders(product, addcolor(product.id), old_insert, comb_orders)

            for p in product.combined:  # Each combined order is planned
                add_time = 0
                if len(self.old_insert) == len(product.insert):  # The inserts could be the same (same number of inserts)
                    bo = True
                    for ins in self.old_insert:
                        if not ins in product.insert:
                            bo = False
                    if not bo:  # The inserts are different
                        add_time = getInsertChangeTime(p.moulds)
                        self.old_insert = p.insert
                else:
                    add_time = getInsertChangeTime(p.moulds)
                    self.old_insert = p.insert
                begin = new_time(end.year, end.month, end.day, end.hour, end.minute + add_time, end.second)
                end = new_time(begin.year, begin.month, begin.day + (p.duration.day - 1), begin.hour + p.duration.hour, begin.minute + p.duration.minute, begin.second + p.duration.second)
                self.schedule.append([p, begin, end])  # Information for the schedule
        self.m_date = end
Exemple #3
0
def mouldChangeCapacity(start_date, end_date):
    mould_change_capacity = pd.read_excel(
        'Mould change capacity.xlsx',
        header=0)  # The amount of mould changes that can be done
    mould_change_capacity['Date'] = mould_change_capacity['Date'].astype(str)
    mould_change_capacity = mould_change_capacity.set_index('Date')
    morning_shift = mould_change_capacity[
        'Morning shift']  # The capacity of the morning shift
    afternoon_shift = mould_change_capacity[
        'Afternoon shift']  # The capacity of the afternoon shift
    night_shift = mould_change_capacity[
        'Night shift']  # The capacity of the night shift
    change_capacity = {
    }  # The dict containing all the mould change capacities of every planning day
    date = start_date  # The date that the planning starts
    while date <= end_date:
        if str(
                date
        ) in mould_change_capacity.index:  # Fill up with the given capacity for each date
            change_capacity[str(date)] = [
                morning_shift[str(date)], afternoon_shift[str(date)],
                night_shift[str(date)]
            ]
        else:
            change_capacity[str(date)] = [
                4, 3, 3
            ]  # Fills up the (standard) capacity for each date
        date = new_time(date.year, date.month, date.day + 1)
    return change_capacity
Exemple #4
0
def ChangeMould(work_center_id, product, old_mould, m_date, mould_changes,
                mould_change_capacity):
    """
    :param work_center_id: The number of the work center that the mould is changed on
    :param product: The product that is the reason the mould needs to be changed
    :param old_mould: The mould that was previously on the work center
    :param m_date: The current date and time of the planning of the work center
    :param mould_changes: The list containg all the mould changes that have already happened
    :param mould_change_capacity: A list containing the number of mould changes that can still happen for each shift each day
    :return: The mould change is scheduled and the date and time that the mould change ends is returned
    """
    """
    Get a possible datetime for the mould change to start 
    when there is still capacity left
    """
    begin = m_date  # The date and time that the mould change begins
    change = False  # True if the mould change can happen at this time according to the capacity
    while not change:
        if not str(
                datetime.datetime(begin.year, begin.month, begin.day)
        ) in mould_change_capacity.keys(
        ):  # The mould change tries to be scheduled outside the allowed date range
            return False
        if 6 <= begin.hour <= 14:  # 6am - 2pm
            if mould_change_capacity[str(
                    datetime.datetime(begin.year, begin.month, begin.day)
            )][0] > 0:  # The capacity allows a mould change
                mould_change_capacity[str(
                    datetime.datetime(
                        begin.year, begin.month,
                        begin.day))][0] -= 1  # The capacity gets decreased
                change = True  # The mould change will get planned
            else:
                begin = new_time(begin.year, begin.month, begin.day,
                                 begin.hour + 1, begin.minute, begin.second)
        elif 14 <= begin.hour <= 22:  # 2pm - 10pm
            if mould_change_capacity[str(
                    datetime.datetime(begin.year, begin.month, begin.day)
            )][1] > 0:  # The capacity allows a mould change
                mould_change_capacity[str(
                    datetime.datetime(begin.year, begin.month,
                                      begin.day))][1] -= 1
                change = True
            else:
                begin = new_time(begin.year, begin.month, begin.day,
                                 begin.hour + 1, begin.minute, begin.second)
        elif 22 <= begin.hour <= 24 or 0 <= begin.hour <= 6:  # 10 pm - 6am
            if mould_change_capacity[str(
                    datetime.datetime(begin.year, begin.month, begin.day)
            )][2] > 0:  # The capacity allows a mould change
                mould_change_capacity[str(
                    datetime.datetime(begin.year, begin.month,
                                      begin.day))][2] -= 1
                change = True
            else:
                begin = new_time(begin.year, begin.month, begin.day,
                                 begin.hour + 1, begin.minute, begin.second)
    """
    Get the time that the changes of the old and new mould are done
    """
    add_time = getMouldChangeTime(product.moulds, type_when="in")
    add_time += getMouldChangeTime(old_mould, type_when="out")
    finished = new_time(begin.year, begin.month, begin.day, begin.hour,
                        begin.minute + add_time, begin.second)
    """
    Find whether there are problems scheduling the mould change
    If there is a problem, the change will be tried to be scheduled 10 min later
    """
    if not problem(
            begin, finished, mould_changes
    ):  # There isn't a conflict while changing the mould (only 1 change at a time)
        mouldChange(begin, finished, mould_changes, work_center_id,
                    product.order, product.moulds, "Change between moulds")
    else:  # There is a conflict while changing the mould at this time
        if 6 <= begin.hour <= 14:  # 6am - 2pm
            mould_change_capacity[str(
                datetime.datetime(
                    begin.year, begin.month,
                    begin.day))][0] += 1  # Turn back the change in capacity
        elif 14 <= begin.hour <= 22:  # 2pm - 10pm
            mould_change_capacity[str(
                datetime.datetime(begin.year, begin.month, begin.day))][1] += 1
        elif 22 <= begin.hour <= 24 or 0 <= begin.hour <= 6:  # 10 pm - 6am
            mould_change_capacity[str(
                datetime.datetime(begin.year, begin.month, begin.day))][2] += 1
        m_date = new_time(begin.year, begin.month, begin.day, begin.hour,
                          begin.minute + 10, begin.second)
        return ChangeMould(
            work_center_id, product, old_mould, m_date, mould_changes,
            mould_change_capacity)  # Plan the mould change again
    return finished  # There is no conflict, so return the time when the mould change is done
Exemple #5
0
    def scheduleTime(self, product, mould_changes, mould_change_capacity, not_planned, end_date):
        """
        :param product: The order that needs to be scheduled
        :param mould_changes: The list containing all mould changes
        :param mould_change_capacity: A dict containing the mould change capacity for each day
        :param not_planned:
        :param end_date:
        :return: Schedules the order on the work center
        """
        begin = self.m_date  # The current date of the planning
        if begin >= end_date:
            not_planned.append([product.id, "No capacity for order on machine", product.order])
            for p in product.combined:
                not_planned.append([p.id, "No capacity for order on machine in for", p.order])
            return

        """ Schedule mould change if necessary """
        if self.old_mould == 'nan' or str(product.moulds) != self.old_mould:  # There is a mould change
            begin = ChangeMould(self.id, product, self.old_mould, self.m_date, mould_changes, mould_change_capacity)  # Change the mould
            if not begin:  # The mould change couldn't be scheduled in time with the capacity
                not_planned.append([product.id, "No capacity for mould change", product.order])
                for p in product.combined:
                    not_planned.append([p.id, "No capacity for mould change", p.order])
                return
            self.old_mould = str(product.moulds)  # Change the last used mould of the work center

        """ Insert change if necessary """
        if self.schedule != [] and self.old_mould != 'nan' and str(product.moulds) == self.old_mould:  # Same mould
            add_time = 0
            if len(self.old_insert) == len(product.insert):
                bo = True
                for ins in self.old_insert:
                    if not ins in product.insert:
                        bo = False
                if not bo:  # Insert change
                    add_time = getInsertChangeTime(product.moulds)
                    self.old_insert = product.insert
                begin = new_time(begin.year, begin. month, begin.day, begin.hour, begin.minute + add_time, begin.second)
            elif len(self.old_insert) != len(product.insert):  # Insert change
                add_time = getInsertChangeTime(product.moulds)
                self.old_insert = product.insert
                begin = new_time(begin.year, begin. month, begin.day, begin.hour, begin.minute + add_time, begin.second)

        if begin >= end_date:
            not_planned.append([product.id, "No capacity for order on machine", product.order])
            for p in product.combined:
                not_planned.append([p.id, "No capacity for order on machine", p.order])
            return

        end = new_time(begin.year, begin.month, begin.day + (product.duration.day - 1), begin.hour + product.duration.hour, begin.minute + product.duration.minute, begin.second + product.duration.second)
        self.schedule.append([product, begin, end])  # Add order to schedule
        self.m_date = end  # Set time of work center

        if len(product.combined) > 0:  # Has Orders with same mould
            no_capacity = False
            for p in product.combined:  # Schedule each combined order
                if not no_capacity:
                    begin = end

                    """ Insert change if necessary """
                    add_time = 0
                    if len(self.old_insert) == len(p.insert):
                        bo = True
                        for ins in self.old_insert:
                            if not ins in p.insert:
                                bo = False
                        if not bo:  # Insert change
                            add_time = getInsertChangeTime(p.moulds)
                            begin = new_time(end.year, end. month, end.day, end.hour, end.minute + add_time, end.second)
                            self.old_insert = p.insert
                    elif len(self.old_insert) != len(p.insert):  # Insert change
                        add_time = getInsertChangeTime(p.moulds)
                        begin = new_time(end.year, end. month, end.day, end.hour, end.minute + add_time, end.second)
                        self.old_insert = p.insert

                    end = new_time(begin.year, begin. month, begin.day + (p.duration.day - 1), begin.hour + p.duration.hour, begin.minute + p.duration.minute, begin.second + p.duration.second)

                    if end > end_date:
                        no_capacity = True
                        not_planned.append([p.id, "No capacity for order on machine", p.order])
                        end = self.m_date
                    else:
                        self.schedule.append([p, begin, end])  # Add order to schedule
                        self.m_date = end  # Set time of work center
                elif no_capacity:
                    not_planned.append([p.id, "No capacity for order on machine", p.order])

        self.getUsageTime()
Exemple #6
0
def prioritiseOrdersDf(df, zcs, begin_date, end_date, batchID):
    """
    :param df: The dataframe containing the orders
    :param zcs: The material info containg the number of machines for each item number
    :param begin_date: The date that the planning begins
    :param end_date: The date that the planning end
    :return: Sorts the dataframe of the orders based on priority
    """
    """ Get the different weights """
    connection = db_connection()
    cursor = connection.cursor(
    )  # This code gets the weights given to different aspects of the orders
    cursor.execute('SELECT Weight_1 FROM dbo.Batch WHERE ID = (?)', batchID)
    (weight_date, ) = cursor.fetchone(
    )  # The importance of planning before the needed on date
    cursor.execute('SELECT Weight_2 FROM dbo.Batch WHERE ID = (?)', batchID)
    (weight_promo,
     ) = cursor.fetchone()  # The importance of planing a promo order
    cursor.execute('SELECT Weight_3 FROM dbo.Batch WHERE ID = (?)', batchID)
    (weight_listing,
     ) = cursor.fetchone()  # The importance of plannig a listing order
    """ Get the cutoff points and the dates of these points """
    cursor.execute('SELECT Cutoff_promo FROM dbo.Batch WHERE ID = (?)',
                   batchID)
    (days_over_end_date_promo, ) = cursor.fetchone(
    )  # Promo orders x days over the end date can still be planned
    if days_over_end_date_promo == None:
        days_over_end_date_promo = 0
    cursor.execute('SELECT Cutoff_listing FROM dbo.Batch WHERE ID = (?)',
                   batchID)
    (days_over_end_date_listing, ) = cursor.fetchone(
    )  # Listing orders x days over the end date can still be planned
    if days_over_end_date_listing == None:
        days_over_end_date_listing = 0
    end_date_promo = new_time(end_date.year, end_date.month,
                              end_date.day + days_over_end_date_promo)
    end_date_listing = new_time(end_date.year, end_date.month,
                                end_date.day + days_over_end_date_listing)
    """ 
    Check whether the orders are valid
    If there is a problem the order is removed
    Otherwise it gets a weight based on different criteria
    """
    n_on = df['needed on']
    orig_document = df['Originating document']
    material_number = df['Material']
    work_center = df['Work center']
    order = df['Order']
    in_production = df['Start Point']
    mould_df = df['Mould']
    prio = []  # A list containing the priority of each order
    amoun = [
    ]  # A list containing the amount of machines each order is compatible with
    wrong = [
    ]  # A list containing the orders that aren't planned and the reason why
    for i in range(len(df["Material"])):  # For each order
        # The order is not needed before the cutoff point of the planning
        if (n_on[i] != "nan" and n_on[i] != "None") and (
                not (str(orig_document[i]) == 'nan'
                     or str(orig_document[i]) == 'None')
        ) and n_on[
                i] > end_date_promo:  # promo with needed on date after allowed promo needed on date
            df = df.drop([i])  # Removes the order (row)
            wrong.append([
                str(material_number[i]), "Needed on date after planning",
                str(order[i])
            ])
        elif (n_on[i] != "nan" and n_on[i] != "None") and str(
                orig_document[i]
        ) == 'nan' or str(orig_document[i]) == 'None' and n_on[
                i] > end_date_listing:  # listing with needed on date after allowed listing needed on date
            df = df.drop([i])  # Removes the order (row)
            wrong.append([
                str(material_number[i]), "Needed on date after planning",
                str(order[i])
            ])

        # The order is a dummy order
        elif str(material_number[i]) == 'nan' or str(
                material_number[i]
        ) == 'None':  # If there is no item number --> orders is dummy order
            if str(work_center[i]) != 'nan' and str(
                    work_center[i]
            ) != 'None':  # There has to be a machine given to plan dummy orders
                p = 0  # The priority of the order (lower number is planned/prioritized earlier)
                if n_on[i] == "nan" or n_on[i] == "None":
                    p += (weight_promo + weight_date + weight_listing)
                elif n_on[i] <= begin_date:
                    p -= weight_date
                elif n_on[i] <= end_date:
                    p -= (weight_date / 2)
                else:
                    p += weight_date
                if not (str(orig_document[i]) == 'nan' or str(orig_document[i])
                        == 'None'):  # If it is a promo order
                    p -= weight_promo  # The priority is higher
                if str(orig_document[i]) == 'nan' or str(
                        orig_document[i]
                ) == 'None':  # If it is a listing order
                    p -= weight_listing
                if str(in_production[i]) == str(
                        1):  # If the order is already on a machine
                    p -= (weight_promo + weight_date + weight_listing
                          )  # This is most important
                prio.append(p)
                amoun.append(
                    1
                )  # There is only one machine that the order can be planned on
            else:
                df = df.drop([i])  # Removes the order (row)
                wrong.append([
                    str(material_number[i]),
                    "Dummy order has no Work center in input",
                    str(order[i])
                ])

        # The order is not a dummy order, but the item number isn't in the database
        elif not str(material_number[i]) in zcs.index:
            df = df.drop([i])  # Removes the order (row)
            if mould_df[i] == None or mould_df[i] == 'nan':
                wrong.append(
                    [str(material_number[i]), "Assembly order",
                     str(order[i])])
            else:
                wrong.append([
                    str(material_number[i]),
                    "Item unknown - Material/Mould not known to bot",
                    str(order[i])
                ])

        # The order is a normal order that is in the database
        else:
            """
            If the order has no mould in the input,
            we add one from the zcs04 data or the historical data
            Otherwise the order will be removed
            """
            if str(mould_df[i]) == 'nan' or str(
                    mould_df[i]) == 'None':  # No mould is given
                mould = zcs['Mould'].loc[str(material_number[i])]
                mould_df[
                    i] = mould  # Adds the mould from the zcs part of the material_info dataframe
            if str(mould_df[i]) == "nan" or str(
                    mould_df[i]) == 'None':  # If there still isn't a mould
                try:
                    mould = zcs["('Mould', 'unique')"].loc[str(
                        material_number[i])]
                    mould = mould.replace('[', '')
                    mould = mould.replace(']', '')
                    mould = mould.split(', ')
                    mould_df[
                        i] = mould  # Adds the mould from the historical data
                except:
                    wrong.append([
                        str(material_number[i]), "Item unknown - No mould",
                        str(order[i])
                    ])
            if str(mould_df[i]) == "nan" or str(
                    mould_df[i]
            ) == 'None':  # If the earlier data couldn't give a mould
                df = df.drop([i])  # Removes the order (row)
                wrong.append([
                    str(material_number[i]),
                    "Order has no mould in the input or database",
                    str(order[i])
                ])
            else:  # There is a mould for this order
                p = 0  # The priority of the order (lower number is planned/prioritized earlier)
                if not (str(orig_document[i]) == 'nan' or str(orig_document[i])
                        == 'None'):  # If it is a promo order
                    p = 1  # The priority is higher
                if str(orig_document[i]) == 'nan' or str(
                        orig_document[i]
                ) == 'None':  # If it is a listing order
                    p = 2
                if str(in_production[i]) == str(
                        1):  # If the order is already on a machine
                    p = 0  # This is most important
                prio.append(p)
                amoun.append(zcs['Amount'][str(material_number[i])])

    df['Priority'] = prio  # Adds the priority of each order to the database
    df['Amount'] = amoun  # Adds the amount of compatible machines to each order
    return sortOrdersDf(df), wrong