We make releasing music easier.
We are DIY artists, label people, software developers and music consumers who are building tools to give indies superpowers in the age of big data.
"Giving indies superpowers in the age of big data."
The directories in the project root all have their own responsibilities:
.github
: All GitHub config, including the continuous integration workflow.asset
: All static assets (images, icons, etc.)class
: Probably the most important directory - the resource root for all functionality of the project. Plain PHP classes, not tied to any particular framework/implementation.data
: User uploaded content and content for the website pages.page
: The entry point to the application - this directory contains the HTML views and the PHP controllers for each route. The files are automatically routed according to the requested URI (www.trackshift.app/account/costs
loadspage/account/costs/index.html
and optionallyindex.php
if it exists).query
: All SQL files used across the project, organised into query collections of their own encapsulated responsibilities.script
: ECMAscript 6 files for client-side enhancements, that automatically compile to a singlescript.js
.style
: SCSS files, organised into collections of specificity, that automatically compile to a singlestyle.css
.test
: Behavioural and unit tests that assure the quality of the code, and that functionality never regresses.vendor
: Created by runningcomposer install
.www
: The public web root - contains all resources
Within the class
directory are namespace-organised directories. Organised within these directories are three types of classes:
- Entities: sometimes referred to as "data models", entities represent a record in the system.
- Repositories: classes that perform create/retrieve/update/delete operations on entities, and link them to the underlying database.
- Functionality collections: any other classes used simply organise functionality, such as user interface, authentication, web content, etc.
User
: Everything starts with aUser
. Whether the user has logged in or not, they have aUser
object representing their current session. A User can be authenticated by having anauthwaveId
associated.Upload
: The first thing aUser
will do is upload one or more files. When a file is uploaded in theUploadRepository
its filename and type are recorded in the Upload table before being processed.Usage
: Once anUpload
is created, it needs processing into usages. EachUsage
represents a row in an uploaded file. All data stored within each row is extracted into a JSON column calleddata
, for when future adjustments need to be made on already-processed data. EachUsage
needs processing to create the relevant Products and Artists.Artist
: As aUsage
is processed, the processor will come across different artists. Currently, artists are directly related to the uploadingUser
, so can safely be matched by name without interfering with any other similarly-named artists that are uploaded by other users.Product
: Another class extracted during the processing is theProduct
. A Product has an assigned artist.Usage
: Each product that has been extracted will have at least 1 usage, which represents the row of data from within anUpload
.ProductEarning
: Usages are converted into earnings which represent the differentMoney
amounts associated to each usage of a Product: earning, cost, outgoing, profit.Cost
: Costs can be added to Products which will be subtracted from the earning.Split
: Splits can be added to Products to divide the remaining profit between different parties, according to theirSplitPercentage
value. A special type of percentageRemainderSplitPercentage
is always added to aSplit
, with a value that is calculated as the remaining split from 100%.
Since the first version, we've switched from SQLite to MySQL. (Insert quote about "how long until you realise MySQL is the solution?").
To achieve the features we need, MySQL imports directly from CSV. This is done by altering the
To automate currency conversion, we need to know the currency of the uploaded statements. Here's where that data lives:
- Bandcamp:
currency
- Cargo Digital:
Currency
- Cargo Physical: Always GBP
- CD Baby: Always USD
- DistroKid: Always USD
- PRS: Always GBP
- Tunecore:
Currency
The cron/exchange-rates.php
script will download all exchange rates from 2010, using https://openexchangerates.org/. These are cached into dated JSON files within data/cache/currency
. The closest date is used at the point of estimation.
No estimation is done on-the-fly, because that would take too much processing time. Instead, there are new fields in the UsageOfProduct table:
originalCurrency
field to store the currency of the upload.originalEarning
is the value taken from the statement upload.earning
is changed now so that it will be set to the same value asoriginalEarning
if the statement is the user's currency, or whatever the corresponding estimate is.statementType
field for future reference.estimateGBP
,estimateUSD
,estimateEUR
fields to store the estimated earning in the three currencies.earningConfirmed
for now, anything non-null indicates that theearning
value is confirmed as accurate. We can use a datetime string. In the future we will want to use a foreign key to theIncome
table, when it's made.
The user will store their currency in the Settings
table. For now, default to GBP, but in the future default using their IP address.