2025-03-01 20:40:38 +00:00

83 lines
3.4 KiB
Python

from django.core.management.base import BaseCommand, CommandError
from products.models import *
from django.db import transaction
class Command(BaseCommand):
help = 'Manage serial code in batch'
def add_arguments(self, parser):
parser.add_argument('--tenant-id', '-t', required=True, type=int)
parser.add_argument('--job', '-j', type=int)
parser.add_argument('--all', '-A', action="store_true", help="apply to all code")
parser.add_argument('--seq-range', "-r", help="code by seq range")
parser.add_argument('--code-file', "-f", help="code list from file")
parser.add_argument('--activate', "-a", action="store_true", help="activate code")
parser.add_argument('--deactivate', "-d", action="store_true", help="deactivate code")
parser.add_argument('--bind-product', "-b", type=int, help="bind to product by id")
parser.add_argument('--unbind-product', "-u", action="store_true", help="unbind product")
def handle(self, *args, **options):
if options.get('job'):
job = Job.objects.get(pk=options['job'])
else:
job = Job.objects.create(name='bind-batch.%d' % options.get('batch'))
try:
job.update('running', 0.0)
tenant = Tenant.objects.get(pk=options['tenant_id'])
query = self.build_query(options)
total = query.count()
done = 0
prod = None
if options.get("bind_product"):
prod = Product.objects.get(tenant=tenant, pk=options['bind_product'])
for batch_ids in self.iterate_batches(query, 10000):
uq = SerialCode.objects.filter(pk__in=batch_ids)
if options.get("activate"):
uq.update(is_active=True)
elif options.get("deactivate"):
uq.update(is_active=False)
elif options.get("unbind_product"):
uq.update(product=None)
elif options.get("bind_product"):
uq.update(product=prod)
transaction.commit()
done += len(batch_ids)
print("code batch op", done, total)
perc = done * 100.0 / total
job.update('running', perc)
job.update('done', 100.0)
except Exception as e:
job.update('error', message=str(e))
raise
def iterate_batches(self, query, batchsize):
total = query.count()
cur = 0
while cur < total:
yield [x.pk for x in query[cur : cur + batchsize]]
cur += batchsize
def build_query(self, options):
tenant = Tenant.objects.get(pk=options['tenant_id'])
query = SerialCode.objects.filter(tenant=tenant).order_by('pk')
if options.get("seq_range"):
begin, end = options['seq_range'].split(',', maxsplit=1)
query = query.filter(seq_num__gte=int(begin),
seq_num__lte=int(end))
elif options.get("code_file"):
codes = self.read_code_file(options['code_file'])
query = query.filter(code__in=codes)
elif options.get("all"):
pass
else:
raise Exception("Code not specified")
return query
def read_code_file(self, cf):
with open(cf, 'r') as f:
return [x for x in f.read().splitlines() if not x.strip().startswith('#')]