def post(self, request, *args, **kwargs): form = self.get_form() item = self.get_object() quantity = request.POST.get('quantity', 0) serials = request.POST.get('serial_numbers', '') dest_id = request.POST.get('destination', None) notes = request.POST.get('note', '') user = request.user valid = True try: destination = StockLocation.objects.get(pk=dest_id) except (ValueError, StockLocation.DoesNotExist): destination = None try: numbers = ExtractSerialNumbers(serials, quantity) except ValidationError as e: form.errors['serial_numbers'] = e.messages valid = False numbers = [] if valid: try: item.serializeStock(quantity, numbers, user, notes=notes, location=destination) except ValidationError as e: messages = e.message_dict for k in messages.keys(): if k in ['quantity', 'destination', 'serial_numbers']: form.errors[k] = messages[k] else: form.non_field_errors = [messages[k]] valid = False data = { 'form_valid': valid, } return self.renderJsonResponse(request, form, data=data)
def test_complete(self): self.allocate_stock(50, 50, 250) self.assertTrue(self.build.isFullyAllocated()) # Generate some serial numbers! serials = ExtractSerialNumbers("1-10", 10) self.build.completeBuild(None, serials, None) self.assertEqual(self.build.status, status.BuildStatus.COMPLETE) # the original BuildItem objects should have been deleted! self.assertEqual(BuildItem.objects.count(), 0) # New stock items should have been created! # - Ten for the build output (as the part was serialized) # - Three for the split items assigned to the build self.assertEqual(StockItem.objects.count(), 16) A = StockItem.objects.get(pk=self.stock_1_1.pk) B = StockItem.objects.get(pk=self.stock_1_2.pk) C = StockItem.objects.get(pk=self.stock_2_1.pk) # Stock should have been subtracted from the original items self.assertEqual(A.quantity, 950) self.assertEqual(B.quantity, 50) self.assertEqual(C.quantity, 4750) # New stock items should have also been allocated to the build allocated = StockItem.objects.filter(build_order=self.build) self.assertEqual(allocated.count(), 3) q = sum([item.quantity for item in allocated.all()]) self.assertEqual(q, 350) # And 10 new stock items created for the build output outputs = StockItem.objects.filter(build=self.build) self.assertEqual(outputs.count(), 10)
def test_complete(self): self.allocate_stock(50, 50, 250) self.assertTrue(self.build.isFullyAllocated()) # Generate some serial numbers! serials = ExtractSerialNumbers("1-10", 10) self.build.completeBuild(None, serials, None) self.assertEqual(self.build.status, status.BuildStatus.COMPLETE) # the original BuildItem objects should have been deleted! self.assertEqual(BuildItem.objects.count(), 0) # New stock items should have been created! # - Ten for the build output (as the part was serialized) # - Three for the split items assigned to the build self.assertEqual(StockItem.objects.count(), 16) # Stock should have been subtracted from the original items self.assertEqual(StockItem.objects.get(pk=1).quantity, 950) self.assertEqual(StockItem.objects.get(pk=2).quantity, 50) self.assertEqual(StockItem.objects.get(pk=3).quantity, 4750) # New stock items created and assigned to the build self.assertEqual(StockItem.objects.get(pk=4).quantity, 50) self.assertEqual(StockItem.objects.get(pk=4).build_order, self.build) self.assertEqual(StockItem.objects.get(pk=4).status, status.StockStatus.ASSIGNED_TO_BUILD) self.assertEqual(StockItem.objects.get(pk=5).quantity, 50) self.assertEqual(StockItem.objects.get(pk=5).build_order, self.build) self.assertEqual(StockItem.objects.get(pk=5).status, status.StockStatus.ASSIGNED_TO_BUILD) self.assertEqual(StockItem.objects.get(pk=6).quantity, 250) self.assertEqual(StockItem.objects.get(pk=6).build_order, self.build) self.assertEqual(StockItem.objects.get(pk=6).status, status.StockStatus.ASSIGNED_TO_BUILD) # And a new stock item created for the build output self.assertEqual(StockItem.objects.get(pk=7).quantity, 1) self.assertEqual(StockItem.objects.get(pk=7).serial, 1) self.assertEqual(StockItem.objects.get(pk=7).build, self.build)
def post(self, request, *args, **kwargs): """ Handle POST of StockItemCreate form. - Manage serial-number valdiation for tracked parts """ part = None form = self.get_form() data = {} valid = form.is_valid() if valid: part_id = form['part'].value() try: part = Part.objects.get(id=part_id) quantity = Decimal(form['quantity'].value()) except (Part.DoesNotExist, ValueError, InvalidOperation): part = None quantity = 1 valid = False form.errors['quantity'] = [_('Invalid quantity')] if quantity < 0: form.errors['quantity'] = [ _('Quantity cannot be less than zero') ] valid = False if part is None: form.errors['part'] = [_('Invalid part selection')] else: # A trackable part must provide serial numbesr if part.trackable: sn = request.POST.get('serial_numbers', '') sn = str(sn).strip() # If user has specified a range of serial numbers if len(sn) > 0: try: serials = ExtractSerialNumbers(sn, quantity) existing = [] for serial in serials: if part.checkIfSerialNumberExists(serial): existing.append(serial) if len(existing) > 0: exists = ",".join([str(x) for x in existing]) form.errors['serial_numbers'] = [ _('The following serial numbers already exist: ({sn})' .format(sn=exists)) ] valid = False else: # At this point we have a list of serial numbers which we know are valid, # and do not currently exist form.clean() form_data = form.cleaned_data if form.is_valid(): for serial in serials: # Create a new stock item for each serial number item = StockItem( part=part, quantity=1, serial=serial, supplier_part=form_data.get( 'supplier_part'), location=form_data.get('location'), batch=form_data.get('batch'), delete_on_deplete=False, status=form_data.get('status'), link=form_data.get('link'), ) item.save(user=request.user) data['success'] = _( 'Created {n} new stock items'.format( n=len(serials))) valid = True except ValidationError as e: form.errors['serial_numbers'] = e.messages valid = False else: # We have a serialized part, but no serial numbers specified... form.clean() form._post_clean() if form.is_valid(): item = form.save(commit=False) item.save(user=request.user) data['pk'] = item.pk data['url'] = item.get_absolute_url() data['success'] = _("Created new stock item") valid = True else: # Referenced Part object is not marked as "trackable" # For non-serialized items, simply save the form. # We need to call _post_clean() here because it is prevented in the form implementation form.clean() form._post_clean() if form.is_valid: item = form.save(commit=False) item.save(user=request.user) data['pk'] = item.pk data['url'] = item.get_absolute_url() data['success'] = _("Created new stock item") valid = True data['form_valid'] = valid and form.is_valid() return self.renderJsonResponse(request, form, data=data)
def post(self, request, *args, **kwargs): """ Handle POST request. Mark the build as COMPLETE - If the form validation passes, the Build objects completeBuild() method is called - Otherwise, the form is passed back to the client """ build = self.get_object() form = self.get_form() confirm = str2bool(request.POST.get('confirm', False)) loc_id = request.POST.get('location', None) valid = False if confirm is False: form.errors['confirm'] = [ _('Confirm completion of build'), ] else: try: location = StockLocation.objects.get(id=loc_id) valid = True except (ValueError, StockLocation.DoesNotExist): form.errors['location'] = [_('Invalid location selected')] serials = [] if build.part.trackable: # A build for a trackable part may optionally specify serial numbers. sn = request.POST.get('serial_numbers', '') sn = str(sn).strip() # If the user has specified serial numbers, check they are valid if len(sn) > 0: try: # Exctract a list of provided serial numbers serials = ExtractSerialNumbers(sn, build.quantity) existing = [] for serial in serials: if build.part.checkIfSerialNumberExists(serial): existing.append(serial) if len(existing) > 0: exists = ",".join([str(x) for x in existing]) form.errors['serial_numbers'] = [ _('The following serial numbers already exist: ({sn})' .format(sn=exists)) ] valid = False except ValidationError as e: form.errors['serial_numbers'] = e.messages valid = False if valid: if not build.completeBuild(location, serials, request.user): form.non_field_errors = [('Build could not be completed')] valid = False data = { 'form_valid': valid, } return self.renderJsonResponse(request, form, data, context=self.get_context_data())
def post(self, request, *args, **kwargs): """ Handle POST of StockItemCreate form. - Manage serial-number valdiation for tracked parts """ form = self.get_form() valid = form.is_valid() if valid: part_id = form['part'].value() try: part = Part.objects.get(id=part_id) quantity = int(form['quantity'].value()) except (Part.DoesNotExist, ValueError): part = None quantity = 1 valid = False if part is None: form.errors['part'] = [_('Invalid part selection')] else: # A trackable part must provide serial numbesr if part.trackable: sn = request.POST.get('serial_numbers', '') try: serials = ExtractSerialNumbers(sn, quantity) existing = [] for serial in serials: if not StockItem.check_serial_number(part, serial): existing.append(serial) if len(existing) > 0: exists = ",".join([str(x) for x in existing]) form.errors['serial_numbers'] = [ _('The following serial numbers already exist: ({sn})' .format(sn=exists)) ] valid = False # At this point we have a list of serial numbers which we know are valid, # and do not currently exist form.clean() data = form.cleaned_data for serial in serials: # Create a new stock item for each serial number item = StockItem( part=part, quantity=1, serial=serial, supplier_part=data.get('supplier_part'), location=data.get('location'), batch=data.get('batch'), delete_on_deplete=False, status=data.get('status'), notes=data.get('notes'), URL=data.get('URL'), ) item.save() except ValidationError as e: form.errors['serial_numbers'] = e.messages valid = False else: # For non-serialized items, simply save the form. # We need to call _post_clean() here because it is prevented in the form implementation form.clean() form._post_clean() form.save() data = { 'form_valid': valid, } return self.renderJsonResponse(request, form, data=data)