Re: [Ledger-smb-devel] API documentation, was Re: Web services revisited
On Wed, May 23, 2012 at 1:45 AM, Nigel Titley ni...@titley.com wrote: On 23/05/2012 06:29, Nigel Titley wrote: OK, I think the time has come to do a from-scratch install on a new virtual machine and see how it goes. I can then check out the documentation at the same time. Well, I've now done this. A brand new install on a brand new Ubuntu virtual machine, postgres 8.4 largely goes perfectly. And I'm very impressed with how the rough edges seem to have been largely smoothed off 1.3. I have a bug report and a question: 1. I created a customer and a couple of parts. The customer was set up with a shipping address and a billing address. I then created an order and changed the ship-to address to the shipping address. I then tried to save the order. At this point I get the error Error! INSERT INTO new_shipto (trans_id, oe_id,location_id) VALUES ( ?, ?, ?) ERROR: permission denied for sequence new_shipto_id_seq Corrected. If you get the latest Roles.sql from svn branches/1.3 and update your database through setup.pl this should be fixed. 2. After I raised the order again, but didn't change the shipping address the order is saved correctly. I now generate an invoice from the sales order. The invoice is generated correctly and appears in AR - reports - transactions. I then go to cash - receipts, select the customer and get the invoice. I select the invoice (with the check box to the right of the invoice) and click update. The invoice disappears and the To pay is set to zero. I then click Post and I'm returned to the cash-receipts screen. So far so good. However when I go to the AR - reports - transactions report, the invoice is not marked as paid. What am I doing wrong? Looking into this one. Best Wishes, Chris Travers -- Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ ___ Ledger-smb-devel mailing list Ledger-smb-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ledger-smb-devel
Re: [Ledger-smb-devel] API documentation, was Re: Web services revisited
2. After I raised the order again, but didn't change the shipping address the order is saved correctly. I now generate an invoice from the sales order. The invoice is generated correctly and appears in AR - reports - transactions. I then go to cash - receipts, select the customer and get the invoice. I select the invoice (with the check box to the right of the invoice) and click update. The invoice disappears and the To pay is set to zero. I then click Post and I'm returned to the cash-receipts screen. So far so good. However when I go to the AR - reports - transactions report, the invoice is not marked as paid. What am I doing wrong? I see the confusion. The final two columns on the screen are what are important. The last one, marked 'X' is actually 'X' as in cross out or delete this invoice from the payment list. It is there to allow you to filter which payments you don't want to pay during your workflow. To the left of that column is one marked To Pay. It's the checkbox there that is important. Click that one to pay those respective invoices. Best Wishes, Chris Travers -- Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ ___ Ledger-smb-devel mailing list Ledger-smb-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ledger-smb-devel
Re: [Ledger-smb-devel] API documentation, was Re: Web services revisited
On 23/05/2012 11:41, Chris Travers wrote: My bad. I had broken something in my development version in correcting an unrelated issue. The checkbox in the pay to field is hidden by default. You do not need to check it. Just don't click the one under the X. Hmm, yes this seems to work, as does exposing the pay-to field and clicking the checkbox. It does make for somewhat less than intuitive behaviour at the moment especially for those of us used to 1.2 where you click the checkbox to make the payment, hence my problems. Thanks for this. Nigel -- Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ ___ Ledger-smb-devel mailing list Ledger-smb-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ledger-smb-devel
[Ledger-smb-devel] Bug in saving preferences
It doesn't seem possible to save stylesheet preference. Changing stylesheet and saving it doesn't seem to have any effect. Nigel -- Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ ___ Ledger-smb-devel mailing list Ledger-smb-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ledger-smb-devel
Re: [Ledger-smb-devel] API documentation
On Tue, 2012-05-22 at 21:49 -0400, Chris Travers wrote: On Tue, May 22, 2012 at 6:28 PM, Robert James Clay j...@rocasa.us wrote: Haven't checked to see how much space they're taking up (there are currently some 61 of them) but those are currently included in the Debian package. (They're created as part of the build and I then use a standard Debian helper script to get them installed in the package.) Perfect. Especially if you have something working for you Besides the man pages and files that are separately installed as examples, I also have most of the rest of the documentation installed with the current Debian packaging (to /usr/share/doc/ledgersmb). The database sub directory, for instance (though I should perhaps add registration of at least the database/ledgersmb.html file, so that it also shows up in the documentation menu). The LedgerSMB Manual, for which I have a note about investigating the creation of an HTML version of the manual from that same source file. The templating guide (presuming that is it's valid), though I've wondered about providing an html version of it with the package rather than the source tex file. The faq.html file (is that current?). The coding-standard.pdf (from 2006, and I'm not actually sure why I have that included in the package installation...) I will put these in a separate tarball. Not sure what you mean. Separate distribution RPM archive for the doc files associated with a particular version? Separate distribution archive for the documentation? Don't want to make things harder for packagers by putting things in multiple places. Which 'things'? Jame -- Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ ___ Ledger-smb-devel mailing list Ledger-smb-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ledger-smb-devel
[Ledger-smb-devel] File import plugin documentation
One of the things high up on my agenda is writing a basic CSV file importer. I see where to put the parsers but there isn't a lot of documentation on how a parser should work, unless I've missed it. Can someone elucidate? Nigel -- Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ ___ Ledger-smb-devel mailing list Ledger-smb-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ledger-smb-devel
[Ledger-smb-devel] Bug in Requirements report
Checking any of the month checkboxes in the requirements report gives an Internal server error The error.log entry is [Wed May 23 09:30:23 2012] [error] [client 91.197.17.140] Premature end of script headers: ic.pl, referer: http://wol.homechip.com/ledgersmb/ic.pl?login=johnaction=requirementsmodule=ic.pl; Math::BigInt: couldn't load specified math lib(s), fallback to Math::BigInt::FastCalc at LedgerSMB/Form.pm line 61 No handle/phrase at /usr/share/perl/5.10/Locale/Maketext.pm line 180 Locale::Maketext::maketext() called at LedgerSMB/Locale.pm line 91 LedgerSMB::Locale::text('LedgerSMB::Locale::en_gb=HASH(0xb0b0728)', undef) called at bin/ic.pl line 2593 main::requirements_report called at bin/ic.pl line 4010 main::continue called at old-handler.pl line 161 main::__ANON__() called at /usr/local/share/perl/5.10.1/Error.pm line 419 eval {...} called at /usr/local/share/perl/5.10.1/Error.pm line 411 Error::subs::try('CODE(0xb08b060)', 'HASH(0xb0c04f0)') called at old-handler.pl line 172 require old-handler.pl called at /usr/local/ledgersmb/ic.pl line 7. Compilation failed in require at /usr/local/ledgersmb/ic.pl line 7. To my knowledge this bug was also present in 1.2, but I never got around to reporting it Nigel -- Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ ___ Ledger-smb-devel mailing list Ledger-smb-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ledger-smb-devel
Re: [Ledger-smb-devel] Bug in Requirements report
On Wed, May 23, 2012 at 6:34 AM, Nigel Titley ni...@titley.com wrote: Checking any of the month checkboxes in the requirements report gives an Internal server error The error.log entry is [Wed May 23 09:30:23 2012] [error] [client 91.197.17.140] Premature end of script headers: ic.pl, referer: http://wol.homechip.com/ledgersmb/ic.pl?login=johnaction=requirementsmodule=ic.pl; Math::BigInt: couldn't load specified math lib(s), fallback to Math::BigInt::FastCalc at LedgerSMB/Form.pm line 61 No handle/phrase at /usr/share/perl/5.10/Locale/Maketext.pm line 180 Locale::Maketext::maketext() called at LedgerSMB/Locale.pm line 91 LedgerSMB::Locale::text('LedgerSMB::Locale::en_gb=HASH(0xb0b0728)', undef) called at bin/ic.pl line 2593 main::requirements_report called at bin/ic.pl line 4010 main::continue called at old-handler.pl line 161 main::__ANON__() called at /usr/local/share/perl/5.10.1/Error.pm line 419 eval {...} called at /usr/local/share/perl/5.10.1/Error.pm line 411 Error::subs::try('CODE(0xb08b060)', 'HASH(0xb0c04f0)') called at old-handler.pl line 172 require old-handler.pl called at /usr/local/ledgersmb/ic.pl line 7. Compilation failed in require at /usr/local/ledgersmb/ic.pl line 7. To my knowledge this bug was also present in 1.2, but I never got around to reporting it Entered into sourceforge as bug 3529106 Nigel -- Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ ___ Ledger-smb-devel mailing list Ledger-smb-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ledger-smb-devel -- Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ ___ Ledger-smb-devel mailing list Ledger-smb-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ledger-smb-devel
Re: [Ledger-smb-devel] API documentation
On Wed, May 23, 2012 at 5:19 AM, Robert James Clay j...@rocasa.us wrote: On Tue, 2012-05-22 at 21:49 -0400, Chris Travers wrote: On Tue, May 22, 2012 at 6:28 PM, Robert James Clay j...@rocasa.us wrote: Haven't checked to see how much space they're taking up (there are currently some 61 of them) but those are currently included in the Debian package. (They're created as part of the build and I then use a standard Debian helper script to get them installed in the package.) Perfect. Especially if you have something working for you Besides the man pages and files that are separately installed as examples, I also have most of the rest of the documentation installed with the current Debian packaging (to /usr/share/doc/ledgersmb). The database sub directory, for instance (though I should perhaps add registration of at least the database/ledgersmb.html file, so that it also shows up in the documentation menu). The LedgerSMB Manual, for which I have a note about investigating the creation of an HTML version of the manual from that same source file. The templating guide (presuming that is it's valid), though I've wondered about providing an html version of it with the package rather than the source tex file. The faq.html file (is that current?). The coding-standard.pdf (from 2006, and I'm not actually sure why I have that included in the package installation...) Last I read the faq was just before 1.3 was released. I don't have an immediate opinion on how up to date it is. Chances are it needs some cleanup. I will put these in a separate tarball. Not sure what you mean. Separate distribution RPM archive for the doc files associated with a particular version? Separate distribution archive for the documentation? No, what I mean is that since the current make approach puts the documentation in an out of the way place, I will make them available in a separate tarball download. The reasoning is that rpm and deb packages etc, can install them properly and not have to worry about also cleaning up whatever I do there. Just trying not to get in the way of the packagers. The idea is that way you can keep doing what you are doing, and ignore what I am doing, and more people know about the documentation. Best Wishes, Chris Travers -- Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ ___ Ledger-smb-devel mailing list Ledger-smb-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ledger-smb-devel
Re: [Ledger-smb-devel] Web services revisited
Hi, On 05/22/2012 05:10 PM, Chris Travers wrote: On Tue, May 22, 2012 at 12:27 PM, John Lockem...@freelock.com wrote: Hi, Chris, One forgotten method, on the object controllers, realized on IRC: ... We need an INDEX handler. GET would presumably get an individual resource, using an internal id guaranteed to be unique. Index would return a collection of resources, and would accept a variety of search parameters, presumably sent via GET parameters. h This would seem to make most sense if we break off subresources into subclasses. Not sure about this -- the way I think about subresources is that they are sugar, convenient ways of crossing relationships. For example, we might have a sugar subresource on customers to access their invoices: GET /rest/1.0/mycompany/customer/23422/invoices ... would essentially be a sugar api for this: GET /rest/1.0/mycompany/invoices/?customer_id=23422 ... at least that's how I think about them. So in most cases, I guess yes these would be different classes -- not subclasses exactly. In Drupal Services, there is a relationships description you can implement to essentially create these -- specify what other handler to call and which path parts to pass as arguments. Maybe make that an optional part of the resource controllers? Also question: should it be possible to PUT or POST a collection? For example, an ar batch? If so how do we want to handle that? For this case, I would expect to be able to POST the collection to a specific URL for the method, which may take an arbitrary payload. If you can think of a more general way to solve this, great -- in my experience, these would be defined individually per module -- basically an RPC-style service when REST isn't quite up to it... One thing I am working on for another project is standardizing a way to update hierarchies -- basically being able to PUT an object with children embedded, and possibly update data on the children. I think that would be the RESTful way to do it -- in my experience collections are more like SELECT queries, and INSERT and UPDATE work on individual rows -- you need to provide additional methods to do a bulk update. It would be nice to be able to handle that because we could define format handlers for things like CSV or Excel and then have apps that upload spreadsheets.. That sounds really good, actually. Some sort of bulk insert/bulk update method? Perhaps that can be as simple as passing a multiple GET parameter, and POST/PUT the collection to the base URL without an id. I would think this could be handled by the same PUT/POST handlers... just have the method detect if it's multiple and loop through the rows... The Index handler should get called when a request comes in via GET, with no unique identifier in the URL. This would also apply to resourcetype sub-handlers... Yeah. One problem right now that I have spotted with the current draft is that it is a fixed-length namespace. I would like to figure out how we want to do this. My thinking is that we should treat subresources proper as only possible where an id has been identified above. But this precludes a general request like: ledgersmb/rest/1.4/mycompany/customer/aging.xml One option would be to use the all keyword to mean that an id is not supplied. So that would become: ledgersmb/rest/1.4/mycompany/customer/all/aging.xml If we go that route, I don't see why we can't extend subclass handlers etc as far as needed. +1 all is a very conventional thing to use here... e.g. possible GET handler: GET /rest/1.0/my_company/ar_transactions/43353 Possible Index handler: GET /rest/1.0/my_company/ar_transactions/?invoice_id=N499216 Now, if only one invoice is found with that number (which it should) would that return a document representing that single invoice or a collection of one? I would expect a collection of one. I would expect a collection anytime I didn't specify an id or used all in place of an id. If none are found do we issue a 404 or a 200 accompanied by an empty collection document? I would expect 200 with an empty collection. 404 would be ok, though. GET /rest/1.0/my_company/ar_transactions/?status=open,closedcustomer=customer1 This would be more obviously a collection of an arbitrary number. Presumably 0 is a valid number of elements in a collection, I would think. Yes. One other minor point to bring up -- paging results. I recommend having a default page size, and using the Range header. I like how Dojo does this with JsonRest Store: Paging http://dojotoolkit.org/reference-guide/1.7/dojo/store/JsonRest.html#id7 JsonRest store uses HTTP's Range header to perform paging. When a request is made for a range of items, JsonRest will include a Range header with an items range unit specifying the range: Range: items=0-24 On your server, you should look at the Range header in the request to know which items to return. The server
Re: [Ledger-smb-devel] Web services revisited
On 05/22/2012 07:06 PM, Chris Travers wrote: On Tue, May 22, 2012 at 12:27 PM, John Lockem...@freelock.com wrote: Possible Index handler: GET /rest/1.0/my_company/ar_transactions/?invoice_id=N499216 I had a thought about this one. Suppose we allow a by= field to specify a non-standard id key? In that case, your URL would look like GET /rest/1.0/my_company/ar_transactions/N499216?by=invnumber The desired result would then be to get a redirect to the the cannonical URL. I am thinking that this avoids issues like: GET /rest/1.0/my_company/customers/A1234/locations/billing?customers_by=meta_numberlocations_by=location_class In that case instead you'd do: GET /rest/1.0/my_company/customers/A1234?by=meta_number Capture the redirect address then do [redirect_address]/locations/billing?by=location_class You could then either do a redirect and add the extension or pursue the redirect with the content type header. Note, by would only be valid where the field is a valid secondary key. The modules would be responsible for enforcing this. Hi, Cool idea, but I'm not sure it's something I would actually use. On the client side, I need a unique key for each object -- that might as well be the same one as LSMB uses -- and I would rather have a single, canonical URL for each object. So redirects to that are good, if they don't break other expectations. And implementing a service, it's easy to assume either individual objects if I have what looks like a resource path (e.g. with an id) or collections otherwise. So I would say this is fine, but not something high on my list or would likely use. It's just as easy to do an index lookup with the search parameters for other keys. The biggest question I would have would be around the defaults. For example, on the AR transactions screen, a search by default only shows open invoices. However, a search by invoice number does return closed invoices even when the closed button is unchecked. This is a very nice feature for usability, but it's also somewhat unexpected. Should either document these exceptions very clearly, or remove them from the web service -- perhaps default to returning all invoices, and force a web service to specify open if that's all they want? Cheers, John Locke http://www.freelock.com -- Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ ___ Ledger-smb-devel mailing list Ledger-smb-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ledger-smb-devel
Re: [Ledger-smb-devel] LedgerSMB accepted into Debian !
On Mon, 2012-05-21 at 11:01 -0400, Chris Travers wrote: On Mon, May 21, 2012 at 6:55 AM, Robert James Clay j...@rocasa.us wrote: But not until after that first version migrates to Debian testing, as getting a newer version uploaded before that would start the 10 day waiting period over again, which would delay a version of LedgerSMB making it into Debian testing before the freeze (for preparing the next stable release). For 1.3.15, the next one should be 1.3.17 anyway. It will be at least that; I'm not done with packaging v1.3.17 yet (besides anything else, I'm making a change in how the templates directory is installed) but certainly it'll be done by the beginning of next month. Perhaps 1.3.18; depending on when that gets released and I can get the debian package for it ready... Jame -- Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ ___ Ledger-smb-devel mailing list Ledger-smb-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ledger-smb-devel
Re: [Ledger-smb-devel] Web services revisited
On Wed, May 23, 2012 at 7:59 AM, John Locke m...@freelock.com wrote: On 05/22/2012 07:06 PM, Chris Travers wrote: On Tue, May 22, 2012 at 12:27 PM, John Lockem...@freelock.com wrote: Possible Index handler: GET /rest/1.0/my_company/ar_transactions/?invoice_id=N499216 I had a thought about this one. Suppose we allow a by= field to specify a non-standard id key? In that case, your URL would look like GET /rest/1.0/my_company/ar_transactions/N499216?by=invnumber The desired result would then be to get a redirect to the the cannonical URL. I am thinking that this avoids issues like: GET /rest/1.0/my_company/customers/A1234/locations/billing?customers_by=meta_numberlocations_by=location_class In that case instead you'd do: GET /rest/1.0/my_company/customers/A1234?by=meta_number Capture the redirect address then do [redirect_address]/locations/billing?by=location_class You could then either do a redirect and add the extension or pursue the redirect with the content type header. Note, by would only be valid where the field is a valid secondary key. The modules would be responsible for enforcing this. Hi, Cool idea, but I'm not sure it's something I would actually use. On the client side, I need a unique key for each object -- that might as well be the same one as LSMB uses -- and I would rather have a single, canonical URL for each object. So redirects to that are good, if they don't break other expectations. The obvious use case might be: ledgersmb/rest/1.0/mycompany/part/912465634532?by=upc I am thinking in particular an inventory applications might get a lot of mileage out of such a mechanism. For example here, if we get a 3xx response we can just pull the id off the end of the redirect for purposes of entering inventory. If we get a 404, we know that this UPC needs to be attached to a part somewhere. For example if we get a 404, we might want to search for the part (after requesting user input) and post the UPC info to that part. (I am expecting to get UPC's/EAN's handled under the make/model table in 1.4, so partnumber is dependent on UPC, but each part may have several UPC's) Another use case might be if I open up some part of web services so you can import the AR invoices I send you as AP invoices in your system. So you get a PDF invoice. You enter the invoice number, and it sends back a redirect to the cannonical URL, and your system imports it. You can then verify that they match before submitting. Of course a collection might work as well here, but it would not be as graceful I think, in the UPC case above. And implementing a service, it's easy to assume either individual objects if I have what looks like a resource path (e.g. with an id) or collections otherwise. So I would say this is fine, but not something high on my list or would likely use. It's just as easy to do an index lookup with the search parameters for other keys. The biggest question I would have would be around the defaults. For example, on the AR transactions screen, a search by default only shows open invoices. However, a search by invoice number does return closed invoices even when the closed button is unchecked. This is a very nice feature for usability, but it's also somewhat unexpected. Should either document these exceptions very clearly, or remove them from the web service -- perhaps default to returning all invoices, and force a web service to specify open if that's all they want? Well, with no boxes checked, the AR report returns no invoices. By default the open box is checked and the closed box is not. I would expect that we'd have to have some default parameters for web services too, and that these would have to be different since the use cases and feedback are different. For example, when doing a search, I would prefer to default to all but exclude ones based on input. So here I would think a more natural way to do a web service would be: ar_transactions/?exclude=open+closed and this way we get back to an empty collection excluding open and closed invoices. As far as posting/retrieving collections, where the data is simply tabular, I am planning on allowing tabular-format uploads, such as CSV, ODS, and eventually Excel. I figure a lot of the logic can be re-used for allowing CSV, XLS, and ODS uploads from the web app as well. Best Wishes, Chris Travers -- Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ ___ Ledger-smb-devel mailing list Ledger-smb-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ledger-smb-devel