Skip Navigation

[Resolved] Creating Functions for Inventory Management

This support ticket is created 7 years, 1 month ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Sun Mon Tue Wed Thu Fri Sat
8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 - -
13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 - -

Supporter timezone: America/New_York (GMT-04:00)

This topic contains 48 replies, has 2 voices.

Last updated by Christian Cox 7 years ago.

Assisted by: Christian Cox.

Author
Posts
#577658

I am scoping a new project and need to figure out if it's functionality will be possible with Toolset. I'll split each query into separate threads to avoid confusion.

The first issue I have relates to Inventory Management.

Aside from Admin, there will need to be two key user Roles, as below…

- Owner
The Owner is the person who's product inventory is being managed through this system.

- Reseller
A Reseller is a person who may sell the products on behalf of the Owner.

Project Intro...
I require a portal that allows Owners to add Voyages with Tickets and Allocation. There will be no booking, simply information on tickets available and sold (allocated) and by which user (Owner or Reseller).

The main issue I face is creating calculations to make the system work correctly (and avoid over-allocation), which I understand may need some custom coding.

I'll run through a basic example below…

An Owner Creates a Voyage with associated details and Inventory. This Inventory will be split between custom ticket types, each with their own custom variations.

Ticket One: 2 Berth Cabin (2 Available)
• Variation 1: Age 16-25
(2 Available)
• Variation 2: Age 26-35
(2 Available)
Ticket Two: 4 Berth Cabin (4 Available)
• Variation 1: Age 16-25
(4 Available)
• Variation 2: Age 26-35
(4 Available)

Overall there are only 6 Tickets available, so within each Ticket, if a Reseller allocated 1 of Variation 1 in the 2 berth cabin, Variation 2 in that cabin would also need to reduce in availability.

If possible with Toolset + a little custom coding, is a function like this something you could talk me through creating?

#577715

Okay so it sounds like each Ticket (CPT) needs to have a custom field that represents the total number available of that Ticket across all Variations (CPT). Then another custom field for number of Ticket already sold. Variations are children of Tickets. Each time a Variation is sold for the parent Ticket, we update the number of that parent Ticket sold, and we also update all the related child Variations to lower the available number remaining. Pretty simple math here, just + / - 1 to the existing field values. All that sounds pretty straightforward, so I could help with those things. I'm not really clear how tickets are related to each other, and if selling from one ticket affects another ticket's availability, so that might add another level of complexity to consider.

Another thing to consider is that you'll have to add some additional validation to ensure that you don't oversell. It's unlikely but it could happen, for instance if an Owner and a Reseller are both logged on and see that 1 ticket is remaining, they might both start the process to mark that ticket sold. If one of them finishes while the other is still working, then they both might actually be able to sell a ticket. So you'll need to have some additional validation code that determines if there truly is a ticket available to sell at the point of form submission. We offer the cred_form_validate API that can help with this.
https://toolset.com/documentation/programmer-reference/cred-api/#cred_form_validate

I can help here as well. You'll have to inspect the parent ticket's number of available and number of sold tickets, and return an error if none are left. Let me know your thoughts.

#577875

Okay, based on the above, I have so far created the following...

Four Custom Post Types: Vessel, Voyage (child of Vessel), Ticket (child of Voyage), Ticket Variation (child of Ticket)
Custom Fields For Ticket: Total Tickets Available, Total Tickets Sold
Custom Fields For Ticket Variation: Total Available For Variation, Total Sold For Variation, Ticket Variation Currency, Ticket Variation Cost, Ticket Variation Sale Cost
Two new User Roles: Ship Owner and Reseller / Agency
Ship Owner can create and edit all Custom Post Types (that are their own)
Reseller / Agency can only edit Ticket Variations

I think you're right in saying Tickets don't need to relate to each other as they are only connected at the Voyage level.

I have not currently created anything on the front-end of the site as the above is all in wp-admin.

So, from what I can tell, the next step should be to build the relationship between Tickets and Variations, namely having the overall availability controlled by the Ticket post type, with individual availability for each Variation impacted by both Total Availability and the Availability of Brother Variations.

If that's correct, how can I best achieve this?

#577880

So, from what I can tell, the next step should be to build the relationship between Tickets and Variations
I guess it depends on where you want to jump into the workflow process. Shall we assume Tickets and Variations are already created somehow, or do we need to consider that part of the process as well?

#577918

Good point, I do need to be figuring that out too and it may impact on the above.

