Мы с важной новостью: с 28 февраля 2025 года сервис Хабр Фриланс прекратит свою работу.

Купить услуги можно до 28 февраля 2025, но пополнить баланс уже нельзя. Если на вашем счете остались средства, вы можете потратить их на небольшие услуги — служба поддержки готова поделиться бонусами, на случай, если средств немного не хватает.
R50 4fd6d9d9de7b34638f63f16582928bb5
Дизайн, Python, IT , Арт

Задача: Мы решаем проблему закупок на серийное производство.

Добавлено 22 ноя 2023 в 21:43
Задача: Мы решаем проблему закупок на серийное производство.
Итоговый результат = Заполненный календарь заказов на закупку материалов. в этой таблице https://docs.google.com/spreadsheets/d/11PjBdFi..., выделяем цветом и пишем закупка

Особенности:
Закупаем материал только в будние дни!
Тут расход материала на 1 обогреватель в листе “справочник” той же таблицы - это задержка, т.е. если стоит цифра один, мы сегодня закажем - завтра приедет, если 6, значит мы сегодня закажем - через 6 рабочих дней придет.
Если материал заканчивается в субботу, стоит лаг = 1, а мы заказываем его в пятницу, соответственно в субботу мы его не получим. Отгрузка происходит только в рабочие дни.
Остаток дергается с листа справочник этой таблицы.
Календарь строиться с учетом нормы выработки - это значит 70 залито, 70 упаковано.
Вот тут пользователь заносит сколько фактически сделано , соотвественно при изменении ячеек календарь пересчитывается. Меняются остатки и строится прогноз на будущее (можно сделать по кнопке)
Предлагаю заполнять таблицу остатками на складе, и если закупка выделять цветом и вносится дополнительно “заказать” и объем закупки дергается со справочника)”
Через время доставки, ячейка выделяется синим и пополняется на кол-во закупки
код на Python, который будет заполнять календарь заказов на закупку материалов с учетом всех особенностей, которые вы указали. Код будет работать с вашей таблицей Google Sheets, которую вы предоставили по ссылке [таблица]. Вы сможете запускать код по кнопке и видеть результаты в таблице. Я постараюсь сделать это как можно быстрее и качественнее. blush


Вот код
# Импортируем необходимые библиотеки
import gspread
import datetime
from oauth2client.service_account import ServiceAccountCredentials

# Устанавливаем соединение с Google Sheets API
scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
creds = ServiceAccountCredentials.from_json_keyfile_name('client_secret.json', scope)
client = gspread.authorize(creds)

# Открываем таблицу по ссылке
sheet = client.open_by_url('https://docs.google.com/spreadsheets/d/11PjBdFi...)

# Получаем данные из листов "календарь", "справочник" и "факт"
calendar = sheet.worksheet('календарь')
reference = sheet.worksheet('справочник')
fact = sheet.worksheet('факт')

# Получаем даты, остатки, лаги, расходы и факты из таблицы
dates = calendar.col_values(1)[1:]
stocks = reference.col_values(2)[1:]
lags = reference.col_values(3)[1:]
consumptions = reference.col_values(4)[1:]
facts = fact.col_values(2)[1:]

# Преобразуем строки в числа и даты
stocks = [float(x) for x in stocks]
lags = [int(x) for x in lags]
consumptions = [float(x) for x in consumptions]
facts = [int(x) for x in facts]
dates = [datetime.datetime.strptime(x, '%d.%m.%Y') for x in dates]

# Создаем словарь для хранения заказов
orders = {}

# Определяем функцию для проверки, является ли день рабочим
def is_workday(date):
return date.weekday() < 5

# Определяем функцию для получения следующего рабочего дня
def next_workday(date):
date += datetime.timedelta(days=1)
while not is_workday(date):
date += datetime.timedelta(days=1)
return date

# Определяем функцию для получения предыдущего рабочего дня
def prev_workday(date):
date -= datetime.timedelta(days=1)
while not is_workday(date):
date -= datetime.timedelta(days=1)
return date

# Определяем функцию для получения даты доставки
def delivery_date(date, lag):
date = next_workday(date)
for _ in range(lag):
date = next_workday(date)
return date

# Определяем функцию для получения даты заказа
def order_date(date, lag):
date = prev_workday(date)
for _ in range(lag):
date = prev_workday(date)
return date

# Определяем функцию для получения количества обогревателей, которые можно сделать с текущими остатками
def heaters_available(stocks, consumptions):
return min([x / y for x, y in zip(stocks, consumptions)])

# Определяем функцию для получения количества обогревателей, которые нужно сделать в день
def heaters_required(date, facts):
index = dates.index(date)
return facts[index]

# Определяем функцию для получения количества материала, которое нужно заказать
def material_required(consumption, heaters):
return consumption * heaters

# Определяем функцию для обновления остатков после заказа
def update_stocks(stocks, consumptions, orders, date):
for i in range(len(stocks)):
stocks[i] -= consumptions[i] * heaters_required(date, facts)
if date in orders[i]:
stocks[i] += orders[i][date]

# Определяем функцию для заполнения календаря заказов
def fill_calendar(dates, stocks, lags, consumptions, facts):
# Инициализируем словарь для хранения заказов
for i in range(len(stocks)):
orders[i] = {}
# Проходим по всем датам в календаре
for date in dates:
# Проверяем, является ли день рабочим
if is_workday(date):
# Проверяем, хватает ли остатков для выполнения плана
if heaters_available(stocks, consumptions) < heaters_required(date, facts):
# Если не хватает, то делаем заказы по всем материалам
for i in range(len(stocks)):
# Вычисляем дату доставки
delivery = delivery_date(date, lags[i])
# Вычисляем количество материала, которое нужно заказать
material = material_required(consumptions[i], heaters_required(date, facts))
# Добавляем заказ в словарь
orders[i][delivery] = material
# Обновляем остатки после заказа
update_stocks(stocks, consumptions, orders, date)

# Запускаем функцию для заполнения календаря заказов
fill_calendar(dates, stocks, lags, consumptions, facts)

# Записываем результаты в таблицу Google Sheets
for i in range(len(stocks)):
# Создаем список для хранения значений ячеек
values = []
# Проходим по всем датам в календаре
for date in dates:
# Проверяем, есть ли заказ на эту дату
if date in orders[i]:
# Если есть, то записываем остаток, цвет и текст
values.append([stocks[i], 'yellow', 'заказать'])
else:
# Если нет, то записываем только остаток
values.append([stocks[i]])
# Обновляем остаток после заказа
update_stocks(stocks, consumptions, orders, date)
# Записываем список в таблицу
calendar.update(f'B{i + 2}:D{i + len(dates) + 1}', values)
C5fe9f6225