def handle(self, **options): # Make sure the debug flag is not set! # When it is set, the django database wrapper collects a list of all sql # statements executed and their timings. This consumes plenty of memory # and cpu time. tmp_debug = settings.DEBUG settings.DEBUG = False # Pick up the options if 'verbosity' in options: verbosity = int(options['verbosity']) else: verbosity = 1 if 'cluster' in options: cluster = int(options['cluster']) else: cluster = 100 if 'demand' in options: demand = int(options['demand']) else: demand = 30 if 'forecast_per_item' in options: forecast_per_item = int(options['forecast_per_item']) else: forecast_per_item = 50 if 'level' in options: level = int(options['level']) else: level = 5 if 'resource' in options: resource = int(options['resource']) else: resource = 60 if 'resource_size' in options: resource_size = int(options['resource_size']) else: resource_size = 5 if 'components' in options: components = int(options['components']) else: components = 200 if 'components_per' in options: components_per = int(options['components_per']) else: components_per = 5 if components == 0: components_per = 0 if 'deliver_lt' in options: deliver_lt = int(options['deliver_lt']) else: deliver_lt = 30 if 'procure_lt' in options: procure_lt = int(options['procure_lt']) else: procure_lt = 40 if 'currentdate' in options: currentdate = options['currentdate'] or datetime.strftime( date.today(), '%Y-%m-%d') else: currentdate = datetime.strftime(date.today(), '%Y-%m-%d') if 'database' in options: database = options['database'] or DEFAULT_DB_ALIAS else: database = DEFAULT_DB_ALIAS if database not in settings.DATABASES: raise CommandError("No database settings known for '%s'" % database) if 'user' in options and options['user']: try: user = User.objects.all().using(database).get( username=options['user']) except: raise CommandError("User '%s' not found" % options['user']) else: user = None random.seed(100) # Initialize random seed to get reproducible results now = datetime.now() task = None try: # Initialize the task if 'task' in options and options['task']: try: task = Task.objects.all().using(database).get( pk=options['task']) except: raise CommandError("Task identifier not found") if task.started or task.finished or task.status != "Waiting" or task.name != 'generate model': raise CommandError("Invalid task identifier") task.status = '0%' task.started = now else: task = Task(name='generate model', submitted=now, started=now, status='0%', user=user) task.arguments = "--cluster=%s --demand=%s --forecast_per_item=%s --level=%s --resource=%s " \ "--resource_size=%s --components=%s --components_per=%s --deliver_lt=%s --procure_lt=%s" % ( cluster, demand, forecast_per_item, level, resource, resource_size, components, components_per, deliver_lt, procure_lt ) task.save(using=database) # Pick up the startdate try: startdate = datetime.strptime(currentdate, '%Y-%m-%d') except: raise CommandError( "current date is not matching format YYYY-MM-DD") # Check whether the database is empty if Buffer.objects.using(database).count( ) > 0 or Item.objects.using(database).count() > 0: raise CommandError( "Database must be empty before creating a model") # Plan start date if verbosity > 0: print("Updating current date...") Parameter.objects.using(database).create(name="currentdate", value=datetime.strftime( startdate, "%Y-%m-%d %H:%M:%S")) Parameter.objects.using(database).create(name="plan.loglevel", value="3") # Planning horizon # minimum 10 daily buckets, weekly buckets till 40 days after current if verbosity > 0: print("Updating buckets...") management.call_command('frepple_createbuckets', user=user, database=database) task.status = '2%' task.save(using=database) # Weeks calendar if verbosity > 0: print("Creating weeks calendar...") with transaction.atomic(using=database): weeks = Calendar.objects.using(database).create(name="Weeks", defaultvalue=0) for i in BucketDetail.objects.using(database).filter( bucket="week").all(): CalendarBucket(startdate=i.startdate, enddate=i.enddate, value=1, calendar=weeks).save(using=database) task.status = '4%' task.save(using=database) # Working days calendar if verbosity > 0: print("Creating working days...") with transaction.atomic(using=database): workingdays = Calendar.objects.using(database).create( name="Working Days", defaultvalue=0) minmax = BucketDetail.objects.using(database).filter( bucket="week").aggregate(Min('startdate'), Max('startdate')) CalendarBucket(startdate=minmax['startdate__min'], enddate=minmax['startdate__max'], value=1, calendar=workingdays, priority=1, saturday=False, sunday=False).save(using=database) task.status = '6%' task.save(using=database) # Parent location loc = Location.objects.using(database).create( name="Factory", available=workingdays) # Create a random list of categories to choose from categories = [ 'cat A', 'cat B', 'cat C', 'cat D', 'cat E', 'cat F', 'cat G' ] # Create customers if verbosity > 0: print("Creating customers...") with transaction.atomic(using=database): cust = [] for i in range(100): c = Customer.objects.using(database).create( name='Cust %03d' % i) cust.append(c) task.status = '8%' task.save(using=database) # Create resources and their calendars if verbosity > 0: print("Creating resources and calendars...") with transaction.atomic(using=database): res = [] for i in range(resource): cal = Calendar.objects.using(database).create( name='capacity for res %03d' % i, category='capacity', defaultvalue=0) CalendarBucket.objects.using(database).create( startdate=startdate, value=resource_size, calendar=cal) r = Resource.objects.using(database).create( name='Res %03d' % i, maximum_calendar=cal, location=loc) res.append(r) task.status = '10%' task.save(using=database) random.shuffle(res) # Create the components if verbosity > 0: print("Creating raw materials...") with transaction.atomic(using=database): comps = [] compsupplier = Supplier.objects.using(database).create( name='component supplier') for i in range(components): it = Item.objects.using(database).create( name='Component %04d' % i, category='Procured', price=str(round(random.uniform(0, 100)))) ld = abs( round(random.normalvariate(procure_lt, procure_lt / 3))) Buffer.objects.using(database).create( name='%s @ %s' % (it.name, loc.name), location=loc, category='Procured', item=it, minimum=20, onhand=str( round(forecast_per_item * random.uniform(1, 3) * ld / 30)), ) ItemSupplier.objects.using(database).create( item=it, location=loc, supplier=compsupplier, leadtime=timedelta(days=ld), sizeminimum=80, sizemultiple=10, priority=1, cost=it.price) comps.append(it) task.status = '12%' task.save(using=database) # Loop over all clusters durations = [timedelta(days=i) for i in range(1, 6)] progress = 88.0 / cluster for i in range(cluster): with transaction.atomic(using=database): if verbosity > 0: print("Creating supply chain for end item %d..." % i) # Item it = Item.objects.using(database).create( name='Itm %05d' % i, category=random.choice(categories), price=str(round(random.uniform(100, 200)))) # Level 0 buffer buf = Buffer.objects.using(database).create( name='%s @ %s' % (it.name, loc.name), item=it, location=loc, category='00') # Demand for j in range(demand): Demand.objects.using(database).create( name='Dmd %05d %05d' % (i, j), item=it, location=loc, quantity=int(random.uniform(1, 6)), # Exponential distribution of due dates, with an average of deliver_lt days. due=startdate + timedelta(days=round( random.expovariate(float(1) / deliver_lt / 24)) / 24), # Orders have higher priority than forecast priority=random.choice([1, 2]), customer=random.choice(cust), category=random.choice(categories)) # Create upstream operations and buffers ops = [] previtem = it for k in range(level): if k == 1 and res: # Create a resource load for operations on level 1 oper = Operation.objects.using(database).create( name='Oper %05d L%02d' % (i, k), type='time_per', location=loc, duration_per=timedelta(days=1), sizemultiple=1, item=previtem) if resource < cluster and i < resource: # When there are more cluster than resources, we try to assure # that each resource is loaded by at least 1 operation. OperationResource.objects.using( database).create(resource=res[i], operation=oper) else: OperationResource.objects.using( database).create( resource=random.choice(res), operation=oper) else: oper = Operation.objects.using(database).create( name='Oper %05d L%02d' % (i, k), duration=random.choice(durations), sizemultiple=1, location=loc, item=previtem) ops.append(oper) # Some inventory in random buffers if random.uniform(0, 1) > 0.8: buf.onhand = int(random.uniform(5, 20)) buf.save(using=database) OperationMaterial.objects.using(database).create( operation=oper, item=previtem, quantity=1, type="end") if k != level - 1: # Consume from the next level in the bill of material it_tmp = Item.objects.using(database).create( name='Itm %05d L%02d' % (i, k + 1), category=random.choice(categories), price=str(round(random.uniform(100, 200)))) buf = Buffer.objects.using(database).create( name='%s @ %s' % (it_tmp.name, loc.name), item=it_tmp, location=loc, category='%02d' % (k + 1)) OperationMaterial.objects.using(database).create( operation=oper, item=it_tmp, quantity=-1) previtem = it_tmp # Consume raw materials / components c = [] for j in range(components_per): o = random.choice(ops) b = random.choice(comps) while (o, b) in c: # A flow with the same operation and buffer already exists o = random.choice(ops) b = random.choice(comps) c.append((o, b)) OperationMaterial.objects.using(database).create( operation=o, item=b, quantity=random.choice([-1, -1, -1, -2, -3])) # Commit the current cluster task.status = '%d%%' % (12 + progress * (i + 1)) task.save(using=database) # Task update task.status = 'Done' task.finished = datetime.now() except Exception as e: if task: task.status = 'Failed' task.message = '%s' % e task.finished = datetime.now() task.save(using=database) raise e finally: if task: task.save(using=database) settings.DEBUG = tmp_debug
def handle(self, **options): # Make sure the debug flag is not set! # When it is set, the django database wrapper collects a list of all sql # statements executed and their timings. This consumes plenty of memory # and cpu time. tmp_debug = settings.DEBUG settings.DEBUG = False # Pick up the options verbosity = int(options["verbosity"]) cluster = int(options["cluster"]) demand = int(options["demand"]) forecast_per_item = int(options["forecast_per_item"]) level = int(options["level"]) resource = int(options["resource"]) resource_size = int(options["resource_size"]) components = int(options["components"]) components_per = int(options["components_per"]) if components <= 0: components_per = 0 deliver_lt = int(options["deliver_lt"]) procure_lt = int(options["procure_lt"]) if options["currentdate"]: currentdate = options["currentdate"] else: currentdate = datetime.strftime(date.today(), "%Y-%m-%d") database = options["database"] if database not in settings.DATABASES: raise CommandError("No database settings known for '%s'" % database) if options["user"]: try: user = User.objects.all().using(database).get( username=options["user"]) except Exception: raise CommandError("User '%s' not found" % options["user"]) else: user = None random.seed(100) # Initialize random seed to get reproducible results now = datetime.now() task = None try: # Initialize the task if options["task"]: try: task = Task.objects.all().using(database).get( pk=options["task"]) except Exception: raise CommandError("Task identifier not found") if (task.started or task.finished or task.status != "Waiting" or task.name not in ("frepple_createmodel", "createmodel")): raise CommandError("Invalid task identifier") task.status = "0%" task.started = now else: task = Task( name="createmodel", submitted=now, started=now, status="0%", user=user, ) task.arguments = ( "--cluster=%s --demand=%s --forecast_per_item=%s --level=%s --resource=%s " "--resource_size=%s --components=%s --components_per=%s --deliver_lt=%s --procure_lt=%s" % ( cluster, demand, forecast_per_item, level, resource, resource_size, components, components_per, deliver_lt, procure_lt, )) task.save(using=database) # Pick up the startdate try: startdate = datetime.strptime(currentdate, "%Y-%m-%d") except Exception: raise CommandError( "current date is not matching format YYYY-MM-DD") # Check whether the database is empty if (Buffer.objects.using(database).count() > 0 or Item.objects.using(database).count() > 0): raise CommandError( "Database must be empty before creating a model") # Plan start date if verbosity > 0: print("Updating current date...") param = Parameter.objects.using(database).get_or_create( name="currentdate")[0] param.value = datetime.strftime(startdate, "%Y-%m-%d %H:%M:%S") param.save(using=database) # Planning horizon # minimum 10 daily buckets, weekly buckets till 40 days after current if verbosity > 0: print("Updating buckets...") management.call_command("createbuckets", user=user, database=database) task.status = "2%" task.save(using=database) # Weeks calendar if verbosity > 0: print("Creating weeks calendar...") with transaction.atomic(using=database): weeks = Calendar.objects.using(database).create(name="Weeks", defaultvalue=0) for i in (BucketDetail.objects.using(database).filter( bucket="week").all()): CalendarBucket( startdate=i.startdate, enddate=i.enddate, value=1, calendar=weeks, ).save(using=database) task.status = "4%" task.save(using=database) # Working days calendar if verbosity > 0: print("Creating working days...") with transaction.atomic(using=database): workingdays = Calendar.objects.using(database).create( name="Working Days", defaultvalue=0) minmax = (BucketDetail.objects.using(database).filter( bucket="week").aggregate(Min("startdate"), Max("startdate"))) CalendarBucket( startdate=minmax["startdate__min"], enddate=minmax["startdate__max"], value=1, calendar=workingdays, priority=1, saturday=False, sunday=False, ).save(using=database) task.status = "6%" task.save(using=database) # Parent location loc = Location.objects.using(database).create( name="Factory", available=workingdays) # Create a random list of categories to choose from categories = [ "cat A", "cat B", "cat C", "cat D", "cat E", "cat F", "cat G" ] # Create customers if verbosity > 0: print("Creating customers...") with transaction.atomic(using=database): cust = [] for i in range(100): c = Customer.objects.using(database).create( name="Cust %03d" % i) cust.append(c) task.status = "8%" task.save(using=database) # Create resources and their calendars if verbosity > 0: print("Creating resources and calendars...") with transaction.atomic(using=database): res = [] for i in range(resource): cal = Calendar.objects.using(database).create( name="capacity for res %03d" % i, category="capacity", defaultvalue=0, ) CalendarBucket.objects.using(database).create( startdate=startdate, value=resource_size, calendar=cal) r = Resource.objects.using(database).create( name="Res %03d" % i, maximum_calendar=cal, location=loc) res.append(r) task.status = "10%" task.save(using=database) random.shuffle(res) # Create the components if verbosity > 0: print("Creating raw materials...") with transaction.atomic(using=database): comps = [] compsupplier = Supplier.objects.using(database).create( name="component supplier") for i in range(components): it = Item.objects.using(database).create( name="Component %04d" % i, category="Procured", cost=str(round(random.uniform(0, 100))), ) ld = abs( round(random.normalvariate(procure_lt, procure_lt / 3))) Buffer.objects.using(database).create( location=loc, category="Procured", item=it, minimum=20, onhand=str( round(forecast_per_item * random.uniform(1, 3) * ld / 30)), ) ItemSupplier.objects.using(database).create( item=it, location=loc, supplier=compsupplier, leadtime=timedelta(days=ld), sizeminimum=80, sizemultiple=10, priority=1, cost=it.cost, ) comps.append(it) task.status = "12%" task.save(using=database) # Loop over all clusters durations = [timedelta(days=i) for i in range(1, 6)] progress = 88.0 / cluster for i in range(cluster): with transaction.atomic(using=database): if verbosity > 0: print("Creating supply chain for end item %d..." % i) # Item it = Item.objects.using(database).create( name="Itm %05d" % i, category=random.choice(categories), cost=str(round(random.uniform(100, 200))), ) # Level 0 buffer buf = Buffer.objects.using(database).create(item=it, location=loc, category="00") # Demand for j in range(demand): Demand.objects.using(database).create( name="Dmd %05d %05d" % (i, j), item=it, location=loc, quantity=int(random.uniform(1, 6)), # Exponential distribution of due dates, with an average of deliver_lt days. due=startdate + timedelta(days=round( random.expovariate(float(1) / deliver_lt / 24)) / 24), # Orders have higher priority than forecast priority=random.choice([1, 2]), customer=random.choice(cust), category=random.choice(categories), ) # Create upstream operations and buffers ops = [] previtem = it for k in range(level): if k == 1 and res: # Create a resource load for operations on level 1 oper = Operation.objects.using(database).create( name="Oper %05d L%02d" % (i, k), type="time_per", location=loc, duration_per=timedelta(days=1), sizemultiple=1, item=previtem, ) if resource < cluster and i < resource: # When there are more cluster than resources, we try to assure # that each resource is loaded by at least 1 operation. OperationResource.objects.using( database).create(resource=res[i], operation=oper) else: OperationResource.objects.using( database).create( resource=random.choice(res), operation=oper) else: oper = Operation.objects.using(database).create( name="Oper %05d L%02d" % (i, k), duration=random.choice(durations), sizemultiple=1, location=loc, item=previtem, ) ops.append(oper) # Some inventory in random buffers if random.uniform(0, 1) > 0.8: buf.onhand = int(random.uniform(5, 20)) buf.save(using=database) OperationMaterial.objects.using(database).create( operation=oper, item=previtem, quantity=1, type="end") if k != level - 1: # Consume from the next level in the bill of material it_tmp = Item.objects.using(database).create( name="Itm %05d L%02d" % (i, k + 1), category=random.choice(categories), cost=str(round(random.uniform(100, 200))), ) buf = Buffer.objects.using(database).create( item=it_tmp, location=loc, category="%02d" % (k + 1)) OperationMaterial.objects.using(database).create( operation=oper, item=it_tmp, quantity=-1) previtem = it_tmp # Consume raw materials / components c = [] for j in range(components_per): o = random.choice(ops) b = random.choice(comps) while (o, b) in c: # A flow with the same operation and buffer already exists o = random.choice(ops) b = random.choice(comps) c.append((o, b)) OperationMaterial.objects.using(database).create( operation=o, item=b, quantity=random.choice([-1, -1, -1, -2, -3]), ) # Commit the current cluster task.status = "%d%%" % (12 + progress * (i + 1)) task.save(using=database) # Task update task.status = "Done" task.finished = datetime.now() except Exception as e: if task: task.status = "Failed" task.message = "%s" % e task.finished = datetime.now() task.save(using=database) raise e finally: if task: task.save(using=database) settings.DEBUG = tmp_debug
def handle(self, **options): # Make sure the debug flag is not set! # When it is set, the django database wrapper collects a list of all sql # statements executed and their timings. This consumes plenty of memory # and cpu time. tmp_debug = settings.DEBUG settings.DEBUG = False # Pick up the options if 'verbosity' in options: verbosity = int(options['verbosity']) else: verbosity = 1 if 'cluster' in options: cluster = int(options['cluster']) else: cluster = 100 if 'demand' in options: demand = int(options['demand']) else: demand = 30 if 'forecast_per_item' in options: forecast_per_item = int(options['forecast_per_item']) else: forecast_per_item = 50 if 'level' in options: level = int(options['level']) else: level = 5 if 'resource' in options: resource = int(options['resource']) else: resource = 60 if 'resource_size' in options: resource_size = int(options['resource_size']) else: resource_size = 5 if 'components' in options: components = int(options['components']) else: components = 200 if 'components_per' in options: components_per = int(options['components_per']) else: components_per = 5 if components == 0: components_per = 0 if 'deliver_lt' in options: deliver_lt = int(options['deliver_lt']) else: deliver_lt = 30 if 'procure_lt' in options: procure_lt = int(options['procure_lt']) else: procure_lt = 40 if 'currentdate' in options: currentdate = options['currentdate'] or datetime.strftime(date.today(), '%Y-%m-%d') else: currentdate = datetime.strftime(date.today(), '%Y-%m-%d') if 'database' in options: database = options['database'] or DEFAULT_DB_ALIAS else: database = DEFAULT_DB_ALIAS if not database in settings.DATABASES: raise CommandError("No database settings known for '%s'" % database ) if 'user' in options and options['user']: try: user = User.objects.all().using(database).get(username=options['user']) except: raise CommandError("User '%s' not found" % options['user'] ) else: user = None random.seed(100) # Initialize random seed to get reproducible results now = datetime.now() task = None try: # Initialize the task if 'task' in options and options['task']: try: task = Task.objects.all().using(database).get(pk=options['task']) except: raise CommandError("Task identifier not found") if task.started or task.finished or task.status != "Waiting" or task.name != 'generate model': raise CommandError("Invalid task identifier") task.status = '0%' task.started = now else: task = Task(name='generate model', submitted=now, started=now, status='0%', user=user) task.arguments = "--cluster=%s --demand=%s --forecast_per_item=%s --level=%s --resource=%s " \ "--resource_size=%s --components=%s --components_per=%s --deliver_lt=%s --procure_lt=%s" % ( cluster, demand, forecast_per_item, level, resource, resource_size, components, components_per, deliver_lt, procure_lt ) task.save(using=database) transaction.commit(using=database) # Pick up the startdate try: startdate = datetime.strptime(currentdate, '%Y-%m-%d') except: raise CommandError("current date is not matching format YYYY-MM-DD") # Check whether the database is empty if Buffer.objects.using(database).count() > 0 or Item.objects.using(database).count() > 0: raise CommandError("Database must be empty before creating a model") # Plan start date if verbosity > 0: print("Updating current date...") param = Parameter.objects.using(database).create(name="currentdate") param.value = datetime.strftime(startdate, "%Y-%m-%d %H:%M:%S") param.save(using=database) # Planning horizon # minimum 10 daily buckets, weekly buckets till 40 days after current if verbosity > 0: print("Updating buckets...") management.call_command('frepple_createbuckets', user=user, database=database) if verbosity > 0: print("Updating horizon telescope...") updateTelescope(10, 40, 730, database) task.status = '2%' task.save(using=database) # Weeks calendar if verbosity > 0: print("Creating weeks calendar...") with transaction.atomic(using=database): weeks = Calendar.objects.using(database).create(name="Weeks", defaultvalue=0) for i in BucketDetail.objects.using(database).filter(bucket="week").all(): CalendarBucket( startdate=i.startdate, enddate=i.enddate, value=1, calendar=weeks ).save(using=database) task.status = '4%' task.save(using=database) # Working days calendar if verbosity > 0: print("Creating working days...") with transaction.atomic(using=database): workingdays = Calendar.objects.using(database).create(name="Working Days", defaultvalue=0) minmax = BucketDetail.objects.using(database).filter(bucket="week").aggregate(Min('startdate'), Max('startdate')) CalendarBucket( startdate=minmax['startdate__min'], enddate=minmax['startdate__max'], value=1, calendar=workingdays, priority=1, saturday=False, sunday=False ).save(using=database) task.status = '6%' task.save(using=database) # Create a random list of categories to choose from categories = [ 'cat A', 'cat B', 'cat C', 'cat D', 'cat E', 'cat F', 'cat G' ] # Create customers if verbosity > 0: print("Creating customers...") with transaction.atomic(using=database): cust = [] for i in range(100): c = Customer.objects.using(database).create(name='Cust %03d' % i) cust.append(c) task.status = '8%' task.save(using=database) # Create resources and their calendars if verbosity > 0: print("Creating resources and calendars...") with transaction.atomic(using=database): res = [] for i in range(resource): loc = Location(name='Loc %05d' % int(random.uniform(1, cluster))) loc.save(using=database) cal = Calendar(name='capacity for res %03d' % i, category='capacity', defaultvalue=0) bkt = CalendarBucket(startdate=startdate, value=resource_size, calendar=cal) cal.save(using=database) bkt.save(using=database) r = Resource.objects.using(database).create( name='Res %03d' % i, maximum_calendar=cal, location=loc ) res.append(r) task.status = '10%' task.save(using=database) random.shuffle(res) # Create the components if verbosity > 0: print("Creating raw materials...") with transaction.atomic(using=database): comps = [] comploc = Location.objects.using(database).create(name='Procured materials') for i in range(components): it = Item.objects.using(database).create( name='Component %04d' % i, category='Procured', price=str(round(random.uniform(0, 100))) ) ld = abs(round(random.normalvariate(procure_lt, procure_lt / 3))) c = Buffer.objects.using(database).create( name='Component %04d' % i, location=comploc, category='Procured', item=it, type='procure', min_inventory=20, max_inventory=100, size_multiple=10, leadtime=str(ld * 86400), onhand=str(round(forecast_per_item * random.uniform(1, 3) * ld / 30)), ) comps.append(c) task.status = '12%' task.save(using=database) # Loop over all clusters durations = [ 86400, 86400 * 2, 86400 * 3, 86400 * 5, 86400 * 6 ] progress = 88.0 / cluster for i in range(cluster): with transaction.atomic(using=database): if verbosity > 0: print("Creating supply chain for end item %d..." % i) # location loc = Location.objects.using(database).get_or_create(name='Loc %05d' % i)[0] loc.available = workingdays loc.save(using=database) # Item and delivery operation oper = Operation.objects.using(database).create(name='Del %05d' % i, sizemultiple=1, location=loc) it = Item.objects.using(database).create( name='Itm %05d' % i, operation=oper, category=random.choice(categories), price=str(round(random.uniform(100, 200))) ) # Level 0 buffer buf = Buffer.objects.using(database).create( name='Buf %05d L00' % i, item=it, location=loc, category='00' ) Flow.objects.using(database).create(operation=oper, thebuffer=buf, quantity=-1) # Demand for j in range(demand): Demand.objects.using(database).create( name='Dmd %05d %05d' % (i, j), item=it, quantity=int(random.uniform(1, 6)), # Exponential distribution of due dates, with an average of deliver_lt days. due=startdate + timedelta(days=round(random.expovariate(float(1) / deliver_lt / 24)) / 24), # Orders have higher priority than forecast priority=random.choice([1, 2]), customer=random.choice(cust), category=random.choice(categories) ) # Create upstream operations and buffers ops = [] for k in range(level): if k == 1 and res: # Create a resource load for operations on level 1 oper = Operation.objects.using(database).create( name='Oper %05d L%02d' % (i, k), type='time_per', location=loc, duration_per=86400, sizemultiple=1, ) if resource < cluster and i < resource: # When there are more cluster than resources, we try to assure # that each resource is loaded by at least 1 operation. Load.objects.using(database).create(resource=res[i], operation=oper) else: Load.objects.using(database).create(resource=random.choice(res), operation=oper) else: oper = Operation.objects.using(database).create( name='Oper %05d L%02d' % (i, k), duration=random.choice(durations), sizemultiple=1, location=loc, ) ops.append(oper) buf.producing = oper # Some inventory in random buffers if random.uniform(0, 1) > 0.8: buf.onhand = int(random.uniform(5, 20)) buf.save(using=database) Flow(operation=oper, thebuffer=buf, quantity=1, type="end").save(using=database) if k != level - 1: # Consume from the next level in the bill of material buf = Buffer.objects.using(database).create( name='Buf %05d L%02d' % (i, k + 1), item=it, location=loc, category='%02d' % (k + 1) ) Flow.objects.using(database).create(operation=oper, thebuffer=buf, quantity=-1) # Consume raw materials / components c = [] for j in range(components_per): o = random.choice(ops) b = random.choice(comps) while (o, b) in c: # A flow with the same operation and buffer already exists o = random.choice(ops) b = random.choice(comps) c.append( (o, b) ) Flow.objects.using(database).create( operation=o, thebuffer=b, quantity=random.choice([-1, -1, -1, -2, -3]) ) # Commit the current cluster task.status = '%d%%' % (12 + progress * (i + 1)) task.save(using=database) # Task update task.status = 'Done' task.finished = datetime.now() except Exception as e: if task: task.status = 'Failed' task.message = '%s' % e task.finished = datetime.now() task.save(using=database) raise e finally: if task: task.save(using=database) settings.DEBUG = tmp_debug