mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-27 19:16:44 +00:00
Order start dates (#8966)
* Add 'start_date' field to orders - PurchaseOrder - SalesOrder - ReturnOrder * Add serializer field * Add API filters * Add table columns * Add fields to forms * Table filters * Add validation check * Refactor BuildOrderTable * Update detail page * Bump API version * Allow sorting by start_date * Fix for purchase order field * Update detail pages * Update playwright tests * Updated playwright tests * Documentation updates * Updated playwright tests
This commit is contained in:
parent
0c56a3132b
commit
eee4916350
15
docs/docs/build/build.md
vendored
15
docs/docs/build/build.md
vendored
@ -96,7 +96,7 @@ When a *Build Order* is created, we then have the ability to *allocate* stock it
|
||||
!!! info "Example - Stock Allocation"
|
||||
Let's say that to assembly a single "Widget", we require 2 "flanges". So, to complete a build of 10 "Widgets", 20 "flanges" will be required. We *allocate* 20 flanged against this build order.
|
||||
|
||||
Allocating stock to a build does not actually subtrack the stock from the database. Allocations signal an *intent* to take that stock for the purpose of this build. Stock allocations are actioned at the completion of a build.
|
||||
Allocating stock to a build does not actually subtract the stock from the database. Allocations signal an *intent* to take that stock for the purpose of this build. Stock allocations are subtracted from stock at the completion of a build.
|
||||
|
||||
!!! info "Part Allocation Information"
|
||||
Any part which has stock allocated to a build order will indicate this on the part information page.
|
||||
@ -243,7 +243,7 @@ The form will validate the build order is ready to be completed, and will preven
|
||||
If you wish to complete the build despite the missing parts, toggle the `Accept Unallocated` option to true to override the warning and allow completion with unallocated parts.
|
||||
|
||||
!!! info "Overallocated Stock Items"
|
||||
If the warning message `Some stock items have been overallocated` is shown, you have more stock than required by the BOM for the part being built allocated to the build order. By default the `Not permissted` option is selected and you will need to return to the allocation screen and remove the extra items before the build can be completed.
|
||||
If the warning message `Some stock items have been overallocated` is shown, you have more stock than required by the BOM for the part being built allocated to the build order. By default the `Not permitted` option is selected and you will need to return to the allocation screen and remove the extra items before the build can be completed.
|
||||
|
||||
Alternatively, you can select `Accept as consumed by this build order` to continue with the allocation and remove the extra items from stock (e.g. if they were destroyed during build), or select `Deallocate before completing this build order` if you would like the extra items to be returned to stock for use in future builds.
|
||||
|
||||
@ -265,17 +265,22 @@ The `Cancel Build` form will be displayed, click on the confirmation switch then
|
||||
|
||||
## Build Scheduling
|
||||
|
||||
Build orders can be scheduled for a future date, to allow for planning of production schedules.
|
||||
|
||||
### Start Date
|
||||
|
||||
Build orders can be optionally scheduled to *start* at a specified date. This may be useful for planning production schedules.
|
||||
Build orders can be optionally scheduled to *start* at a specified date, by setting the *Start Date* field. This field can be left blank if the build is to start immediately.
|
||||
|
||||
### Target Date
|
||||
|
||||
Build orders can be optionally scheduled to be completed by a certain date, by setting the *Target Date* field. This field can be left blank if the build has no specific deadline.
|
||||
|
||||
### Overdue Builds
|
||||
|
||||
Build orders may (optionally) have a target completion date specified. If this date is reached but the build order remains incomplete, then the build is considered *overdue*.
|
||||
If the *Target Date* is reached but the build order remains incomplete, then the build is considered *overdue*.
|
||||
|
||||
This can be useful for tracking production delays, and can be used to generate reports on build order performance.
|
||||
|
||||
|
||||
## Build Order Settings
|
||||
|
||||
The following [global settings](../settings/global.md) are available for adjusting the behavior of build orders:
|
||||
|
@ -107,19 +107,19 @@ Each item marked as "received" is automatically converted into a stock item.
|
||||
|
||||
To see the list of stock items created from the purchase order, click on the <span class="badge inventree nav side"><span class='fas fa-sign-in-alt'></span> Received Items</span> tab.
|
||||
|
||||
### Complete Order
|
||||
## Complete Order
|
||||
|
||||
Once the quantity of all __received__ items is equal or above the quantity of all line items, the order will be automatically marked as __complete__.
|
||||
|
||||
It is also possible to complete the order before all items were received (or if there were missing items).
|
||||
To do so, click on the <span class='fas fa-check-circle'></span> button on the main purchase order detail panel and confirm the order was completed.
|
||||
|
||||
### Cancel Order
|
||||
## Cancel Order
|
||||
|
||||
In the event that the order won't be processed, user has the option of cancelling the order instead.
|
||||
To do so, simply click on the <span class='fas fa-times-circle'></span> button on the main purchase order detail panel and confirm the purchase order has been cancelled.
|
||||
|
||||
### Duplicate Purchase Order
|
||||
## Duplicate Purchase Order
|
||||
|
||||
Duplicating a Purchase Order allows the user to quickly create a new *copy* of an existing order, using the same supplier and line item information.
|
||||
|
||||
@ -141,7 +141,23 @@ A new purchase order is then created based on the currently selected order:
|
||||
{% include "img.html" %}
|
||||
{% endwith %}
|
||||
|
||||
### Calendar view
|
||||
## Order Scheduling
|
||||
|
||||
Purchase orders can be scheduled for a future date, to allow for planning of future orders.
|
||||
|
||||
### Start Date
|
||||
|
||||
The *Start Date* of the purchase order is the date on which the order is scheduled to be issued to the supplier.
|
||||
|
||||
### Target Date
|
||||
|
||||
The *Target Date* of the purchase order is the date on which the order is expected to be completed / received from the supplier.
|
||||
|
||||
### Overdue Orders
|
||||
|
||||
If the *Target Date* of the purchase order is reached but the order has not been completed, the order will be marked as *overdue*.
|
||||
|
||||
## Calendar view
|
||||
|
||||
Using the button to the top right of the list of Purchase Orders, the view can be switched to a calendar view using the button <span class='fas fa-calendar-alt'></span>. This view shows orders with a defined target date only.
|
||||
|
||||
|
@ -115,7 +115,23 @@ While [line items](#line-items) must reference a particular stock item, extra li
|
||||
|
||||
Custom [reports](../report/templates.md) can be generated against each Return Order.
|
||||
|
||||
### Calendar view
|
||||
## Order Scheduling
|
||||
|
||||
Return Orders can be scheduled to be completed on a specific date. This can be useful for planning and tracking the return of items.
|
||||
|
||||
### Start Date
|
||||
|
||||
The *Start Date* of the return order is the date on which the order is scheduled to be issued to the customer.
|
||||
|
||||
### Target Date
|
||||
|
||||
The *Target Date* of the return order is the date on which the order is scheduled to be completed.
|
||||
|
||||
### Overdue Orders
|
||||
|
||||
If the *Target Date* of a return order has passed, the order will be marked as *Overdue*. This can be useful for tracking orders which are behind schedule.
|
||||
|
||||
## Calendar view
|
||||
|
||||
Using the button to the top right of the list of Return Orders, the view can be switched to a calendar view using the button <span class='fas fa-calendar-alt'></span>. This view shows orders with a defined target date only.
|
||||
|
||||
|
@ -60,7 +60,7 @@ Fill out the rest of the form with the sales order information then click on <sp
|
||||
|
||||
Each Sales Order is uniquely identified by its *Reference* field. Read more about [reference fields](../settings/reference.md).
|
||||
|
||||
#### Add Line Items
|
||||
### Add Line Items
|
||||
|
||||
On the sales order detail page, user can link parts to the sales order selecting the <span class="badge inventree nav side"><span class='fas fa-list-ol'></span> Line Items</span> tab then clicking on the <span class="badge inventree add"><span class='fas fa-plus-circle'></span> Add Line Item</span> button.
|
||||
|
||||
@ -71,7 +71,7 @@ Once the "Add Line Item" form opens, select a part in the list.
|
||||
|
||||
Fill out the rest of the form then click on <span class="badge inventree confirm">Submit</span>
|
||||
|
||||
#### Shipments
|
||||
## Shipments
|
||||
|
||||
After all line items were added to the sales order, user needs to create one or more [shipments](#sales-order-shipments) in order to allocate stock for those parts.
|
||||
|
||||
@ -82,7 +82,7 @@ In order to create a new shipment:
|
||||
|
||||
Repeat the two steps above to create more shipments.
|
||||
|
||||
#### Allocate Stock Items
|
||||
### Allocate Stock Items
|
||||
|
||||
After shipments were created, user can either:
|
||||
|
||||
@ -91,7 +91,7 @@ After shipments were created, user can either:
|
||||
|
||||
During the allocation process, user is required to select the desired shipment that will contain the stock items.
|
||||
|
||||
#### Complete Shipment
|
||||
### Complete Shipment
|
||||
|
||||
To complete a shipment, click on the <span class="badge inventree nav side"><span class='fas fa-truck-loading'></span> Pending Shipments</span> tab then click on <span class='fas fa-truck'></span> button shown in the shipment table.
|
||||
|
||||
@ -99,16 +99,31 @@ Fill out the "Complete Shipment" form then click on <span class="badge inventree
|
||||
|
||||
To view all the completed shipment, click on the <span class="badge inventree nav side"><span class='fas fa-truck'></span> Completed Shipments</span> tab. In the completed shipments table, click on the <span class='fas fa-plus'></span> icon next to each shipment reference to see the items and quantities which were shipped.
|
||||
|
||||
### Complete Order
|
||||
## Complete Order
|
||||
|
||||
Once all items in the sales order have been shipped, click on <span class="badge inventree add"><span class='fas fa-check-circle'></span> Complete Order</span> to mark the sales order as shipped. Confirm then click on <span class="badge inventree confirm">Submit</span> to complete the order.
|
||||
|
||||
### Cancel Order
|
||||
## Cancel Order
|
||||
|
||||
To cancel the order, click on the <span class='fas fa-tools'></span> menu button next to the <span class="badge inventree add"><span class='fas fa-check-circle'></span> Complete Order</span> button, then click on the "<span class='fas fa-tools'></span> Cancel Order" menu option. Confirm then click on the <span class="badge inventree confirm">Submit</span> to cancel the order.
|
||||
|
||||
## Order Scheduling
|
||||
|
||||
### Calendar view
|
||||
Sales orders can be scheduled for a future date, to allow for order scheduling.
|
||||
|
||||
### Start Date
|
||||
|
||||
The *Start Date* of the sales order is the date on which the order is scheduled to be issued, allowing work to begin on the order.
|
||||
|
||||
### Target Date
|
||||
|
||||
The *Target Date* of the sales order is the date on which the order is scheduled to be completed and shipped.
|
||||
|
||||
### Overdue Orders
|
||||
|
||||
If the *Target Date* of the sales order has passed, the order will be marked as *overdue*.
|
||||
|
||||
## Calendar view
|
||||
|
||||
Using the button to the top right of the list of Sales Orders, the view can be switched to a calendar view using the button <span class='fas fa-calendar-alt'></span>. This view shows orders with a defined target date only.
|
||||
|
||||
|
@ -1,13 +1,19 @@
|
||||
"""InvenTree API version information."""
|
||||
|
||||
# InvenTree API version
|
||||
INVENTREE_API_VERSION = 305
|
||||
INVENTREE_API_VERSION = 306
|
||||
|
||||
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
||||
|
||||
|
||||
INVENTREE_API_TEXT = """
|
||||
|
||||
v3-6 0 2025-01-28 : https://github.com/inventree/InvenTree/pull/8966
|
||||
- Adds "start_date" to PurchasesOrder API
|
||||
- Adds "start_date" to SalesOrder API
|
||||
- Adds "start_date" to ReturnOrder API
|
||||
- Updated API filters
|
||||
|
||||
v305 - 2025-01-26 : https://github.com/inventree/InvenTree/pull/8950
|
||||
- Bug fixes for the SupplierPart API
|
||||
- Refactoring for data export via API
|
||||
|
@ -181,6 +181,30 @@ class OrderFilter(rest_filters.FilterSet):
|
||||
label=_('Created After'), field_name='creation_date', lookup_expr='gt'
|
||||
)
|
||||
|
||||
has_start_date = rest_filters.BooleanFilter(
|
||||
label=_('Has Start Date'), method='filter_has_start_date'
|
||||
)
|
||||
|
||||
def filter_has_start_date(self, queryset, name, value):
|
||||
"""Filter by whether or not the order has a start date."""
|
||||
return queryset.filter(start_date__isnull=not str2bool(value))
|
||||
|
||||
start_date_before = InvenTreeDateFilter(
|
||||
label=_('Start Date Before'), field_name='start_date', lookup_expr='lt'
|
||||
)
|
||||
|
||||
start_date_after = InvenTreeDateFilter(
|
||||
label=_('Start Date After'), field_name='start_date', lookup_expr='gt'
|
||||
)
|
||||
|
||||
has_target_date = rest_filters.BooleanFilter(
|
||||
label=_('Has Target Date'), method='filter_has_target_date'
|
||||
)
|
||||
|
||||
def filter_has_target_date(self, queryset, name, value):
|
||||
"""Filter by whether or not the order has a target date."""
|
||||
return queryset.filter(target_date__isnull=not str2bool(value))
|
||||
|
||||
target_date_before = InvenTreeDateFilter(
|
||||
label=_('Target Date Before'), field_name='target_date', lookup_expr='lt'
|
||||
)
|
||||
@ -336,6 +360,7 @@ class PurchaseOrderList(
|
||||
'created_by',
|
||||
'reference',
|
||||
'supplier__name',
|
||||
'start_date',
|
||||
'target_date',
|
||||
'complete_date',
|
||||
'line_items',
|
||||
@ -797,6 +822,7 @@ class SalesOrderList(
|
||||
'customer__name',
|
||||
'customer_reference',
|
||||
'status',
|
||||
'start_date',
|
||||
'target_date',
|
||||
'line_items',
|
||||
'shipment_date',
|
||||
@ -1383,6 +1409,7 @@ class ReturnOrderList(
|
||||
'customer_reference',
|
||||
'line_items',
|
||||
'status',
|
||||
'start_date',
|
||||
'target_date',
|
||||
'complete_date',
|
||||
'project_code',
|
||||
|
@ -0,0 +1,28 @@
|
||||
# Generated by Django 4.2.18 on 2025-01-27 12:50
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('order', '0105_auto_20241128_0431'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='purchaseorder',
|
||||
name='start_date',
|
||||
field=models.DateField(blank=True, help_text='Scheduled start date for this order', null=True, verbose_name='Start date'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='returnorder',
|
||||
name='start_date',
|
||||
field=models.DateField(blank=True, help_text='Scheduled start date for this order', null=True, verbose_name='Start date'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='salesorder',
|
||||
name='start_date',
|
||||
field=models.DateField(blank=True, help_text='Scheduled start date for this order', null=True, verbose_name='Start date'),
|
||||
),
|
||||
]
|
@ -203,6 +203,8 @@ class Order(
|
||||
creation_date: Automatic date of order creation
|
||||
created_by: User who created this order (automatically captured)
|
||||
issue_date: Date the order was issued
|
||||
start_date: Date the order is scheduled to be started
|
||||
target_date: Expected or desired completion date
|
||||
complete_date: Date the order was completed
|
||||
responsible: User (or group) responsible for managing the order
|
||||
"""
|
||||
@ -244,6 +246,13 @@ class Order(
|
||||
'contact': _('Contact does not match selected company')
|
||||
})
|
||||
|
||||
# Target date should be *after* the start date
|
||||
if self.start_date and self.target_date and self.start_date > self.target_date:
|
||||
raise ValidationError({
|
||||
'target_date': _('Target date must be after start date'),
|
||||
'start_date': _('Start date must be before target date'),
|
||||
})
|
||||
|
||||
def clean_line_item(self, line):
|
||||
"""Clean a line item for this order.
|
||||
|
||||
@ -310,6 +319,13 @@ class Order(
|
||||
blank=True, verbose_name=_('Link'), help_text=_('Link to external page')
|
||||
)
|
||||
|
||||
start_date = models.DateField(
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name=_('Start date'),
|
||||
help_text=_('Scheduled start date for this order'),
|
||||
)
|
||||
|
||||
target_date = models.DateField(
|
||||
blank=True,
|
||||
null=True,
|
||||
|
@ -186,8 +186,9 @@ class AbstractOrderSerializer(DataImportExportSerializerMixin, serializers.Seria
|
||||
"""Construct a set of fields for this serializer."""
|
||||
return [
|
||||
'pk',
|
||||
'creation_date',
|
||||
'created_by',
|
||||
'creation_date',
|
||||
'start_date',
|
||||
'target_date',
|
||||
'description',
|
||||
'line_items',
|
||||
|
@ -170,6 +170,9 @@ export function usePurchaseOrderFields({
|
||||
order_currency: {
|
||||
icon: <IconCoins />
|
||||
},
|
||||
start_date: {
|
||||
icon: <IconCalendar />
|
||||
},
|
||||
target_date: {
|
||||
icon: <IconCalendar />
|
||||
},
|
||||
|
@ -1,6 +1,11 @@
|
||||
import { t } from '@lingui/macro';
|
||||
import { Flex, Table } from '@mantine/core';
|
||||
import { IconAddressBook, IconUser, IconUsers } from '@tabler/icons-react';
|
||||
import {
|
||||
IconAddressBook,
|
||||
IconCalendar,
|
||||
IconUser,
|
||||
IconUsers
|
||||
} from '@tabler/icons-react';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import RemoveRowButton from '../components/buttons/RemoveRowButton';
|
||||
@ -39,7 +44,12 @@ export function useReturnOrderFields({
|
||||
customer_reference: {},
|
||||
project_code: {},
|
||||
order_currency: {},
|
||||
target_date: {},
|
||||
start_date: {
|
||||
icon: <IconCalendar />
|
||||
},
|
||||
target_date: {
|
||||
icon: <IconCalendar />
|
||||
},
|
||||
link: {},
|
||||
contact: {
|
||||
icon: <IconUser />,
|
||||
|
@ -1,6 +1,11 @@
|
||||
import { t } from '@lingui/macro';
|
||||
import { Table } from '@mantine/core';
|
||||
import { IconAddressBook, IconUser, IconUsers } from '@tabler/icons-react';
|
||||
import {
|
||||
IconAddressBook,
|
||||
IconCalendar,
|
||||
IconUser,
|
||||
IconUsers
|
||||
} from '@tabler/icons-react';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import RemoveRowButton from '../components/buttons/RemoveRowButton';
|
||||
@ -40,7 +45,12 @@ export function useSalesOrderFields({
|
||||
customer_reference: {},
|
||||
project_code: {},
|
||||
order_currency: {},
|
||||
target_date: {},
|
||||
start_date: {
|
||||
icon: <IconCalendar />
|
||||
},
|
||||
target_date: {
|
||||
icon: <IconCalendar />
|
||||
},
|
||||
link: {},
|
||||
contact: {
|
||||
icon: <IconUser />,
|
||||
|
@ -186,6 +186,7 @@ export default function BuildDetail() {
|
||||
name: 'creation_date',
|
||||
label: t`Created`,
|
||||
icon: 'calendar',
|
||||
copy: true,
|
||||
hidden: !build.creation_date
|
||||
},
|
||||
{
|
||||
@ -193,6 +194,7 @@ export default function BuildDetail() {
|
||||
name: 'start_date',
|
||||
label: t`Start Date`,
|
||||
icon: 'calendar',
|
||||
copy: true,
|
||||
hidden: !build.start_date
|
||||
},
|
||||
{
|
||||
@ -200,6 +202,7 @@ export default function BuildDetail() {
|
||||
name: 'target_date',
|
||||
label: t`Target Date`,
|
||||
icon: 'calendar',
|
||||
copy: true,
|
||||
hidden: !build.target_date
|
||||
},
|
||||
{
|
||||
@ -207,6 +210,7 @@ export default function BuildDetail() {
|
||||
name: 'completion_date',
|
||||
label: t`Completed`,
|
||||
icon: 'calendar',
|
||||
copy: true,
|
||||
hidden: !build.completion_date
|
||||
},
|
||||
{
|
||||
|
@ -243,6 +243,14 @@ export default function PurchaseOrderDetail() {
|
||||
copy: true,
|
||||
hidden: !order.issue_date
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'start_date',
|
||||
label: t`Start Date`,
|
||||
icon: 'calendar',
|
||||
copy: true,
|
||||
hidden: !order.start_date
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'target_date',
|
||||
|
@ -214,6 +214,14 @@ export default function ReturnOrderDetail() {
|
||||
copy: true,
|
||||
hidden: !order.issue_date
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'start_date',
|
||||
label: t`Start Date`,
|
||||
icon: 'calendar',
|
||||
copy: true,
|
||||
hidden: !order.start_date
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'target_date',
|
||||
|
@ -225,6 +225,14 @@ export default function SalesOrderDetail() {
|
||||
copy: true,
|
||||
hidden: !order.issue_date
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'start_date',
|
||||
label: t`Start Date`,
|
||||
icon: 'calendar',
|
||||
hidden: !order.start_date,
|
||||
copy: true
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'target_date',
|
||||
|
@ -243,6 +243,14 @@ export function DateColumn(props: TableColumnProps): TableColumn {
|
||||
};
|
||||
}
|
||||
|
||||
export function StartDateColumn(props: TableColumnProps): TableColumn {
|
||||
return DateColumn({
|
||||
accessor: 'start_date',
|
||||
title: t`Start Date`,
|
||||
...props
|
||||
});
|
||||
}
|
||||
|
||||
export function TargetDateColumn(props: TableColumnProps): TableColumn {
|
||||
return DateColumn({
|
||||
accessor: 'target_date',
|
||||
|
@ -169,6 +169,24 @@ export function CreatedAfterFilter(): TableFilter {
|
||||
};
|
||||
}
|
||||
|
||||
export function StartDateBeforeFilter(): TableFilter {
|
||||
return {
|
||||
name: 'start_date_before',
|
||||
label: t`Start Date Before`,
|
||||
description: t`Show items with a start date before this date`,
|
||||
type: 'date'
|
||||
};
|
||||
}
|
||||
|
||||
export function StartDateAfterFilter(): TableFilter {
|
||||
return {
|
||||
name: 'start_date_after',
|
||||
label: t`Start Date After`,
|
||||
description: t`Show items with a start date after this date`,
|
||||
type: 'date'
|
||||
};
|
||||
}
|
||||
|
||||
export function TargetDateBeforeFilter(): TableFilter {
|
||||
return {
|
||||
name: 'target_date_before',
|
||||
|
@ -26,6 +26,7 @@ import {
|
||||
ProjectCodeColumn,
|
||||
ReferenceColumn,
|
||||
ResponsibleColumn,
|
||||
StartDateColumn,
|
||||
StatusColumn,
|
||||
TargetDateColumn
|
||||
} from '../ColumnRenderers';
|
||||
@ -43,6 +44,8 @@ import {
|
||||
OverdueFilter,
|
||||
ProjectCodeFilter,
|
||||
ResponsibleFilter,
|
||||
StartDateAfterFilter,
|
||||
StartDateBeforeFilter,
|
||||
type TableFilter,
|
||||
TargetDateAfterFilter,
|
||||
TargetDateBeforeFilter
|
||||
@ -107,11 +110,7 @@ export function BuildOrderTable({
|
||||
sortable: true
|
||||
},
|
||||
CreationDateColumn({}),
|
||||
DateColumn({
|
||||
accessor: 'start_date',
|
||||
title: t`Start Date`,
|
||||
sortable: true
|
||||
}),
|
||||
StartDateColumn({}),
|
||||
TargetDateColumn({}),
|
||||
DateColumn({
|
||||
accessor: 'completion_date',
|
||||
@ -156,18 +155,8 @@ export function BuildOrderTable({
|
||||
CreatedAfterFilter(),
|
||||
TargetDateBeforeFilter(),
|
||||
TargetDateAfterFilter(),
|
||||
{
|
||||
name: 'start_date_before',
|
||||
type: 'date',
|
||||
label: t`Start Date Before`,
|
||||
description: t`Show items with a start date before this date`
|
||||
},
|
||||
{
|
||||
name: 'start_date_after',
|
||||
type: 'date',
|
||||
label: t`Start Date After`,
|
||||
description: t`Show items with a start date after this date`
|
||||
},
|
||||
StartDateBeforeFilter(),
|
||||
StartDateAfterFilter(),
|
||||
{
|
||||
name: 'has_target_date',
|
||||
type: 'boolean',
|
||||
|
@ -26,6 +26,7 @@ import {
|
||||
ProjectCodeColumn,
|
||||
ReferenceColumn,
|
||||
ResponsibleColumn,
|
||||
StartDateColumn,
|
||||
StatusColumn,
|
||||
TargetDateColumn
|
||||
} from '../ColumnRenderers';
|
||||
@ -44,6 +45,8 @@ import {
|
||||
OverdueFilter,
|
||||
ProjectCodeFilter,
|
||||
ResponsibleFilter,
|
||||
StartDateAfterFilter,
|
||||
StartDateBeforeFilter,
|
||||
type TableFilter,
|
||||
TargetDateAfterFilter,
|
||||
TargetDateBeforeFilter
|
||||
@ -79,6 +82,20 @@ export function PurchaseOrderTable({
|
||||
CreatedAfterFilter(),
|
||||
TargetDateBeforeFilter(),
|
||||
TargetDateAfterFilter(),
|
||||
StartDateBeforeFilter(),
|
||||
StartDateAfterFilter(),
|
||||
{
|
||||
name: 'has_target_date',
|
||||
type: 'boolean',
|
||||
label: t`Has Target Date`,
|
||||
description: t`Show orders with a target date`
|
||||
},
|
||||
{
|
||||
name: 'has_start_date',
|
||||
type: 'boolean',
|
||||
label: t`Has Start Date`,
|
||||
description: t`Show orders with a start date`
|
||||
},
|
||||
CompletedBeforeFilter(),
|
||||
CompletedAfterFilter(),
|
||||
ProjectCodeFilter({ choices: projectCodeFilters.choices }),
|
||||
@ -120,6 +137,7 @@ export function PurchaseOrderTable({
|
||||
ProjectCodeColumn({}),
|
||||
CreationDateColumn({}),
|
||||
CreatedByColumn({}),
|
||||
StartDateColumn({}),
|
||||
TargetDateColumn({}),
|
||||
CompletionDateColumn({
|
||||
accessor: 'complete_date'
|
||||
|
@ -26,6 +26,7 @@ import {
|
||||
ProjectCodeColumn,
|
||||
ReferenceColumn,
|
||||
ResponsibleColumn,
|
||||
StartDateColumn,
|
||||
StatusColumn,
|
||||
TargetDateColumn
|
||||
} from '../ColumnRenderers';
|
||||
@ -44,6 +45,8 @@ import {
|
||||
OverdueFilter,
|
||||
ProjectCodeFilter,
|
||||
ResponsibleFilter,
|
||||
StartDateAfterFilter,
|
||||
StartDateBeforeFilter,
|
||||
type TableFilter,
|
||||
TargetDateAfterFilter,
|
||||
TargetDateBeforeFilter
|
||||
@ -76,6 +79,20 @@ export function ReturnOrderTable({
|
||||
CreatedAfterFilter(),
|
||||
TargetDateBeforeFilter(),
|
||||
TargetDateAfterFilter(),
|
||||
StartDateBeforeFilter(),
|
||||
StartDateAfterFilter(),
|
||||
{
|
||||
name: 'has_target_date',
|
||||
type: 'boolean',
|
||||
label: t`Has Target Date`,
|
||||
description: t`Show orders with a target date`
|
||||
},
|
||||
{
|
||||
name: 'has_start_date',
|
||||
type: 'boolean',
|
||||
label: t`Has Start Date`,
|
||||
description: t`Show orders with a start date`
|
||||
},
|
||||
CompletedBeforeFilter(),
|
||||
CompletedAfterFilter(),
|
||||
HasProjectCodeFilter(),
|
||||
@ -129,6 +146,7 @@ export function ReturnOrderTable({
|
||||
ProjectCodeColumn({}),
|
||||
CreationDateColumn({}),
|
||||
CreatedByColumn({}),
|
||||
StartDateColumn({}),
|
||||
TargetDateColumn({}),
|
||||
CompletionDateColumn({
|
||||
accessor: 'complete_date'
|
||||
|
@ -27,6 +27,7 @@ import {
|
||||
ReferenceColumn,
|
||||
ResponsibleColumn,
|
||||
ShipmentDateColumn,
|
||||
StartDateColumn,
|
||||
StatusColumn,
|
||||
TargetDateColumn
|
||||
} from '../ColumnRenderers';
|
||||
@ -45,6 +46,8 @@ import {
|
||||
OverdueFilter,
|
||||
ProjectCodeFilter,
|
||||
ResponsibleFilter,
|
||||
StartDateAfterFilter,
|
||||
StartDateBeforeFilter,
|
||||
type TableFilter,
|
||||
TargetDateAfterFilter,
|
||||
TargetDateBeforeFilter
|
||||
@ -77,6 +80,20 @@ export function SalesOrderTable({
|
||||
CreatedAfterFilter(),
|
||||
TargetDateBeforeFilter(),
|
||||
TargetDateAfterFilter(),
|
||||
StartDateBeforeFilter(),
|
||||
StartDateAfterFilter(),
|
||||
{
|
||||
name: 'has_target_date',
|
||||
type: 'boolean',
|
||||
label: t`Has Target Date`,
|
||||
description: t`Show orders with a target date`
|
||||
},
|
||||
{
|
||||
name: 'has_start_date',
|
||||
type: 'boolean',
|
||||
label: t`Has Start Date`,
|
||||
description: t`Show orders with a start date`
|
||||
},
|
||||
CompletedBeforeFilter(),
|
||||
CompletedAfterFilter(),
|
||||
HasProjectCodeFilter(),
|
||||
@ -166,6 +183,7 @@ export function SalesOrderTable({
|
||||
ProjectCodeColumn({}),
|
||||
CreationDateColumn({}),
|
||||
CreatedByColumn({}),
|
||||
StartDateColumn({}),
|
||||
TargetDateColumn({}),
|
||||
ShipmentDateColumn({}),
|
||||
ResponsibleColumn({}),
|
||||
|
@ -3,11 +3,12 @@ import { baseUrl } from '../defaults.ts';
|
||||
import {
|
||||
clearTableFilters,
|
||||
clickButtonIfVisible,
|
||||
openFilterDrawer
|
||||
openFilterDrawer,
|
||||
setTableChoiceFilter
|
||||
} from '../helpers.ts';
|
||||
import { doQuickLogin } from '../login.ts';
|
||||
|
||||
test('Purchase Orders', async ({ page }) => {
|
||||
test('Purchase Orders - List', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
await page.getByRole('tab', { name: 'Purchasing' }).click();
|
||||
@ -22,10 +23,17 @@ test('Purchase Orders', async ({ page }) => {
|
||||
await page.getByText('Pending').first().waitFor();
|
||||
await page.getByText('On Hold').first().waitFor();
|
||||
|
||||
// Click through to a particular purchase order
|
||||
await page.getByRole('cell', { name: 'PO0013' }).click();
|
||||
// Filter by 'has start date'
|
||||
await setTableChoiceFilter(page, 'Has Start Date', 'Yes');
|
||||
await page.getByRole('cell', { name: 'Scheduled purchase order' }).waitFor();
|
||||
|
||||
// Click through to a particular purchase order
|
||||
await page.getByRole('cell', { name: 'PO0015' }).click();
|
||||
await page.getByRole('button', { name: 'Issue Order' }).waitFor();
|
||||
|
||||
// Expected values
|
||||
await page.getByText('2025-06-12').waitFor(); // Start Date
|
||||
await page.getByText('2025-07-17').waitFor(); // Target Date
|
||||
});
|
||||
|
||||
test('Purchase Orders - Barcodes', async ({ page }) => {
|
||||
@ -70,7 +78,7 @@ test('Purchase Orders - Barcodes', async ({ page }) => {
|
||||
await page.getByRole('button', { name: 'Issue Order' }).waitFor();
|
||||
|
||||
// Ensure we can scan back to this page, with the associated barcode
|
||||
await page.goto(`${baseUrl}/`);
|
||||
await page.getByRole('tab', { name: 'Sales' }).click();
|
||||
await page.waitForTimeout(250);
|
||||
await page.getByRole('button', { name: 'Open Barcode Scanner' }).click();
|
||||
await page.getByPlaceholder('Enter barcode data').fill('1234567890');
|
||||
|
@ -33,6 +33,7 @@ test('Tables - Filters', async ({ page }) => {
|
||||
await setTableChoiceFilter(page, 'Responsible', 'readers');
|
||||
await setTableChoiceFilter(page, 'Assigned to me', 'No');
|
||||
await setTableChoiceFilter(page, 'Project Code', 'PRO-ZEN');
|
||||
await setTableChoiceFilter(page, 'Has Start Date', 'Yes');
|
||||
|
||||
await clearTableFilters(page);
|
||||
});
|
||||
@ -49,4 +50,17 @@ test('Tables - Columns', async ({ page }) => {
|
||||
// De-select some items
|
||||
await page.getByRole('menuitem', { name: 'Description' }).click();
|
||||
await page.getByRole('menuitem', { name: 'Stocktake' }).click();
|
||||
await page.keyboard.press('Escape');
|
||||
|
||||
await page.goto(`${baseUrl}/sales/index/salesorders`);
|
||||
|
||||
// Open column selector
|
||||
await page.getByLabel('table-select-columns').click();
|
||||
|
||||
await page.getByRole('menuitem', { name: 'Start Date' }).click();
|
||||
await page.getByRole('menuitem', { name: 'Target Date' }).click();
|
||||
await page.getByRole('menuitem', { name: 'Reference', exact: true }).click();
|
||||
await page.getByRole('menuitem', { name: 'Project Code' }).click();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user