What I need is for Ship Owners to be able to log in to create and edit their own Vessels, Voyages, Tickets and Variations. They'll only have a small number of Vessels, but each vessel may have 30+ Voyages, each with their own Tickets and Ticket Variations.

A Reseller would then log in and see available Tickets and Variations that are children of the Vessels they are approved to be able to see. Preferably a Ship Owner would be able to manage which Resellers can access their Tickets and Variations on a per-Vessel basis.

It would be absolutely ideal if neither of their log in areas looked like wp-admin.

Ship Owners are able to allocate Variations as sold for their own Vessels. Ship Owners shouldn't be able to see the data of any other Ship Owners. Resellers only have read access to Vessels, Voyages and Tickets, but can mark Variations as sold.

Preferably when a Variation is marked as sold, the User who sold it would be able to enter a Booking Reference and some comments that are then logged somewhere that both they and the Ship Owner can view them.

So beyond the simple plus and minus 1 on availability, we'd like Admin and Ship Owners to be able to view who has marked what as sold and when.

I think that covers most of the overall process - does any of this stand out as not possible to you?

#577923

Preferably a Ship Owner would be able to manage which Resellers can access their Tickets and Variations on a per-Vessel basis.
Everything should be handled pretty well in Toolset, except this requirement, which might require a bit of extra work to accomplish correctly. Toolset's Access plugin works by allowing you to restrict Access based on a few factors, but on a post-by-post basis it uses Post Groups. You can create Post Groups and assign them to posts arbitrarily in wp-admin. If your Ship Owners do not have wp-admin access, they might not be able to apply a post group effectively to a Vessel post, or create a new Post Group and manage its Resellers. This would have to be accomplished in wp-admin, as there is not currently a public API available for these features.

There is another option which would allow you to maintain the non-wp-admin approach. This option uses a custom field applied to the Vessel post type. This custom field would hold a list of values that indicate which Reseller IDs should be able to see the related Vessel, and its child Voyages and Tickets and Variations. When Ship Owners create a Vessel, they would be prompted to check off individual Resellers who should have access.

On the front-end of the site, you can use this custom field value to filter Views of posts. However, this custom field does not restrict the Reseller's ability to visit the URLs created by WordPress for other Vessels, Voyages, Tickets, etc. So extra work will be required to set up conditional logic on each URL generated by WordPress for individual Vessels, Voyages, Tickets, and Variations. This can be accomplished with a Content Template and some inline conditionals. If you're not planning to utilize the URL structures provided by WordPress (yoursite.com/vessel/some-vessel-name would be the single post page for a Vessel), then this becomes less of a concern because everything is displayed by Views.

#577959

When Ship Owners create a Vessel, they would be prompted to check off individual Resellers who should have access.
This would be the best option

With regard to the URLs, I don't expect Ship Owners or Resellers to deliberately try their luck at accessing others data, though if there is a solution to control it that would be good to implement. To clarify on what you've said, you're saying that using Views will mean they won't 'see' any links to the data of others, then adjusting the URLs will mean they can't find it by typing direct URLs to others data?

#577974

With regard to the URLs, I don't expect Ship Owners or Resellers to deliberately try their luck at accessing others data, though if there is a solution to control it that would be good to implement.
Okay yes, the solution here is to use conditional HTML in your Content Templates or Template Layouts to restrict the content on those pages, even if the URLs are still accessible by manually typing them out. More info on conditionals:
https://toolset.com/documentation/user-guides/conditional-html-output-in-views/

To clarify on what you've said, you're saying that using Views will mean they won't 'see' any links to the data of others, then adjusting the URLs will mean they can't find it by typing direct URLs to others data?
The first part, yes. If you set up your View filters correctly then you can restrict the results and only show the accessible posts. Let's say you want to show a list of Vessels a user has access to. You will create a View of Vessels, filtered by the custom field set up by the Ship Owner. If the custom field value contains the same value as the current User ID, then the Vessel will be displayed in the View. If not, the Vessel will not appear for that User.

Regarding the second part about adjusting URLs, let me explain a bit more. By default, WordPress creates unique URLs for each Voyage, Vessel, Ticket, and Variation like yoursite.com/voyage/voyage-name, where "voyage" is the post type slug, and "voyage-name" is the post slug. This is where it gets tricky because anyone can type those URLs manually and access those pages by guessing other Voyage names. There are a few options for handling this. You can tell WordPress to not create these URLs automatically for each Voyage, but that removes the unique page for each Voyage or Vessel etc entirely for all users. So you would have to set up custom pages that display each Voyage's content some other way, usually with a URL parameter of some kind (yoursite.com/voyages?voyage=12345, yoursite.com/tickets?ticket=23456).

Or, you can use the conditional HTML approach I mentioned above, where you allow users to access restricted URLs but you restrict the content on those pages using conditional logic.

#577978

Okay, so instead of making the URLs unpredictable we simply restrict the Page Content the same way we restrict the results in Views. That sounds to me like it solves both problems together.

If so, and given all of the above, where would you recommend beginning with the setup process?

#577994

First, it's generally a good idea to set up a staging site. You can use this as a playground without affecting your final, live site, and you can always test upgrades and new plugins here before deploying them to the live site.

I would start creating my custom post types next. Set up the necessary post relationships between these post types, and the necessary custom fields. Create a few of each post type, and manually fill in their custom fields, so you have some content to work with. This will force you to think about how data is stored in each post, and how you have to structure things. Don't worry about CRED or conditional display or access permissions at first, just create things manually in the backend and pretend everyone can see everything for now on the front-end. In other words, work on content structure.

Set up Content Templates that will display the correct information on each single post page for Vessels, Voyages, Tickets and Variations. Test these out with your demo content. Then, set up some Views that will represent what your Ship Owners and your Resellers will see when browse the site. For example, you might want to show Ship Owners a list of the Vessels they manage. You might want to show Resellers a list of the tickets they have sold to date, or a list of Vessels they have access to. You might need to create custom Pages to hold this information. In other words, work on content display.

Next, you could work on CRED forms, which will allow your Ship Owners to create Vessels and Tickets, and allow your Resellers or Ship Owners to edit Variations. This is where you will need some custom code that listens for any CRED form submissions and performs the necessary calculations and modifications automatically. In other words, work on business logic / workflows.

Finally, I would tackle additional restrictions. At that point you should be able to log in as any user type and navigate the full process. You'll find that you need to filter some Views or apply some inline conditional code in specific places.

#578340

I'm making g progress on the above and have a quick question for you...

When a Ship Owners or Reseller logs that they have made a booking, would the booking reference and comments fields be a part of the Variation post type or a part of a new CPT that is a child of that variation?

#578348

I don't think you need a new child of Variations to handle this if standard WordPress comments are sufficient. You can enable or disable standard comments on each individual post type from the post type editor's options panel. If standard post comments aren't sufficient, then a child post type may be necessary.

To indicate a booking, I was thinking that you would set a custom field on the sold Variation post, like a checkbox. Then you could use this custom field in a query to return a list of booked Variations for a given Ticket. You would also update the total number of Tickets sold in the parent ticket, as well as the number of available Variations remaining in all of its child Variations. Is there something else you need to capture as a Booking Reference, like an ID number or other identifier? If so, then I would store that information in a custom field on the Variation post. When the Owner or Reseller edits a Variation with CRED to mark it booked, they could also enter a booking reference. This relates the Variation to the Booking info in another system, and your site users can access that information in a View of sold Variations.

#578360

When a Variation is booked, the information we need to capture is as follows...

1. The Variation, Ticket and Voyage Code (I assume the parent and grandparent data can be brought out in a custom View or report)
2. The Ship Owner or Reseller that made the booking
3. The number of places they booked in that instance
4. A Booking Reference (which would have to be text entry)
5. The Price it was booked at (either standard price or the sale price if one is entered)

This process may happen 20+ times per variation, with the data from each needing to be stored. I assume you're saying repetition of these fields is possible with CRED editing of the Variation post or through comments?

When a user goes to enter a booking, we would not want them to see any of the previous bookings made in that form (they would be elsewhere in a report/view).

Would it still make most sense to do this with comments or, given the above, would you suggest a child CPT of the Variation?

#578370

This process may happen 20+ times per variation, with the data from each needing to be stored.
Okay I thought some simple custom fields would be sufficient here, but now that I understand it in more detail, you will actually need another post type to capture all of this information for each Booking. This post type will be a child of Variations. With that in mind, when someone marks a Variation "booked" they will actually be submitting a CRED form that creates a Booking post that is a child of the current Variation. You will also need some custom code here that helps update the number of Variations still available to book, as well as the number of Tickets sold.

#578759

I'm almost at a point where I have the front-end as it should be and have a quick question:

The landing page after log in will be an overview of Voyages, Split by Vessel name. The View will be filtered so that Ship Owners only see Vessels that they Own, but Resellers will need to have this View filtered based on the custom permissions set by multiple Ship Owners. My question is, will this need to be two separate views, one for the Ship Owners and one for Resellers, in order to achieve this?